From a772372b2bbb44da2f6800ac9befdcda2fd34a7d Mon Sep 17 00:00:00 2001 From: Michael Mainguy Date: Mon, 29 Dec 2025 11:49:56 -0600 Subject: [PATCH] Add public URL sharing with express-pouchdb sync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add express-pouchdb for self-hosted PouchDB sync server - Public databases (/db/public/:db) accessible without auth - Add auth middleware for public/private database access - Simplify share button to copy current URL to clipboard - Move feature config from static JSON to dynamic API endpoint - Add PouchDB sync to PouchData class for real-time collaboration - Fix Express 5 compatibility by patching req.query - Skip express.json() for /pouchdb routes (stream handling) - Remove unused PouchdbPersistenceManager and old share system 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .gitignore | 1 + package-lock.json | 1966 ++++++++++++++++- package.json | 8 +- public/api/user/README.md | 89 - public/api/user/features | 26 - public/api/user/features-basic.json | 26 - public/api/user/features-free.json | 26 - public/api/user/features-none.json | 26 - public/api/user/features-pro.json | 26 - server.js | 53 +- server/api/index.js | 4 + server/api/user.js | 155 ++ server/middleware/dbAuth.js | 78 + server/services/databaseService.js | 62 + src/integration/database/pouchData.ts | 49 + .../database/pouchdbPersistenceManager.ts | 409 ---- src/react/pages/vrExperience.tsx | 30 +- src/util/featureConfig.ts | 4 +- src/util/functions/getPath.ts | 45 +- src/vrApp.ts | 1 - 20 files changed, 2418 insertions(+), 666 deletions(-) delete mode 100644 public/api/user/README.md delete mode 100644 public/api/user/features delete mode 100644 public/api/user/features-basic.json delete mode 100644 public/api/user/features-free.json delete mode 100644 public/api/user/features-none.json delete mode 100644 public/api/user/features-pro.json create mode 100644 server/api/user.js create mode 100644 server/middleware/dbAuth.js create mode 100644 server/services/databaseService.js delete mode 100644 src/integration/database/pouchdbPersistenceManager.ts diff --git a/.gitignore b/.gitignore index c3bb0db..a7762e1 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ dist-ssr # Local Netlify folder .netlify +/data/ diff --git a/package-lock.json b/package-lock.json index 7eb5d79..2ae2a80 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "immersive", - "version": "0.0.8-34", + "version": "0.0.8-41", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "immersive", - "version": "0.0.8-34", + "version": "0.0.8-41", "license": "MIT", "dependencies": { "@auth0/auth0-react": "^2.2.4", @@ -37,13 +37,17 @@ "dotenv": "^17.2.3", "events": "^3.3.0", "express": "^5.2.1", + "express-pouchdb": "^4.2.0", "hash-wasm": "4.11.0", "hls.js": "^1.1.4", "js-crypto-aes": "1.0.6", + "leveldown": "^6.1.1", "loglevel": "^1.9.1", "meaningful-string": "^1.4.0", "peer-lite": "2.0.2", "pouchdb": "^8.0.1", + "pouchdb-adapter-leveldb": "^9.0.0", + "pouchdb-adapter-memory": "^9.0.0", "pouchdb-find": "^8.0.1", "query-string": "^8.1.0", "react-router-dom": "^6.26.1", @@ -1651,6 +1655,15 @@ "node": ">=0.4.0" } }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", + "license": "BSD-3-Clause OR MIT", + "engines": { + "node": ">=0.4.2" + } + }, "node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -1670,6 +1683,24 @@ "extend": "^3.0.2" } }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "license": "ISC" + }, + "node_modules/argsarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/argsarray/-/argsarray-0.0.1.tgz", + "integrity": "sha512-u96dg2GcAKtpTrBdDoFIM7PjcBA+6rSP0OR94MOReNRyUECL6MtQt5XXmRr4qrftYaef9+l5hcpO5te7sML1Cg==", + "license": "WTFPL" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -1688,6 +1719,15 @@ "node": "*" } }, + "node_modules/ast-types": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz", + "integrity": "sha512-qEdtR2UH78yyHX/AUNfXmJTlM48XoFZKBdwi1nzkI1mJL21cmbu0cvjxjpkXJ5NENMq42H+hNs8VLJcqXLerBQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -1723,6 +1763,21 @@ "integrity": "sha512-m3pNLk5Qy1XyHIv9NtVzqb2j+ihk2ysuLDYrRng0gi0VZ8pl1qNhuRsEoUwlwiXxiccnbAphPvYvznSCZPr+tQ==", "peer": true }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/base62": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/base62/-/base62-1.2.8.tgz", + "integrity": "sha512-V6YHUbjLxN1ymqNLb1DPHoU1CpfdL7d2YTIp5W3U4hhoG4hhxNmsFDs66M9EXxBiSEke5Bt5dwdfMwwZF70iLA==", + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -1742,6 +1797,39 @@ } ] }, + "node_modules/base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "license": "MIT" + }, "node_modules/body-parser": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.1.tgz", @@ -1766,6 +1854,16 @@ "url": "https://opencollective.com/express" } }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", @@ -1818,16 +1916,6 @@ "node": ">=6.14.2" } }, - "node_modules/bufferutil/node_modules/node-gyp-build": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", - "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -1897,6 +1985,15 @@ "resolved": "https://registry.npmjs.org/canvas-hypertxt/-/canvas-hypertxt-1.0.3.tgz", "integrity": "sha512-+VsMpRr64jYgKq2IeFUNel3vCZH/IzS+iXSHxmUV3IUH5dXlC9xHz4AwtPZisDxZ5MWcuK0V+TXgPKFPiZnxzg==" }, + "node_modules/catering": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/catering/-/catering-2.1.1.tgz", + "integrity": "sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/chai": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", @@ -1996,6 +2093,107 @@ "node": "^12.20.0 || >=14" } }, + "node_modules/commoner": { + "version": "0.10.8", + "resolved": "https://registry.npmjs.org/commoner/-/commoner-0.10.8.tgz", + "integrity": "sha512-3/qHkNMM6o/KGXHITA14y78PcfmXh4+AOCJpSoF73h4VY1JpdGv3CHMS5+JW6SwLhfJt4RhNmLAa7+RRX/62EQ==", + "license": "MIT", + "dependencies": { + "commander": "^2.5.0", + "detective": "^4.3.1", + "glob": "^5.0.15", + "graceful-fs": "^4.1.2", + "iconv-lite": "^0.4.5", + "mkdirp": "^0.5.0", + "private": "^0.1.6", + "q": "^1.1.2", + "recast": "^0.11.17" + }, + "bin": { + "commonize": "bin/commonize" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commoner/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/commoner/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/compression/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, "node_modules/confbox": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", @@ -2038,6 +2236,25 @@ "node": ">= 0.6" } }, + "node_modules/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, "node_modules/cookie-signature": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", @@ -2088,6 +2305,64 @@ "node": ">=10" } }, + "node_modules/couchdb-calculate-session-id": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/couchdb-calculate-session-id/-/couchdb-calculate-session-id-1.1.3.tgz", + "integrity": "sha512-7RJSTHf8cmeS07oB90LB1Kx7Yxbz/WQJOq9YEKpKJ6Eamca4ovXczMoZs6DlEu01j6DUgW6Z7zQpMxvYaOxskQ==", + "license": "Apache-2.0", + "dependencies": { + "aproba": "^1.0.1", + "base64url": "^3.0.0", + "crypto-lite": "^0.2.0" + } + }, + "node_modules/couchdb-eval": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/couchdb-eval/-/couchdb-eval-4.2.0.tgz", + "integrity": "sha512-wMTb6FQIi2103q3gVJARl2J4Qc5Mqs+pC6sXIgDXn03D3UFWcsHJE7u2OQdr74p8k/PWkawPFZCtwvnK1J6oLQ==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.0", + "pouchdb-plugin-error": "4.2.0" + } + }, + "node_modules/couchdb-objects": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/couchdb-objects/-/couchdb-objects-4.2.0.tgz", + "integrity": "sha512-YHy56nUy5BxakeErqYmWp1QtcfFet/q+fRDJDZWJIIeUnZzMlm6S6xgF99shhWNwys4YpXcLhTr+ctgdFlW5Xw==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.0", + "header-case-normalizer": "^1.0.3", + "is-empty": "^1.2.0", + "pouchdb-promise": "^6.4.1", + "random-uuid-v4": "0.0.8" + } + }, + "node_modules/couchdb-render": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/couchdb-render/-/couchdb-render-4.2.0.tgz", + "integrity": "sha512-2NH4+QJQdAaUa/YB/5zioYjXoPKg6Ui22nUDAJVyXoEgkiP4AWEOQEDVpOv7JTM3N8KqUdyVoChqzPY7yJJ9tA==", + "license": "Apache-2.0", + "dependencies": { + "couchdb-eval": "4.2.0", + "couchdb-resp-completer": "4.2.0", + "extend": "^3.0.0", + "is-empty": "^1.2.0", + "pouchdb-plugin-error": "4.2.0" + } + }, + "node_modules/couchdb-resp-completer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/couchdb-resp-completer/-/couchdb-resp-completer-4.2.0.tgz", + "integrity": "sha512-PbA+krf4EYyXMe68/sZjVrZoPCkSJExeo5hj+NzFJrzjwfMq5m89o5Wf2SBcaWC5SZMf/Bh6TP4qqv5icFMKog==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.0", + "is-empty": "^1.2.0", + "pouchdb-plugin-error": "4.2.0" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -2102,6 +2377,12 @@ "node": ">= 8" } }, + "node_modules/crypto-lite": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/crypto-lite/-/crypto-lite-0.2.0.tgz", + "integrity": "sha512-g80sI65b5Gfg4BltF1GMdyjwiGWtQPnEMDmu1/QAA4S1UY+jmuZM5iopakOuUnkn6TUPJYsacKEeALnbd68r1Q==", + "license": "MIT" + }, "node_modules/css-color-keywords": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", @@ -2216,6 +2497,15 @@ "node": ">=6" } }, + "node_modules/defined": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz", + "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -2224,6 +2514,12 @@ "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==", + "license": "MIT" + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -2248,6 +2544,28 @@ "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" }, + "node_modules/detective": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", + "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", + "license": "MIT", + "dependencies": { + "acorn": "^5.2.1", + "defined": "^1.0.0" + } + }, + "node_modules/detective/node_modules/acorn": { + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -2337,6 +2655,15 @@ "write-stream": "~0.4.3" } }, + "node_modules/equals": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/equals/-/equals-1.0.5.tgz", + "integrity": "sha512-wI15a6ZoaaXPv+55+Vh2Kqn3+efKRv8QPtcGTjW5xmanMnQzESdAt566jevtMZyt3W/jwLDTzXpMph5ECDJ2zg==", + "license": "MIT", + "dependencies": { + "jkroso-type": "1" + } + }, "node_modules/errno": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", @@ -2394,6 +2721,17 @@ "node": ">= 0.4" } }, + "node_modules/es3ify": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/es3ify/-/es3ify-0.2.2.tgz", + "integrity": "sha512-QQ6yXmQM/cfWYj9/DM3hPRcHBZdWCoJU+35CoaMqw53sH2uqr29EZ0ne1PF/3LIG/cmawn1SbCPqcZE+siHmwg==", + "license": "MIT", + "dependencies": { + "esprima": "^2.7.1", + "jstransform": "~11.0.0", + "through": "~2.3.4" + } + }, "node_modules/es5-ext": { "version": "0.10.64", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", @@ -2500,6 +2838,31 @@ "node": ">=0.10" } }, + "node_modules/esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/esprima-fb": { + "version": "15001.1.0-dev-harmony-fb", + "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-15001.1.0-dev-harmony-fb.tgz", + "integrity": "sha512-59dDGQo2b3M/JfKIws0/z8dcXH2mnVHkfSPRhCYS91JNGfGNwr7GsSF6qzWZuOGvw5Ii0w9TtylrX07MGmlOoQ==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", @@ -2609,6 +2972,444 @@ "url": "https://opencollective.com/express" } }, + "node_modules/express-pouchdb": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/express-pouchdb/-/express-pouchdb-4.2.0.tgz", + "integrity": "sha512-UHA2q/A+rIEptefwBODTlH42PoaRro7eAnupztaBdoZofTXdaUcDcVZ1/QrwGeewGJLNf6+1Oia7wO4IX+rSew==", + "license": "Apache-2.0", + "dependencies": { + "basic-auth": "^2.0.0", + "body-parser": "^1.16.1", + "compression": "^1.6.2", + "cookie-parser": "^1.4.3", + "denodeify": "^1.2.1", + "express": "^4.14.1", + "extend": "^3.0.0", + "header-case-normalizer": "^1.0.3", + "mkdirp": "^0.5.0", + "multiparty": "^4.1.3", + "on-finished": "^2.3.0", + "pouchdb-all-dbs": "^1.0.2", + "pouchdb-auth": "4.2.0", + "pouchdb-collections": "^7.0.0", + "pouchdb-fauxton": "^0.0.6", + "pouchdb-find": "^7.0.0", + "pouchdb-list": "4.2.0", + "pouchdb-promise": "^6.4.1", + "pouchdb-replicator": "4.2.0", + "pouchdb-rewrite": "4.2.0", + "pouchdb-security": "4.2.0", + "pouchdb-show": "4.2.0", + "pouchdb-size": "4.2.0", + "pouchdb-update": "4.2.0", + "pouchdb-validation": "4.2.0", + "pouchdb-vhost": "4.2.0", + "pouchdb-wrappers": "4.2.0", + "raw-body": "^2.2.0", + "sanitize-filename": "^1.6.1", + "uuid": "^3.0.1" + } + }, + "node_modules/express-pouchdb/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-pouchdb/node_modules/body-parser": { + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/express-pouchdb/node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-pouchdb/node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" + }, + "node_modules/express-pouchdb/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express-pouchdb/node_modules/express": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.14.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "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" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-pouchdb/node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express-pouchdb/node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-pouchdb/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/express-pouchdb/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-pouchdb/node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/express-pouchdb/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/express-pouchdb/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-pouchdb/node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" + }, + "node_modules/express-pouchdb/node_modules/pouchdb-abstract-mapreduce": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/pouchdb-abstract-mapreduce/-/pouchdb-abstract-mapreduce-7.3.1.tgz", + "integrity": "sha512-0zKXVFBvrfc1KnN0ggrB762JDmZnUpePHywo9Bq3Jy+L1FnoG7fXM5luFfvv5/T0gEw+ZTIwoocZECMnESBI9w==", + "license": "Apache-2.0", + "dependencies": { + "pouchdb-binary-utils": "7.3.1", + "pouchdb-collate": "7.3.1", + "pouchdb-collections": "7.3.1", + "pouchdb-errors": "7.3.1", + "pouchdb-fetch": "7.3.1", + "pouchdb-mapreduce-utils": "7.3.1", + "pouchdb-md5": "7.3.1", + "pouchdb-utils": "7.3.1" + } + }, + "node_modules/express-pouchdb/node_modules/pouchdb-binary-utils": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/pouchdb-binary-utils/-/pouchdb-binary-utils-7.3.1.tgz", + "integrity": "sha512-crZJNfAEOnUoRk977Qtmk4cxEv6sNKllQ6vDDKgQrQLFjMUXma35EHzNyIJr1s76J77Q4sqKQAmxz9Y40yHGtw==", + "license": "Apache-2.0", + "dependencies": { + "buffer-from": "1.1.2" + } + }, + "node_modules/express-pouchdb/node_modules/pouchdb-collate": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/pouchdb-collate/-/pouchdb-collate-7.3.1.tgz", + "integrity": "sha512-o4gyGqDMLMSNzf6EDTr3eHaH/JRMoqRhdc+eV+oA8u00nTBtr9wD+jypVe2LbgKLJ4NWqx2qVkXiTiQdUFtsLQ==", + "license": "Apache-2.0" + }, + "node_modules/express-pouchdb/node_modules/pouchdb-collections": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/pouchdb-collections/-/pouchdb-collections-7.3.1.tgz", + "integrity": "sha512-yUyDqR+OJmtwgExOSJegpBJXDLAEC84TWnbAYycyh+DZoA51Yw0+XVQF5Vh8Ii90/Ut2xo88fmrmp0t6kqom8w==", + "license": "Apache-2.0" + }, + "node_modules/express-pouchdb/node_modules/pouchdb-errors": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/pouchdb-errors/-/pouchdb-errors-7.3.1.tgz", + "integrity": "sha512-Zktz4gnXEUcZcty8FmyvtYUYsHskoST05m6H5/E2gg/0mCfEXq/XeyyLkZHaZmqD0ZPS9yNmASB1VaFWEKEaDw==", + "license": "Apache-2.0", + "dependencies": { + "inherits": "2.0.4" + } + }, + "node_modules/express-pouchdb/node_modules/pouchdb-fetch": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/pouchdb-fetch/-/pouchdb-fetch-7.3.1.tgz", + "integrity": "sha512-205xAtvdHRPQ4fp1h9+RmT9oQabo9gafuPmWsS9aEl3ER54WbY8Vaj1JHZGbU4KtMTYvW7H5088zLS7Nrusuag==", + "license": "Apache-2.0", + "dependencies": { + "abort-controller": "3.0.0", + "fetch-cookie": "0.11.0", + "node-fetch": "2.6.7" + } + }, + "node_modules/express-pouchdb/node_modules/pouchdb-find": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/pouchdb-find/-/pouchdb-find-7.3.1.tgz", + "integrity": "sha512-AeqUfAVY1c7IFaY36BRT0vIz9r4VTKq/YOWTmiqndOZUQ/pDGxyO2fNFal6NN3PyYww0JijlD377cPvhnrhJVA==", + "license": "Apache-2.0", + "dependencies": { + "pouchdb-abstract-mapreduce": "7.3.1", + "pouchdb-collate": "7.3.1", + "pouchdb-errors": "7.3.1", + "pouchdb-fetch": "7.3.1", + "pouchdb-md5": "7.3.1", + "pouchdb-selector-core": "7.3.1", + "pouchdb-utils": "7.3.1" + } + }, + "node_modules/express-pouchdb/node_modules/pouchdb-mapreduce-utils": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/pouchdb-mapreduce-utils/-/pouchdb-mapreduce-utils-7.3.1.tgz", + "integrity": "sha512-oUMcq82+4pTGQ6dtrhgORHOVHZSr6w/5tFIUGlv7RABIDvJarL4snMawADjlpiEwPdiQ/ESG8Fqt8cxqvqsIgg==", + "license": "Apache-2.0", + "dependencies": { + "argsarray": "0.0.1", + "inherits": "2.0.4", + "pouchdb-collections": "7.3.1", + "pouchdb-utils": "7.3.1" + } + }, + "node_modules/express-pouchdb/node_modules/pouchdb-md5": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/pouchdb-md5/-/pouchdb-md5-7.3.1.tgz", + "integrity": "sha512-aDV8ui/mprnL3xmt0gT/81DFtTtJiKyn+OxIAbwKPMfz/rDFdPYvF0BmDC9QxMMzGfkV+JJUjU6at0PPs2mRLg==", + "license": "Apache-2.0", + "dependencies": { + "pouchdb-binary-utils": "7.3.1", + "spark-md5": "3.0.2" + } + }, + "node_modules/express-pouchdb/node_modules/pouchdb-selector-core": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/pouchdb-selector-core/-/pouchdb-selector-core-7.3.1.tgz", + "integrity": "sha512-HBX+nNGXcaL9z0uNpwSMRq2GNZd3EZXW+fe9rJHS0hvJohjZL7aRJLoaXfEdHPRTNW+CpjM3Rny60eGekQdI/w==", + "license": "Apache-2.0", + "dependencies": { + "pouchdb-collate": "7.3.1", + "pouchdb-utils": "7.3.1" + } + }, + "node_modules/express-pouchdb/node_modules/pouchdb-utils": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/pouchdb-utils/-/pouchdb-utils-7.3.1.tgz", + "integrity": "sha512-R3hHBo1zTdTu/NFs3iqkcaQAPwhIH0gMIdfVKd5lbDYlmP26rCG5pdS+v7NuoSSFLJ4xxnaGV+Gjf4duYsJ8wQ==", + "license": "Apache-2.0", + "dependencies": { + "argsarray": "0.0.1", + "clone-buffer": "1.0.0", + "immediate": "3.3.0", + "inherits": "2.0.4", + "pouchdb-collections": "7.3.1", + "pouchdb-errors": "7.3.1", + "pouchdb-md5": "7.3.1", + "uuid": "8.3.2" + } + }, + "node_modules/express-pouchdb/node_modules/pouchdb-utils/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/express-pouchdb/node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express-pouchdb/node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-pouchdb/node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/express-pouchdb/node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-pouchdb/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-pouchdb/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.", + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, "node_modules/express-static-gzip": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/express-static-gzip/-/express-static-gzip-2.2.0.tgz", @@ -2915,6 +3716,31 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==" + }, + "node_modules/gar": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/gar/-/gar-1.0.4.tgz", + "integrity": "sha512-w4n9cPWyP7aHxKxYHFQMegj7WIAsL/YX/C4Bs5Rr8s1H9M1rNtRWRsw+ovYMkXDQ5S4ZbYHsHAPmevPjPgw44w==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT" + }, + "node_modules/get-folder-size": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/get-folder-size/-/get-folder-size-2.0.1.tgz", + "integrity": "sha512-+CEb+GDCM7tkOS2wdMKTn9vU7DgnKUTuDlehkNJKNSovdCOVxs14OfKCk4cvSaR3za4gj+OBdl9opPN9xrJ0zA==", + "license": "MIT", + "dependencies": { + "gar": "^1.0.4", + "tiny-each-async": "2.0.3" + }, + "bin": { + "get-folder-size": "bin/get-folder-size" + } + }, "node_modules/get-func-name": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", @@ -2981,6 +3807,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -3036,8 +3879,7 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/has-flag": { "version": "3.0.0", @@ -3075,6 +3917,12 @@ "node": ">= 0.4" } }, + "node_modules/header-case-normalizer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/header-case-normalizer/-/header-case-normalizer-1.0.3.tgz", + "integrity": "sha512-wKAlzwV5I4m/am8J9eUN3S7WyXJufzMAKjmNScCbqlUF2J42kx8Nx8blw/L9z3tGklVuTYUo1dhohpG6RaV7LA==", + "license": "Apache-2.0" + }, "node_modules/hls.js": { "version": "1.5.15", "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.5.15.tgz", @@ -3186,6 +4034,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -3218,6 +4077,29 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "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", + "engines": { + "node": ">=4" + } + }, "node_modules/is-core-module": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", @@ -3232,6 +4114,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-empty": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-empty/-/is-empty-1.2.0.tgz", + "integrity": "sha512-F2FnH/otLNJv0J6wc73A5Xo7oHLNnqplYqZhUu01tD54DIPvxIRSTSLkrUB/M0nHO4vo1O9PDfN4KoTxCzLh/w==", + "license": "MIT" + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -3315,6 +4203,12 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/jkroso-type": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/jkroso-type/-/jkroso-type-1.1.1.tgz", + "integrity": "sha512-zZgay+fPG6PgMUrpyFADmQmvLo39+AZa7Gc5pZhev2RhDxwANEq2etwD8d0e6rTg5NkwOIlQmaEmns3draC6Ng==", + "license": "MIT" + }, "node_modules/js-cookie": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", @@ -3375,6 +4269,46 @@ "node": ">= 10.0.0" } }, + "node_modules/jstransform": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/jstransform/-/jstransform-11.0.3.tgz", + "integrity": "sha512-LGm87w0A8E92RrcXt94PnNHkFqHmgDy3mKHvNZOG7QepKCTCH/VB6S+IEN+bT4uLN3gVpOT0vvOOVd96osG71g==", + "license": "BSD-3-Clause", + "dependencies": { + "base62": "^1.1.0", + "commoner": "^0.10.1", + "esprima-fb": "^15001.1.0-dev-harmony-fb", + "object-assign": "^2.0.0", + "source-map": "^0.4.2" + }, + "bin": { + "jstransform": "bin/jstransform" + }, + "engines": { + "node": ">=0.8.8" + } + }, + "node_modules/jstransform/node_modules/object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha512-CdsOUYIh5wIiozhJ3rLQgmUTgcyzFwZZrqhkKhODMoGtPKM+wt0h0CNIoauJWMsS9822EdzPsF/6mb4nLvPN5g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jstransform/node_modules/source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha512-Y8nIfcb1s/7DcobUz1yOO1GSp7gyL+D9zLHDehT7iRESqGSxjJ448Sg7rvfgsRJCnKLdSl11uGf0s9X80cH0/A==", + "license": "BSD-3-Clause", + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/klona": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", @@ -3506,11 +4440,13 @@ "end-stream": "~0.1.0" } }, - "node_modules/leveldown": { + "node_modules/level/node_modules/leveldown": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-5.6.0.tgz", "integrity": "sha512-iB8O/7Db9lPaITU1aA2txU/cBEXAt4vWwKQRrrWuS6XDgbP4QZGj9BL2aNbwb002atoQ/lIotJkfyzz+ygQnUQ==", + "deprecated": "Superseded by classic-level (https://github.com/Level/community#faq)", "hasInstallScript": true, + "license": "MIT", "dependencies": { "abstract-leveldown": "~6.2.1", "napi-macros": "~2.0.0", @@ -3520,6 +4456,97 @@ "node": ">=8.6.0" } }, + "node_modules/level/node_modules/node-gyp-build": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.1.1.tgz", + "integrity": "sha512-dSq1xmcPDKPZ2EED2S6zw/b9NKsqzXRE6dVr8TVQnI3FJOTteUMuqF3Qqs6LZg+mLGYJWqQzMbIjMtJqTv87nQ==", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/leveldown": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-6.1.1.tgz", + "integrity": "sha512-88c+E+Eizn4CkQOBHwqlCJaTNEjGpaEIikn1S+cINc5E9HEvJ77bqY4JY/HxT5u0caWqsc3P3DcFIKBI1vHt+A==", + "deprecated": "Superseded by classic-level (https://github.com/Level/community#faq)", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "abstract-leveldown": "^7.2.0", + "napi-macros": "~2.0.0", + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/leveldown/node_modules/abstract-leveldown": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-7.2.0.tgz", + "integrity": "sha512-DnhQwcFEaYsvYDnACLZhMmCWd3rkOeEvglpa4q5i/5Jlm3UIsWaxVzuXvDLFCSCWRO3yy2/+V/G7FusFgejnfQ==", + "deprecated": "Superseded by abstract-level (https://github.com/Level/community#faq)", + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "catering": "^2.0.0", + "is-buffer": "^2.0.5", + "level-concat-iterator": "^3.0.0", + "level-supports": "^2.0.1", + "queue-microtask": "^1.2.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/leveldown/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/leveldown/node_modules/level-concat-iterator": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/level-concat-iterator/-/level-concat-iterator-3.1.0.tgz", + "integrity": "sha512-BWRCMHBxbIqPxJ8vHOvKUsaO0v1sLYZtjN3K2iZJsRBYtp+ONsY6Jfi6hy9K3+zolgQRryhIn2NRZjZnWJ9NmQ==", + "deprecated": "Superseded by abstract-level (https://github.com/Level/community#faq)", + "license": "MIT", + "dependencies": { + "catering": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/leveldown/node_modules/level-supports": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-2.1.0.tgz", + "integrity": "sha512-E486g1NCjW5cF78KGPrMDRBYzPuueMZ6VBXHT6gC7A8UYWGiM14fGgp+s/L1oFfDWSPV/+SFkYCmZ0SiESkRKA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/levelup": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/levelup/-/levelup-4.4.0.tgz", @@ -3535,6 +4562,21 @@ "node": ">=6" } }, + "node_modules/lie": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", + "integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==", + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/lie/node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "license": "MIT" + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -3631,6 +4673,34 @@ "node": ">= 0.8" } }, + "node_modules/memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha512-iVrGHZB8i4OQfM155xx8akvG9FIj+ht14DX5CQkCTG4EHzZ3d3sgckIf/Lm9ivZalEsFuEVnWv2B2WZvbrro2w==", + "deprecated": "Superseded by memory-level (https://github.com/Level/community#faq)", + "dependencies": { + "abstract-leveldown": "~2.7.1", + "functional-red-black-tree": "^1.0.1", + "immediate": "^3.2.3", + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" + } + }, + "node_modules/memdown/node_modules/abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "deprecated": "Superseded by abstract-level (https://github.com/Level/community#faq)", + "dependencies": { + "xtend": "~4.0.0" + } + }, + "node_modules/memdown/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/merge-descriptors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", @@ -3658,6 +4728,15 @@ "node": ">= 8" } }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -3714,6 +4793,39 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/mlly": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.1.tgz", @@ -3732,6 +4844,54 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/multiparty": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.2.3.tgz", + "integrity": "sha512-Ak6EUJZuhGS8hJ3c2fY6UW5MbkGUPMBEGd13djUzoY/BHqV/gTuFWtC6IuVA7A2+v3yjBS6c4or50xhzTQZImQ==", + "license": "MIT", + "dependencies": { + "http-errors": "~1.8.1", + "safe-buffer": "5.2.1", + "uid-safe": "2.1.5" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/multiparty/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multiparty/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multiparty/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/nano-css": { "version": "5.6.2", "resolved": "https://registry.npmjs.org/nano-css/-/nano-css-5.6.2.tgz", @@ -3812,9 +4972,10 @@ } }, "node_modules/node-gyp-build": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.1.1.tgz", - "integrity": "sha512-dSq1xmcPDKPZ2EED2S6zw/b9NKsqzXRE6dVr8TVQnI3FJOTteUMuqF3Qqs6LZg+mLGYJWqQzMbIjMtJqTv87nQ==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", @@ -3889,6 +5050,15 @@ "node": ">= 0.8" } }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3973,6 +5143,15 @@ "node": ">= 0.8" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -4128,6 +5307,329 @@ "pouchdb-utils": "8.0.1" } }, + "node_modules/pouchdb-adapter-leveldb": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-adapter-leveldb/-/pouchdb-adapter-leveldb-9.0.0.tgz", + "integrity": "sha512-kF5OAN8io3j9HWP7SY0ycJrhpXxklGpO0A6On0TZXZzji2wwjLNMBxyaPGVbVni95+/t1u7Xdo3r0cAjfm+mww==", + "license": "Apache-2.0", + "dependencies": { + "level": "6.0.1", + "level-write-stream": "1.0.0", + "leveldown": "6.1.1", + "pouchdb-adapter-leveldb-core": "9.0.0", + "pouchdb-merge": "9.0.0", + "through2": "3.0.2" + } + }, + "node_modules/pouchdb-adapter-leveldb-core": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-adapter-leveldb-core/-/pouchdb-adapter-leveldb-core-9.0.0.tgz", + "integrity": "sha512-b3ZGPtVXyivGL5SK3AIDG7PrNsZdoDpGFkmTytDTtctkVhxOg71gnXXP+CrupENPqSNG/eGbKW4w+bbMpxy6aA==", + "license": "Apache-2.0", + "dependencies": { + "double-ended-queue": "2.1.0-0", + "levelup": "4.4.0", + "pouchdb-adapter-utils": "9.0.0", + "pouchdb-binary-utils": "9.0.0", + "pouchdb-core": "9.0.0", + "pouchdb-errors": "9.0.0", + "pouchdb-json": "9.0.0", + "pouchdb-md5": "9.0.0", + "pouchdb-merge": "9.0.0", + "pouchdb-utils": "9.0.0", + "sublevel-pouchdb": "9.0.0", + "through2": "3.0.2" + } + }, + "node_modules/pouchdb-adapter-leveldb-core/node_modules/fetch-cookie": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/fetch-cookie/-/fetch-cookie-2.2.0.tgz", + "integrity": "sha512-h9AgfjURuCgA2+2ISl8GbavpUdR+WGAM2McW/ovn4tVccegp8ZqCKWSBR8uRdM8dDNlx5WdKRWxBYUwteLDCNQ==", + "license": "Unlicense", + "dependencies": { + "set-cookie-parser": "^2.4.8", + "tough-cookie": "^4.0.0" + } + }, + "node_modules/pouchdb-adapter-leveldb-core/node_modules/node-fetch": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/pouchdb-adapter-leveldb-core/node_modules/pouchdb-binary-utils": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-binary-utils/-/pouchdb-binary-utils-9.0.0.tgz", + "integrity": "sha512-2OMtgDZi82vqs+zNDE0YiYjOaWkYCUcZJZKK3WkRr+XYRu+2B7umJrnygJFhUwoGedBbHSrlQBLhdNV3F1AX1A==", + "license": "Apache-2.0" + }, + "node_modules/pouchdb-adapter-leveldb-core/node_modules/pouchdb-changes-filter": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-changes-filter/-/pouchdb-changes-filter-9.0.0.tgz", + "integrity": "sha512-ig0fo0WLgIjAniFJ19Uw1Y+oxiypqC+Skhd8BCETRVXOhLBzueRwEQR4thffyo0UayYVqldJfSR5wHSDvEVk/A==", + "license": "Apache-2.0", + "dependencies": { + "pouchdb-errors": "9.0.0", + "pouchdb-selector-core": "9.0.0", + "pouchdb-utils": "9.0.0" + } + }, + "node_modules/pouchdb-adapter-leveldb-core/node_modules/pouchdb-collate": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-collate/-/pouchdb-collate-9.0.0.tgz", + "integrity": "sha512-TrnEDNZEmIIl+W3xKUO8h+geqVLQ90oZe5ujPkl8myUzpREULWXWQBnV5EzPXVEKDBpJlb8T3I6oy/zdWGQpdA==", + "license": "Apache-2.0" + }, + "node_modules/pouchdb-adapter-leveldb-core/node_modules/pouchdb-core": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-core/-/pouchdb-core-9.0.0.tgz", + "integrity": "sha512-98SJgs8bqXhr4gMGuOTR8yVeLlMYy797zlOtdlvlXIxIicvocyA8ColhVVhdBXPNOGxT2HwReIMywdIVAgibpg==", + "license": "Apache-2.0", + "dependencies": { + "pouchdb-changes-filter": "9.0.0", + "pouchdb-errors": "9.0.0", + "pouchdb-fetch": "9.0.0", + "pouchdb-merge": "9.0.0", + "pouchdb-utils": "9.0.0", + "uuid": "8.3.2" + } + }, + "node_modules/pouchdb-adapter-leveldb-core/node_modules/pouchdb-errors": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-errors/-/pouchdb-errors-9.0.0.tgz", + "integrity": "sha512-961PSMLhW0UqqdJ566g+CdLZ5pkBJRd6l4WWpCDdD0USvE4xYfYGzv43w7nZZBw1k3Xdy092yqPge7yX/tfnyw==", + "license": "Apache-2.0" + }, + "node_modules/pouchdb-adapter-leveldb-core/node_modules/pouchdb-fetch": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-fetch/-/pouchdb-fetch-9.0.0.tgz", + "integrity": "sha512-TbE3cUcAJQrwb9kr44tDP0X+NAbcqgjsTvcL30L4xzBNJeCPTIRjukYX80s154SHJUXBxcWRiPsMmNqpXsjfCA==", + "license": "Apache-2.0", + "dependencies": { + "fetch-cookie": "2.2.0", + "node-fetch": "2.6.9" + } + }, + "node_modules/pouchdb-adapter-leveldb-core/node_modules/pouchdb-md5": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-md5/-/pouchdb-md5-9.0.0.tgz", + "integrity": "sha512-58xUYBvW3/s+aH0j4uOhhN8yCk0LQ254cxBzI/gbKA9PrfwHpe4zrr0L/ia5ml3A30oH1f8aTnuVMwWDkFcuww==", + "license": "Apache-2.0", + "dependencies": { + "pouchdb-binary-utils": "9.0.0", + "spark-md5": "3.0.2" + } + }, + "node_modules/pouchdb-adapter-leveldb-core/node_modules/pouchdb-merge": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-merge/-/pouchdb-merge-9.0.0.tgz", + "integrity": "sha512-Xh+TgOZCkGoZpI589btKf/cTiuQ5CsnPl9YpdW4h0cAPusniN6XNsR62F+/HbL9wirI6XTEPHUrk7MsQbk3S3A==", + "license": "Apache-2.0", + "dependencies": { + "pouchdb-utils": "9.0.0" + } + }, + "node_modules/pouchdb-adapter-leveldb-core/node_modules/pouchdb-selector-core": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-selector-core/-/pouchdb-selector-core-9.0.0.tgz", + "integrity": "sha512-ZYHYsdoedwm8j5tYofz+3+uUSK8i+7tRCBb01T0OuqDQb17+w5mzjHF8Ppi160xdPUPaWCo1Un+nLWGJzkmA3g==", + "license": "Apache-2.0", + "dependencies": { + "pouchdb-collate": "9.0.0", + "pouchdb-utils": "9.0.0" + } + }, + "node_modules/pouchdb-adapter-leveldb-core/node_modules/pouchdb-utils": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-utils/-/pouchdb-utils-9.0.0.tgz", + "integrity": "sha512-xWZE5c+nAslgmLC8JBZbky8AYgdz7pKtv7KTSi6CD2tuQD0WyNKib0YnhZndeE84dksTeZlqlg56RQHsHoB2LQ==", + "license": "Apache-2.0", + "dependencies": { + "pouchdb-errors": "9.0.0", + "pouchdb-md5": "9.0.0", + "uuid": "8.3.2" + } + }, + "node_modules/pouchdb-adapter-leveldb-core/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/pouchdb-adapter-leveldb/node_modules/pouchdb-binary-utils": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-binary-utils/-/pouchdb-binary-utils-9.0.0.tgz", + "integrity": "sha512-2OMtgDZi82vqs+zNDE0YiYjOaWkYCUcZJZKK3WkRr+XYRu+2B7umJrnygJFhUwoGedBbHSrlQBLhdNV3F1AX1A==", + "license": "Apache-2.0" + }, + "node_modules/pouchdb-adapter-leveldb/node_modules/pouchdb-errors": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-errors/-/pouchdb-errors-9.0.0.tgz", + "integrity": "sha512-961PSMLhW0UqqdJ566g+CdLZ5pkBJRd6l4WWpCDdD0USvE4xYfYGzv43w7nZZBw1k3Xdy092yqPge7yX/tfnyw==", + "license": "Apache-2.0" + }, + "node_modules/pouchdb-adapter-leveldb/node_modules/pouchdb-md5": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-md5/-/pouchdb-md5-9.0.0.tgz", + "integrity": "sha512-58xUYBvW3/s+aH0j4uOhhN8yCk0LQ254cxBzI/gbKA9PrfwHpe4zrr0L/ia5ml3A30oH1f8aTnuVMwWDkFcuww==", + "license": "Apache-2.0", + "dependencies": { + "pouchdb-binary-utils": "9.0.0", + "spark-md5": "3.0.2" + } + }, + "node_modules/pouchdb-adapter-leveldb/node_modules/pouchdb-merge": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-merge/-/pouchdb-merge-9.0.0.tgz", + "integrity": "sha512-Xh+TgOZCkGoZpI589btKf/cTiuQ5CsnPl9YpdW4h0cAPusniN6XNsR62F+/HbL9wirI6XTEPHUrk7MsQbk3S3A==", + "license": "Apache-2.0", + "dependencies": { + "pouchdb-utils": "9.0.0" + } + }, + "node_modules/pouchdb-adapter-leveldb/node_modules/pouchdb-utils": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-utils/-/pouchdb-utils-9.0.0.tgz", + "integrity": "sha512-xWZE5c+nAslgmLC8JBZbky8AYgdz7pKtv7KTSi6CD2tuQD0WyNKib0YnhZndeE84dksTeZlqlg56RQHsHoB2LQ==", + "license": "Apache-2.0", + "dependencies": { + "pouchdb-errors": "9.0.0", + "pouchdb-md5": "9.0.0", + "uuid": "8.3.2" + } + }, + "node_modules/pouchdb-adapter-leveldb/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/pouchdb-adapter-memory": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-adapter-memory/-/pouchdb-adapter-memory-9.0.0.tgz", + "integrity": "sha512-XbCwJ5f5U9dGdkiDikzYjTebdPHuA6Ghylx1Pq0lDe4y6l8R9xhjDSUy56pJ8G2F4Z+8QdB5FBY9EQoFlFSXWQ==", + "dependencies": { + "memdown": "1.4.1", + "pouchdb-adapter-leveldb-core": "9.0.0" + } + }, + "node_modules/pouchdb-adapter-utils": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-adapter-utils/-/pouchdb-adapter-utils-9.0.0.tgz", + "integrity": "sha512-hmbm4ey0HL0vtoY1tRTPIt2FfYjvMh3DWoGGSxXDTS73qTFQ+Fhhi5I0AnN9PcD2omfKQAVXiYks4kkMvlAHqA==", + "license": "Apache-2.0", + "dependencies": { + "pouchdb-binary-utils": "9.0.0", + "pouchdb-errors": "9.0.0", + "pouchdb-md5": "9.0.0", + "pouchdb-merge": "9.0.0", + "pouchdb-utils": "9.0.0" + } + }, + "node_modules/pouchdb-adapter-utils/node_modules/pouchdb-binary-utils": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-binary-utils/-/pouchdb-binary-utils-9.0.0.tgz", + "integrity": "sha512-2OMtgDZi82vqs+zNDE0YiYjOaWkYCUcZJZKK3WkRr+XYRu+2B7umJrnygJFhUwoGedBbHSrlQBLhdNV3F1AX1A==", + "license": "Apache-2.0" + }, + "node_modules/pouchdb-adapter-utils/node_modules/pouchdb-errors": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-errors/-/pouchdb-errors-9.0.0.tgz", + "integrity": "sha512-961PSMLhW0UqqdJ566g+CdLZ5pkBJRd6l4WWpCDdD0USvE4xYfYGzv43w7nZZBw1k3Xdy092yqPge7yX/tfnyw==", + "license": "Apache-2.0" + }, + "node_modules/pouchdb-adapter-utils/node_modules/pouchdb-md5": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-md5/-/pouchdb-md5-9.0.0.tgz", + "integrity": "sha512-58xUYBvW3/s+aH0j4uOhhN8yCk0LQ254cxBzI/gbKA9PrfwHpe4zrr0L/ia5ml3A30oH1f8aTnuVMwWDkFcuww==", + "license": "Apache-2.0", + "dependencies": { + "pouchdb-binary-utils": "9.0.0", + "spark-md5": "3.0.2" + } + }, + "node_modules/pouchdb-adapter-utils/node_modules/pouchdb-merge": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-merge/-/pouchdb-merge-9.0.0.tgz", + "integrity": "sha512-Xh+TgOZCkGoZpI589btKf/cTiuQ5CsnPl9YpdW4h0cAPusniN6XNsR62F+/HbL9wirI6XTEPHUrk7MsQbk3S3A==", + "license": "Apache-2.0", + "dependencies": { + "pouchdb-utils": "9.0.0" + } + }, + "node_modules/pouchdb-adapter-utils/node_modules/pouchdb-utils": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-utils/-/pouchdb-utils-9.0.0.tgz", + "integrity": "sha512-xWZE5c+nAslgmLC8JBZbky8AYgdz7pKtv7KTSi6CD2tuQD0WyNKib0YnhZndeE84dksTeZlqlg56RQHsHoB2LQ==", + "license": "Apache-2.0", + "dependencies": { + "pouchdb-errors": "9.0.0", + "pouchdb-md5": "9.0.0", + "uuid": "8.3.2" + } + }, + "node_modules/pouchdb-adapter-utils/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/pouchdb-all-dbs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pouchdb-all-dbs/-/pouchdb-all-dbs-1.1.1.tgz", + "integrity": "sha512-UUnsdmcnRSQ8MAOYSJjfTwKkQNb/6fvOfd/f7dNNivWZ2YDYVuMfgw1WQdL634yEtcXTxAENZ/EyLRdzPCB41A==", + "license": "Apache-2.0", + "dependencies": { + "argsarray": "0.0.1", + "es3ify": "^0.2.2", + "inherits": "~2.0.1", + "pouchdb-promise": "6.4.3", + "tiny-queue": "^0.2.0" + } + }, + "node_modules/pouchdb-auth": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pouchdb-auth/-/pouchdb-auth-4.2.0.tgz", + "integrity": "sha512-Enp9A8PvsJOdcxnHYl/RcZnOgGxI3Fbip5bZGF8pdOOKg2jJpKr6V/VRdFYGt7eWPbB4W0UZXrGxarePVjg10w==", + "license": "Apache-2.0", + "dependencies": { + "base64url": "^3.0.0", + "couchdb-calculate-session-id": "^1.1.0", + "crypto-lite": "^0.2.0", + "pouchdb-bulkdocs-wrapper": "4.2.0", + "pouchdb-plugin-error": "4.2.0", + "pouchdb-promise": "^6.4.1", + "pouchdb-req-http-query": "4.2.0", + "pouchdb-system-db": "4.2.0", + "pouchdb-validation": "4.2.0", + "pouchdb-wrappers": "4.2.0", + "promise-nodify": "^1.0.2", + "secure-random": "^1.1.1" + } + }, "node_modules/pouchdb-binary-utils": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/pouchdb-binary-utils/-/pouchdb-binary-utils-8.0.1.tgz", @@ -4136,6 +5638,15 @@ "buffer-from": "1.1.2" } }, + "node_modules/pouchdb-bulkdocs-wrapper": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pouchdb-bulkdocs-wrapper/-/pouchdb-bulkdocs-wrapper-4.2.0.tgz", + "integrity": "sha512-9Zuzot30FoD4Cp9ZqIjb6/7+xyXTFRaXzp1wdigzecdp/D6wgWqo6rKCXKHTZYPEcGB97vMNRYqld6wbA89FCA==", + "license": "Apache-2.0", + "dependencies": { + "pouchdb-promise": "^6.4.1" + } + }, "node_modules/pouchdb-changes-filter": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/pouchdb-changes-filter/-/pouchdb-changes-filter-8.0.1.tgz", @@ -4146,6 +5657,12 @@ "pouchdb-utils": "8.0.1" } }, + "node_modules/pouchdb-changeslike-wrapper": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pouchdb-changeslike-wrapper/-/pouchdb-changeslike-wrapper-4.2.0.tgz", + "integrity": "sha512-vsz3sTXH2YdWTd+dSBWEFOrdtIM07peQ9dSzROONyG7dqGlr9e2uSj+mXqTm8jBLDwUfcjZu16DTUg2AdWtWJg==", + "license": "Apache-2.0" + }, "node_modules/pouchdb-collate": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/pouchdb-collate/-/pouchdb-collate-8.0.1.tgz", @@ -4183,6 +5700,12 @@ "resolved": "https://registry.npmjs.org/pouchdb-errors/-/pouchdb-errors-8.0.1.tgz", "integrity": "sha512-H+ZsQxcG/JV3Tn29gnM6c9+lRPCN91ZYOkoIICsLjVRYgOTzN1AvNUD/G5JCB+81aI/u3fxZec0LEaZh6g6NHA==" }, + "node_modules/pouchdb-fauxton": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/pouchdb-fauxton/-/pouchdb-fauxton-0.0.6.tgz", + "integrity": "sha512-eClyvP5HKoj7Nc3BXHSJo03GV+14jeLVqLba/s32I1jH79I3oh2AIqVlqH+gxaPrMXcHOpho/R+CBD44/LkZEA==", + "license": "Apache-2.0" + }, "node_modules/pouchdb-fetch": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/pouchdb-fetch/-/pouchdb-fetch-8.0.1.tgz", @@ -4207,6 +5730,30 @@ "pouchdb-utils": "8.0.1" } }, + "node_modules/pouchdb-json": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pouchdb-json/-/pouchdb-json-9.0.0.tgz", + "integrity": "sha512-aI41mYVyI195GXuT1Ys7mLIB/Mvrz11ihoTP6km6hYqVgSuaUxuZcFUozlyTJiZXr7H5kdhNgclhlVnjir4JAA==", + "license": "Apache-2.0", + "dependencies": { + "vuvuzela": "1.0.3" + } + }, + "node_modules/pouchdb-list": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pouchdb-list/-/pouchdb-list-4.2.0.tgz", + "integrity": "sha512-+nAM3SiN645LxEqsjDIyeAp7FeyuYbz0O2kMARDJl7ERKDu6slrCf8fLJmy/b1VrCLFUebVVMIU1NyJSV4ISLQ==", + "license": "Apache-2.0", + "dependencies": { + "couchdb-objects": "4.2.0", + "couchdb-render": "4.2.0", + "extend": "^3.0.0", + "pouchdb-plugin-error": "4.2.0", + "pouchdb-promise": "^6.4.1", + "pouchdb-req-http-query": "4.2.0", + "promise-nodify": "^1.0.2" + } + }, "node_modules/pouchdb-mapreduce-utils": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/pouchdb-mapreduce-utils/-/pouchdb-mapreduce-utils-8.0.1.tgz", @@ -4233,6 +5780,90 @@ "pouchdb-utils": "8.0.1" } }, + "node_modules/pouchdb-plugin-error": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pouchdb-plugin-error/-/pouchdb-plugin-error-4.2.0.tgz", + "integrity": "sha512-dkgckrU7m7sa1WDRNFevsgi9DnqXkH09wXCCSc8D536mQCU3uo4jRyy/mtlSfT56NWGcieWTKNI0HQi3rhqKtg==", + "license": "Apache-2.0" + }, + "node_modules/pouchdb-promise": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/pouchdb-promise/-/pouchdb-promise-6.4.3.tgz", + "integrity": "sha512-ruJaSFXwzsxRHQfwNHjQfsj58LBOY1RzGzde4PM5CWINZwFjCQAhZwfMrch2o/0oZT6d+Xtt0HTWhq35p3b0qw==", + "license": "Apache-2.0", + "dependencies": { + "lie": "3.1.1" + } + }, + "node_modules/pouchdb-replicator": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pouchdb-replicator/-/pouchdb-replicator-4.2.0.tgz", + "integrity": "sha512-TdWED3Efz2snWC4Pv+MGnf9zf0RNRfw3gf2TloOm6UBiIur09Zh7Sx5HaSXw/zp45PVIv9Zhr7CuifaHIeny6Q==", + "license": "Apache-2.0", + "dependencies": { + "equals": "^1.0.5", + "extend": "^3.0.0", + "pouchdb-plugin-error": "4.2.0", + "pouchdb-promise": "^6.4.1", + "pouchdb-system-db": "4.2.0", + "pouchdb-validation": "4.2.0", + "promise-nodify": "^1.0.2", + "random-uuid-v4": "0.0.8" + } + }, + "node_modules/pouchdb-req-http-query": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pouchdb-req-http-query/-/pouchdb-req-http-query-4.2.0.tgz", + "integrity": "sha512-iDQmNy6stYf4mwRJI0qtbpp2+2PfRIAzwSlJYwakQCZZ83qOgjgwtew1Bq+uq3Zm/YClE6ox8ZFctQG8T/RtVQ==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.0", + "header-case-normalizer": "^1.0.3", + "pouchdb-plugin-error": "4.2.0", + "pouchdb-promise": "^6.4.1", + "xmlhttprequest-cookie": "^0.9.2" + } + }, + "node_modules/pouchdb-rewrite": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pouchdb-rewrite/-/pouchdb-rewrite-4.2.0.tgz", + "integrity": "sha512-koK7ky4X6jlSDQln30dNlCOVxjALQs3Le5JT23l0b7wp8tFgTRo5SyoRpimzGn+lAk0GMwwBYvsCQa/HV+u0yQ==", + "license": "Apache-2.0", + "dependencies": { + "couchdb-objects": "4.2.0", + "extend": "^3.0.0", + "pouchdb-plugin-error": "4.2.0", + "pouchdb-req-http-query": "4.2.0", + "pouchdb-route": "4.2.0", + "promise-nodify": "^1.0.2" + } + }, + "node_modules/pouchdb-route": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pouchdb-route/-/pouchdb-route-4.2.0.tgz", + "integrity": "sha512-jZNdqwYT8+uZgZIQhhonIf5/v3NzuAIw/T6+klAQm4FRryUGNMnP3G24Omj8zjHq3tX5daVmAjA1LNT5k6Jh1w==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.0", + "pouchdb-plugin-error": "4.2.0" + } + }, + "node_modules/pouchdb-security": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pouchdb-security/-/pouchdb-security-4.2.0.tgz", + "integrity": "sha512-BmPQlQmMnJXqHAksl6wWyEwZsnjwj4nss0OAYQokSjHDJ6j00gjbL8klG0BDM++wwCW8JbXfZ8sdtCpI3MC+fA==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.0", + "pouchdb-bulkdocs-wrapper": "4.2.0", + "pouchdb-changeslike-wrapper": "4.2.0", + "pouchdb-plugin-error": "4.2.0", + "pouchdb-promise": "^6.4.1", + "pouchdb-req-http-query": "4.2.0", + "pouchdb-wrappers": "4.2.0", + "promise-nodify": "^1.0.2" + } + }, "node_modules/pouchdb-selector-core": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/pouchdb-selector-core/-/pouchdb-selector-core-8.0.1.tgz", @@ -4242,6 +5873,59 @@ "pouchdb-utils": "8.0.1" } }, + "node_modules/pouchdb-show": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pouchdb-show/-/pouchdb-show-4.2.0.tgz", + "integrity": "sha512-uA0gY+65snwUc2Ei+DfAFK5kVA9lwMKRwAlitbtT2GBXTRsCyHvfaQuMyIJSByTAtAwno6Wmvw8Anf9iu0ds/g==", + "license": "Apache-2.0", + "dependencies": { + "couchdb-objects": "4.2.0", + "couchdb-render": "4.2.0", + "pouchdb-plugin-error": "4.2.0", + "pouchdb-promise": "^6.4.1", + "pouchdb-req-http-query": "4.2.0", + "promise-nodify": "^1.0.2" + } + }, + "node_modules/pouchdb-size": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pouchdb-size/-/pouchdb-size-4.2.0.tgz", + "integrity": "sha512-tHzJCL1BEduLR4y6TN4NCS5HES+jrk7NzJzRrpPz8orWXKR8x9oBdA4g2bS4pZwKR+A6l7XfYrnUyvBpQmO4Fw==", + "license": "Apache-2.0", + "dependencies": { + "bluebird": "^3.4.7", + "get-folder-size": "^2.0.0", + "pouchdb-wrappers": "4.2.0", + "promise-nodify": "^1.0.2" + } + }, + "node_modules/pouchdb-system-db": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pouchdb-system-db/-/pouchdb-system-db-4.2.0.tgz", + "integrity": "sha512-zH+5xdGIzWbcHaQoP5/AC9DWhyKqiZFSUKIl3E+WvWCHrZgTaxXX3ICK6GGFE2zjBEzSbEHqlSMZd6cTfy2XPQ==", + "license": "Apache-2.0", + "dependencies": { + "pouchdb-changeslike-wrapper": "4.2.0", + "pouchdb-plugin-error": "4.2.0", + "pouchdb-security": "4.2.0", + "pouchdb-wrappers": "4.2.0" + } + }, + "node_modules/pouchdb-update": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pouchdb-update/-/pouchdb-update-4.2.0.tgz", + "integrity": "sha512-tKkGUliho04xai5ia8tyTf0T/CmFAhKc+Em0d6G2LyaYittkJp39IhnHdhq0jmK1FC+8FBRlGXEmWTeeCx0RRQ==", + "license": "Apache-2.0", + "dependencies": { + "couchdb-eval": "4.2.0", + "couchdb-objects": "4.2.0", + "couchdb-resp-completer": "4.2.0", + "pouchdb-plugin-error": "4.2.0", + "pouchdb-promise": "^6.4.1", + "pouchdb-req-http-query": "4.2.0", + "promise-nodify": "^1.0.2" + } + }, "node_modules/pouchdb-utils": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/pouchdb-utils/-/pouchdb-utils-8.0.1.tgz", @@ -4263,6 +5947,67 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/pouchdb-validation": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pouchdb-validation/-/pouchdb-validation-4.2.0.tgz", + "integrity": "sha512-S/hmAVVQ7Tv4n3nZJVQEVwFblHLu9TXZEO0qeT4Z/xbYqUYHKXIQ+kRZMl/CscYNLDlVzpHBaSDmGxlZhUWXKQ==", + "license": "Apache-2.0", + "dependencies": { + "couchdb-eval": "4.2.0", + "couchdb-objects": "4.2.0", + "pouchdb-bulkdocs-wrapper": "4.2.0", + "pouchdb-plugin-error": "4.2.0", + "pouchdb-promise": "^6.4.1", + "pouchdb-wrappers": "4.2.0", + "random-uuid-v4": "0.0.8" + } + }, + "node_modules/pouchdb-vhost": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pouchdb-vhost/-/pouchdb-vhost-4.2.0.tgz", + "integrity": "sha512-+KsT9EN7Kje1ENBTYDMxBip6Dtaera3IHiMGt0cBlOLBmjPhlfhyvMkK/DafngJALJsdYkGEYPvrB6p/tjSsVw==", + "license": "Apache-2.0", + "dependencies": { + "pouchdb-route": "4.2.0", + "promise-nodify": "^1.0.2" + } + }, + "node_modules/pouchdb-wrappers": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pouchdb-wrappers/-/pouchdb-wrappers-4.2.0.tgz", + "integrity": "sha512-ADnQKEgWsf2a3qEXj1njP7D1I1OeA0Z+O7OfXN4mK623Re/hvz869Xes8i8oJXscAh6gz/fzjiU6ElbLF6Wd5w==", + "license": "Apache-2.0", + "dependencies": { + "promise-nodify": "^1.0.2" + } + }, + "node_modules/pouchdb/node_modules/leveldown": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-5.6.0.tgz", + "integrity": "sha512-iB8O/7Db9lPaITU1aA2txU/cBEXAt4vWwKQRrrWuS6XDgbP4QZGj9BL2aNbwb002atoQ/lIotJkfyzz+ygQnUQ==", + "deprecated": "Superseded by classic-level (https://github.com/Level/community#faq)", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "abstract-leveldown": "~6.2.1", + "napi-macros": "~2.0.0", + "node-gyp-build": "~4.1.0" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/pouchdb/node_modules/node-gyp-build": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.1.1.tgz", + "integrity": "sha512-dSq1xmcPDKPZ2EED2S6zw/b9NKsqzXRE6dVr8TVQnI3FJOTteUMuqF3Qqs6LZg+mLGYJWqQzMbIjMtJqTv87nQ==", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, "node_modules/pouchdb/node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -4315,6 +6060,21 @@ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true }, + "node_modules/private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/promise-nodify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/promise-nodify/-/promise-nodify-1.0.2.tgz", + "integrity": "sha512-j9RWp/40Ttja+wxiEjS5Ud5liHQxAA5K+STc9Vh09mF4zpNEuXTR35U6Uk5qVCsf6qp2v5UnLWa7SNmZ6M1ewQ==", + "license": "Apache-2.0" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -4351,6 +6111,17 @@ "node": ">=6" } }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", + "license": "MIT", + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, "node_modules/qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", @@ -4391,7 +6162,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -4418,6 +6188,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/random-uuid-v4": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/random-uuid-v4/-/random-uuid-v4-0.0.8.tgz", + "integrity": "sha512-KXQm6yiEMSmXRXPtb18oQuKtCmlT1YMbTavc/8p6PdEIldCAoMNDwF+0NvVnTa0w7kOSu+o2KTxkVEu7Vxen6g==", + "license": "Unlicense" + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -4638,6 +6423,34 @@ "string_decoder": "~0.10.x" } }, + "node_modules/recast": { + "version": "0.11.23", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", + "integrity": "sha512-+nixG+3NugceyR8O1bLU45qs84JgI3+8EauyRZafLgC9XbdAOIVgwV1Pe2da0YzGo62KzWoZwUpVEQf6qNAXWA==", + "license": "MIT", + "dependencies": { + "ast-types": "0.9.6", + "esprima": "~3.1.0", + "private": "~0.1.5", + "source-map": "~0.5.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/recast/node_modules/esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha512-AWwVMNxwhN8+NIPQzAQZCm7RkLC4RbM3B1OobMuyp3i+w73X57KCKaVIxaRZb+DYCojq7rspo+fmuQfAboyhFg==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/recordrtc": { "version": "5.6.2", "resolved": "https://registry.npmjs.org/recordrtc/-/recordrtc-5.6.2.tgz", @@ -4825,6 +6638,15 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, + "node_modules/sanitize-filename": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", + "license": "WTFPL OR ISC", + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", @@ -4845,6 +6667,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/secure-random": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/secure-random/-/secure-random-1.1.2.tgz", + "integrity": "sha512-H2bdSKERKdBV1SwoqYm6C0y+9EA94v6SUBOWO8kDndc4NoUih7Dv6Tsgma7zO1lv27wIvjlD0ZpMQk7um5dheQ==", + "license": "MIT" + }, "node_modules/send": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", @@ -4915,6 +6743,12 @@ "url": "https://opencollective.com/express" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, "node_modules/set-harmonic-interval": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz", @@ -5262,6 +7096,17 @@ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" }, + "node_modules/sublevel-pouchdb": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/sublevel-pouchdb/-/sublevel-pouchdb-9.0.0.tgz", + "integrity": "sha512-pX4r8+F7wuts0C81kUJ341h4bl2aRe7qV572FE8X1FMz9VkKlmi2nPD1vfeiOJXz5Y09I4MHjGULAbqvTfQZEQ==", + "license": "Apache-2.0", + "dependencies": { + "level-codec": "9.0.2", + "ltgt": "2.2.1", + "readable-stream": "1.1.14" + } + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -5297,6 +7142,12 @@ "node": ">=10" } }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "license": "MIT" + }, "node_modules/through2": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", @@ -5327,6 +7178,18 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/tiny-each-async": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tiny-each-async/-/tiny-each-async-2.0.3.tgz", + "integrity": "sha512-5ROII7nElnAirvFn8g7H7MtpfV1daMcyfTGQwsn/x2VtyV+VPiO5CjReCJtWLvoKTDEDmZocf3cNPraiMnBXLA==", + "license": "MIT" + }, + "node_modules/tiny-queue": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tiny-queue/-/tiny-queue-0.2.1.tgz", + "integrity": "sha512-EijGsv7kzd9I9g0ByCl6h42BWNGUZrlCSejfrb3AKeHC33SGbASu1VDf5O3rRiiUOhAC9CHdZxFPbZu0HmR70A==", + "license": "Apache 2" + }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", @@ -5404,6 +7267,15 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "license": "WTFPL", + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, "node_modules/ts-easing": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/ts-easing/-/ts-easing-0.2.0.tgz", @@ -5505,6 +7377,18 @@ "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", "dev": true }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "license": "MIT", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/uint8-to-b64": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/uint8-to-b64/-/uint8-to-b64-1.0.2.tgz", @@ -5657,21 +7541,26 @@ "node": ">=6.14.2" } }, - "node_modules/utf-8-validate/node_modules/node-gyp-build": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", - "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } + "node_modules/utf8-byte-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", + "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", + "license": "(WTFPL OR MIT)" }, "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==" }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", @@ -5962,6 +7851,27 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-0.0.4.tgz", "integrity": "sha512-azrivNydKRYt7zwLV5wWUK7YzKTWs3q87xSmY6DlHapPrCvaT6ZrukvM5erV+yCSSPmZT8zkSdttOHQpWWm9zw==" }, + "node_modules/xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/xmlhttprequest-cookie": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/xmlhttprequest-cookie/-/xmlhttprequest-cookie-0.9.9.tgz", + "integrity": "sha512-39xloHdqRonNUa68sTiCqOfXK1AKAEPU0mKCfNsDL+D6zkQoz8DNqJpN/vitCOo1xUvHiHH8K8Z3RiM7wMkxpQ==", + "license": "MIT", + "dependencies": { + "xmlhttprequest": ">=1.8.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index 7804995..9132b07 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "immersive", "private": true, - "version": "0.0.8-34", + "version": "0.0.8-42", "type": "module", "license": "MIT", "engines": { @@ -46,13 +46,17 @@ "dotenv": "^17.2.3", "events": "^3.3.0", "express": "^5.2.1", + "express-pouchdb": "^4.2.0", "hash-wasm": "4.11.0", "hls.js": "^1.1.4", "js-crypto-aes": "1.0.6", + "leveldown": "^6.1.1", "loglevel": "^1.9.1", "meaningful-string": "^1.4.0", "peer-lite": "2.0.2", "pouchdb": "^8.0.1", + "pouchdb-adapter-leveldb": "^9.0.0", + "pouchdb-adapter-memory": "^9.0.0", "pouchdb-find": "^8.0.1", "query-string": "^8.1.0", "react-router-dom": "^6.26.1", @@ -73,4 +77,4 @@ "vite-plugin-cp": "^1.0.0", "vitest": "^1.4.0" } -} +} \ No newline at end of file diff --git a/public/api/user/README.md b/public/api/user/README.md deleted file mode 100644 index bee9d43..0000000 --- a/public/api/user/README.md +++ /dev/null @@ -1,89 +0,0 @@ -# Feature Configuration Testing - -This directory contains static JSON files for testing different user tiers locally. - -## Available Configurations - -### Default: `features` (none tier) -- **What you see**: Only the home page -- **All pages and features**: Disabled -- **Use case**: Unauthenticated users or when API is unavailable - -### Free Tier: `features-free.json` -- **Pages**: All marketing pages + VR Experience -- **Features**: Basic diagram creation, management, immersive mode -- **Limits**: 6 diagrams max, 100MB storage -- **No access to**: Templates, private/encrypted designs, collaboration - -### Basic Tier: `features-basic.json` -- **Pages**: All pages available -- **Features**: Free features + templates + private designs -- **Limits**: 25 diagrams max, 500MB storage -- **No access to**: Encrypted designs, collaboration - -### Pro Tier: `features-pro.json` -- **Pages**: All pages available -- **Features**: Everything unlocked -- **Limits**: Unlimited (indicated by -1) - -## How to Test Locally - -### Method 1: Copy the file you want to test -```bash -# Test free tier -cp public/api/user/features-free.json public/api/user/features - -# Test basic tier -cp public/api/user/features-basic.json public/api/user/features - -# Test pro tier -cp public/api/user/features-pro.json public/api/user/features - -# Test none/default (locked down) -cp public/api/user/features-none.json public/api/user/features -``` - -### Method 2: Symlink (easier for switching) -```bash -# Remove the default file -rm public/api/user/features - -# Create a symlink to the tier you want to test -ln -s features-free.json public/api/user/features -# or -ln -s features-basic.json public/api/user/features -# or -ln -s features-pro.json public/api/user/features -``` - -## What Changes Between Tiers - -| Feature | None | Free | Basic | Pro | -|---------|------|------|-------|-----| -| Pages (Examples, Docs, Pricing) | ❌ | ✅ | ✅ | ✅ | -| VR Experience | ❌ | ✅ | ✅ | ✅ | -| Create Diagram | ❌ | ✅ | ✅ | ✅ | -| Create From Template | ❌ | ❌ | ✅ | ✅ | -| Private Designs | ❌ | ❌ | ✅ | ✅ | -| Encrypted Designs | ❌ | ❌ | ❌ | ✅ | -| Share/Collaborate | ❌ | ❌ | ❌ | ✅ | -| Max Diagrams | 0 | 6 | 25 | ∞ | -| Storage | 0 | 100MB | 500MB | ∞ | - -## Backend Implementation (Future) - -When you're ready to implement the backend, create an endpoint at: -``` -GET https://www.deepdiagram.com/api/user/features -``` - -The endpoint should: -1. Validate the Auth0 JWT token from `Authorization: Bearer ` header -2. Query the user's subscription tier from your database -3. Return JSON matching one of these structures based on their tier -4. Handle errors gracefully (401 for invalid token, 403 for unauthorized) - -The frontend will automatically fall back to the static `features` file if: -- User is not authenticated -- API returns an error -- Network request fails diff --git a/public/api/user/features b/public/api/user/features deleted file mode 100644 index 12fb4e6..0000000 --- a/public/api/user/features +++ /dev/null @@ -1,26 +0,0 @@ -{ - "tier": "basic", - "pages": { - "examples": "coming-soon", - "documentation": "coming-soon", - "pricing": "coming-soon", - "vrExperience": "on" - }, - "features": { - "createDiagram": "on", - "createFromTemplate": "coming-soon", - "manageDiagrams": "on", - "shareCollaborate": "coming-soon", - "privateDesigns": "coming-soon", - "encryptedDesigns": "pro", - "editData": "coming-soon", - "config": "on", - "enterImmersive": "on", - "launchMetaQuest": "on" - }, - "limits": { - "maxDiagrams": 10, - "maxCollaborators": 0, - "storageQuotaMB": 200 - } -} diff --git a/public/api/user/features-basic.json b/public/api/user/features-basic.json deleted file mode 100644 index a2b7cc9..0000000 --- a/public/api/user/features-basic.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "tier": "basic", - "pages": { - "examples": "on", - "documentation": "on", - "pricing": "on", - "vrExperience": "on" - }, - "features": { - "createDiagram": "on", - "createFromTemplate": "on", - "manageDiagrams": "on", - "shareCollaborate": "coming-soon", - "privateDesigns": "on", - "encryptedDesigns": "pro", - "editData": "on", - "config": "on", - "enterImmersive": "on", - "launchMetaQuest": "on" - }, - "limits": { - "maxDiagrams": 25, - "maxCollaborators": 0, - "storageQuotaMB": 500 - } -} diff --git a/public/api/user/features-free.json b/public/api/user/features-free.json deleted file mode 100644 index 4ff824a..0000000 --- a/public/api/user/features-free.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "tier": "free", - "pages": { - "examples": "on", - "documentation": "on", - "pricing": "on", - "vrExperience": "on" - }, - "features": { - "createDiagram": "on", - "createFromTemplate": "coming-soon", - "manageDiagrams": "on", - "shareCollaborate": "coming-soon", - "privateDesigns": "coming-soon", - "encryptedDesigns": "pro", - "editData": "on", - "config": "on", - "enterImmersive": "on", - "launchMetaQuest": "on" - }, - "limits": { - "maxDiagrams": 6, - "maxCollaborators": 0, - "storageQuotaMB": 100 - } -} diff --git a/public/api/user/features-none.json b/public/api/user/features-none.json deleted file mode 100644 index 6265836..0000000 --- a/public/api/user/features-none.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "tier": "none", - "pages": { - "examples": "off", - "documentation": "off", - "pricing": "off", - "vrExperience": "off" - }, - "features": { - "createDiagram": "off", - "createFromTemplate": "off", - "manageDiagrams": "off", - "shareCollaborate": "off", - "privateDesigns": "off", - "encryptedDesigns": "off", - "editData": "off", - "config": "off", - "enterImmersive": "off", - "launchMetaQuest": "off" - }, - "limits": { - "maxDiagrams": 0, - "maxCollaborators": 0, - "storageQuotaMB": 0 - } -} diff --git a/public/api/user/features-pro.json b/public/api/user/features-pro.json deleted file mode 100644 index a9f4ddd..0000000 --- a/public/api/user/features-pro.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "tier": "pro", - "pages": { - "examples": "on", - "documentation": "on", - "pricing": "on", - "vrExperience": "on" - }, - "features": { - "createDiagram": "on", - "createFromTemplate": "on", - "manageDiagrams": "on", - "shareCollaborate": "on", - "privateDesigns": "on", - "encryptedDesigns": "on", - "editData": "on", - "config": "on", - "enterImmersive": "on", - "launchMetaQuest": "on" - }, - "limits": { - "maxDiagrams": -1, - "maxCollaborators": -1, - "storageQuotaMB": -1 - } -} diff --git a/server.js b/server.js index b8933ca..f8f4525 100644 --- a/server.js +++ b/server.js @@ -3,6 +3,8 @@ import ViteExpress from "vite-express"; import cors from "cors"; import dotenv from "dotenv"; import apiRoutes from "./server/api/index.js"; +import { pouchApp, PouchDB } from "./server/services/databaseService.js"; +import { dbAuthMiddleware } from "./server/middleware/dbAuth.js"; // Load .env.local first, then fall back to .env dotenv.config({ path: '.env.local' }); @@ -20,11 +22,60 @@ if (allowedOrigins.length > 0) { })); } -app.use(express.json()); +// Parse JSON for all routes EXCEPT /pouchdb (express-pouchdb handles its own body parsing) +app.use((req, res, next) => { + if (req.path.startsWith('/pouchdb')) { + return next(); + } + express.json()(req, res, next); +}); // API routes app.use("/api", apiRoutes); +// Test endpoint to verify PouchDB is working +app.get("/pouchdb-test/:dbname", async (req, res) => { + try { + const dbName = req.params.dbname; + console.log(`[Test] Creating database: ${dbName}`); + const db = new PouchDB(dbName); + const info = await db.info(); + console.log(`[Test] Database info:`, info); + + // Try to add a test doc + const result = await db.put({ _id: 'test-doc', hello: 'world' }); + console.log(`[Test] Added doc:`, result); + + // Read it back + const doc = await db.get('test-doc'); + console.log(`[Test] Got doc:`, doc); + + res.json({ success: true, info, doc }); + } catch (err) { + console.error(`[Test] Error:`, err); + res.status(500).json({ error: err.message, stack: err.stack }); + } +}); + +// PouchDB database sync endpoint with auth middleware +// Public databases (/pouchdb/public-*) are accessible without auth +// Private databases (/pouchdb/private-*) require authentication +// Patch req.query for Express 5 compatibility with express-pouchdb +app.use("/pouchdb", dbAuthMiddleware, (req, res, next) => { + // Express 5 makes req.query read-only, but express-pouchdb needs to write to it + // Redefine as writable property + Object.defineProperty(req, 'query', { + value: { ...req.query }, + writable: true, + configurable: true + }); + next(); +}, pouchApp, (err, req, res, next) => { + // Error handler for express-pouchdb + console.error('[PouchDB Error]', err); + res.status(500).json({ error: err.message, stack: err.stack }); +}); + // Check if running in API-only mode (split deployment) const apiOnly = process.env.API_ONLY === "true"; diff --git a/server/api/index.js b/server/api/index.js index fe07685..e65a1e2 100644 --- a/server/api/index.js +++ b/server/api/index.js @@ -2,12 +2,16 @@ import { Router } from "express"; import claudeRouter from "./claude.js"; import ollamaRouter from "./ollama.js"; import sessionRouter from "./session.js"; +import userRouter from "./user.js"; const router = Router(); // Session management router.use("/session", sessionRouter); +// User features +router.use("/user", userRouter); + // Claude API proxy router.use("/claude", claudeRouter); diff --git a/server/api/user.js b/server/api/user.js new file mode 100644 index 0000000..a977db7 --- /dev/null +++ b/server/api/user.js @@ -0,0 +1,155 @@ +import { Router } from "express"; + +const router = Router(); + +// Feature configurations by tier +const FEATURE_CONFIGS = { + none: { + tier: 'none', + pages: { + examples: 'off', + documentation: 'off', + pricing: 'off', + vrExperience: 'off', + }, + features: { + createDiagram: 'off', + createFromTemplate: 'off', + manageDiagrams: 'off', + shareCollaborate: 'off', + privateDesigns: 'off', + encryptedDesigns: 'off', + editData: 'off', + config: 'off', + enterImmersive: 'off', + launchMetaQuest: 'off', + }, + limits: { + maxDiagrams: 0, + maxCollaborators: 0, + storageQuotaMB: 0, + }, + }, + free: { + tier: 'free', + pages: { + examples: 'on', + documentation: 'on', + pricing: 'on', + vrExperience: 'on', + }, + features: { + createDiagram: 'on', + createFromTemplate: 'coming-soon', + manageDiagrams: 'on', + shareCollaborate: 'on', + privateDesigns: 'coming-soon', + encryptedDesigns: 'pro', + editData: 'on', + config: 'on', + enterImmersive: 'on', + launchMetaQuest: 'on', + }, + limits: { + maxDiagrams: 6, + maxCollaborators: 0, + storageQuotaMB: 100, + }, + }, + basic: { + tier: 'basic', + pages: { + examples: 'on', + documentation: 'on', + pricing: 'on', + vrExperience: 'on', + }, + features: { + createDiagram: 'on', + createFromTemplate: 'on', + manageDiagrams: 'on', + shareCollaborate: 'on', + privateDesigns: 'on', + encryptedDesigns: 'pro', + editData: 'on', + config: 'on', + enterImmersive: 'on', + launchMetaQuest: 'on', + }, + limits: { + maxDiagrams: 25, + maxCollaborators: 0, + storageQuotaMB: 500, + }, + }, + pro: { + tier: 'pro', + pages: { + examples: 'on', + documentation: 'on', + pricing: 'on', + vrExperience: 'on', + }, + features: { + createDiagram: 'on', + createFromTemplate: 'on', + manageDiagrams: 'on', + shareCollaborate: 'on', + privateDesigns: 'on', + encryptedDesigns: 'on', + editData: 'on', + config: 'on', + enterImmersive: 'on', + launchMetaQuest: 'on', + }, + limits: { + maxDiagrams: -1, + maxCollaborators: -1, + storageQuotaMB: -1, + }, + }, +}; + +// Default tier for authenticated users without a specific tier +const DEFAULT_TIER = 'basic'; + +/** + * GET /api/user/features + * Returns feature configuration for the current user + * + * Query params: + * - tier: Override tier for testing (e.g., ?tier=pro) + */ +router.get("/features", (req, res) => { + // Allow tier override via query param for testing + const tierOverride = req.query.tier; + + // TODO: In production, determine tier from JWT token or user database + // For now, use query param override or default to 'basic' + const tier = tierOverride && FEATURE_CONFIGS[tierOverride] + ? tierOverride + : DEFAULT_TIER; + + const config = FEATURE_CONFIGS[tier]; + + console.log(`[User] Returning feature config for tier: ${tier}`); + res.json(config); +}); + +/** + * GET /api/user/features/:tier + * Returns feature configuration for a specific tier (for testing/admin) + */ +router.get("/features/:tier", (req, res) => { + const { tier } = req.params; + const config = FEATURE_CONFIGS[tier]; + + if (!config) { + return res.status(404).json({ error: `Unknown tier: ${tier}` }); + } + + console.log(`[User] Returning feature config for tier: ${tier}`); + res.json(config); +}); + +export default router; diff --git a/server/middleware/dbAuth.js b/server/middleware/dbAuth.js new file mode 100644 index 0000000..4390863 --- /dev/null +++ b/server/middleware/dbAuth.js @@ -0,0 +1,78 @@ +/** + * Database authentication middleware. + * Allows public databases to be accessed without auth. + * Private databases require authentication. + */ + +/** + * Middleware to handle database authentication based on path. + * + * Database naming patterns: + * / - Root endpoint, always allowed (server info) + * /public-{dbname} - No auth required, anyone can read/write + * /private-{dbname} - Auth required + * /{dbname} - Treated as private by default + */ +export function dbAuthMiddleware(req, res, next) { + // Extract the database name (first segment after /pouchdb/) + const pathParts = req.path.split('/').filter(Boolean); + const dbName = pathParts[0] || ''; + + // Allow root endpoint (server info check) + if (req.path === '/' || req.path === '') { + console.log(`[DB Auth] Root access: ${req.method} ${req.path}`); + return next(); + } + + // Check if this is a public database (name starts with 'public-') + const isPublic = dbName.startsWith('public-'); + + if (isPublic) { + // No auth required for public databases + console.log(`[DB Auth] Public access: ${req.method} ${req.path}`); + return next(); + } + + // For private databases, check for auth header + const auth = req.headers.authorization; + + if (!auth) { + console.log(`[DB Auth] Unauthorized access attempt: ${req.method} ${req.path}`); + return res.status(401).json({ + error: 'unauthorized', + reason: 'Authentication required for private databases' + }); + } + + // Parse Basic auth header + if (auth.startsWith('Basic ')) { + try { + const credentials = Buffer.from(auth.slice(6), 'base64').toString(); + const [username, password] = credentials.split(':'); + + // For now, accept any credentials for private databases + // TODO: Implement proper user verification + req.dbUser = { name: username }; + console.log(`[DB Auth] Authenticated: ${username} accessing ${req.path}`); + return next(); + } catch (err) { + console.log(`[DB Auth] Invalid auth header: ${err.message}`); + } + } + + // TODO: Add JWT/Bearer token support for Auth0 integration + if (auth.startsWith('Bearer ')) { + // For now, accept bearer tokens without verification + // TODO: Verify JWT with Auth0 + req.dbUser = { name: 'bearer-user' }; + console.log(`[DB Auth] Bearer token access: ${req.path}`); + return next(); + } + + return res.status(401).json({ + error: 'unauthorized', + reason: 'Invalid authentication' + }); +} + +export default dbAuthMiddleware; diff --git a/server/services/databaseService.js b/server/services/databaseService.js new file mode 100644 index 0000000..e95aaf0 --- /dev/null +++ b/server/services/databaseService.js @@ -0,0 +1,62 @@ +/** + * Database service using express-pouchdb for self-hosted database sync. + * Provides PouchDB HTTP API compatible with client-side PouchDB replication. + */ + +import PouchDB from 'pouchdb'; +import PouchDBAdapterMemory from 'pouchdb-adapter-memory'; +import expressPouchdb from 'express-pouchdb'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +// Register memory adapter (works in Node.js without leveldown issues) +PouchDB.plugin(PouchDBAdapterMemory); + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +// Data directory for persistent storage (used for logs) +const DATA_DIR = process.env.DATA_DIR || path.join(__dirname, '../../data'); + +// Use memory adapter for now - data persists while server is running +// TODO: Switch to leveldb once version conflicts are resolved +const memPouchDB = PouchDB.defaults({ + adapter: 'memory' +}); + +// Create express-pouchdb middleware +// Using 'minimumForPouchDB' mode for lightweight operation +// Include routes needed for PouchDB replication +const pouchApp = expressPouchdb(memPouchDB, { + mode: 'minimumForPouchDB', + overrideMode: { + include: [ + 'routes/root', // GET / - server info + 'routes/db', // PUT/GET/DELETE /:db + 'routes/all-dbs', // GET /_all_dbs + 'routes/changes', // GET /:db/_changes + 'routes/bulk-docs', // POST /:db/_bulk_docs + 'routes/bulk-get', // POST /:db/_bulk_get + 'routes/all-docs', // GET /:db/_all_docs + 'routes/revs-diff', // POST /:db/_revs_diff + 'routes/documents' // GET/PUT/DELETE /:db/:docid + ] + }, + logPath: path.join(DATA_DIR, 'logs', 'pouchdb.log') +}); + +console.log(`[Database] Initialized express-pouchdb with data dir: ${DATA_DIR}`); + +// Test that PouchDB can create databases +(async () => { + try { + const testDb = new memPouchDB('_test_db'); + const info = await testDb.info(); + console.log('[Database] Test DB created successfully:', info); + await testDb.destroy(); + console.log('[Database] Test DB destroyed'); + } catch (err) { + console.error('[Database] Failed to create test database:', err); + } +})(); + +export { memPouchDB as PouchDB, pouchApp }; diff --git a/src/integration/database/pouchData.ts b/src/integration/database/pouchData.ts index e4e2327..f5922aa 100644 --- a/src/integration/database/pouchData.ts +++ b/src/integration/database/pouchData.ts @@ -5,18 +5,67 @@ import {DiagramEventObserverMask} from "../../diagram/types/diagramEventObserver import log, {Logger} from "loglevel"; import PouchDB from 'pouchdb'; import {importDiagramFromJSON, DiagramExport} from "../../util/functions/exportDiagramAsJSON"; +import {isPublicPath, getRemoteDbPath} from "../../util/functions/getPath"; export class PouchData { public readonly onDBEntityUpdateObservable: Observable = new Observable(); public readonly onDBEntityRemoveObservable: Observable = new Observable(); private _db: PouchDB; + private _remote: PouchDB; private _diagramManager: DiagramManager; private _logger: Logger = log.getLogger('PouchData'); private _dbName: string; + private _syncHandler: any; constructor(dbname: string) { this._db = new PouchDB(dbname); this._dbName = dbname; + + // Start sync for public databases + this.initSync(); + } + + /** + * Initialize sync with remote express-pouchdb for public databases + */ + private initSync() { + const remoteDbPath = getRemoteDbPath(); + const isPublic = isPublicPath(); + + if (!remoteDbPath || !isPublic) { + this._logger.debug('[Sync] Not a public path, skipping remote sync'); + return; + } + + const remoteUrl = `${window.location.origin}/pouchdb/${remoteDbPath}`; + this._logger.info(`[Sync] Connecting to remote: ${remoteUrl}`); + + this._remote = new PouchDB(remoteUrl); + + // Start live bidirectional sync + this._syncHandler = this._db.sync(this._remote, { live: true, retry: true }) + .on('change', (info) => { + this._logger.debug('[Sync] Change:', info.direction, info.change.docs.length, 'docs'); + // Process incoming changes + if (info.direction === 'pull' && info.change && info.change.docs) { + info.change.docs.forEach((doc) => { + if (doc._deleted) { + this.onDBEntityRemoveObservable.notifyObservers(doc); + } else if (doc.id && doc.id !== 'metadata') { + this.onDBEntityUpdateObservable.notifyObservers(doc); + } + }); + } + }) + .on('paused', (info) => { + this._logger.debug('[Sync] Paused - up to date'); + }) + .on('active', () => { + this._logger.debug('[Sync] Active - syncing'); + }) + .on('error', (err) => { + this._logger.error('[Sync] Error:', err); + }); } public setDiagramManager(diagramManager: DiagramManager) { this._diagramManager = diagramManager; diff --git a/src/integration/database/pouchdbPersistenceManager.ts b/src/integration/database/pouchdbPersistenceManager.ts deleted file mode 100644 index 5b55564..0000000 --- a/src/integration/database/pouchdbPersistenceManager.ts +++ /dev/null @@ -1,409 +0,0 @@ -import PouchDB from 'pouchdb'; -import {DiagramEntity, DiagramEntityType, DiagramEventType} from "../../diagram/types/diagramEntity"; -import {Observable} from "@babylonjs/core"; -import axios from "axios"; -import {DiagramManager} from "../../diagram/diagramManager"; -import log, {Logger} from "loglevel"; -import {ascii_to_hex} from "../functions/hexFunctions"; -import {getPath} from "../../util/functions/getPath"; -import {DiagramEventObserverMask} from "../../diagram/types/diagramEventObserverMask"; -import {syncDoc} from "../functions/syncDoc"; -import {checkDb} from "../functions/checkDb"; -import {UserModelType} from "../../users/userTypes"; -import {getMe} from "../../util/me"; -import {Encryption} from "../encryption"; -import {Presence} from "../presence"; - -type PasswordEvent = { - detail: string; -} -type PasswordEvent2 = { - password: string; - id: string; - encrypted: boolean; -} -export class PouchdbPersistenceManager { - private _logger: Logger = log.getLogger('PouchdbPersistenceManager'); - onDBEntityUpdateObservable: Observable = new Observable(); - onDBEntityRemoveObservable: Observable = new Observable(); - private db: PouchDB; - private remote: PouchDB; - private user: string; - private _encryption = new Encryption(); - private _encKey = null; - private _diagramManager: DiagramManager; - private _salt: string; - private _failCount: number = 0; - - constructor() { - document.addEventListener('passwordset', (evt) => { - this._encKey = ((evt as unknown) as PasswordEvent).detail || null; - if (this._encKey && typeof (this._encKey) == 'string') { - this.initialize().then(() => { - this._logger.debug('Initialized'); - }); - } - this._logger.debug(evt); - }); - document.addEventListener('dbcreated', (evt: CustomEvent) => { - const detail = ((evt.detail as unknown) as PasswordEvent2); - const password = detail.password; - const id = detail.id; - if (detail.encrypted) { - this._encKey = password; - } else { - this._encKey = null; - } - //this._encKey = password; - this.db = new PouchDB(detail.id, {auto_compaction: true}); - this.setupMetadata(id).then(() => { - document.location.href = '/db/' + id; - }).catch((err) => { - console.log(err); - }) - - }); - } - - public setDiagramManager(diagramManager: DiagramManager) { - this._diagramManager = diagramManager; - diagramManager.onDiagramEventObservable.add((evt) => { - this._logger.debug(evt); - if (!evt?.entity) { - this._logger.warn('no entity'); - return; - } - if (!evt?.entity?.id) { - this._logger.warn('no entity id'); - return; - } - switch (evt.type) { - case DiagramEventType.REMOVE: - this.remove(evt.entity.id); - break; - case DiagramEventType.ADD: - case DiagramEventType.MODIFY: - case DiagramEventType.DROP: - this.upsert(evt.entity); - break; - default: - this._logger.warn('unknown diagram event type', evt); - } - }, DiagramEventObserverMask.TO_DB); - - this.onDBEntityUpdateObservable.add((evt) => { - this._logger.debug(evt); - if (evt.id != 'metadata' && evt?.type == DiagramEntityType.USER) { - diagramManager.onDiagramEventObservable.notifyObservers({ - type: DiagramEventType.ADD, - entity: evt - }, DiagramEventObserverMask.FROM_DB); - } else { - - } - - }); - - - this.onDBEntityRemoveObservable.add((entity) => { - this._logger.debug(entity); - diagramManager.onDiagramEventObservable.notifyObservers( - {type: DiagramEventType.REMOVE, entity: entity}, DiagramEventObserverMask.FROM_DB); - }); - } - - public async remove(id: string) { - if (!id) { - return; - } - try { - const doc = await this.db.get(id); - this.db.remove(doc); - } catch (err) { - this._logger.error(err); - } - } - - public async upsert(entity: DiagramEntity) { - if (!entity) { - return; - } - if (entity.template == '#image-template' && !entity.image) { - this._logger.error('no image data', entity); - return; - } - - if (this._encKey && !this._encryption.ready) { - await this._encryption.setPassword(this._encKey); - } - try { - const doc = await this.db.get(entity.id, {conflicts: true, include_docs: true}); - if (doc && doc._conflicts) { - this._logger.warn('CONFLICTS!', doc._conflicts); - } - if (this._encKey) { - if (!doc.encrypted) { - this._logger.warn("current local doc is not encrypted, encrypting"); - } - await this._encryption.encryptObject(entity); - const newDoc = { - _id: doc._id, - _rev: doc._rev, - encrypted: this._encryption.getEncrypted() - } - this.db.put(newDoc) - } else { - if (doc) { - if (doc.encrypted) { - this._logger.error("current local doc is encrypted, but encryption key is missing... saving in plaintext"); - } - const newDoc = {_id: doc._id, _rev: doc._rev, ...entity}; - this.db.put(newDoc); - } else { - this.db.put({_id: entity.id, ...entity}); - } - } - - } catch (err) { - if (err.status == 404) { - try { - if (this._encKey) { - if (!this._encryption.ready) { - this._logger.error('Encryption not ready, there is a potential problem when this happens, we will generate a new salt which may cause data loss and/or slowness'); - await this._encryption.setPassword(this._encKey); - } - await this._encryption.encryptObject(entity); - const newDoc = { - _id: entity.id, - encrypted: this._encryption.getEncrypted() - } - this.db.put(newDoc); - } else { - this._logger.info('no encryption key, saving in plaintext'); - const newEntity = {_id: entity.id, ...entity}; - this.db.put(newEntity); - } - } catch (err2) { - this._logger.error("Unable to save document"); - this._logger.error(err2); - } - } else { - this._logger.error("Unknown error with document get from db"); - this._logger.error(err); - } - } - } - - public async initialize() { - if (!await this.initLocal()) { - return; - } - await this.sendLocalDataToScene(); - } - - private async setupMetadata(current: string): Promise { - try { - const doc = await this.db.get('metadata'); - if (doc.encrypted) { - if (!this._salt && doc.encrypted.salt) { - this._logger.warn('Missing Salt'); - this._salt = doc.encrypted.salt; - } - if (!this._encKey) { - const promptPassword = new CustomEvent('promptpassword', {detail: 'Please enter password'}); - document.dispatchEvent(promptPassword); - return false; - } - if (!this._encryption.ready) { - this._logger.warn("Encryption not ready, setting password"); - await this._encryption.setPassword(this._encKey, doc.encrypted.salt); - } - const decrypted = await this._encryption.decryptToObject(doc.encrypted.encrypted, doc.encrypted.iv); - if (decrypted.friendly) { - this._logger.info("Storing Document friendly name in local storage, decrypted"); - localStorage.setItem(current, decrypted.friendly); - } - } else { - if (doc && doc.friendly) { - this._logger.info("Storing Document friendly name in local storage"); - localStorage.setItem(current, doc.friendly); - this._encKey = null; - } - if (doc && doc.camera) { - - } - } - } catch (err) { - if (err.status == 404) { - this._logger.debug('no metadata found'); - const friendly = localStorage.getItem(current); - if (friendly) { - if (this._encKey) { - if (!this._encryption.ready) { - await this._encryption.setPassword(this._encKey); - } - await this._encryption.encryptObject({friendly: friendly}); - await this.db.put({_id: 'metadata', id: 'metadata', encrypted: this._encryption.getEncrypted()}) - } else { - this._logger.debug('local friendly name found ', friendly, ' setting metadata'); - const newDoc = {_id: 'metadata', id: 'metadata', friendly: friendly}; - await this.db.put(newDoc); - } - } else { - this._logger.warn('no friendly name found'); - } - } - } - return true; - } - - private async initLocal(): Promise { - try { - - let sync = false; - let current = getPath(); - if (current && current != 'localdb') { - sync = true; - } else { - current = 'localdb'; - } - this.db = new PouchDB(current, {auto_compaction: true}); - if (sync) { - if (await this.setupMetadata(current)) { - await this.beginSync(current); - } - } - return true; - } catch (err) { - this._logger.error(err); - this._logger.error('cannot initialize pouchdb for sync'); - return false; - } - } - - private async sendLocalDataToScene() { - let salt = null; - const clear = localStorage.getItem('clearLocal'); - try { - const all = await this.db.allDocs({include_docs: true}); - for (const dbEntity of all.rows) { - this._logger.debug(dbEntity.doc); - if (clear) { - this.remove(dbEntity.id); - } else { - if (dbEntity.doc.encrypted) { - if (!salt || salt != dbEntity.doc.encrypted.salt) { - await this._encryption.setPassword(this._encKey, dbEntity.doc.encrypted.salt); - salt = dbEntity.doc.encrypted.salt; - } - const decrypted = await this._encryption.decryptToObject(dbEntity.doc.encrypted.encrypted, dbEntity.doc.encrypted.iv); - - if (decrypted.id != 'metadata') { - this.onDBEntityUpdateObservable.notifyObservers(decrypted, DiagramEventObserverMask.FROM_DB); - } - - } else { - - if (dbEntity.id != 'metadata') { - this.onDBEntityUpdateObservable.notifyObservers(dbEntity.doc, DiagramEventObserverMask.FROM_DB); - } - - - } - } - if (clear) { - localStorage.removeItem('clearLocal'); - } - } - } catch (err) { - switch (err.message) { - case 'WebCrypto_DecryptionFailure: ': - case 'Invalid data type!': - this._failCount++; - if (this._failCount < 5) { - const promptPassword = new CustomEvent('promptpassword', {detail: 'Please enter password'}); - document.dispatchEvent(promptPassword); - } else { - this._logger.error('Too many decryption failures, Ignoring... This may compromise your data security'); - window.alert('Too many decryption failures, Ignoring... This may compromise your data security'); - } - } - this._logger.error(err); - } - } - - private async beginSync(localName: string) { - try { - const userHex = ascii_to_hex(localName); - const remoteDbName = 'userdb-' + userHex; - const remoteUserName = localName; - const password = this._encKey || localName; - - if (await checkDb(localName, remoteDbName, password) == false) { - return; - } - - const userEndpoint: string = import.meta.env.VITE_USER_ENDPOINT - this._logger.debug(userEndpoint); - this._logger.debug(remoteDbName); - const target = await axios.get(userEndpoint); - if (target.status != 200) { - this._logger.warn(target.statusText); - return; - } - if (target.data && target.data.userCtx) { - if (!target.data.userCtx.name || target.data.userCtx.name != remoteUserName) { - try { - const buildTarget = await axios.post(userEndpoint, - {username: remoteUserName, password: password}); - if (buildTarget.status != 200) { - this._logger.error(buildTarget.statusText); - return; - } else { - this.user = buildTarget.data.userCtx; - this._logger.debug(this.user); - } - } catch (err) { - if (err.response && err.response.status == 401) { - this._logger.warn(err); - const promptPassword = new CustomEvent('promptpassword', {detail: 'Please enter password'}); - document.dispatchEvent(promptPassword); - } - - // } else { - this._logger.error(err); - } - - } - } - - const remoteEndpoint: string = import.meta.env.VITE_SYNCDB_ENDPOINT; - this._logger.debug(remoteEndpoint + remoteDbName); - this.remote = new PouchDB(remoteEndpoint + remoteDbName, - {auth: {username: remoteUserName, password: password}, skip_setup: true}); - const dbInfo = await this.remote.info(); - this._logger.debug(dbInfo); - const presence: Presence = new Presence(getMe(), remoteDbName); - this._diagramManager.onUserEventObservable.add((user: UserModelType) => { - //this._logger.debug(user); - presence.sendUser(user); - }, -1, false, this); - this.db.sync(this.remote, {live: true, retry: true}) - .on('change', (info) => { - syncDoc(info, this.onDBEntityRemoveObservable, this.onDBEntityUpdateObservable, this._encryption, this._encKey); - }) - .on('active', (info) => { - this._logger.debug('sync active', info) - }) - .on('paused', (info) => { - this._logger.debug('sync paused', info) - }) - .on('error', (err) => { - this._logger.error('sync error', err) - }); - } catch (err) { - this._logger.error(err); - } - } -} - diff --git a/src/react/pages/vrExperience.tsx b/src/react/pages/vrExperience.tsx index 549ced9..101d679 100644 --- a/src/react/pages/vrExperience.tsx +++ b/src/react/pages/vrExperience.tsx @@ -40,6 +40,7 @@ export default function VrExperience() { const createFromTemplateState = useFeatureState('createFromTemplate'); const manageDiagramsState = useFeatureState('manageDiagrams'); const shareCollaborateState = useFeatureState('shareCollaborate'); + console.log('[Share] shareCollaborateState:', shareCollaborateState); const editDataState = useFeatureState('editData'); const configState = useFeatureState('config'); const enterImmersiveState = useFeatureState('enterImmersive'); @@ -121,6 +122,30 @@ export default function VrExperience() { const [showVRPrompt, setShowVRPrompt] = useState(false); const [chatOpen, setChatOpen] = useState(!isMobileVRDevice()); // Show chat by default on desktop + // Handle share: simply copy current URL to clipboard + const handleShare = async () => { + const shareUrl = window.location.href; + logger.info(`Sharing URL: ${shareUrl}`); + + // Try to copy URL to clipboard with fallback + let copied = false; + try { + if (navigator.clipboard && navigator.clipboard.writeText) { + await navigator.clipboard.writeText(shareUrl); + copied = true; + } + } catch (clipboardError) { + logger.warn('Clipboard API failed:', clipboardError); + } + + if (copied) { + alert(`URL copied to clipboard!\n\n${shareUrl}`); + } else { + // Fallback: show URL in prompt so user can copy manually + prompt('Share URL (copy manually):', shareUrl); + } + }; + useEffect(() => { const canvas = document.getElementById('vrCanvas'); if (!canvas) { @@ -131,6 +156,7 @@ export default function VrExperience() { logger.debug('destroying vrApp'); vrApp.dispose(); } + console.log('[Share] Initializing VrApp with dbName:', dbName); vrApp = new VrApp(canvas as HTMLCanvasElement, dbName); closeManage(); @@ -329,9 +355,9 @@ export default function VrExperience() { {shouldShow(shareCollaborateState) && ( )} diff --git a/src/util/featureConfig.ts b/src/util/featureConfig.ts index f705770..6a6fd7a 100644 --- a/src/util/featureConfig.ts +++ b/src/util/featureConfig.ts @@ -56,7 +56,7 @@ export const DEFAULT_FEATURE_CONFIG: FeatureConfig = { createDiagram: 'basic', // Guests can create diagrams createFromTemplate: 'coming-soon', // Coming soon for guests manageDiagrams: 'basic', // Guests can manage their local diagrams - shareCollaborate: 'coming-soon', // Coming soon for guests + shareCollaborate: 'on', // Share diagrams via link privateDesigns: 'coming-soon', // Coming soon for guests encryptedDesigns: 'pro', // No encryption for guests editData: 'coming-soon', // Guests can edit data @@ -83,7 +83,7 @@ export const BASIC_FEATURE_CONFIG: FeatureConfig = { createDiagram: 'on', createFromTemplate: 'coming-soon', manageDiagrams: 'on', - shareCollaborate: 'coming-soon', + shareCollaborate: 'on', privateDesigns: 'coming-soon', encryptedDesigns: 'pro', editData: 'coming-soon', diff --git a/src/util/functions/getPath.ts b/src/util/functions/getPath.ts index b4e8777..d52fdb7 100644 --- a/src/util/functions/getPath.ts +++ b/src/util/functions/getPath.ts @@ -1,10 +1,51 @@ export function getPath(): string { const path = window.location.pathname.split('/'); + // Handle /db/public/:db or /db/private/:db patterns + if (path.length >= 4 && path[1] === 'db') { + return path[3]; + } + // Legacy pattern /db/:db if (path.length == 3 && path[1]) { return path[2]; - } else { - return null; } + return null; +} + +/** + * Check if the current path is a public database + * Public paths: /db/public/:db + * Private paths: /db/private/:db + */ +export function isPublicPath(): boolean { + const path = window.location.pathname.split('/'); + return path.length >= 3 && path[1] === 'db' && path[2] === 'public'; +} + +/** + * Get the database type from the current path + */ +export function getDbType(): 'public' | 'private' | null { + const path = window.location.pathname.split('/'); + if (path.length >= 3 && path[1] === 'db') { + if (path[2] === 'public') return 'public'; + if (path[2] === 'private') return 'private'; + } + return null; +} + +/** + * Get the full database path for PouchDB sync + * Returns: public-{dbname} or private-{dbname} + * Uses dash separator instead of slash for express-pouchdb compatibility + */ +export function getRemoteDbPath(): string | null { + const path = window.location.pathname.split('/'); + if (path.length >= 4 && path[1] === 'db') { + const type = path[2]; // 'public' or 'private' + const dbName = path[3]; + return `${type}-${dbName}`; + } + return null; } export function getParameter(name: string) { diff --git a/src/vrApp.ts b/src/vrApp.ts index 073f995..3ecf1f7 100644 --- a/src/vrApp.ts +++ b/src/vrApp.ts @@ -23,7 +23,6 @@ import {PouchData} from "./integration/database/pouchData"; const webGpu = false; log.setLevel('debug', false); -log.getLogger('PouchdbPersistenceManager').setLevel('debug', false); export default class VrApp { //preTasks = [havokModule]; private logger: Logger = log.getLogger('App');