├── .eslintrc.js ├── .gitignore ├── .npm └── package │ ├── .gitignore │ ├── README │ └── npm-shrinkwrap.json ├── .versions ├── README.md ├── main-client.js ├── main-server.js ├── messenger.js ├── observe-changes.js ├── package-lock.json ├── package.js ├── package.json ├── publish.js ├── redis.js ├── write-client.js ├── write-server.js └── write.js /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: 'airbnb-base', 3 | rules: { 4 | 'no-underscore-dangle': 'off', 5 | 'no-param-reassign': 'off', 6 | 'import/no-cycle': 'off', 7 | 'no-restricted-syntax': 'off', 8 | 'no-continue': 'off', 9 | 'no-console': 'off', 10 | 'import/prefer-default-export': 'off', 11 | 'no-await-in-loop': 'off', 12 | 'no-void': 'off', 13 | indent: ['error', 4], 14 | 'max-len': ['warn', { 15 | code: 120, 16 | }], 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules -------------------------------------------------------------------------------- /.npm/package/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.npm/package/README: -------------------------------------------------------------------------------- 1 | This directory and the files immediately inside it are automatically generated 2 | when you change this package's NPM dependencies. Commit the files in this 3 | directory (npm-shrinkwrap.json, .gitignore, and this README) to source control 4 | so that others run the same versions of sub-dependencies. 5 | 6 | You should NOT check in the node_modules directory that Meteor automatically 7 | creates; if you are using git, the .gitignore file tells git to ignore it. 8 | -------------------------------------------------------------------------------- /.npm/package/npm-shrinkwrap.json: -------------------------------------------------------------------------------- 1 | { 2 | "lockfileVersion": 4, 3 | "dependencies": { 4 | "@redis/bloom": { 5 | "version": "1.2.0", 6 | "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz", 7 | "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==" 8 | }, 9 | "@redis/client": { 10 | "version": "1.6.0", 11 | "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.0.tgz", 12 | "integrity": "sha512-aR0uffYI700OEEH4gYnitAnv3vzVGXCFvYfdpu/CJKvk4pHfLPEy/JSZyrpQ+15WhXe1yJRXLtfQ84s4mEXnPg==" 13 | }, 14 | "@redis/graph": { 15 | "version": "1.1.1", 16 | "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.1.tgz", 17 | "integrity": "sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==" 18 | }, 19 | "@redis/json": { 20 | "version": "1.0.7", 21 | "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.7.tgz", 22 | "integrity": "sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ==" 23 | }, 24 | "@redis/search": { 25 | "version": "1.2.0", 26 | "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.2.0.tgz", 27 | "integrity": "sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw==" 28 | }, 29 | "@redis/time-series": { 30 | "version": "1.1.0", 31 | "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.1.0.tgz", 32 | "integrity": "sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==" 33 | }, 34 | "cluster-key-slot": { 35 | "version": "1.1.2", 36 | "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", 37 | "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==" 38 | }, 39 | "generic-pool": { 40 | "version": "3.9.0", 41 | "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", 42 | "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==" 43 | }, 44 | "lru-cache": { 45 | "version": "11.0.2", 46 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz", 47 | "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==" 48 | }, 49 | "redis": { 50 | "version": "4.7.0", 51 | "resolved": "https://registry.npmjs.org/redis/-/redis-4.7.0.tgz", 52 | "integrity": "sha512-zvmkHEAdGMn+hMRXuMBtu4Vo5P6rHQjLoHftu+lBqq8ZTA3RCVC/WzD790bkKKiNFp7d5/9PcSD19fJyyRvOdQ==" 53 | }, 54 | "yallist": { 55 | "version": "4.0.0", 56 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 57 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /.versions: -------------------------------------------------------------------------------- 1 | babel-compiler@7.11.3 2 | babel-runtime@1.5.2 3 | base64@1.0.13 4 | chatra:redpubsub@1.0.1 5 | core-runtime@1.0.0 6 | diff-sequence@1.1.3 7 | dynamic-import@0.7.4 8 | ecmascript@0.16.10 9 | ecmascript-runtime@0.8.3 10 | ecmascript-runtime-client@0.12.3 11 | ecmascript-runtime-server@0.11.1 12 | ejson@1.1.4 13 | fetch@0.1.6 14 | geojson-utils@1.0.12 15 | id-map@1.2.0 16 | inter-process-messaging@0.1.2 17 | meteor@2.1.0 18 | minimongo@2.0.2 19 | modern-browsers@0.2.1 20 | modules@0.20.3 21 | modules-runtime@0.13.2 22 | mongo-decimal@0.2.0 23 | mongo-id@1.0.9 24 | ordered-dict@1.2.0 25 | promise@1.0.0 26 | random@1.2.2 27 | react-fast-refresh@0.2.9 28 | tracker@1.3.4 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # chatra:redpubsub 2 | 3 | [![Version](https://img.shields.io/badge/meteor-%203.x-brightgreen?logo=meteor&logoColor=white)](https://github.com/chatr/safe-update) 4 | [![License](https://img.shields.io/badge/license-MIT-blue)](LICENSE) 5 | 6 | Custom pub/sub interface for Meteor on top of Redis, updated for Meteor 3 compatibility. 7 | 8 | ## Table of Contents 9 | 10 | - [Introduction](#introduction) 11 | - [Features](#features) 12 | - [Installation](#installation) 13 | - [Compatibility](#compatibility) 14 | - [Configuration](#configuration) 15 | - [Usage](#usage) 16 | - [Server Side](#server-side) 17 | - [Publishing Data](#publishing-data) 18 | - [Configuring Channels](#configuring-channels) 19 | - [Using `RPS.write`](#using-rpswrite-on-the-server) 20 | - [Publishing with `withoutMongo` Option](#publishing-with-withoutmongo-option) 21 | - [Publishing Multiple Collections Simultaneously](#publishing-multiple-collections-simultaneously) 22 | - [Server-Side observeChanges](#server-side-observechanges) 23 | - [Client Side](#client-side) 24 | - [Subscribing to Data](#subscribing-to-data) 25 | - [Using `RPS.write`](#using-rpswrite-on-the-client) 26 | - [Examples](#examples) 27 | - [License](#license) 28 | 29 | --- 30 | 31 | ## Introduction 32 | 33 | The `chatra:redpubsub` package provides a custom publish/subscribe interface for Meteor applications, leveraging Redis for real-time data synchronization across multiple server instances. This package is especially useful for scaling Meteor applications horizontally, ensuring that all instances remain in sync. 34 | 35 | --- 36 | 37 | ## Features 38 | 39 | - **Real-Time Data Synchronization:** Uses Redis channels to synchronize data changes across multiple Meteor server instances. 40 | - **Custom Channels:** Configure custom channels for fine-grained control over data publication. 41 | - **Asynchronous Operations:** Fully supports asynchronous MongoDB operations introduced in Meteor 3. 42 | - **No Fibers Dependency** 43 | 44 | --- 45 | 46 | ## Installation 47 | 48 | ```shell 49 | meteor add chatra:redpubsub 50 | ``` 51 | 52 | Ensure that you have Redis installed and running. Set the `RPS_REDIS_URL` environment variable to point to your Redis instance: 53 | 54 | ```shell 55 | export RPS_REDIS_URL=redis://localhost:6379 56 | ``` 57 | 58 | --- 59 | 60 | ## Compatibility 61 | 62 | - **Meteor version 3 and above:** Fully compatible, using the new asynchronous Meteor collections’ methods. 63 | 64 | --- 65 | 66 | ## Configuration 67 | 68 | ### Setting Up Redis Connection 69 | 70 | The package uses the `RPS_REDIS_URL` environment variable to connect to your Redis instance. The URL should be in the format: 71 | 72 | ``` 73 | redis://:[password]@[hostname]:[port] 74 | ``` 75 | 76 | Example: 77 | 78 | ```shell 79 | export RPS_REDIS_URL=redis://localhost:6379 80 | ``` 81 | 82 | ### Configuring Channels 83 | 84 | You can configure channels on a per-collection basis using `RPS.config`: 85 | 86 | ```js 87 | // server/main.js 88 | import { RPS } from 'meteor/chatra:redpubsub'; 89 | 90 | RPS.config['collectionName'] = { 91 | channels: (doc, selector, fields) => { 92 | // Return a channel name or an array of channel names 93 | return `custom_channel_${doc.userId}`; 94 | }, 95 | }; 96 | ``` 97 | 98 | --- 99 | 100 | ## Usage 101 | 102 | ### Server Side 103 | 104 | #### Publishing Data 105 | 106 | Use `RPS.publish` to publish data to clients: 107 | 108 | ```js 109 | // server/main.js 110 | import { Meteor } from 'meteor/meteor'; 111 | import { RPS } from 'meteor/chatra:redpubsub'; 112 | import { CollectionName } from '/imports/api/collectionName'; 113 | 114 | Meteor.publish('collectionName', function () { 115 | return RPS.publish(this, { 116 | collection: CollectionName, 117 | options: { 118 | selector: {}, // MongoDB selector 119 | options: {}, // Find options 120 | }, 121 | }); 122 | }); 123 | ``` 124 | 125 | #### Configuring Channels 126 | 127 | You can configure custom channels for a collection: 128 | 129 | ```js 130 | // server/main.js 131 | RPS.config['collectionName'] = { 132 | channels: (doc) => `channel_${doc.userId}`, 133 | }; 134 | ``` 135 | 136 | #### Using `RPS.write` on the Server 137 | 138 | Perform write operations and automatically publish changes: 139 | 140 | ```js 141 | // server/main.js 142 | import { RPS } from 'meteor/chatra:redpubsub'; 143 | import { CollectionName } from '/imports/api/collectionName'; 144 | 145 | async function updateDocument(docId, updateFields) { 146 | const options = { 147 | selector: { _id: docId }, 148 | modifier: { $set: updateFields }, 149 | options: {}, // MongoDB update options 150 | }; 151 | 152 | try { 153 | const result = await RPS.write(CollectionName, 'update', options); 154 | console.log('Document updated:', result); 155 | } catch (err) { 156 | console.error('Error updating document:', err); 157 | } 158 | } 159 | ``` 160 | 161 | #### Publishing with `withoutMongo` Option 162 | 163 | This option allows you to publish changes without querying the database after the write operation. 164 | 165 | ```js 166 | // server/main.js 167 | import { Meteor } from 'meteor/meteor'; 168 | import { RPS } from 'meteor/chatra:redpubsub'; 169 | import { MyCollection } from '/imports/api/myCollection'; 170 | 171 | Meteor.publish('withoutMongoPub', function () { 172 | return RPS.publish(this, { 173 | collection: MyCollection, 174 | options: { 175 | selector: { active: true }, 176 | withoutMongo: true, // Disable additional Mongo query after write 177 | }, 178 | }); 179 | }); 180 | ``` 181 | 182 | #### Publishing Multiple Collections Simultaneously 183 | 184 | You can pass an array of publication requests to `RPS.publish` to publish multiple collections at once: 185 | 186 | ```js 187 | // server/main.js 188 | import { Meteor } from 'meteor/meteor'; 189 | import { RPS } from 'meteor/chatra:redpubsub'; 190 | import { CollectionOne } from '/imports/api/collectionOne'; 191 | import { CollectionTwo } from '/imports/api/collectionTwo'; 192 | 193 | Meteor.publish('multiCollections', function () { 194 | return RPS.publish(this, [ 195 | { 196 | collection: CollectionOne, 197 | options: { selector: {} }, 198 | }, 199 | { 200 | collection: CollectionTwo, 201 | options: { selector: {} }, 202 | }, 203 | ]); 204 | }); 205 | ``` 206 | 207 | #### Server-Side observeChanges 208 | 209 | You can directly call `RPS.observeChanges` on the server to perform custom actions when data changes occur: 210 | 211 | ```js 212 | // server/observe.js 213 | import { RPS } from 'meteor/chatra:redpubsub'; 214 | import { CollectionName } from '/imports/api/collectionName'; 215 | 216 | async function observeServerChanges() { 217 | const handler = await RPS.observeChanges( 218 | CollectionName, 219 | { selector: {} }, 220 | { 221 | added: (id, fields) => { 222 | console.log('Document added:', id, fields); 223 | }, 224 | changed: (id, fields) => { 225 | console.log('Document changed:', id, fields); 226 | }, 227 | removed: (id) => { 228 | console.log('Document removed:', id); 229 | }, 230 | } 231 | ); 232 | 233 | // To stop observing: 234 | // handler.stop(); 235 | } 236 | 237 | observeServerChanges(); 238 | ``` 239 | 240 | ### Client Side 241 | 242 | #### Subscribing to Data 243 | 244 | Subscribe to the published data: 245 | 246 | ```js 247 | // client/main.js 248 | import { Meteor } from 'meteor/meteor'; 249 | import { CollectionName } from '/imports/api/collectionName'; 250 | 251 | Meteor.subscribe('collectionName'); 252 | ``` 253 | 254 | #### Using `RPS.write` on the Client 255 | 256 | Perform write operations from the client: 257 | 258 | ```js 259 | // client/main.js 260 | import { RPS } from 'meteor/chatra:redpubsub'; 261 | import { CollectionName } from '/imports/api/collectionName'; 262 | 263 | async function insertDocument(doc) { 264 | try { 265 | const result = await RPS.write(CollectionName, 'insert', { doc }); 266 | console.log('Document inserted:', result); 267 | } catch (err) { 268 | console.error('Error inserting document:', err); 269 | } 270 | } 271 | ``` 272 | 273 | --- 274 | 275 | ## Examples 276 | 277 | ### Full Example 278 | 279 | #### Server 280 | 281 | ```js 282 | // server/main.js 283 | import { Meteor } from 'meteor/meteor'; 284 | import { RPS } from 'meteor/chatra:redpubsub'; 285 | import { Messages } from '/imports/api/messages'; 286 | 287 | RPS.config['messages'] = { 288 | channels: (doc) => `user_${doc.userId}_channel`, 289 | }; 290 | 291 | Meteor.publish('userMessages', function () { 292 | const userId = this.userId; 293 | if (!userId) { 294 | return this.ready(); 295 | } 296 | 297 | return RPS.publish(this, { 298 | collection: Messages, 299 | options: { 300 | selector: { userId }, 301 | }, 302 | }); 303 | }); 304 | 305 | Meteor.methods({ 306 | async 'messages.insert'(text) { 307 | const userId = this.userId; 308 | if (!userId) { 309 | throw new Meteor.Error('Not authorized'); 310 | } 311 | 312 | const doc = { 313 | text, 314 | userId, 315 | createdAt: new Date(), 316 | }; 317 | 318 | return await RPS.write(Messages, 'insert', { doc }); 319 | }, 320 | }); 321 | ``` 322 | 323 | #### Client 324 | 325 | ```js 326 | // client/main.js 327 | import { Meteor } from 'meteor/meteor'; 328 | import { Messages } from '/imports/api/messages'; 329 | 330 | Meteor.subscribe('userMessages'); 331 | 332 | Messages.find().observeChanges({ 333 | added(id, fields) { 334 | console.log('Message added:', id, fields); 335 | }, 336 | changed(id, fields) { 337 | console.log('Message changed:', id, fields); 338 | }, 339 | removed(id) { 340 | console.log('Message removed:', id); 341 | }, 342 | }); 343 | 344 | async function sendMessage(text) { 345 | try { 346 | await Meteor.callAsync('messages.insert', text); 347 | console.log('Message sent'); 348 | } catch (err) { 349 | console.error('Error sending message:', err); 350 | } 351 | } 352 | ``` 353 | 354 | ## License 355 | 356 | This package is licensed under the MIT License. -------------------------------------------------------------------------------- /main-client.js: -------------------------------------------------------------------------------- 1 | import { write as writeClient } from './write-client'; 2 | 3 | // Expose the RPS object on the client. 4 | export const RPS = { 5 | write: writeClient, // Client-side write operation. 6 | }; 7 | -------------------------------------------------------------------------------- /main-server.js: -------------------------------------------------------------------------------- 1 | import { write as writeServer } from './write-server'; 2 | import { publish } from './publish'; 3 | import { observeChanges } from './observe-changes'; 4 | import './redis'; 5 | 6 | // Expose the RPS object on the server. 7 | export const RPS = { 8 | write: writeServer, // Server-side write operation with publishing. 9 | publish, // Publish method to hook into Meteor.publish. 10 | observeChanges, // Method to observe changes on a collection. 11 | config: {}, // Configuration object for custom channels etc. 12 | }; 13 | -------------------------------------------------------------------------------- /messenger.js: -------------------------------------------------------------------------------- 1 | import { subscribe, unsubscribe } from './redis'; 2 | 3 | /** 4 | * Messenger class handles registration of observers on channels, 5 | * routing messages from Redis to the corresponding observer callbacks. 6 | */ 7 | class Messenger { 8 | constructor() { 9 | // Map of channel names to objects with observer keys as properties. 10 | this.channels = {}; 11 | // Map of observer keys to channel names. 12 | this.observers = {}; 13 | // Global message handler callback (can be set externally). 14 | this.onMessage = null; 15 | } 16 | 17 | /** 18 | * Registers an observer for a given channel. 19 | * @param {string} observerKey Unique key identifying the observer. 20 | * @param {string} channel The Redis channel to subscribe to. 21 | */ 22 | addObserver(observerKey, channel) { 23 | // Create channel entry if it doesn't exist. 24 | if (!this.channels[channel]) { 25 | this.channels[channel] = {}; 26 | } 27 | // Register the observer key on this channel. 28 | this.channels[channel][observerKey] = true; 29 | // Map the observer key to the channel. 30 | this.observers[observerKey] = channel; 31 | // Subscribe to the Redis channel. 32 | subscribe(channel); 33 | } 34 | 35 | /** 36 | * Removes an observer from a channel. 37 | * @param {string} observerKey Unique key identifying the observer. 38 | */ 39 | removeObserver(observerKey) { 40 | const channel = this.observers[observerKey]; 41 | if (channel) { 42 | // Remove observer from the channel's observer list. 43 | delete this.channels[channel][observerKey]; 44 | // If no more observers on the channel, unsubscribe from Redis. 45 | if (Object.keys(this.channels[channel]).length === 0) { 46 | unsubscribe(channel); 47 | delete this.channels[channel]; 48 | } 49 | } 50 | // Remove the observer mapping. 51 | delete this.observers[observerKey]; 52 | } 53 | 54 | /** 55 | * Handles an incoming message for a given channel. 56 | * Delegates the processing to an externally defined onMessage callback. 57 | * @param {string} channel The channel on which the message was received. 58 | * @param {Object} message The message object. 59 | */ 60 | handleMessage(channel, message) { 61 | if (this.onMessage) { 62 | this.onMessage(channel, message); 63 | } 64 | } 65 | } 66 | 67 | const messenger = new Messenger(); 68 | 69 | export { messenger }; 70 | -------------------------------------------------------------------------------- /observe-changes.js: -------------------------------------------------------------------------------- 1 | import { LRUCache } from 'lru-cache' 2 | import { Random } from 'meteor/random'; 3 | import { EJSON } from 'meteor/ejson'; 4 | import { Minimongo } from 'meteor/minimongo'; 5 | import { DiffSequence } from 'meteor/diff-sequence'; 6 | import { messenger } from './messenger'; 7 | 8 | // Global cache for compiled projection functions. 9 | // Key: JSON string of projection fields, Value: compiled projection function. 10 | const projectionCache = new LRUCache({ 11 | max: 50000, // Limit the number of cached projections. 12 | ttl: 1000 * 60 * 60 * 8, // Cache for 8 hours. 13 | }); 14 | 15 | // Global cache for matchers. 16 | // Key: JSON string of the selector, Value: Minimongo.Matcher instance. 17 | const matcherCache = new LRUCache({ 18 | max: 50000, // Limit the number of cached matchers. 19 | ttl: 1000 * 60 * 60 * 8, // Cache for 8 hours. 20 | }); 21 | 22 | // Global map for observers indexed by a unique observer key. 23 | const observers = {}; 24 | 25 | /** 26 | * Utility function to extract the top-level field name from a dot-notated path. 27 | * @param {string} path The full dot-notated path. 28 | * @return {string} The top-level field. 29 | */ 30 | function topLevelPath(path) { 31 | const index = path.indexOf('.'); 32 | return index !== -1 ? path.substring(0, index) : path; 33 | } 34 | 35 | /** 36 | * Helper function to omit specified keys from an object. 37 | * @param {Object} obj - The object to filter. 38 | * @param {string[]} keys - An array of keys to omit. 39 | * @return {Object} A new object without the omitted keys. 40 | */ 41 | function omit(obj, keys) { 42 | const result = {}; 43 | for (const key in obj) { 44 | if (Object.prototype.hasOwnProperty.call(obj, key) && !keys.includes(key)) { 45 | result[key] = obj[key]; 46 | } 47 | } 48 | return result; 49 | } 50 | 51 | /** 52 | * Observer class monitors changes on a MongoDB collection. 53 | * It handles initial fetch, diff computation, and calls registered listeners 54 | * when documents are added, changed, or removed. 55 | */ 56 | class Observer { 57 | /** 58 | * Constructs an Observer instance. 59 | * @param {Mongo.Collection} collection The collection to observe. 60 | * @param {Object} options Options including selector, fields, etc. 61 | * @param {string} key A unique key for the observer. 62 | */ 63 | constructor(collection, options, key) { 64 | this.collection = collection; 65 | this.options = options; 66 | // MongoDB selector for documents to observe. 67 | this.selector = options.selector || {}; 68 | // Options for the Mongo find query. 69 | this.findOptions = options.options || {}; 70 | this.findOptions.fields = this.findOptions.fields || {}; 71 | // If limit is set and lazyLimit option is not true, we always re-fetch. 72 | this.needToFetchAlways = this.findOptions.limit && !options.lazyLimit; 73 | // Quick find options used for lightweight queries (only _id field). 74 | this.quickFindOptions = { ...this.findOptions, fields: { _id: 1 } }; 75 | 76 | // Setup projection: which fields to include/exclude. 77 | this.projectionFields = { ...this.findOptions.fields }; 78 | this.projectionIncluding = null; 79 | this._initializeProjection(); 80 | 81 | // Channel name for receiving updates (default to collection name). 82 | this.channel = options.channel || collection._name; 83 | this.key = key; 84 | // Map of listeners for different subscriptions (listenerId => callbacks). 85 | this.listeners = {}; 86 | // Set of actions (added/changed/removed) requested by listeners. 87 | this.actions = {}; 88 | // Cached documents keyed by their _id. 89 | this.docs = {}; 90 | // To handle out-of-order messages, store last method and timestamp per document. 91 | this.lastMethod = {}; 92 | this.lastTs = {}; 93 | // Queue of messages received while processing is paused. 94 | this.messageQueue = []; 95 | this.paused = false; 96 | this.initiallyFetched = false; 97 | this.initialized = false; 98 | 99 | // Validate that _id is not excluded from fields. 100 | if (this.findOptions.fields._id === 0 || this.findOptions.fields._id === false) { 101 | throw new Error('You may not observe a cursor with {fields: {_id: 0}}'); 102 | } 103 | 104 | this.initialize(); 105 | } 106 | 107 | /** 108 | * Initializes projection settings. 109 | * @private 110 | */ 111 | _initializeProjection() { 112 | if (this.projectionFields) { 113 | // Build a map of top-level fields from the projection. 114 | this.projectionTopFields = {}; 115 | Object.entries(this.projectionFields).forEach(([path, rule]) => { 116 | if (path === '_id') { 117 | return; 118 | } 119 | // Convert rule to boolean (include/exclude). 120 | rule = !!rule; 121 | if (this.projectionIncluding === null) { 122 | this.projectionIncluding = rule; 123 | } 124 | if (this.projectionIncluding !== rule) { 125 | throw new Error('You cannot currently mix including and excluding fields.'); 126 | } 127 | // Save only the top-level field. 128 | this.projectionTopFields[topLevelPath(path)] = rule; 129 | }); 130 | 131 | // If docsMixin is provided, merge or remove mixin fields accordingly. 132 | if (this.options.docsMixin) { 133 | Object.keys(this.options.docsMixin).forEach((key) => { 134 | if (this.projectionIncluding) { 135 | this.projectionFields[key] = 1; 136 | } else { 137 | delete this.projectionFields[key]; 138 | } 139 | }); 140 | } 141 | 142 | // Create a key from the projectionFields object to check the cache. 143 | const projectionKey = JSON.stringify(this.projectionFields); 144 | if (projectionCache.has(projectionKey)) { 145 | // Use cached compiled projection function. 146 | this.projectionFn = projectionCache.get(projectionKey); 147 | } else { 148 | // Compile a new projection function and cache it. 149 | const compiled = Minimongo.LocalCollection._compileProjection(this.projectionFields); 150 | projectionCache.set(projectionKey, compiled); 151 | this.projectionFn = compiled; 152 | } 153 | } else { 154 | // If no projectionFields are provided, use identity function. 155 | this.projectionFn = (doc) => doc; 156 | } 157 | 158 | // Create a key from the selector object to check the cache. 159 | const selectorKey = JSON.stringify(this.selector); 160 | if (matcherCache.has(selectorKey)) { 161 | // Use cached matcher. 162 | this.matcher = matcherCache.get(selectorKey); 163 | } else { 164 | try { 165 | // Create a new matcher and cache it. 166 | this.matcher = new Minimongo.Matcher(this.selector); 167 | matcherCache.set(selectorKey, this.matcher); 168 | } catch (err) { 169 | console.error('[Observer._initializeProjection] Error compiling matcher:', err); 170 | } 171 | } 172 | 173 | try { 174 | // Combine projection with matcher if possible. 175 | this.findOptions.fields = this.projectionFields 176 | && this.matcher.combineIntoProjection(this.projectionFields); 177 | } catch (err) { 178 | console.error('[Observer._initializeProjection] Error combining matcher/projection:', err); 179 | } 180 | } 181 | 182 | /** 183 | * Initializes the observer by registering it with the messenger. 184 | * This allows the observer to receive messages via its channel. 185 | */ 186 | initialize() { 187 | if (this.initialized) { 188 | return; 189 | } 190 | // Register the observer unless it is marked as nonreactive. 191 | if (!this.options.nonreactive) { 192 | messenger.addObserver(this.key, this.channel); 193 | } 194 | this.initialized = true; 195 | } 196 | 197 | /** 198 | * Adds a new listener (subscription) to this observer. 199 | * The listener receives callbacks for added/changed/removed events. 200 | * @param {string} listenerId Unique identifier for the listener. 201 | * @param {Object} callbacks An object with added, changed, removed callback functions. 202 | */ 203 | async addListener(listenerId, callbacks) { 204 | this.listeners[listenerId] = callbacks || {}; 205 | // Update the list of actions (what events to watch) based on listener callbacks. 206 | this._refreshActionsList(listenerId); 207 | // Pause message processing while performing the initial fetch. 208 | this.pause(); 209 | // Fetch the initial set of documents. 210 | await this.initialFetch(); 211 | // Send initial added events to the new listener. 212 | this.initialAdd(listenerId); 213 | // Resume processing of queued messages. 214 | this.resume(); 215 | } 216 | 217 | /** 218 | * Refreshes the list of actions (e.g., added, changed, removed) that should be observed. 219 | * @param {string=} listenerId Optional listenerId to refresh only one listener's actions. 220 | * @private 221 | */ 222 | _refreshActionsList(listenerId) { 223 | if (listenerId) { 224 | // Update actions for the given listener. 225 | Object.keys(this.listeners[listenerId]).forEach((action) => { 226 | this.actions[action] = 1; 227 | }); 228 | } else { 229 | // Update actions for all listeners. 230 | const actions = {}; 231 | Object.values(this.listeners).forEach((callbacks) => { 232 | Object.keys(callbacks).forEach((action) => { 233 | actions[action] = 1; 234 | }); 235 | }); 236 | this.actions = actions; 237 | } 238 | } 239 | 240 | /** 241 | * Performs the initial fetch of documents from the collection. 242 | * Stores the documents in the observer's cache. 243 | */ 244 | async initialFetch() { 245 | if (this.initiallyFetched) { 246 | return; 247 | } 248 | 249 | if (!this.options.withoutMongo) { 250 | // Execute the Mongo query asynchronously. 251 | const cursor = this.collection.find(this.selector, this.findOptions); 252 | const docs = await cursor.fetchAsync(); 253 | // Store each document in the observer cache, applying docsMixin if provided. 254 | for (const doc of docs) { 255 | this.docs[doc._id] = this.options.docsMixin ? { ...doc, ...this.options.docsMixin } : doc; 256 | } 257 | } 258 | 259 | this.initiallyFetched = true; 260 | } 261 | 262 | /** 263 | * Sends initial "added" events to a newly added listener. 264 | * @param {string} listenerId The listener identifier. 265 | */ 266 | initialAdd(listenerId) { 267 | const callbacks = this.listeners[listenerId]; 268 | // For each cached document, call the "added" callback. 269 | Object.entries(this.docs).forEach(([id, doc]) => { 270 | if (doc && callbacks.added) { 271 | callbacks.added(id, this.projectionFn(doc)); 272 | } 273 | }); 274 | } 275 | 276 | /** 277 | * Calls all listeners for a particular action (added/changed/removed) for a document. 278 | * @param {string} action The type of action. 279 | * @param {string} id The document _id. 280 | * @param {Object=} fields The fields to send to the client. 281 | */ 282 | callListeners(action, id, fields) { 283 | Object.values(this.listeners).forEach((callbacks) => { 284 | if (callbacks && callbacks[action]) { 285 | callbacks[action](id, fields); 286 | } 287 | }); 288 | } 289 | 290 | /** 291 | * Removes a listener from the observer. 292 | * If no listeners remain, the observer stops observing. 293 | * @param {string} listenerId The listener identifier. 294 | */ 295 | removeListener(listenerId) { 296 | delete this.listeners[listenerId]; 297 | if (Object.keys(this.listeners).length === 0) { 298 | // Stop the observer if no listeners remain. 299 | this.kill(); 300 | this.actions = {}; 301 | } else { 302 | // Refresh the list of actions. 303 | this._refreshActionsList(); 304 | } 305 | } 306 | 307 | /** 308 | * Pauses the processing of incoming messages. 309 | */ 310 | pause() { 311 | this.paused = true; 312 | } 313 | 314 | /** 315 | * Resumes processing of messages. 316 | * Processes any messages that were queued while paused. 317 | */ 318 | resume() { 319 | // Process messages in the queue. 320 | while (this.messageQueue.length) { 321 | // Note: In this implementation, handleMessage is asynchronous, 322 | // but we do not await here because order is not critical. 323 | this.handleMessage(this.messageQueue.shift()); 324 | } 325 | this.paused = false; 326 | } 327 | 328 | /** 329 | * Stops the observer and unregisters it from the messenger. 330 | */ 331 | kill() { 332 | if (!this.initialized) return; 333 | this.initialized = false; 334 | if (!this.options.nonreactive) { 335 | messenger.removeObserver(this.key); 336 | } 337 | delete observers[this.key]; 338 | } 339 | 340 | /** 341 | * Handles an incoming message from the messenger. 342 | * If the observer is not ready, the message may be queued. 343 | * @param {Object} message The incoming message. 344 | */ 345 | onMessage(message) { 346 | if (!this.initiallyFetched) { 347 | return; 348 | } 349 | // Filter messages based on withoutMongo and withMongoOnly flags. 350 | if (message.withoutMongo && this.options.withMongoOnly) { 351 | return; 352 | } 353 | if (this.paused) { 354 | // Queue message if processing is paused. 355 | this.messageQueue.push(message); 356 | } else { 357 | this.handleMessage(message); 358 | } 359 | } 360 | 361 | /** 362 | * Processes an incoming message. 363 | * Applies changes to the cached documents and calls listeners accordingly. 364 | * @param {Object} message The message to process. 365 | */ 366 | async handleMessage(message) { 367 | // Helper to compute modified fields from a Mongo modifier. 368 | const computeModifiedFields = () => { 369 | if (!message.modifier || message._modifiedFields) { 370 | return; 371 | } 372 | message._modifiedFields = {}; 373 | 374 | // Iterate over each entry in the modifier object. 375 | // For example, message.modifier might look like: 376 | // { $set: { "user.name": "Alice", "user.email": "alice@example.com" }, $inc: { "score": 1 } } 377 | Object.entries(message.modifier).forEach(([op, params]) => { 378 | if (op.charAt(0) === '$') { 379 | // For each field path in the parameters object of the operator, extract the top-level field. 380 | // For example, for the path "user.name", topLevelPath will return "user". 381 | Object.keys(params).forEach((path) => { 382 | // Mark the top-level field as modified. 383 | message._modifiedFields[topLevelPath(path)] = true; 384 | }); 385 | } 386 | }); 387 | }; 388 | 389 | // Matching logic: check if document matches selector. 390 | if (this.matcher && message.doc) { 391 | if (!this.matcher.documentMatches(message.doc).result) { 392 | if (this.docs[message.id]) { 393 | // Document no longer matches; notify removal. 394 | this.callListeners('removed', message.id); 395 | this.docs[message.id] = null; 396 | if (!this.needToFetchAlways) { 397 | return; 398 | } 399 | } else { 400 | return; 401 | } 402 | } else if (this.docs[message.id] && !this.needToFetchAlways) { 403 | if (!this.actions.changed) { 404 | return; 405 | } 406 | if (this.projectionIncluding && message.modifier) { 407 | computeModifiedFields(); 408 | // Check if any relevant top-level field was modified. 409 | const relevantModifier = Object.keys(message._modifiedFields).some( 410 | (field) => this.projectionTopFields[field], 411 | ); 412 | if (!relevantModifier) { 413 | return; 414 | } 415 | } 416 | } 417 | } 418 | 419 | let fetchedRightIds; 420 | let ids = Array.isArray(message.id) ? message.id : [message.id]; 421 | 422 | if (this.needToFetchAlways) { 423 | const cursor = this.collection.find(this.selector, this.quickFindOptions); 424 | const docs = await cursor.fetchAsync(); 425 | fetchedRightIds = docs.map((doc) => doc._id); 426 | } 427 | 428 | if (message.withoutMongo && !ids) { 429 | try { 430 | const selectorKey = JSON.stringify(message.selector); 431 | let matcherForMessage; 432 | if (matcherCache.has(selectorKey)) { 433 | matcherForMessage = matcherCache.get(selectorKey); 434 | } else { 435 | matcherForMessage = new Minimongo.Matcher(message.selector); 436 | matcherCache.set(selectorKey, matcherForMessage); 437 | } 438 | ids = Object.values(this.docs) 439 | .filter((doc) => doc && matcherForMessage.documentMatches(doc).result) 440 | .map((doc) => doc._id); 441 | } catch (err) { 442 | console.error('[Observer.handleMessage] Error compiling matcher:', err); 443 | } 444 | } 445 | 446 | if (!ids || ids.length === 0) { 447 | return; 448 | } 449 | 450 | // Process each document id from the message. 451 | for (const id of ids) { 452 | const lastTs = this.lastTs[id]; 453 | const badTS = lastTs >= message.ts; 454 | const lastMethod = this.lastMethod[id]; 455 | 456 | // Update timestamp if message is newer. 457 | this.lastTs[id] = badTS ? lastTs : message.ts; 458 | 459 | // Skip message if out-of-order and not applicable. 460 | if ( 461 | badTS 462 | && lastMethod 463 | && ( 464 | (message.method !== 'remove' && lastMethod === 'remove') 465 | || (message.method === 'remove' && (lastMethod === 'insert' || lastMethod === 'upsert')) 466 | ) 467 | ) { 468 | continue; 469 | } 470 | 471 | this.lastMethod[id] = message.method; 472 | 473 | const oldDoc = this.docs[id]; 474 | const knownId = !!oldDoc; 475 | const isRightId = !fetchedRightIds || fetchedRightIds.includes(id); 476 | 477 | let newDoc = message.doc; 478 | 479 | if (!newDoc) { 480 | if (message.method === 'insert' && !badTS) { 481 | newDoc = { ...message.selector, _id: id }; 482 | } else if (message.withoutMongo && message.method !== 'remove') { 483 | try { 484 | if (oldDoc) { 485 | // Retrieve a cached matcher for message.selector. 486 | const selectorKey = JSON.stringify(message.selector); 487 | let matcherForMessage; 488 | if (matcherCache.has(selectorKey)) { 489 | matcherForMessage = matcherCache.get(selectorKey); 490 | } else { 491 | matcherForMessage = new Minimongo.Matcher(message.selector); 492 | matcherCache.set(selectorKey, matcherForMessage); 493 | } 494 | // If oldDoc does not match the selector, skip processing. 495 | if (!matcherForMessage.documentMatches(oldDoc).result) { 496 | continue; 497 | } 498 | } 499 | newDoc = { _id: id, ...oldDoc }; 500 | Minimongo.LocalCollection._modify(newDoc, message.modifier); 501 | } catch (err) { 502 | console.error('[Observer.handleMessage] Error modifying document:', err); 503 | } 504 | } 505 | } 506 | 507 | if ( 508 | !newDoc 509 | && oldDoc 510 | && (message.method === 'update' || message.method === 'upsert') 511 | && isRightId 512 | && !badTS 513 | ) { 514 | try { 515 | newDoc = EJSON.clone(oldDoc); 516 | Minimongo.LocalCollection._modify(newDoc, message.modifier); 517 | } catch (err) { 518 | console.error('[Observer.handleMessage] Error modifying document:', err); 519 | } 520 | } 521 | 522 | const needToFetch = !newDoc && isRightId && message.method !== 'remove'; 523 | if (needToFetch) { 524 | newDoc = await this.collection.findOneAsync({ ...this.selector, _id: id }, this.findOptions); 525 | } 526 | 527 | // Validate that the new document is acceptable. 528 | const docIsOk = newDoc && isRightId && ( 529 | message.withoutMongo 530 | || needToFetch 531 | || ( 532 | this.matcher 533 | ? (message.doc || this.matcher.documentMatches(newDoc).result) 534 | : await this.collection.find({ ...this.selector, _id: id }, this.quickFindOptions).countAsync() 535 | ) 536 | ); 537 | 538 | if (message.method !== 'remove' && docIsOk) { 539 | if (this.options.docsMixin) { 540 | // Compute modified fields and merge docsMixin into newDoc, 541 | // omitting any keys that have been modified. 542 | computeModifiedFields(); 543 | Object.assign( 544 | newDoc, 545 | omit(this.options.docsMixin, Object.keys(message._modifiedFields || {})), 546 | ); 547 | } 548 | 549 | let action; 550 | let fields; 551 | if (knownId) { 552 | action = 'changed'; 553 | fields = DiffSequence.makeChangedFields(newDoc, oldDoc); 554 | } else { 555 | action = 'added'; 556 | fields = newDoc; 557 | } 558 | 559 | const finalFields = this.projectionFn(fields); 560 | if (Object.keys(finalFields).length > 0) { 561 | this.callListeners(action, id, finalFields); 562 | } 563 | this.docs[id] = newDoc; 564 | } else if (knownId) { 565 | this.callListeners('removed', id); 566 | this.docs[id] = null; 567 | } 568 | 569 | if (fetchedRightIds) { 570 | // Remove documents that are no longer valid. 571 | for (const [docId, doc] of Object.entries(this.docs)) { 572 | if (doc && !fetchedRightIds.includes(docId)) { 573 | this.callListeners('removed', docId); 574 | this.docs[docId] = null; 575 | } 576 | } 577 | // Add documents that are newly fetched. 578 | for (const fetchId of fetchedRightIds) { 579 | if (!this.docs[fetchId]) { 580 | const doc = await this.collection.findOneAsync({ _id: fetchId }, this.findOptions); 581 | if (!doc) { 582 | if (this.docs[fetchId]) { 583 | this.callListeners('removed', fetchId); 584 | this.docs[fetchId] = null; 585 | } 586 | continue; 587 | } 588 | if (this.options.docsMixin) { 589 | Object.assign( 590 | doc, 591 | omit(this.options.docsMixin, Object.keys(message._modifiedFields || {})), 592 | ); 593 | } 594 | this.callListeners('added', fetchId, this.projectionFn(doc)); 595 | this.docs[fetchId] = doc; 596 | } 597 | } 598 | } 599 | } 600 | } 601 | } 602 | 603 | // Set the global messenger callback to route incoming messages 604 | // to all observers registered on the channel. 605 | messenger.onMessage = (channel, message) => { 606 | const observersInChannel = messenger.channels[channel]; 607 | if (observersInChannel) { 608 | Object.keys(observersInChannel).forEach((observerKey) => { 609 | const observer = observers[observerKey]; 610 | if (observer) { 611 | observer.onMessage(message); 612 | } 613 | }); 614 | } 615 | }; 616 | 617 | /** 618 | * Sets up an observation on a MongoDB collection. 619 | * @param {Mongo.Collection} collection The collection to observe. 620 | * @param {Object=} options Observation options (selector, fields, etc). 621 | * @param {Object} callbacks Callback functions for added, changed, removed events. 622 | * @return {Object} An object with a stop() method to end the observation and the current docs cache. 623 | */ 624 | async function observeChanges(collection, options = {}, callbacks = {}) { 625 | // Generate a unique listener id. 626 | const listenerId = Random.id(); 627 | const collectionName = collection._name; 628 | // Create a unique key for the observer based on collection and options. 629 | const observerKey = options.observerKey || JSON.stringify([collectionName, options]); 630 | 631 | let observer = observers[observerKey]; 632 | if (!observer) { 633 | // If no observer exists for this key, create one. 634 | observer = new Observer(collection, options, observerKey); 635 | observers[observerKey] = observer; 636 | } 637 | 638 | // Add the listener to the observer. 639 | await observer.addListener(listenerId, callbacks); 640 | 641 | return { 642 | stop() { 643 | observer.removeListener(listenerId); 644 | }, 645 | docs: observer.docs, // Expose the cached documents. 646 | }; 647 | } 648 | 649 | export { observeChanges }; 650 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redpubsub", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "redpubsub", 9 | "version": "1.0.0", 10 | "devDependencies": { 11 | "eslint": "^8.57.1", 12 | "eslint-config-airbnb-base": "^15.0.0" 13 | } 14 | }, 15 | "node_modules/@eslint-community/eslint-utils": { 16 | "version": "4.4.1", 17 | "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", 18 | "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", 19 | "dev": true, 20 | "license": "MIT", 21 | "dependencies": { 22 | "eslint-visitor-keys": "^3.4.3" 23 | }, 24 | "engines": { 25 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 26 | }, 27 | "funding": { 28 | "url": "https://opencollective.com/eslint" 29 | }, 30 | "peerDependencies": { 31 | "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" 32 | } 33 | }, 34 | "node_modules/@eslint-community/regexpp": { 35 | "version": "4.12.1", 36 | "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", 37 | "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", 38 | "dev": true, 39 | "license": "MIT", 40 | "engines": { 41 | "node": "^12.0.0 || ^14.0.0 || >=16.0.0" 42 | } 43 | }, 44 | "node_modules/@eslint/eslintrc": { 45 | "version": "2.1.4", 46 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", 47 | "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", 48 | "dev": true, 49 | "license": "MIT", 50 | "dependencies": { 51 | "ajv": "^6.12.4", 52 | "debug": "^4.3.2", 53 | "espree": "^9.6.0", 54 | "globals": "^13.19.0", 55 | "ignore": "^5.2.0", 56 | "import-fresh": "^3.2.1", 57 | "js-yaml": "^4.1.0", 58 | "minimatch": "^3.1.2", 59 | "strip-json-comments": "^3.1.1" 60 | }, 61 | "engines": { 62 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 63 | }, 64 | "funding": { 65 | "url": "https://opencollective.com/eslint" 66 | } 67 | }, 68 | "node_modules/@eslint/js": { 69 | "version": "8.57.1", 70 | "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", 71 | "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", 72 | "dev": true, 73 | "license": "MIT", 74 | "engines": { 75 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 76 | } 77 | }, 78 | "node_modules/@humanwhocodes/config-array": { 79 | "version": "0.13.0", 80 | "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", 81 | "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", 82 | "deprecated": "Use @eslint/config-array instead", 83 | "dev": true, 84 | "license": "Apache-2.0", 85 | "dependencies": { 86 | "@humanwhocodes/object-schema": "^2.0.3", 87 | "debug": "^4.3.1", 88 | "minimatch": "^3.0.5" 89 | }, 90 | "engines": { 91 | "node": ">=10.10.0" 92 | } 93 | }, 94 | "node_modules/@humanwhocodes/module-importer": { 95 | "version": "1.0.1", 96 | "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", 97 | "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", 98 | "dev": true, 99 | "license": "Apache-2.0", 100 | "engines": { 101 | "node": ">=12.22" 102 | }, 103 | "funding": { 104 | "type": "github", 105 | "url": "https://github.com/sponsors/nzakas" 106 | } 107 | }, 108 | "node_modules/@humanwhocodes/object-schema": { 109 | "version": "2.0.3", 110 | "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", 111 | "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", 112 | "deprecated": "Use @eslint/object-schema instead", 113 | "dev": true, 114 | "license": "BSD-3-Clause" 115 | }, 116 | "node_modules/@nodelib/fs.scandir": { 117 | "version": "2.1.5", 118 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 119 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 120 | "dev": true, 121 | "license": "MIT", 122 | "dependencies": { 123 | "@nodelib/fs.stat": "2.0.5", 124 | "run-parallel": "^1.1.9" 125 | }, 126 | "engines": { 127 | "node": ">= 8" 128 | } 129 | }, 130 | "node_modules/@nodelib/fs.stat": { 131 | "version": "2.0.5", 132 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 133 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 134 | "dev": true, 135 | "license": "MIT", 136 | "engines": { 137 | "node": ">= 8" 138 | } 139 | }, 140 | "node_modules/@nodelib/fs.walk": { 141 | "version": "1.2.8", 142 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 143 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 144 | "dev": true, 145 | "license": "MIT", 146 | "dependencies": { 147 | "@nodelib/fs.scandir": "2.1.5", 148 | "fastq": "^1.6.0" 149 | }, 150 | "engines": { 151 | "node": ">= 8" 152 | } 153 | }, 154 | "node_modules/@rtsao/scc": { 155 | "version": "1.1.0", 156 | "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", 157 | "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", 158 | "dev": true, 159 | "license": "MIT", 160 | "peer": true 161 | }, 162 | "node_modules/@types/json5": { 163 | "version": "0.0.29", 164 | "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", 165 | "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", 166 | "dev": true, 167 | "license": "MIT", 168 | "peer": true 169 | }, 170 | "node_modules/@ungap/structured-clone": { 171 | "version": "1.2.1", 172 | "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.1.tgz", 173 | "integrity": "sha512-fEzPV3hSkSMltkw152tJKNARhOupqbH96MZWyRjNaYZOMIzbrTeQDG+MTc6Mr2pgzFQzFxAfmhGDNP5QK++2ZA==", 174 | "dev": true, 175 | "license": "ISC" 176 | }, 177 | "node_modules/acorn": { 178 | "version": "8.14.0", 179 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", 180 | "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", 181 | "dev": true, 182 | "license": "MIT", 183 | "bin": { 184 | "acorn": "bin/acorn" 185 | }, 186 | "engines": { 187 | "node": ">=0.4.0" 188 | } 189 | }, 190 | "node_modules/acorn-jsx": { 191 | "version": "5.3.2", 192 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", 193 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 194 | "dev": true, 195 | "license": "MIT", 196 | "peerDependencies": { 197 | "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" 198 | } 199 | }, 200 | "node_modules/ajv": { 201 | "version": "6.12.6", 202 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 203 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 204 | "dev": true, 205 | "license": "MIT", 206 | "dependencies": { 207 | "fast-deep-equal": "^3.1.1", 208 | "fast-json-stable-stringify": "^2.0.0", 209 | "json-schema-traverse": "^0.4.1", 210 | "uri-js": "^4.2.2" 211 | }, 212 | "funding": { 213 | "type": "github", 214 | "url": "https://github.com/sponsors/epoberezkin" 215 | } 216 | }, 217 | "node_modules/ansi-regex": { 218 | "version": "5.0.1", 219 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 220 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 221 | "dev": true, 222 | "license": "MIT", 223 | "engines": { 224 | "node": ">=8" 225 | } 226 | }, 227 | "node_modules/ansi-styles": { 228 | "version": "4.3.0", 229 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 230 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 231 | "dev": true, 232 | "license": "MIT", 233 | "dependencies": { 234 | "color-convert": "^2.0.1" 235 | }, 236 | "engines": { 237 | "node": ">=8" 238 | }, 239 | "funding": { 240 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 241 | } 242 | }, 243 | "node_modules/argparse": { 244 | "version": "2.0.1", 245 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 246 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 247 | "dev": true, 248 | "license": "Python-2.0" 249 | }, 250 | "node_modules/array-buffer-byte-length": { 251 | "version": "1.0.2", 252 | "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", 253 | "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", 254 | "dev": true, 255 | "license": "MIT", 256 | "peer": true, 257 | "dependencies": { 258 | "call-bound": "^1.0.3", 259 | "is-array-buffer": "^3.0.5" 260 | }, 261 | "engines": { 262 | "node": ">= 0.4" 263 | }, 264 | "funding": { 265 | "url": "https://github.com/sponsors/ljharb" 266 | } 267 | }, 268 | "node_modules/array-includes": { 269 | "version": "3.1.8", 270 | "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", 271 | "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", 272 | "dev": true, 273 | "license": "MIT", 274 | "peer": true, 275 | "dependencies": { 276 | "call-bind": "^1.0.7", 277 | "define-properties": "^1.2.1", 278 | "es-abstract": "^1.23.2", 279 | "es-object-atoms": "^1.0.0", 280 | "get-intrinsic": "^1.2.4", 281 | "is-string": "^1.0.7" 282 | }, 283 | "engines": { 284 | "node": ">= 0.4" 285 | }, 286 | "funding": { 287 | "url": "https://github.com/sponsors/ljharb" 288 | } 289 | }, 290 | "node_modules/array.prototype.findlastindex": { 291 | "version": "1.2.5", 292 | "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", 293 | "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", 294 | "dev": true, 295 | "license": "MIT", 296 | "peer": true, 297 | "dependencies": { 298 | "call-bind": "^1.0.7", 299 | "define-properties": "^1.2.1", 300 | "es-abstract": "^1.23.2", 301 | "es-errors": "^1.3.0", 302 | "es-object-atoms": "^1.0.0", 303 | "es-shim-unscopables": "^1.0.2" 304 | }, 305 | "engines": { 306 | "node": ">= 0.4" 307 | }, 308 | "funding": { 309 | "url": "https://github.com/sponsors/ljharb" 310 | } 311 | }, 312 | "node_modules/array.prototype.flat": { 313 | "version": "1.3.3", 314 | "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", 315 | "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", 316 | "dev": true, 317 | "license": "MIT", 318 | "peer": true, 319 | "dependencies": { 320 | "call-bind": "^1.0.8", 321 | "define-properties": "^1.2.1", 322 | "es-abstract": "^1.23.5", 323 | "es-shim-unscopables": "^1.0.2" 324 | }, 325 | "engines": { 326 | "node": ">= 0.4" 327 | }, 328 | "funding": { 329 | "url": "https://github.com/sponsors/ljharb" 330 | } 331 | }, 332 | "node_modules/array.prototype.flatmap": { 333 | "version": "1.3.3", 334 | "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", 335 | "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", 336 | "dev": true, 337 | "license": "MIT", 338 | "peer": true, 339 | "dependencies": { 340 | "call-bind": "^1.0.8", 341 | "define-properties": "^1.2.1", 342 | "es-abstract": "^1.23.5", 343 | "es-shim-unscopables": "^1.0.2" 344 | }, 345 | "engines": { 346 | "node": ">= 0.4" 347 | }, 348 | "funding": { 349 | "url": "https://github.com/sponsors/ljharb" 350 | } 351 | }, 352 | "node_modules/arraybuffer.prototype.slice": { 353 | "version": "1.0.4", 354 | "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", 355 | "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", 356 | "dev": true, 357 | "license": "MIT", 358 | "peer": true, 359 | "dependencies": { 360 | "array-buffer-byte-length": "^1.0.1", 361 | "call-bind": "^1.0.8", 362 | "define-properties": "^1.2.1", 363 | "es-abstract": "^1.23.5", 364 | "es-errors": "^1.3.0", 365 | "get-intrinsic": "^1.2.6", 366 | "is-array-buffer": "^3.0.4" 367 | }, 368 | "engines": { 369 | "node": ">= 0.4" 370 | }, 371 | "funding": { 372 | "url": "https://github.com/sponsors/ljharb" 373 | } 374 | }, 375 | "node_modules/available-typed-arrays": { 376 | "version": "1.0.7", 377 | "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", 378 | "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", 379 | "dev": true, 380 | "license": "MIT", 381 | "peer": true, 382 | "dependencies": { 383 | "possible-typed-array-names": "^1.0.0" 384 | }, 385 | "engines": { 386 | "node": ">= 0.4" 387 | }, 388 | "funding": { 389 | "url": "https://github.com/sponsors/ljharb" 390 | } 391 | }, 392 | "node_modules/balanced-match": { 393 | "version": "1.0.2", 394 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 395 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 396 | "dev": true, 397 | "license": "MIT" 398 | }, 399 | "node_modules/brace-expansion": { 400 | "version": "1.1.11", 401 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 402 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 403 | "dev": true, 404 | "license": "MIT", 405 | "dependencies": { 406 | "balanced-match": "^1.0.0", 407 | "concat-map": "0.0.1" 408 | } 409 | }, 410 | "node_modules/call-bind": { 411 | "version": "1.0.8", 412 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", 413 | "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", 414 | "dev": true, 415 | "license": "MIT", 416 | "dependencies": { 417 | "call-bind-apply-helpers": "^1.0.0", 418 | "es-define-property": "^1.0.0", 419 | "get-intrinsic": "^1.2.4", 420 | "set-function-length": "^1.2.2" 421 | }, 422 | "engines": { 423 | "node": ">= 0.4" 424 | }, 425 | "funding": { 426 | "url": "https://github.com/sponsors/ljharb" 427 | } 428 | }, 429 | "node_modules/call-bind-apply-helpers": { 430 | "version": "1.0.1", 431 | "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", 432 | "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", 433 | "dev": true, 434 | "license": "MIT", 435 | "dependencies": { 436 | "es-errors": "^1.3.0", 437 | "function-bind": "^1.1.2" 438 | }, 439 | "engines": { 440 | "node": ">= 0.4" 441 | } 442 | }, 443 | "node_modules/call-bound": { 444 | "version": "1.0.3", 445 | "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", 446 | "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", 447 | "dev": true, 448 | "license": "MIT", 449 | "dependencies": { 450 | "call-bind-apply-helpers": "^1.0.1", 451 | "get-intrinsic": "^1.2.6" 452 | }, 453 | "engines": { 454 | "node": ">= 0.4" 455 | }, 456 | "funding": { 457 | "url": "https://github.com/sponsors/ljharb" 458 | } 459 | }, 460 | "node_modules/callsites": { 461 | "version": "3.1.0", 462 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 463 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 464 | "dev": true, 465 | "license": "MIT", 466 | "engines": { 467 | "node": ">=6" 468 | } 469 | }, 470 | "node_modules/chalk": { 471 | "version": "4.1.2", 472 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 473 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 474 | "dev": true, 475 | "license": "MIT", 476 | "dependencies": { 477 | "ansi-styles": "^4.1.0", 478 | "supports-color": "^7.1.0" 479 | }, 480 | "engines": { 481 | "node": ">=10" 482 | }, 483 | "funding": { 484 | "url": "https://github.com/chalk/chalk?sponsor=1" 485 | } 486 | }, 487 | "node_modules/color-convert": { 488 | "version": "2.0.1", 489 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 490 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 491 | "dev": true, 492 | "license": "MIT", 493 | "dependencies": { 494 | "color-name": "~1.1.4" 495 | }, 496 | "engines": { 497 | "node": ">=7.0.0" 498 | } 499 | }, 500 | "node_modules/color-name": { 501 | "version": "1.1.4", 502 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 503 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 504 | "dev": true, 505 | "license": "MIT" 506 | }, 507 | "node_modules/concat-map": { 508 | "version": "0.0.1", 509 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 510 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 511 | "dev": true, 512 | "license": "MIT" 513 | }, 514 | "node_modules/confusing-browser-globals": { 515 | "version": "1.0.11", 516 | "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", 517 | "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", 518 | "dev": true, 519 | "license": "MIT" 520 | }, 521 | "node_modules/cross-spawn": { 522 | "version": "7.0.6", 523 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", 524 | "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", 525 | "dev": true, 526 | "license": "MIT", 527 | "dependencies": { 528 | "path-key": "^3.1.0", 529 | "shebang-command": "^2.0.0", 530 | "which": "^2.0.1" 531 | }, 532 | "engines": { 533 | "node": ">= 8" 534 | } 535 | }, 536 | "node_modules/data-view-buffer": { 537 | "version": "1.0.2", 538 | "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", 539 | "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", 540 | "dev": true, 541 | "license": "MIT", 542 | "peer": true, 543 | "dependencies": { 544 | "call-bound": "^1.0.3", 545 | "es-errors": "^1.3.0", 546 | "is-data-view": "^1.0.2" 547 | }, 548 | "engines": { 549 | "node": ">= 0.4" 550 | }, 551 | "funding": { 552 | "url": "https://github.com/sponsors/ljharb" 553 | } 554 | }, 555 | "node_modules/data-view-byte-length": { 556 | "version": "1.0.2", 557 | "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", 558 | "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", 559 | "dev": true, 560 | "license": "MIT", 561 | "peer": true, 562 | "dependencies": { 563 | "call-bound": "^1.0.3", 564 | "es-errors": "^1.3.0", 565 | "is-data-view": "^1.0.2" 566 | }, 567 | "engines": { 568 | "node": ">= 0.4" 569 | }, 570 | "funding": { 571 | "url": "https://github.com/sponsors/inspect-js" 572 | } 573 | }, 574 | "node_modules/data-view-byte-offset": { 575 | "version": "1.0.1", 576 | "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", 577 | "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", 578 | "dev": true, 579 | "license": "MIT", 580 | "peer": true, 581 | "dependencies": { 582 | "call-bound": "^1.0.2", 583 | "es-errors": "^1.3.0", 584 | "is-data-view": "^1.0.1" 585 | }, 586 | "engines": { 587 | "node": ">= 0.4" 588 | }, 589 | "funding": { 590 | "url": "https://github.com/sponsors/ljharb" 591 | } 592 | }, 593 | "node_modules/debug": { 594 | "version": "4.4.0", 595 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 596 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 597 | "dev": true, 598 | "license": "MIT", 599 | "dependencies": { 600 | "ms": "^2.1.3" 601 | }, 602 | "engines": { 603 | "node": ">=6.0" 604 | }, 605 | "peerDependenciesMeta": { 606 | "supports-color": { 607 | "optional": true 608 | } 609 | } 610 | }, 611 | "node_modules/deep-is": { 612 | "version": "0.1.4", 613 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", 614 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", 615 | "dev": true, 616 | "license": "MIT" 617 | }, 618 | "node_modules/define-data-property": { 619 | "version": "1.1.4", 620 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", 621 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", 622 | "dev": true, 623 | "license": "MIT", 624 | "dependencies": { 625 | "es-define-property": "^1.0.0", 626 | "es-errors": "^1.3.0", 627 | "gopd": "^1.0.1" 628 | }, 629 | "engines": { 630 | "node": ">= 0.4" 631 | }, 632 | "funding": { 633 | "url": "https://github.com/sponsors/ljharb" 634 | } 635 | }, 636 | "node_modules/define-properties": { 637 | "version": "1.2.1", 638 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", 639 | "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", 640 | "dev": true, 641 | "license": "MIT", 642 | "dependencies": { 643 | "define-data-property": "^1.0.1", 644 | "has-property-descriptors": "^1.0.0", 645 | "object-keys": "^1.1.1" 646 | }, 647 | "engines": { 648 | "node": ">= 0.4" 649 | }, 650 | "funding": { 651 | "url": "https://github.com/sponsors/ljharb" 652 | } 653 | }, 654 | "node_modules/doctrine": { 655 | "version": "3.0.0", 656 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 657 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 658 | "dev": true, 659 | "license": "Apache-2.0", 660 | "dependencies": { 661 | "esutils": "^2.0.2" 662 | }, 663 | "engines": { 664 | "node": ">=6.0.0" 665 | } 666 | }, 667 | "node_modules/dunder-proto": { 668 | "version": "1.0.1", 669 | "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", 670 | "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", 671 | "dev": true, 672 | "license": "MIT", 673 | "dependencies": { 674 | "call-bind-apply-helpers": "^1.0.1", 675 | "es-errors": "^1.3.0", 676 | "gopd": "^1.2.0" 677 | }, 678 | "engines": { 679 | "node": ">= 0.4" 680 | } 681 | }, 682 | "node_modules/es-abstract": { 683 | "version": "1.23.9", 684 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", 685 | "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", 686 | "dev": true, 687 | "license": "MIT", 688 | "peer": true, 689 | "dependencies": { 690 | "array-buffer-byte-length": "^1.0.2", 691 | "arraybuffer.prototype.slice": "^1.0.4", 692 | "available-typed-arrays": "^1.0.7", 693 | "call-bind": "^1.0.8", 694 | "call-bound": "^1.0.3", 695 | "data-view-buffer": "^1.0.2", 696 | "data-view-byte-length": "^1.0.2", 697 | "data-view-byte-offset": "^1.0.1", 698 | "es-define-property": "^1.0.1", 699 | "es-errors": "^1.3.0", 700 | "es-object-atoms": "^1.0.0", 701 | "es-set-tostringtag": "^2.1.0", 702 | "es-to-primitive": "^1.3.0", 703 | "function.prototype.name": "^1.1.8", 704 | "get-intrinsic": "^1.2.7", 705 | "get-proto": "^1.0.0", 706 | "get-symbol-description": "^1.1.0", 707 | "globalthis": "^1.0.4", 708 | "gopd": "^1.2.0", 709 | "has-property-descriptors": "^1.0.2", 710 | "has-proto": "^1.2.0", 711 | "has-symbols": "^1.1.0", 712 | "hasown": "^2.0.2", 713 | "internal-slot": "^1.1.0", 714 | "is-array-buffer": "^3.0.5", 715 | "is-callable": "^1.2.7", 716 | "is-data-view": "^1.0.2", 717 | "is-regex": "^1.2.1", 718 | "is-shared-array-buffer": "^1.0.4", 719 | "is-string": "^1.1.1", 720 | "is-typed-array": "^1.1.15", 721 | "is-weakref": "^1.1.0", 722 | "math-intrinsics": "^1.1.0", 723 | "object-inspect": "^1.13.3", 724 | "object-keys": "^1.1.1", 725 | "object.assign": "^4.1.7", 726 | "own-keys": "^1.0.1", 727 | "regexp.prototype.flags": "^1.5.3", 728 | "safe-array-concat": "^1.1.3", 729 | "safe-push-apply": "^1.0.0", 730 | "safe-regex-test": "^1.1.0", 731 | "set-proto": "^1.0.0", 732 | "string.prototype.trim": "^1.2.10", 733 | "string.prototype.trimend": "^1.0.9", 734 | "string.prototype.trimstart": "^1.0.8", 735 | "typed-array-buffer": "^1.0.3", 736 | "typed-array-byte-length": "^1.0.3", 737 | "typed-array-byte-offset": "^1.0.4", 738 | "typed-array-length": "^1.0.7", 739 | "unbox-primitive": "^1.1.0", 740 | "which-typed-array": "^1.1.18" 741 | }, 742 | "engines": { 743 | "node": ">= 0.4" 744 | }, 745 | "funding": { 746 | "url": "https://github.com/sponsors/ljharb" 747 | } 748 | }, 749 | "node_modules/es-define-property": { 750 | "version": "1.0.1", 751 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", 752 | "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", 753 | "dev": true, 754 | "license": "MIT", 755 | "engines": { 756 | "node": ">= 0.4" 757 | } 758 | }, 759 | "node_modules/es-errors": { 760 | "version": "1.3.0", 761 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 762 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 763 | "dev": true, 764 | "license": "MIT", 765 | "engines": { 766 | "node": ">= 0.4" 767 | } 768 | }, 769 | "node_modules/es-object-atoms": { 770 | "version": "1.1.0", 771 | "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.0.tgz", 772 | "integrity": "sha512-Ujz8Al/KfOVR7fkaghAB1WvnLsdYxHDWmfoi2vlA2jZWRg31XhIC1a4B+/I24muD8iSbHxJ1JkrfqmWb65P/Mw==", 773 | "dev": true, 774 | "license": "MIT", 775 | "dependencies": { 776 | "es-errors": "^1.3.0" 777 | }, 778 | "engines": { 779 | "node": ">= 0.4" 780 | } 781 | }, 782 | "node_modules/es-set-tostringtag": { 783 | "version": "2.1.0", 784 | "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", 785 | "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", 786 | "dev": true, 787 | "license": "MIT", 788 | "peer": true, 789 | "dependencies": { 790 | "es-errors": "^1.3.0", 791 | "get-intrinsic": "^1.2.6", 792 | "has-tostringtag": "^1.0.2", 793 | "hasown": "^2.0.2" 794 | }, 795 | "engines": { 796 | "node": ">= 0.4" 797 | } 798 | }, 799 | "node_modules/es-shim-unscopables": { 800 | "version": "1.0.2", 801 | "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", 802 | "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", 803 | "dev": true, 804 | "license": "MIT", 805 | "peer": true, 806 | "dependencies": { 807 | "hasown": "^2.0.0" 808 | } 809 | }, 810 | "node_modules/es-to-primitive": { 811 | "version": "1.3.0", 812 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", 813 | "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", 814 | "dev": true, 815 | "license": "MIT", 816 | "peer": true, 817 | "dependencies": { 818 | "is-callable": "^1.2.7", 819 | "is-date-object": "^1.0.5", 820 | "is-symbol": "^1.0.4" 821 | }, 822 | "engines": { 823 | "node": ">= 0.4" 824 | }, 825 | "funding": { 826 | "url": "https://github.com/sponsors/ljharb" 827 | } 828 | }, 829 | "node_modules/escape-string-regexp": { 830 | "version": "4.0.0", 831 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 832 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 833 | "dev": true, 834 | "license": "MIT", 835 | "engines": { 836 | "node": ">=10" 837 | }, 838 | "funding": { 839 | "url": "https://github.com/sponsors/sindresorhus" 840 | } 841 | }, 842 | "node_modules/eslint": { 843 | "version": "8.57.1", 844 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", 845 | "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", 846 | "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", 847 | "dev": true, 848 | "license": "MIT", 849 | "dependencies": { 850 | "@eslint-community/eslint-utils": "^4.2.0", 851 | "@eslint-community/regexpp": "^4.6.1", 852 | "@eslint/eslintrc": "^2.1.4", 853 | "@eslint/js": "8.57.1", 854 | "@humanwhocodes/config-array": "^0.13.0", 855 | "@humanwhocodes/module-importer": "^1.0.1", 856 | "@nodelib/fs.walk": "^1.2.8", 857 | "@ungap/structured-clone": "^1.2.0", 858 | "ajv": "^6.12.4", 859 | "chalk": "^4.0.0", 860 | "cross-spawn": "^7.0.2", 861 | "debug": "^4.3.2", 862 | "doctrine": "^3.0.0", 863 | "escape-string-regexp": "^4.0.0", 864 | "eslint-scope": "^7.2.2", 865 | "eslint-visitor-keys": "^3.4.3", 866 | "espree": "^9.6.1", 867 | "esquery": "^1.4.2", 868 | "esutils": "^2.0.2", 869 | "fast-deep-equal": "^3.1.3", 870 | "file-entry-cache": "^6.0.1", 871 | "find-up": "^5.0.0", 872 | "glob-parent": "^6.0.2", 873 | "globals": "^13.19.0", 874 | "graphemer": "^1.4.0", 875 | "ignore": "^5.2.0", 876 | "imurmurhash": "^0.1.4", 877 | "is-glob": "^4.0.0", 878 | "is-path-inside": "^3.0.3", 879 | "js-yaml": "^4.1.0", 880 | "json-stable-stringify-without-jsonify": "^1.0.1", 881 | "levn": "^0.4.1", 882 | "lodash.merge": "^4.6.2", 883 | "minimatch": "^3.1.2", 884 | "natural-compare": "^1.4.0", 885 | "optionator": "^0.9.3", 886 | "strip-ansi": "^6.0.1", 887 | "text-table": "^0.2.0" 888 | }, 889 | "bin": { 890 | "eslint": "bin/eslint.js" 891 | }, 892 | "engines": { 893 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 894 | }, 895 | "funding": { 896 | "url": "https://opencollective.com/eslint" 897 | } 898 | }, 899 | "node_modules/eslint-config-airbnb-base": { 900 | "version": "15.0.0", 901 | "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", 902 | "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", 903 | "dev": true, 904 | "license": "MIT", 905 | "dependencies": { 906 | "confusing-browser-globals": "^1.0.10", 907 | "object.assign": "^4.1.2", 908 | "object.entries": "^1.1.5", 909 | "semver": "^6.3.0" 910 | }, 911 | "engines": { 912 | "node": "^10.12.0 || >=12.0.0" 913 | }, 914 | "peerDependencies": { 915 | "eslint": "^7.32.0 || ^8.2.0", 916 | "eslint-plugin-import": "^2.25.2" 917 | } 918 | }, 919 | "node_modules/eslint-import-resolver-node": { 920 | "version": "0.3.9", 921 | "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", 922 | "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", 923 | "dev": true, 924 | "license": "MIT", 925 | "peer": true, 926 | "dependencies": { 927 | "debug": "^3.2.7", 928 | "is-core-module": "^2.13.0", 929 | "resolve": "^1.22.4" 930 | } 931 | }, 932 | "node_modules/eslint-import-resolver-node/node_modules/debug": { 933 | "version": "3.2.7", 934 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 935 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 936 | "dev": true, 937 | "license": "MIT", 938 | "peer": true, 939 | "dependencies": { 940 | "ms": "^2.1.1" 941 | } 942 | }, 943 | "node_modules/eslint-module-utils": { 944 | "version": "2.12.0", 945 | "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", 946 | "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", 947 | "dev": true, 948 | "license": "MIT", 949 | "peer": true, 950 | "dependencies": { 951 | "debug": "^3.2.7" 952 | }, 953 | "engines": { 954 | "node": ">=4" 955 | }, 956 | "peerDependenciesMeta": { 957 | "eslint": { 958 | "optional": true 959 | } 960 | } 961 | }, 962 | "node_modules/eslint-module-utils/node_modules/debug": { 963 | "version": "3.2.7", 964 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 965 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 966 | "dev": true, 967 | "license": "MIT", 968 | "peer": true, 969 | "dependencies": { 970 | "ms": "^2.1.1" 971 | } 972 | }, 973 | "node_modules/eslint-plugin-import": { 974 | "version": "2.31.0", 975 | "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", 976 | "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", 977 | "dev": true, 978 | "license": "MIT", 979 | "peer": true, 980 | "dependencies": { 981 | "@rtsao/scc": "^1.1.0", 982 | "array-includes": "^3.1.8", 983 | "array.prototype.findlastindex": "^1.2.5", 984 | "array.prototype.flat": "^1.3.2", 985 | "array.prototype.flatmap": "^1.3.2", 986 | "debug": "^3.2.7", 987 | "doctrine": "^2.1.0", 988 | "eslint-import-resolver-node": "^0.3.9", 989 | "eslint-module-utils": "^2.12.0", 990 | "hasown": "^2.0.2", 991 | "is-core-module": "^2.15.1", 992 | "is-glob": "^4.0.3", 993 | "minimatch": "^3.1.2", 994 | "object.fromentries": "^2.0.8", 995 | "object.groupby": "^1.0.3", 996 | "object.values": "^1.2.0", 997 | "semver": "^6.3.1", 998 | "string.prototype.trimend": "^1.0.8", 999 | "tsconfig-paths": "^3.15.0" 1000 | }, 1001 | "engines": { 1002 | "node": ">=4" 1003 | }, 1004 | "peerDependencies": { 1005 | "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" 1006 | } 1007 | }, 1008 | "node_modules/eslint-plugin-import/node_modules/debug": { 1009 | "version": "3.2.7", 1010 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 1011 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 1012 | "dev": true, 1013 | "license": "MIT", 1014 | "peer": true, 1015 | "dependencies": { 1016 | "ms": "^2.1.1" 1017 | } 1018 | }, 1019 | "node_modules/eslint-plugin-import/node_modules/doctrine": { 1020 | "version": "2.1.0", 1021 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", 1022 | "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", 1023 | "dev": true, 1024 | "license": "Apache-2.0", 1025 | "peer": true, 1026 | "dependencies": { 1027 | "esutils": "^2.0.2" 1028 | }, 1029 | "engines": { 1030 | "node": ">=0.10.0" 1031 | } 1032 | }, 1033 | "node_modules/eslint-scope": { 1034 | "version": "7.2.2", 1035 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", 1036 | "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", 1037 | "dev": true, 1038 | "license": "BSD-2-Clause", 1039 | "dependencies": { 1040 | "esrecurse": "^4.3.0", 1041 | "estraverse": "^5.2.0" 1042 | }, 1043 | "engines": { 1044 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 1045 | }, 1046 | "funding": { 1047 | "url": "https://opencollective.com/eslint" 1048 | } 1049 | }, 1050 | "node_modules/eslint-visitor-keys": { 1051 | "version": "3.4.3", 1052 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", 1053 | "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", 1054 | "dev": true, 1055 | "license": "Apache-2.0", 1056 | "engines": { 1057 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 1058 | }, 1059 | "funding": { 1060 | "url": "https://opencollective.com/eslint" 1061 | } 1062 | }, 1063 | "node_modules/espree": { 1064 | "version": "9.6.1", 1065 | "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", 1066 | "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", 1067 | "dev": true, 1068 | "license": "BSD-2-Clause", 1069 | "dependencies": { 1070 | "acorn": "^8.9.0", 1071 | "acorn-jsx": "^5.3.2", 1072 | "eslint-visitor-keys": "^3.4.1" 1073 | }, 1074 | "engines": { 1075 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 1076 | }, 1077 | "funding": { 1078 | "url": "https://opencollective.com/eslint" 1079 | } 1080 | }, 1081 | "node_modules/esquery": { 1082 | "version": "1.6.0", 1083 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", 1084 | "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", 1085 | "dev": true, 1086 | "license": "BSD-3-Clause", 1087 | "dependencies": { 1088 | "estraverse": "^5.1.0" 1089 | }, 1090 | "engines": { 1091 | "node": ">=0.10" 1092 | } 1093 | }, 1094 | "node_modules/esrecurse": { 1095 | "version": "4.3.0", 1096 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 1097 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 1098 | "dev": true, 1099 | "license": "BSD-2-Clause", 1100 | "dependencies": { 1101 | "estraverse": "^5.2.0" 1102 | }, 1103 | "engines": { 1104 | "node": ">=4.0" 1105 | } 1106 | }, 1107 | "node_modules/estraverse": { 1108 | "version": "5.3.0", 1109 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 1110 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 1111 | "dev": true, 1112 | "license": "BSD-2-Clause", 1113 | "engines": { 1114 | "node": ">=4.0" 1115 | } 1116 | }, 1117 | "node_modules/esutils": { 1118 | "version": "2.0.3", 1119 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 1120 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 1121 | "dev": true, 1122 | "license": "BSD-2-Clause", 1123 | "engines": { 1124 | "node": ">=0.10.0" 1125 | } 1126 | }, 1127 | "node_modules/fast-deep-equal": { 1128 | "version": "3.1.3", 1129 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 1130 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 1131 | "dev": true, 1132 | "license": "MIT" 1133 | }, 1134 | "node_modules/fast-json-stable-stringify": { 1135 | "version": "2.1.0", 1136 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 1137 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 1138 | "dev": true, 1139 | "license": "MIT" 1140 | }, 1141 | "node_modules/fast-levenshtein": { 1142 | "version": "2.0.6", 1143 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 1144 | "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", 1145 | "dev": true, 1146 | "license": "MIT" 1147 | }, 1148 | "node_modules/fastq": { 1149 | "version": "1.18.0", 1150 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", 1151 | "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", 1152 | "dev": true, 1153 | "license": "ISC", 1154 | "dependencies": { 1155 | "reusify": "^1.0.4" 1156 | } 1157 | }, 1158 | "node_modules/file-entry-cache": { 1159 | "version": "6.0.1", 1160 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", 1161 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", 1162 | "dev": true, 1163 | "license": "MIT", 1164 | "dependencies": { 1165 | "flat-cache": "^3.0.4" 1166 | }, 1167 | "engines": { 1168 | "node": "^10.12.0 || >=12.0.0" 1169 | } 1170 | }, 1171 | "node_modules/find-up": { 1172 | "version": "5.0.0", 1173 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 1174 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 1175 | "dev": true, 1176 | "license": "MIT", 1177 | "dependencies": { 1178 | "locate-path": "^6.0.0", 1179 | "path-exists": "^4.0.0" 1180 | }, 1181 | "engines": { 1182 | "node": ">=10" 1183 | }, 1184 | "funding": { 1185 | "url": "https://github.com/sponsors/sindresorhus" 1186 | } 1187 | }, 1188 | "node_modules/flat-cache": { 1189 | "version": "3.2.0", 1190 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", 1191 | "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", 1192 | "dev": true, 1193 | "license": "MIT", 1194 | "dependencies": { 1195 | "flatted": "^3.2.9", 1196 | "keyv": "^4.5.3", 1197 | "rimraf": "^3.0.2" 1198 | }, 1199 | "engines": { 1200 | "node": "^10.12.0 || >=12.0.0" 1201 | } 1202 | }, 1203 | "node_modules/flatted": { 1204 | "version": "3.3.2", 1205 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", 1206 | "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", 1207 | "dev": true, 1208 | "license": "ISC" 1209 | }, 1210 | "node_modules/for-each": { 1211 | "version": "0.3.3", 1212 | "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", 1213 | "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", 1214 | "dev": true, 1215 | "license": "MIT", 1216 | "peer": true, 1217 | "dependencies": { 1218 | "is-callable": "^1.1.3" 1219 | } 1220 | }, 1221 | "node_modules/fs.realpath": { 1222 | "version": "1.0.0", 1223 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1224 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", 1225 | "dev": true, 1226 | "license": "ISC" 1227 | }, 1228 | "node_modules/function-bind": { 1229 | "version": "1.1.2", 1230 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 1231 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 1232 | "dev": true, 1233 | "license": "MIT", 1234 | "funding": { 1235 | "url": "https://github.com/sponsors/ljharb" 1236 | } 1237 | }, 1238 | "node_modules/function.prototype.name": { 1239 | "version": "1.1.8", 1240 | "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", 1241 | "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", 1242 | "dev": true, 1243 | "license": "MIT", 1244 | "peer": true, 1245 | "dependencies": { 1246 | "call-bind": "^1.0.8", 1247 | "call-bound": "^1.0.3", 1248 | "define-properties": "^1.2.1", 1249 | "functions-have-names": "^1.2.3", 1250 | "hasown": "^2.0.2", 1251 | "is-callable": "^1.2.7" 1252 | }, 1253 | "engines": { 1254 | "node": ">= 0.4" 1255 | }, 1256 | "funding": { 1257 | "url": "https://github.com/sponsors/ljharb" 1258 | } 1259 | }, 1260 | "node_modules/functions-have-names": { 1261 | "version": "1.2.3", 1262 | "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", 1263 | "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", 1264 | "dev": true, 1265 | "license": "MIT", 1266 | "peer": true, 1267 | "funding": { 1268 | "url": "https://github.com/sponsors/ljharb" 1269 | } 1270 | }, 1271 | "node_modules/get-intrinsic": { 1272 | "version": "1.2.7", 1273 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", 1274 | "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", 1275 | "dev": true, 1276 | "license": "MIT", 1277 | "dependencies": { 1278 | "call-bind-apply-helpers": "^1.0.1", 1279 | "es-define-property": "^1.0.1", 1280 | "es-errors": "^1.3.0", 1281 | "es-object-atoms": "^1.0.0", 1282 | "function-bind": "^1.1.2", 1283 | "get-proto": "^1.0.0", 1284 | "gopd": "^1.2.0", 1285 | "has-symbols": "^1.1.0", 1286 | "hasown": "^2.0.2", 1287 | "math-intrinsics": "^1.1.0" 1288 | }, 1289 | "engines": { 1290 | "node": ">= 0.4" 1291 | }, 1292 | "funding": { 1293 | "url": "https://github.com/sponsors/ljharb" 1294 | } 1295 | }, 1296 | "node_modules/get-proto": { 1297 | "version": "1.0.1", 1298 | "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", 1299 | "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", 1300 | "dev": true, 1301 | "license": "MIT", 1302 | "dependencies": { 1303 | "dunder-proto": "^1.0.1", 1304 | "es-object-atoms": "^1.0.0" 1305 | }, 1306 | "engines": { 1307 | "node": ">= 0.4" 1308 | } 1309 | }, 1310 | "node_modules/get-symbol-description": { 1311 | "version": "1.1.0", 1312 | "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", 1313 | "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", 1314 | "dev": true, 1315 | "license": "MIT", 1316 | "peer": true, 1317 | "dependencies": { 1318 | "call-bound": "^1.0.3", 1319 | "es-errors": "^1.3.0", 1320 | "get-intrinsic": "^1.2.6" 1321 | }, 1322 | "engines": { 1323 | "node": ">= 0.4" 1324 | }, 1325 | "funding": { 1326 | "url": "https://github.com/sponsors/ljharb" 1327 | } 1328 | }, 1329 | "node_modules/glob": { 1330 | "version": "7.2.3", 1331 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", 1332 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", 1333 | "deprecated": "Glob versions prior to v9 are no longer supported", 1334 | "dev": true, 1335 | "license": "ISC", 1336 | "dependencies": { 1337 | "fs.realpath": "^1.0.0", 1338 | "inflight": "^1.0.4", 1339 | "inherits": "2", 1340 | "minimatch": "^3.1.1", 1341 | "once": "^1.3.0", 1342 | "path-is-absolute": "^1.0.0" 1343 | }, 1344 | "engines": { 1345 | "node": "*" 1346 | }, 1347 | "funding": { 1348 | "url": "https://github.com/sponsors/isaacs" 1349 | } 1350 | }, 1351 | "node_modules/glob-parent": { 1352 | "version": "6.0.2", 1353 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", 1354 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", 1355 | "dev": true, 1356 | "license": "ISC", 1357 | "dependencies": { 1358 | "is-glob": "^4.0.3" 1359 | }, 1360 | "engines": { 1361 | "node": ">=10.13.0" 1362 | } 1363 | }, 1364 | "node_modules/globals": { 1365 | "version": "13.24.0", 1366 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", 1367 | "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", 1368 | "dev": true, 1369 | "license": "MIT", 1370 | "dependencies": { 1371 | "type-fest": "^0.20.2" 1372 | }, 1373 | "engines": { 1374 | "node": ">=8" 1375 | }, 1376 | "funding": { 1377 | "url": "https://github.com/sponsors/sindresorhus" 1378 | } 1379 | }, 1380 | "node_modules/globalthis": { 1381 | "version": "1.0.4", 1382 | "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", 1383 | "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", 1384 | "dev": true, 1385 | "license": "MIT", 1386 | "peer": true, 1387 | "dependencies": { 1388 | "define-properties": "^1.2.1", 1389 | "gopd": "^1.0.1" 1390 | }, 1391 | "engines": { 1392 | "node": ">= 0.4" 1393 | }, 1394 | "funding": { 1395 | "url": "https://github.com/sponsors/ljharb" 1396 | } 1397 | }, 1398 | "node_modules/gopd": { 1399 | "version": "1.2.0", 1400 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", 1401 | "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", 1402 | "dev": true, 1403 | "license": "MIT", 1404 | "engines": { 1405 | "node": ">= 0.4" 1406 | }, 1407 | "funding": { 1408 | "url": "https://github.com/sponsors/ljharb" 1409 | } 1410 | }, 1411 | "node_modules/graphemer": { 1412 | "version": "1.4.0", 1413 | "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", 1414 | "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", 1415 | "dev": true, 1416 | "license": "MIT" 1417 | }, 1418 | "node_modules/has-bigints": { 1419 | "version": "1.1.0", 1420 | "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", 1421 | "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", 1422 | "dev": true, 1423 | "license": "MIT", 1424 | "peer": true, 1425 | "engines": { 1426 | "node": ">= 0.4" 1427 | }, 1428 | "funding": { 1429 | "url": "https://github.com/sponsors/ljharb" 1430 | } 1431 | }, 1432 | "node_modules/has-flag": { 1433 | "version": "4.0.0", 1434 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1435 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1436 | "dev": true, 1437 | "license": "MIT", 1438 | "engines": { 1439 | "node": ">=8" 1440 | } 1441 | }, 1442 | "node_modules/has-property-descriptors": { 1443 | "version": "1.0.2", 1444 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", 1445 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", 1446 | "dev": true, 1447 | "license": "MIT", 1448 | "dependencies": { 1449 | "es-define-property": "^1.0.0" 1450 | }, 1451 | "funding": { 1452 | "url": "https://github.com/sponsors/ljharb" 1453 | } 1454 | }, 1455 | "node_modules/has-proto": { 1456 | "version": "1.2.0", 1457 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", 1458 | "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", 1459 | "dev": true, 1460 | "license": "MIT", 1461 | "peer": true, 1462 | "dependencies": { 1463 | "dunder-proto": "^1.0.0" 1464 | }, 1465 | "engines": { 1466 | "node": ">= 0.4" 1467 | }, 1468 | "funding": { 1469 | "url": "https://github.com/sponsors/ljharb" 1470 | } 1471 | }, 1472 | "node_modules/has-symbols": { 1473 | "version": "1.1.0", 1474 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", 1475 | "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", 1476 | "dev": true, 1477 | "license": "MIT", 1478 | "engines": { 1479 | "node": ">= 0.4" 1480 | }, 1481 | "funding": { 1482 | "url": "https://github.com/sponsors/ljharb" 1483 | } 1484 | }, 1485 | "node_modules/has-tostringtag": { 1486 | "version": "1.0.2", 1487 | "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", 1488 | "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", 1489 | "dev": true, 1490 | "license": "MIT", 1491 | "peer": true, 1492 | "dependencies": { 1493 | "has-symbols": "^1.0.3" 1494 | }, 1495 | "engines": { 1496 | "node": ">= 0.4" 1497 | }, 1498 | "funding": { 1499 | "url": "https://github.com/sponsors/ljharb" 1500 | } 1501 | }, 1502 | "node_modules/hasown": { 1503 | "version": "2.0.2", 1504 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 1505 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 1506 | "dev": true, 1507 | "license": "MIT", 1508 | "dependencies": { 1509 | "function-bind": "^1.1.2" 1510 | }, 1511 | "engines": { 1512 | "node": ">= 0.4" 1513 | } 1514 | }, 1515 | "node_modules/ignore": { 1516 | "version": "5.3.2", 1517 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", 1518 | "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", 1519 | "dev": true, 1520 | "license": "MIT", 1521 | "engines": { 1522 | "node": ">= 4" 1523 | } 1524 | }, 1525 | "node_modules/import-fresh": { 1526 | "version": "3.3.0", 1527 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 1528 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 1529 | "dev": true, 1530 | "license": "MIT", 1531 | "dependencies": { 1532 | "parent-module": "^1.0.0", 1533 | "resolve-from": "^4.0.0" 1534 | }, 1535 | "engines": { 1536 | "node": ">=6" 1537 | }, 1538 | "funding": { 1539 | "url": "https://github.com/sponsors/sindresorhus" 1540 | } 1541 | }, 1542 | "node_modules/imurmurhash": { 1543 | "version": "0.1.4", 1544 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 1545 | "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", 1546 | "dev": true, 1547 | "license": "MIT", 1548 | "engines": { 1549 | "node": ">=0.8.19" 1550 | } 1551 | }, 1552 | "node_modules/inflight": { 1553 | "version": "1.0.6", 1554 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1555 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 1556 | "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.", 1557 | "dev": true, 1558 | "license": "ISC", 1559 | "dependencies": { 1560 | "once": "^1.3.0", 1561 | "wrappy": "1" 1562 | } 1563 | }, 1564 | "node_modules/inherits": { 1565 | "version": "2.0.4", 1566 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1567 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 1568 | "dev": true, 1569 | "license": "ISC" 1570 | }, 1571 | "node_modules/internal-slot": { 1572 | "version": "1.1.0", 1573 | "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", 1574 | "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", 1575 | "dev": true, 1576 | "license": "MIT", 1577 | "peer": true, 1578 | "dependencies": { 1579 | "es-errors": "^1.3.0", 1580 | "hasown": "^2.0.2", 1581 | "side-channel": "^1.1.0" 1582 | }, 1583 | "engines": { 1584 | "node": ">= 0.4" 1585 | } 1586 | }, 1587 | "node_modules/is-array-buffer": { 1588 | "version": "3.0.5", 1589 | "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", 1590 | "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", 1591 | "dev": true, 1592 | "license": "MIT", 1593 | "peer": true, 1594 | "dependencies": { 1595 | "call-bind": "^1.0.8", 1596 | "call-bound": "^1.0.3", 1597 | "get-intrinsic": "^1.2.6" 1598 | }, 1599 | "engines": { 1600 | "node": ">= 0.4" 1601 | }, 1602 | "funding": { 1603 | "url": "https://github.com/sponsors/ljharb" 1604 | } 1605 | }, 1606 | "node_modules/is-async-function": { 1607 | "version": "2.1.0", 1608 | "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.0.tgz", 1609 | "integrity": "sha512-GExz9MtyhlZyXYLxzlJRj5WUCE661zhDa1Yna52CN57AJsymh+DvXXjyveSioqSRdxvUrdKdvqB1b5cVKsNpWQ==", 1610 | "dev": true, 1611 | "license": "MIT", 1612 | "peer": true, 1613 | "dependencies": { 1614 | "call-bound": "^1.0.3", 1615 | "get-proto": "^1.0.1", 1616 | "has-tostringtag": "^1.0.2", 1617 | "safe-regex-test": "^1.1.0" 1618 | }, 1619 | "engines": { 1620 | "node": ">= 0.4" 1621 | }, 1622 | "funding": { 1623 | "url": "https://github.com/sponsors/ljharb" 1624 | } 1625 | }, 1626 | "node_modules/is-bigint": { 1627 | "version": "1.1.0", 1628 | "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", 1629 | "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", 1630 | "dev": true, 1631 | "license": "MIT", 1632 | "peer": true, 1633 | "dependencies": { 1634 | "has-bigints": "^1.0.2" 1635 | }, 1636 | "engines": { 1637 | "node": ">= 0.4" 1638 | }, 1639 | "funding": { 1640 | "url": "https://github.com/sponsors/ljharb" 1641 | } 1642 | }, 1643 | "node_modules/is-boolean-object": { 1644 | "version": "1.2.1", 1645 | "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz", 1646 | "integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==", 1647 | "dev": true, 1648 | "license": "MIT", 1649 | "peer": true, 1650 | "dependencies": { 1651 | "call-bound": "^1.0.2", 1652 | "has-tostringtag": "^1.0.2" 1653 | }, 1654 | "engines": { 1655 | "node": ">= 0.4" 1656 | }, 1657 | "funding": { 1658 | "url": "https://github.com/sponsors/ljharb" 1659 | } 1660 | }, 1661 | "node_modules/is-callable": { 1662 | "version": "1.2.7", 1663 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", 1664 | "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", 1665 | "dev": true, 1666 | "license": "MIT", 1667 | "peer": true, 1668 | "engines": { 1669 | "node": ">= 0.4" 1670 | }, 1671 | "funding": { 1672 | "url": "https://github.com/sponsors/ljharb" 1673 | } 1674 | }, 1675 | "node_modules/is-core-module": { 1676 | "version": "2.16.1", 1677 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", 1678 | "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", 1679 | "dev": true, 1680 | "license": "MIT", 1681 | "peer": true, 1682 | "dependencies": { 1683 | "hasown": "^2.0.2" 1684 | }, 1685 | "engines": { 1686 | "node": ">= 0.4" 1687 | }, 1688 | "funding": { 1689 | "url": "https://github.com/sponsors/ljharb" 1690 | } 1691 | }, 1692 | "node_modules/is-data-view": { 1693 | "version": "1.0.2", 1694 | "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", 1695 | "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", 1696 | "dev": true, 1697 | "license": "MIT", 1698 | "peer": true, 1699 | "dependencies": { 1700 | "call-bound": "^1.0.2", 1701 | "get-intrinsic": "^1.2.6", 1702 | "is-typed-array": "^1.1.13" 1703 | }, 1704 | "engines": { 1705 | "node": ">= 0.4" 1706 | }, 1707 | "funding": { 1708 | "url": "https://github.com/sponsors/ljharb" 1709 | } 1710 | }, 1711 | "node_modules/is-date-object": { 1712 | "version": "1.1.0", 1713 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", 1714 | "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", 1715 | "dev": true, 1716 | "license": "MIT", 1717 | "peer": true, 1718 | "dependencies": { 1719 | "call-bound": "^1.0.2", 1720 | "has-tostringtag": "^1.0.2" 1721 | }, 1722 | "engines": { 1723 | "node": ">= 0.4" 1724 | }, 1725 | "funding": { 1726 | "url": "https://github.com/sponsors/ljharb" 1727 | } 1728 | }, 1729 | "node_modules/is-extglob": { 1730 | "version": "2.1.1", 1731 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1732 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 1733 | "dev": true, 1734 | "license": "MIT", 1735 | "engines": { 1736 | "node": ">=0.10.0" 1737 | } 1738 | }, 1739 | "node_modules/is-finalizationregistry": { 1740 | "version": "1.1.1", 1741 | "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", 1742 | "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", 1743 | "dev": true, 1744 | "license": "MIT", 1745 | "peer": true, 1746 | "dependencies": { 1747 | "call-bound": "^1.0.3" 1748 | }, 1749 | "engines": { 1750 | "node": ">= 0.4" 1751 | }, 1752 | "funding": { 1753 | "url": "https://github.com/sponsors/ljharb" 1754 | } 1755 | }, 1756 | "node_modules/is-generator-function": { 1757 | "version": "1.1.0", 1758 | "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", 1759 | "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", 1760 | "dev": true, 1761 | "license": "MIT", 1762 | "peer": true, 1763 | "dependencies": { 1764 | "call-bound": "^1.0.3", 1765 | "get-proto": "^1.0.0", 1766 | "has-tostringtag": "^1.0.2", 1767 | "safe-regex-test": "^1.1.0" 1768 | }, 1769 | "engines": { 1770 | "node": ">= 0.4" 1771 | }, 1772 | "funding": { 1773 | "url": "https://github.com/sponsors/ljharb" 1774 | } 1775 | }, 1776 | "node_modules/is-glob": { 1777 | "version": "4.0.3", 1778 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 1779 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 1780 | "dev": true, 1781 | "license": "MIT", 1782 | "dependencies": { 1783 | "is-extglob": "^2.1.1" 1784 | }, 1785 | "engines": { 1786 | "node": ">=0.10.0" 1787 | } 1788 | }, 1789 | "node_modules/is-map": { 1790 | "version": "2.0.3", 1791 | "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", 1792 | "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", 1793 | "dev": true, 1794 | "license": "MIT", 1795 | "peer": true, 1796 | "engines": { 1797 | "node": ">= 0.4" 1798 | }, 1799 | "funding": { 1800 | "url": "https://github.com/sponsors/ljharb" 1801 | } 1802 | }, 1803 | "node_modules/is-number-object": { 1804 | "version": "1.1.1", 1805 | "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", 1806 | "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", 1807 | "dev": true, 1808 | "license": "MIT", 1809 | "peer": true, 1810 | "dependencies": { 1811 | "call-bound": "^1.0.3", 1812 | "has-tostringtag": "^1.0.2" 1813 | }, 1814 | "engines": { 1815 | "node": ">= 0.4" 1816 | }, 1817 | "funding": { 1818 | "url": "https://github.com/sponsors/ljharb" 1819 | } 1820 | }, 1821 | "node_modules/is-path-inside": { 1822 | "version": "3.0.3", 1823 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", 1824 | "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", 1825 | "dev": true, 1826 | "license": "MIT", 1827 | "engines": { 1828 | "node": ">=8" 1829 | } 1830 | }, 1831 | "node_modules/is-regex": { 1832 | "version": "1.2.1", 1833 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", 1834 | "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", 1835 | "dev": true, 1836 | "license": "MIT", 1837 | "peer": true, 1838 | "dependencies": { 1839 | "call-bound": "^1.0.2", 1840 | "gopd": "^1.2.0", 1841 | "has-tostringtag": "^1.0.2", 1842 | "hasown": "^2.0.2" 1843 | }, 1844 | "engines": { 1845 | "node": ">= 0.4" 1846 | }, 1847 | "funding": { 1848 | "url": "https://github.com/sponsors/ljharb" 1849 | } 1850 | }, 1851 | "node_modules/is-set": { 1852 | "version": "2.0.3", 1853 | "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", 1854 | "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", 1855 | "dev": true, 1856 | "license": "MIT", 1857 | "peer": true, 1858 | "engines": { 1859 | "node": ">= 0.4" 1860 | }, 1861 | "funding": { 1862 | "url": "https://github.com/sponsors/ljharb" 1863 | } 1864 | }, 1865 | "node_modules/is-shared-array-buffer": { 1866 | "version": "1.0.4", 1867 | "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", 1868 | "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", 1869 | "dev": true, 1870 | "license": "MIT", 1871 | "peer": true, 1872 | "dependencies": { 1873 | "call-bound": "^1.0.3" 1874 | }, 1875 | "engines": { 1876 | "node": ">= 0.4" 1877 | }, 1878 | "funding": { 1879 | "url": "https://github.com/sponsors/ljharb" 1880 | } 1881 | }, 1882 | "node_modules/is-string": { 1883 | "version": "1.1.1", 1884 | "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", 1885 | "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", 1886 | "dev": true, 1887 | "license": "MIT", 1888 | "peer": true, 1889 | "dependencies": { 1890 | "call-bound": "^1.0.3", 1891 | "has-tostringtag": "^1.0.2" 1892 | }, 1893 | "engines": { 1894 | "node": ">= 0.4" 1895 | }, 1896 | "funding": { 1897 | "url": "https://github.com/sponsors/ljharb" 1898 | } 1899 | }, 1900 | "node_modules/is-symbol": { 1901 | "version": "1.1.1", 1902 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", 1903 | "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", 1904 | "dev": true, 1905 | "license": "MIT", 1906 | "peer": true, 1907 | "dependencies": { 1908 | "call-bound": "^1.0.2", 1909 | "has-symbols": "^1.1.0", 1910 | "safe-regex-test": "^1.1.0" 1911 | }, 1912 | "engines": { 1913 | "node": ">= 0.4" 1914 | }, 1915 | "funding": { 1916 | "url": "https://github.com/sponsors/ljharb" 1917 | } 1918 | }, 1919 | "node_modules/is-typed-array": { 1920 | "version": "1.1.15", 1921 | "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", 1922 | "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", 1923 | "dev": true, 1924 | "license": "MIT", 1925 | "peer": true, 1926 | "dependencies": { 1927 | "which-typed-array": "^1.1.16" 1928 | }, 1929 | "engines": { 1930 | "node": ">= 0.4" 1931 | }, 1932 | "funding": { 1933 | "url": "https://github.com/sponsors/ljharb" 1934 | } 1935 | }, 1936 | "node_modules/is-weakmap": { 1937 | "version": "2.0.2", 1938 | "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", 1939 | "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", 1940 | "dev": true, 1941 | "license": "MIT", 1942 | "peer": true, 1943 | "engines": { 1944 | "node": ">= 0.4" 1945 | }, 1946 | "funding": { 1947 | "url": "https://github.com/sponsors/ljharb" 1948 | } 1949 | }, 1950 | "node_modules/is-weakref": { 1951 | "version": "1.1.0", 1952 | "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz", 1953 | "integrity": "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==", 1954 | "dev": true, 1955 | "license": "MIT", 1956 | "peer": true, 1957 | "dependencies": { 1958 | "call-bound": "^1.0.2" 1959 | }, 1960 | "engines": { 1961 | "node": ">= 0.4" 1962 | }, 1963 | "funding": { 1964 | "url": "https://github.com/sponsors/ljharb" 1965 | } 1966 | }, 1967 | "node_modules/is-weakset": { 1968 | "version": "2.0.4", 1969 | "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", 1970 | "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", 1971 | "dev": true, 1972 | "license": "MIT", 1973 | "peer": true, 1974 | "dependencies": { 1975 | "call-bound": "^1.0.3", 1976 | "get-intrinsic": "^1.2.6" 1977 | }, 1978 | "engines": { 1979 | "node": ">= 0.4" 1980 | }, 1981 | "funding": { 1982 | "url": "https://github.com/sponsors/ljharb" 1983 | } 1984 | }, 1985 | "node_modules/isarray": { 1986 | "version": "2.0.5", 1987 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", 1988 | "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", 1989 | "dev": true, 1990 | "license": "MIT", 1991 | "peer": true 1992 | }, 1993 | "node_modules/isexe": { 1994 | "version": "2.0.0", 1995 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1996 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 1997 | "dev": true, 1998 | "license": "ISC" 1999 | }, 2000 | "node_modules/js-yaml": { 2001 | "version": "4.1.0", 2002 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 2003 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 2004 | "dev": true, 2005 | "license": "MIT", 2006 | "dependencies": { 2007 | "argparse": "^2.0.1" 2008 | }, 2009 | "bin": { 2010 | "js-yaml": "bin/js-yaml.js" 2011 | } 2012 | }, 2013 | "node_modules/json-buffer": { 2014 | "version": "3.0.1", 2015 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", 2016 | "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", 2017 | "dev": true, 2018 | "license": "MIT" 2019 | }, 2020 | "node_modules/json-schema-traverse": { 2021 | "version": "0.4.1", 2022 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 2023 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 2024 | "dev": true, 2025 | "license": "MIT" 2026 | }, 2027 | "node_modules/json-stable-stringify-without-jsonify": { 2028 | "version": "1.0.1", 2029 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 2030 | "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", 2031 | "dev": true, 2032 | "license": "MIT" 2033 | }, 2034 | "node_modules/json5": { 2035 | "version": "1.0.2", 2036 | "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", 2037 | "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", 2038 | "dev": true, 2039 | "license": "MIT", 2040 | "peer": true, 2041 | "dependencies": { 2042 | "minimist": "^1.2.0" 2043 | }, 2044 | "bin": { 2045 | "json5": "lib/cli.js" 2046 | } 2047 | }, 2048 | "node_modules/keyv": { 2049 | "version": "4.5.4", 2050 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", 2051 | "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", 2052 | "dev": true, 2053 | "license": "MIT", 2054 | "dependencies": { 2055 | "json-buffer": "3.0.1" 2056 | } 2057 | }, 2058 | "node_modules/levn": { 2059 | "version": "0.4.1", 2060 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 2061 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 2062 | "dev": true, 2063 | "license": "MIT", 2064 | "dependencies": { 2065 | "prelude-ls": "^1.2.1", 2066 | "type-check": "~0.4.0" 2067 | }, 2068 | "engines": { 2069 | "node": ">= 0.8.0" 2070 | } 2071 | }, 2072 | "node_modules/locate-path": { 2073 | "version": "6.0.0", 2074 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 2075 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 2076 | "dev": true, 2077 | "license": "MIT", 2078 | "dependencies": { 2079 | "p-locate": "^5.0.0" 2080 | }, 2081 | "engines": { 2082 | "node": ">=10" 2083 | }, 2084 | "funding": { 2085 | "url": "https://github.com/sponsors/sindresorhus" 2086 | } 2087 | }, 2088 | "node_modules/lodash.merge": { 2089 | "version": "4.6.2", 2090 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 2091 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 2092 | "dev": true, 2093 | "license": "MIT" 2094 | }, 2095 | "node_modules/math-intrinsics": { 2096 | "version": "1.1.0", 2097 | "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", 2098 | "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", 2099 | "dev": true, 2100 | "license": "MIT", 2101 | "engines": { 2102 | "node": ">= 0.4" 2103 | } 2104 | }, 2105 | "node_modules/minimatch": { 2106 | "version": "3.1.2", 2107 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 2108 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 2109 | "dev": true, 2110 | "license": "ISC", 2111 | "dependencies": { 2112 | "brace-expansion": "^1.1.7" 2113 | }, 2114 | "engines": { 2115 | "node": "*" 2116 | } 2117 | }, 2118 | "node_modules/minimist": { 2119 | "version": "1.2.8", 2120 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 2121 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 2122 | "dev": true, 2123 | "license": "MIT", 2124 | "peer": true, 2125 | "funding": { 2126 | "url": "https://github.com/sponsors/ljharb" 2127 | } 2128 | }, 2129 | "node_modules/ms": { 2130 | "version": "2.1.3", 2131 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 2132 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 2133 | "dev": true, 2134 | "license": "MIT" 2135 | }, 2136 | "node_modules/natural-compare": { 2137 | "version": "1.4.0", 2138 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 2139 | "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", 2140 | "dev": true, 2141 | "license": "MIT" 2142 | }, 2143 | "node_modules/object-inspect": { 2144 | "version": "1.13.3", 2145 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", 2146 | "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", 2147 | "dev": true, 2148 | "license": "MIT", 2149 | "peer": true, 2150 | "engines": { 2151 | "node": ">= 0.4" 2152 | }, 2153 | "funding": { 2154 | "url": "https://github.com/sponsors/ljharb" 2155 | } 2156 | }, 2157 | "node_modules/object-keys": { 2158 | "version": "1.1.1", 2159 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 2160 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 2161 | "dev": true, 2162 | "license": "MIT", 2163 | "engines": { 2164 | "node": ">= 0.4" 2165 | } 2166 | }, 2167 | "node_modules/object.assign": { 2168 | "version": "4.1.7", 2169 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", 2170 | "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", 2171 | "dev": true, 2172 | "license": "MIT", 2173 | "dependencies": { 2174 | "call-bind": "^1.0.8", 2175 | "call-bound": "^1.0.3", 2176 | "define-properties": "^1.2.1", 2177 | "es-object-atoms": "^1.0.0", 2178 | "has-symbols": "^1.1.0", 2179 | "object-keys": "^1.1.1" 2180 | }, 2181 | "engines": { 2182 | "node": ">= 0.4" 2183 | }, 2184 | "funding": { 2185 | "url": "https://github.com/sponsors/ljharb" 2186 | } 2187 | }, 2188 | "node_modules/object.entries": { 2189 | "version": "1.1.8", 2190 | "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", 2191 | "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", 2192 | "dev": true, 2193 | "license": "MIT", 2194 | "dependencies": { 2195 | "call-bind": "^1.0.7", 2196 | "define-properties": "^1.2.1", 2197 | "es-object-atoms": "^1.0.0" 2198 | }, 2199 | "engines": { 2200 | "node": ">= 0.4" 2201 | } 2202 | }, 2203 | "node_modules/object.fromentries": { 2204 | "version": "2.0.8", 2205 | "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", 2206 | "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", 2207 | "dev": true, 2208 | "license": "MIT", 2209 | "peer": true, 2210 | "dependencies": { 2211 | "call-bind": "^1.0.7", 2212 | "define-properties": "^1.2.1", 2213 | "es-abstract": "^1.23.2", 2214 | "es-object-atoms": "^1.0.0" 2215 | }, 2216 | "engines": { 2217 | "node": ">= 0.4" 2218 | }, 2219 | "funding": { 2220 | "url": "https://github.com/sponsors/ljharb" 2221 | } 2222 | }, 2223 | "node_modules/object.groupby": { 2224 | "version": "1.0.3", 2225 | "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", 2226 | "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", 2227 | "dev": true, 2228 | "license": "MIT", 2229 | "peer": true, 2230 | "dependencies": { 2231 | "call-bind": "^1.0.7", 2232 | "define-properties": "^1.2.1", 2233 | "es-abstract": "^1.23.2" 2234 | }, 2235 | "engines": { 2236 | "node": ">= 0.4" 2237 | } 2238 | }, 2239 | "node_modules/object.values": { 2240 | "version": "1.2.1", 2241 | "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", 2242 | "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", 2243 | "dev": true, 2244 | "license": "MIT", 2245 | "peer": true, 2246 | "dependencies": { 2247 | "call-bind": "^1.0.8", 2248 | "call-bound": "^1.0.3", 2249 | "define-properties": "^1.2.1", 2250 | "es-object-atoms": "^1.0.0" 2251 | }, 2252 | "engines": { 2253 | "node": ">= 0.4" 2254 | }, 2255 | "funding": { 2256 | "url": "https://github.com/sponsors/ljharb" 2257 | } 2258 | }, 2259 | "node_modules/once": { 2260 | "version": "1.4.0", 2261 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 2262 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 2263 | "dev": true, 2264 | "license": "ISC", 2265 | "dependencies": { 2266 | "wrappy": "1" 2267 | } 2268 | }, 2269 | "node_modules/optionator": { 2270 | "version": "0.9.4", 2271 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", 2272 | "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", 2273 | "dev": true, 2274 | "license": "MIT", 2275 | "dependencies": { 2276 | "deep-is": "^0.1.3", 2277 | "fast-levenshtein": "^2.0.6", 2278 | "levn": "^0.4.1", 2279 | "prelude-ls": "^1.2.1", 2280 | "type-check": "^0.4.0", 2281 | "word-wrap": "^1.2.5" 2282 | }, 2283 | "engines": { 2284 | "node": ">= 0.8.0" 2285 | } 2286 | }, 2287 | "node_modules/own-keys": { 2288 | "version": "1.0.1", 2289 | "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", 2290 | "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", 2291 | "dev": true, 2292 | "license": "MIT", 2293 | "peer": true, 2294 | "dependencies": { 2295 | "get-intrinsic": "^1.2.6", 2296 | "object-keys": "^1.1.1", 2297 | "safe-push-apply": "^1.0.0" 2298 | }, 2299 | "engines": { 2300 | "node": ">= 0.4" 2301 | }, 2302 | "funding": { 2303 | "url": "https://github.com/sponsors/ljharb" 2304 | } 2305 | }, 2306 | "node_modules/p-limit": { 2307 | "version": "3.1.0", 2308 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 2309 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 2310 | "dev": true, 2311 | "license": "MIT", 2312 | "dependencies": { 2313 | "yocto-queue": "^0.1.0" 2314 | }, 2315 | "engines": { 2316 | "node": ">=10" 2317 | }, 2318 | "funding": { 2319 | "url": "https://github.com/sponsors/sindresorhus" 2320 | } 2321 | }, 2322 | "node_modules/p-locate": { 2323 | "version": "5.0.0", 2324 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 2325 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 2326 | "dev": true, 2327 | "license": "MIT", 2328 | "dependencies": { 2329 | "p-limit": "^3.0.2" 2330 | }, 2331 | "engines": { 2332 | "node": ">=10" 2333 | }, 2334 | "funding": { 2335 | "url": "https://github.com/sponsors/sindresorhus" 2336 | } 2337 | }, 2338 | "node_modules/parent-module": { 2339 | "version": "1.0.1", 2340 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 2341 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 2342 | "dev": true, 2343 | "license": "MIT", 2344 | "dependencies": { 2345 | "callsites": "^3.0.0" 2346 | }, 2347 | "engines": { 2348 | "node": ">=6" 2349 | } 2350 | }, 2351 | "node_modules/path-exists": { 2352 | "version": "4.0.0", 2353 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 2354 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 2355 | "dev": true, 2356 | "license": "MIT", 2357 | "engines": { 2358 | "node": ">=8" 2359 | } 2360 | }, 2361 | "node_modules/path-is-absolute": { 2362 | "version": "1.0.1", 2363 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 2364 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 2365 | "dev": true, 2366 | "license": "MIT", 2367 | "engines": { 2368 | "node": ">=0.10.0" 2369 | } 2370 | }, 2371 | "node_modules/path-key": { 2372 | "version": "3.1.1", 2373 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 2374 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 2375 | "dev": true, 2376 | "license": "MIT", 2377 | "engines": { 2378 | "node": ">=8" 2379 | } 2380 | }, 2381 | "node_modules/path-parse": { 2382 | "version": "1.0.7", 2383 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 2384 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 2385 | "dev": true, 2386 | "license": "MIT", 2387 | "peer": true 2388 | }, 2389 | "node_modules/possible-typed-array-names": { 2390 | "version": "1.0.0", 2391 | "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", 2392 | "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", 2393 | "dev": true, 2394 | "license": "MIT", 2395 | "peer": true, 2396 | "engines": { 2397 | "node": ">= 0.4" 2398 | } 2399 | }, 2400 | "node_modules/prelude-ls": { 2401 | "version": "1.2.1", 2402 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 2403 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 2404 | "dev": true, 2405 | "license": "MIT", 2406 | "engines": { 2407 | "node": ">= 0.8.0" 2408 | } 2409 | }, 2410 | "node_modules/punycode": { 2411 | "version": "2.3.1", 2412 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", 2413 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", 2414 | "dev": true, 2415 | "license": "MIT", 2416 | "engines": { 2417 | "node": ">=6" 2418 | } 2419 | }, 2420 | "node_modules/queue-microtask": { 2421 | "version": "1.2.3", 2422 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 2423 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 2424 | "dev": true, 2425 | "funding": [ 2426 | { 2427 | "type": "github", 2428 | "url": "https://github.com/sponsors/feross" 2429 | }, 2430 | { 2431 | "type": "patreon", 2432 | "url": "https://www.patreon.com/feross" 2433 | }, 2434 | { 2435 | "type": "consulting", 2436 | "url": "https://feross.org/support" 2437 | } 2438 | ], 2439 | "license": "MIT" 2440 | }, 2441 | "node_modules/reflect.getprototypeof": { 2442 | "version": "1.0.10", 2443 | "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", 2444 | "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", 2445 | "dev": true, 2446 | "license": "MIT", 2447 | "peer": true, 2448 | "dependencies": { 2449 | "call-bind": "^1.0.8", 2450 | "define-properties": "^1.2.1", 2451 | "es-abstract": "^1.23.9", 2452 | "es-errors": "^1.3.0", 2453 | "es-object-atoms": "^1.0.0", 2454 | "get-intrinsic": "^1.2.7", 2455 | "get-proto": "^1.0.1", 2456 | "which-builtin-type": "^1.2.1" 2457 | }, 2458 | "engines": { 2459 | "node": ">= 0.4" 2460 | }, 2461 | "funding": { 2462 | "url": "https://github.com/sponsors/ljharb" 2463 | } 2464 | }, 2465 | "node_modules/regexp.prototype.flags": { 2466 | "version": "1.5.4", 2467 | "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", 2468 | "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", 2469 | "dev": true, 2470 | "license": "MIT", 2471 | "peer": true, 2472 | "dependencies": { 2473 | "call-bind": "^1.0.8", 2474 | "define-properties": "^1.2.1", 2475 | "es-errors": "^1.3.0", 2476 | "get-proto": "^1.0.1", 2477 | "gopd": "^1.2.0", 2478 | "set-function-name": "^2.0.2" 2479 | }, 2480 | "engines": { 2481 | "node": ">= 0.4" 2482 | }, 2483 | "funding": { 2484 | "url": "https://github.com/sponsors/ljharb" 2485 | } 2486 | }, 2487 | "node_modules/resolve": { 2488 | "version": "1.22.10", 2489 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", 2490 | "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", 2491 | "dev": true, 2492 | "license": "MIT", 2493 | "peer": true, 2494 | "dependencies": { 2495 | "is-core-module": "^2.16.0", 2496 | "path-parse": "^1.0.7", 2497 | "supports-preserve-symlinks-flag": "^1.0.0" 2498 | }, 2499 | "bin": { 2500 | "resolve": "bin/resolve" 2501 | }, 2502 | "engines": { 2503 | "node": ">= 0.4" 2504 | }, 2505 | "funding": { 2506 | "url": "https://github.com/sponsors/ljharb" 2507 | } 2508 | }, 2509 | "node_modules/resolve-from": { 2510 | "version": "4.0.0", 2511 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 2512 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 2513 | "dev": true, 2514 | "license": "MIT", 2515 | "engines": { 2516 | "node": ">=4" 2517 | } 2518 | }, 2519 | "node_modules/reusify": { 2520 | "version": "1.0.4", 2521 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 2522 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 2523 | "dev": true, 2524 | "license": "MIT", 2525 | "engines": { 2526 | "iojs": ">=1.0.0", 2527 | "node": ">=0.10.0" 2528 | } 2529 | }, 2530 | "node_modules/rimraf": { 2531 | "version": "3.0.2", 2532 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 2533 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 2534 | "deprecated": "Rimraf versions prior to v4 are no longer supported", 2535 | "dev": true, 2536 | "license": "ISC", 2537 | "dependencies": { 2538 | "glob": "^7.1.3" 2539 | }, 2540 | "bin": { 2541 | "rimraf": "bin.js" 2542 | }, 2543 | "funding": { 2544 | "url": "https://github.com/sponsors/isaacs" 2545 | } 2546 | }, 2547 | "node_modules/run-parallel": { 2548 | "version": "1.2.0", 2549 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 2550 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 2551 | "dev": true, 2552 | "funding": [ 2553 | { 2554 | "type": "github", 2555 | "url": "https://github.com/sponsors/feross" 2556 | }, 2557 | { 2558 | "type": "patreon", 2559 | "url": "https://www.patreon.com/feross" 2560 | }, 2561 | { 2562 | "type": "consulting", 2563 | "url": "https://feross.org/support" 2564 | } 2565 | ], 2566 | "license": "MIT", 2567 | "dependencies": { 2568 | "queue-microtask": "^1.2.2" 2569 | } 2570 | }, 2571 | "node_modules/safe-array-concat": { 2572 | "version": "1.1.3", 2573 | "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", 2574 | "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", 2575 | "dev": true, 2576 | "license": "MIT", 2577 | "peer": true, 2578 | "dependencies": { 2579 | "call-bind": "^1.0.8", 2580 | "call-bound": "^1.0.2", 2581 | "get-intrinsic": "^1.2.6", 2582 | "has-symbols": "^1.1.0", 2583 | "isarray": "^2.0.5" 2584 | }, 2585 | "engines": { 2586 | "node": ">=0.4" 2587 | }, 2588 | "funding": { 2589 | "url": "https://github.com/sponsors/ljharb" 2590 | } 2591 | }, 2592 | "node_modules/safe-push-apply": { 2593 | "version": "1.0.0", 2594 | "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", 2595 | "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", 2596 | "dev": true, 2597 | "license": "MIT", 2598 | "peer": true, 2599 | "dependencies": { 2600 | "es-errors": "^1.3.0", 2601 | "isarray": "^2.0.5" 2602 | }, 2603 | "engines": { 2604 | "node": ">= 0.4" 2605 | }, 2606 | "funding": { 2607 | "url": "https://github.com/sponsors/ljharb" 2608 | } 2609 | }, 2610 | "node_modules/safe-regex-test": { 2611 | "version": "1.1.0", 2612 | "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", 2613 | "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", 2614 | "dev": true, 2615 | "license": "MIT", 2616 | "peer": true, 2617 | "dependencies": { 2618 | "call-bound": "^1.0.2", 2619 | "es-errors": "^1.3.0", 2620 | "is-regex": "^1.2.1" 2621 | }, 2622 | "engines": { 2623 | "node": ">= 0.4" 2624 | }, 2625 | "funding": { 2626 | "url": "https://github.com/sponsors/ljharb" 2627 | } 2628 | }, 2629 | "node_modules/semver": { 2630 | "version": "6.3.1", 2631 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", 2632 | "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", 2633 | "dev": true, 2634 | "license": "ISC", 2635 | "bin": { 2636 | "semver": "bin/semver.js" 2637 | } 2638 | }, 2639 | "node_modules/set-function-length": { 2640 | "version": "1.2.2", 2641 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", 2642 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", 2643 | "dev": true, 2644 | "license": "MIT", 2645 | "dependencies": { 2646 | "define-data-property": "^1.1.4", 2647 | "es-errors": "^1.3.0", 2648 | "function-bind": "^1.1.2", 2649 | "get-intrinsic": "^1.2.4", 2650 | "gopd": "^1.0.1", 2651 | "has-property-descriptors": "^1.0.2" 2652 | }, 2653 | "engines": { 2654 | "node": ">= 0.4" 2655 | } 2656 | }, 2657 | "node_modules/set-function-name": { 2658 | "version": "2.0.2", 2659 | "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", 2660 | "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", 2661 | "dev": true, 2662 | "license": "MIT", 2663 | "peer": true, 2664 | "dependencies": { 2665 | "define-data-property": "^1.1.4", 2666 | "es-errors": "^1.3.0", 2667 | "functions-have-names": "^1.2.3", 2668 | "has-property-descriptors": "^1.0.2" 2669 | }, 2670 | "engines": { 2671 | "node": ">= 0.4" 2672 | } 2673 | }, 2674 | "node_modules/set-proto": { 2675 | "version": "1.0.0", 2676 | "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", 2677 | "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", 2678 | "dev": true, 2679 | "license": "MIT", 2680 | "peer": true, 2681 | "dependencies": { 2682 | "dunder-proto": "^1.0.1", 2683 | "es-errors": "^1.3.0", 2684 | "es-object-atoms": "^1.0.0" 2685 | }, 2686 | "engines": { 2687 | "node": ">= 0.4" 2688 | } 2689 | }, 2690 | "node_modules/shebang-command": { 2691 | "version": "2.0.0", 2692 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 2693 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 2694 | "dev": true, 2695 | "license": "MIT", 2696 | "dependencies": { 2697 | "shebang-regex": "^3.0.0" 2698 | }, 2699 | "engines": { 2700 | "node": ">=8" 2701 | } 2702 | }, 2703 | "node_modules/shebang-regex": { 2704 | "version": "3.0.0", 2705 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 2706 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 2707 | "dev": true, 2708 | "license": "MIT", 2709 | "engines": { 2710 | "node": ">=8" 2711 | } 2712 | }, 2713 | "node_modules/side-channel": { 2714 | "version": "1.1.0", 2715 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", 2716 | "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", 2717 | "dev": true, 2718 | "license": "MIT", 2719 | "peer": true, 2720 | "dependencies": { 2721 | "es-errors": "^1.3.0", 2722 | "object-inspect": "^1.13.3", 2723 | "side-channel-list": "^1.0.0", 2724 | "side-channel-map": "^1.0.1", 2725 | "side-channel-weakmap": "^1.0.2" 2726 | }, 2727 | "engines": { 2728 | "node": ">= 0.4" 2729 | }, 2730 | "funding": { 2731 | "url": "https://github.com/sponsors/ljharb" 2732 | } 2733 | }, 2734 | "node_modules/side-channel-list": { 2735 | "version": "1.0.0", 2736 | "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", 2737 | "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", 2738 | "dev": true, 2739 | "license": "MIT", 2740 | "peer": true, 2741 | "dependencies": { 2742 | "es-errors": "^1.3.0", 2743 | "object-inspect": "^1.13.3" 2744 | }, 2745 | "engines": { 2746 | "node": ">= 0.4" 2747 | }, 2748 | "funding": { 2749 | "url": "https://github.com/sponsors/ljharb" 2750 | } 2751 | }, 2752 | "node_modules/side-channel-map": { 2753 | "version": "1.0.1", 2754 | "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", 2755 | "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", 2756 | "dev": true, 2757 | "license": "MIT", 2758 | "peer": true, 2759 | "dependencies": { 2760 | "call-bound": "^1.0.2", 2761 | "es-errors": "^1.3.0", 2762 | "get-intrinsic": "^1.2.5", 2763 | "object-inspect": "^1.13.3" 2764 | }, 2765 | "engines": { 2766 | "node": ">= 0.4" 2767 | }, 2768 | "funding": { 2769 | "url": "https://github.com/sponsors/ljharb" 2770 | } 2771 | }, 2772 | "node_modules/side-channel-weakmap": { 2773 | "version": "1.0.2", 2774 | "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", 2775 | "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", 2776 | "dev": true, 2777 | "license": "MIT", 2778 | "peer": true, 2779 | "dependencies": { 2780 | "call-bound": "^1.0.2", 2781 | "es-errors": "^1.3.0", 2782 | "get-intrinsic": "^1.2.5", 2783 | "object-inspect": "^1.13.3", 2784 | "side-channel-map": "^1.0.1" 2785 | }, 2786 | "engines": { 2787 | "node": ">= 0.4" 2788 | }, 2789 | "funding": { 2790 | "url": "https://github.com/sponsors/ljharb" 2791 | } 2792 | }, 2793 | "node_modules/string.prototype.trim": { 2794 | "version": "1.2.10", 2795 | "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", 2796 | "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", 2797 | "dev": true, 2798 | "license": "MIT", 2799 | "peer": true, 2800 | "dependencies": { 2801 | "call-bind": "^1.0.8", 2802 | "call-bound": "^1.0.2", 2803 | "define-data-property": "^1.1.4", 2804 | "define-properties": "^1.2.1", 2805 | "es-abstract": "^1.23.5", 2806 | "es-object-atoms": "^1.0.0", 2807 | "has-property-descriptors": "^1.0.2" 2808 | }, 2809 | "engines": { 2810 | "node": ">= 0.4" 2811 | }, 2812 | "funding": { 2813 | "url": "https://github.com/sponsors/ljharb" 2814 | } 2815 | }, 2816 | "node_modules/string.prototype.trimend": { 2817 | "version": "1.0.9", 2818 | "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", 2819 | "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", 2820 | "dev": true, 2821 | "license": "MIT", 2822 | "peer": true, 2823 | "dependencies": { 2824 | "call-bind": "^1.0.8", 2825 | "call-bound": "^1.0.2", 2826 | "define-properties": "^1.2.1", 2827 | "es-object-atoms": "^1.0.0" 2828 | }, 2829 | "engines": { 2830 | "node": ">= 0.4" 2831 | }, 2832 | "funding": { 2833 | "url": "https://github.com/sponsors/ljharb" 2834 | } 2835 | }, 2836 | "node_modules/string.prototype.trimstart": { 2837 | "version": "1.0.8", 2838 | "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", 2839 | "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", 2840 | "dev": true, 2841 | "license": "MIT", 2842 | "peer": true, 2843 | "dependencies": { 2844 | "call-bind": "^1.0.7", 2845 | "define-properties": "^1.2.1", 2846 | "es-object-atoms": "^1.0.0" 2847 | }, 2848 | "engines": { 2849 | "node": ">= 0.4" 2850 | }, 2851 | "funding": { 2852 | "url": "https://github.com/sponsors/ljharb" 2853 | } 2854 | }, 2855 | "node_modules/strip-ansi": { 2856 | "version": "6.0.1", 2857 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2858 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2859 | "dev": true, 2860 | "license": "MIT", 2861 | "dependencies": { 2862 | "ansi-regex": "^5.0.1" 2863 | }, 2864 | "engines": { 2865 | "node": ">=8" 2866 | } 2867 | }, 2868 | "node_modules/strip-bom": { 2869 | "version": "3.0.0", 2870 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", 2871 | "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", 2872 | "dev": true, 2873 | "license": "MIT", 2874 | "peer": true, 2875 | "engines": { 2876 | "node": ">=4" 2877 | } 2878 | }, 2879 | "node_modules/strip-json-comments": { 2880 | "version": "3.1.1", 2881 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 2882 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 2883 | "dev": true, 2884 | "license": "MIT", 2885 | "engines": { 2886 | "node": ">=8" 2887 | }, 2888 | "funding": { 2889 | "url": "https://github.com/sponsors/sindresorhus" 2890 | } 2891 | }, 2892 | "node_modules/supports-color": { 2893 | "version": "7.2.0", 2894 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 2895 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 2896 | "dev": true, 2897 | "license": "MIT", 2898 | "dependencies": { 2899 | "has-flag": "^4.0.0" 2900 | }, 2901 | "engines": { 2902 | "node": ">=8" 2903 | } 2904 | }, 2905 | "node_modules/supports-preserve-symlinks-flag": { 2906 | "version": "1.0.0", 2907 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 2908 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 2909 | "dev": true, 2910 | "license": "MIT", 2911 | "peer": true, 2912 | "engines": { 2913 | "node": ">= 0.4" 2914 | }, 2915 | "funding": { 2916 | "url": "https://github.com/sponsors/ljharb" 2917 | } 2918 | }, 2919 | "node_modules/text-table": { 2920 | "version": "0.2.0", 2921 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 2922 | "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", 2923 | "dev": true, 2924 | "license": "MIT" 2925 | }, 2926 | "node_modules/tsconfig-paths": { 2927 | "version": "3.15.0", 2928 | "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", 2929 | "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", 2930 | "dev": true, 2931 | "license": "MIT", 2932 | "peer": true, 2933 | "dependencies": { 2934 | "@types/json5": "^0.0.29", 2935 | "json5": "^1.0.2", 2936 | "minimist": "^1.2.6", 2937 | "strip-bom": "^3.0.0" 2938 | } 2939 | }, 2940 | "node_modules/type-check": { 2941 | "version": "0.4.0", 2942 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 2943 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 2944 | "dev": true, 2945 | "license": "MIT", 2946 | "dependencies": { 2947 | "prelude-ls": "^1.2.1" 2948 | }, 2949 | "engines": { 2950 | "node": ">= 0.8.0" 2951 | } 2952 | }, 2953 | "node_modules/type-fest": { 2954 | "version": "0.20.2", 2955 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", 2956 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", 2957 | "dev": true, 2958 | "license": "(MIT OR CC0-1.0)", 2959 | "engines": { 2960 | "node": ">=10" 2961 | }, 2962 | "funding": { 2963 | "url": "https://github.com/sponsors/sindresorhus" 2964 | } 2965 | }, 2966 | "node_modules/typed-array-buffer": { 2967 | "version": "1.0.3", 2968 | "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", 2969 | "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", 2970 | "dev": true, 2971 | "license": "MIT", 2972 | "peer": true, 2973 | "dependencies": { 2974 | "call-bound": "^1.0.3", 2975 | "es-errors": "^1.3.0", 2976 | "is-typed-array": "^1.1.14" 2977 | }, 2978 | "engines": { 2979 | "node": ">= 0.4" 2980 | } 2981 | }, 2982 | "node_modules/typed-array-byte-length": { 2983 | "version": "1.0.3", 2984 | "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", 2985 | "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", 2986 | "dev": true, 2987 | "license": "MIT", 2988 | "peer": true, 2989 | "dependencies": { 2990 | "call-bind": "^1.0.8", 2991 | "for-each": "^0.3.3", 2992 | "gopd": "^1.2.0", 2993 | "has-proto": "^1.2.0", 2994 | "is-typed-array": "^1.1.14" 2995 | }, 2996 | "engines": { 2997 | "node": ">= 0.4" 2998 | }, 2999 | "funding": { 3000 | "url": "https://github.com/sponsors/ljharb" 3001 | } 3002 | }, 3003 | "node_modules/typed-array-byte-offset": { 3004 | "version": "1.0.4", 3005 | "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", 3006 | "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", 3007 | "dev": true, 3008 | "license": "MIT", 3009 | "peer": true, 3010 | "dependencies": { 3011 | "available-typed-arrays": "^1.0.7", 3012 | "call-bind": "^1.0.8", 3013 | "for-each": "^0.3.3", 3014 | "gopd": "^1.2.0", 3015 | "has-proto": "^1.2.0", 3016 | "is-typed-array": "^1.1.15", 3017 | "reflect.getprototypeof": "^1.0.9" 3018 | }, 3019 | "engines": { 3020 | "node": ">= 0.4" 3021 | }, 3022 | "funding": { 3023 | "url": "https://github.com/sponsors/ljharb" 3024 | } 3025 | }, 3026 | "node_modules/typed-array-length": { 3027 | "version": "1.0.7", 3028 | "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", 3029 | "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", 3030 | "dev": true, 3031 | "license": "MIT", 3032 | "peer": true, 3033 | "dependencies": { 3034 | "call-bind": "^1.0.7", 3035 | "for-each": "^0.3.3", 3036 | "gopd": "^1.0.1", 3037 | "is-typed-array": "^1.1.13", 3038 | "possible-typed-array-names": "^1.0.0", 3039 | "reflect.getprototypeof": "^1.0.6" 3040 | }, 3041 | "engines": { 3042 | "node": ">= 0.4" 3043 | }, 3044 | "funding": { 3045 | "url": "https://github.com/sponsors/ljharb" 3046 | } 3047 | }, 3048 | "node_modules/unbox-primitive": { 3049 | "version": "1.1.0", 3050 | "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", 3051 | "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", 3052 | "dev": true, 3053 | "license": "MIT", 3054 | "peer": true, 3055 | "dependencies": { 3056 | "call-bound": "^1.0.3", 3057 | "has-bigints": "^1.0.2", 3058 | "has-symbols": "^1.1.0", 3059 | "which-boxed-primitive": "^1.1.1" 3060 | }, 3061 | "engines": { 3062 | "node": ">= 0.4" 3063 | }, 3064 | "funding": { 3065 | "url": "https://github.com/sponsors/ljharb" 3066 | } 3067 | }, 3068 | "node_modules/uri-js": { 3069 | "version": "4.4.1", 3070 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 3071 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 3072 | "dev": true, 3073 | "license": "BSD-2-Clause", 3074 | "dependencies": { 3075 | "punycode": "^2.1.0" 3076 | } 3077 | }, 3078 | "node_modules/which": { 3079 | "version": "2.0.2", 3080 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 3081 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 3082 | "dev": true, 3083 | "license": "ISC", 3084 | "dependencies": { 3085 | "isexe": "^2.0.0" 3086 | }, 3087 | "bin": { 3088 | "node-which": "bin/node-which" 3089 | }, 3090 | "engines": { 3091 | "node": ">= 8" 3092 | } 3093 | }, 3094 | "node_modules/which-boxed-primitive": { 3095 | "version": "1.1.1", 3096 | "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", 3097 | "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", 3098 | "dev": true, 3099 | "license": "MIT", 3100 | "peer": true, 3101 | "dependencies": { 3102 | "is-bigint": "^1.1.0", 3103 | "is-boolean-object": "^1.2.1", 3104 | "is-number-object": "^1.1.1", 3105 | "is-string": "^1.1.1", 3106 | "is-symbol": "^1.1.1" 3107 | }, 3108 | "engines": { 3109 | "node": ">= 0.4" 3110 | }, 3111 | "funding": { 3112 | "url": "https://github.com/sponsors/ljharb" 3113 | } 3114 | }, 3115 | "node_modules/which-builtin-type": { 3116 | "version": "1.2.1", 3117 | "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", 3118 | "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", 3119 | "dev": true, 3120 | "license": "MIT", 3121 | "peer": true, 3122 | "dependencies": { 3123 | "call-bound": "^1.0.2", 3124 | "function.prototype.name": "^1.1.6", 3125 | "has-tostringtag": "^1.0.2", 3126 | "is-async-function": "^2.0.0", 3127 | "is-date-object": "^1.1.0", 3128 | "is-finalizationregistry": "^1.1.0", 3129 | "is-generator-function": "^1.0.10", 3130 | "is-regex": "^1.2.1", 3131 | "is-weakref": "^1.0.2", 3132 | "isarray": "^2.0.5", 3133 | "which-boxed-primitive": "^1.1.0", 3134 | "which-collection": "^1.0.2", 3135 | "which-typed-array": "^1.1.16" 3136 | }, 3137 | "engines": { 3138 | "node": ">= 0.4" 3139 | }, 3140 | "funding": { 3141 | "url": "https://github.com/sponsors/ljharb" 3142 | } 3143 | }, 3144 | "node_modules/which-collection": { 3145 | "version": "1.0.2", 3146 | "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", 3147 | "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", 3148 | "dev": true, 3149 | "license": "MIT", 3150 | "peer": true, 3151 | "dependencies": { 3152 | "is-map": "^2.0.3", 3153 | "is-set": "^2.0.3", 3154 | "is-weakmap": "^2.0.2", 3155 | "is-weakset": "^2.0.3" 3156 | }, 3157 | "engines": { 3158 | "node": ">= 0.4" 3159 | }, 3160 | "funding": { 3161 | "url": "https://github.com/sponsors/ljharb" 3162 | } 3163 | }, 3164 | "node_modules/which-typed-array": { 3165 | "version": "1.1.18", 3166 | "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", 3167 | "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", 3168 | "dev": true, 3169 | "license": "MIT", 3170 | "peer": true, 3171 | "dependencies": { 3172 | "available-typed-arrays": "^1.0.7", 3173 | "call-bind": "^1.0.8", 3174 | "call-bound": "^1.0.3", 3175 | "for-each": "^0.3.3", 3176 | "gopd": "^1.2.0", 3177 | "has-tostringtag": "^1.0.2" 3178 | }, 3179 | "engines": { 3180 | "node": ">= 0.4" 3181 | }, 3182 | "funding": { 3183 | "url": "https://github.com/sponsors/ljharb" 3184 | } 3185 | }, 3186 | "node_modules/word-wrap": { 3187 | "version": "1.2.5", 3188 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", 3189 | "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", 3190 | "dev": true, 3191 | "license": "MIT", 3192 | "engines": { 3193 | "node": ">=0.10.0" 3194 | } 3195 | }, 3196 | "node_modules/wrappy": { 3197 | "version": "1.0.2", 3198 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 3199 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 3200 | "dev": true, 3201 | "license": "ISC" 3202 | }, 3203 | "node_modules/yocto-queue": { 3204 | "version": "0.1.0", 3205 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 3206 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 3207 | "dev": true, 3208 | "license": "MIT", 3209 | "engines": { 3210 | "node": ">=10" 3211 | }, 3212 | "funding": { 3213 | "url": "https://github.com/sponsors/sindresorhus" 3214 | } 3215 | } 3216 | } 3217 | } 3218 | -------------------------------------------------------------------------------- /package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | name: 'chatra:redpubsub', 3 | version: '1.0.1', 4 | summary: 'Custom pub/sub interface for Meteor on top of Redis', 5 | git: 'https://github.com/chatr/redpubsub.git', 6 | documentation: 'README.md', 7 | }); 8 | 9 | Npm.depends({ 10 | redis: '4.7.0', 11 | 'lru-cache': '11.0.2', 12 | }); 13 | 14 | Package.onUse((api) => { 15 | api.versionsFrom('3.0'); 16 | api.use(['ecmascript', 'random', 'ejson']); 17 | api.use(['minimongo', 'diff-sequence'], 'server'); 18 | 19 | api.mainModule('main-client.js', 'client'); 20 | api.mainModule('main-server.js', 'server'); 21 | 22 | api.export('RPS', ['client', 'server']); 23 | }); 24 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redpubsub", 3 | "version": "1.0.1", 4 | "devDependencies": { 5 | "eslint": "^8.57.1", 6 | "eslint-config-airbnb-base": "^15.0.0" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /publish.js: -------------------------------------------------------------------------------- 1 | import { observeChanges } from './observe-changes'; 2 | 3 | /** 4 | * Publishes data to the client using RPS. 5 | * It sets up observation on the given collection and sends added/changed/removed events. 6 | * @param {Object} sub The Meteor subscription object. 7 | * @param {Array|Object} requests A single request or an array of requests describing the publication. 8 | * @return {Object|Array} A handler or array of handlers to stop the observers. 9 | */ 10 | async function publish(sub, requests) { 11 | // Ensure requests is an array. 12 | requests = Array.isArray(requests) ? requests : [requests]; 13 | 14 | // Map each request to an observeChanges call. 15 | const handlersPromises = requests.map((request) => { 16 | // Determine the collection name (either provided or from collection._name). 17 | const collectionName = request.collectionName || request.collection._name; 18 | return observeChanges( 19 | request.collection, 20 | { ...request.options }, 21 | { 22 | // When a document is added, forward it via sub.added. 23 | added: (id, fields) => { 24 | sub.added(collectionName, id, fields); 25 | }, 26 | // When a document is changed, forward it via sub.changed. 27 | changed: (id, fields) => { 28 | sub.changed(collectionName, id, fields); 29 | }, 30 | // When a document is removed, forward it via sub.removed. 31 | removed: (id) => { 32 | sub.removed(collectionName, id); 33 | }, 34 | }, 35 | ); 36 | }); 37 | 38 | // Wait for all observeChanges handlers to be set up. 39 | const handlers = await Promise.all(handlersPromises); 40 | 41 | // Signal that the subscription is ready. 42 | sub.ready(); 43 | // When the subscription stops, remove all observers. 44 | sub.onStop(() => { 45 | handlers.forEach((handler) => { 46 | handler.stop(); 47 | }); 48 | }); 49 | 50 | // Return a single handler if only one request was passed. 51 | return handlers.length > 1 ? handlers : handlers[0]; 52 | } 53 | 54 | export { publish }; 55 | -------------------------------------------------------------------------------- /redis.js: -------------------------------------------------------------------------------- 1 | import { Random } from 'meteor/random'; 2 | import { createClient } from 'redis'; 3 | import { messenger } from './messenger'; 4 | 5 | // Generate a unique server id to prevent echoing messages sent by this server. 6 | const serverId = Random.id(); 7 | // Object to store Redis clients for publishing and subscribing. 8 | const clients = {}; 9 | 10 | /** 11 | * Parses the Redis connection URL from the environment variable. 12 | * @return {Object} The Redis connection options. 13 | */ 14 | function parseRedisEnvUrl() { 15 | if (process.env.RPS_REDIS_URL) { 16 | return { url: process.env.RPS_REDIS_URL }; 17 | } 18 | return {}; 19 | } 20 | 21 | const redisConfig = parseRedisEnvUrl(); 22 | 23 | /** 24 | * Creates a Redis client for either publishing or subscribing. 25 | * @param {string} key The client key, e.g., 'pub' or 'sub'. 26 | */ 27 | async function createRedisClient(key) { 28 | const logLabel = `RPS: [${key}]`; 29 | console.info(`${logLabel} connecting to Redis...`, redisConfig); 30 | 31 | const client = createClient(redisConfig); 32 | clients[key] = client; 33 | 34 | // Attach error handler. 35 | client.on('error', (err) => { 36 | if (err.errors) { 37 | console.error(`${logLabel} Errors:\n${err.errors.join('\n')}`); 38 | } else { 39 | console.error(`${logLabel} ${err}`); 40 | } 41 | }); 42 | 43 | // Log when the client connects. 44 | client.on('connect', () => { 45 | console.info(`${logLabel} connected to Redis!`); 46 | }); 47 | 48 | // Log reconnection attempts. 49 | client.on('reconnecting', () => { 50 | console.info(`${logLabel} reconnecting to Redis...`); 51 | }); 52 | 53 | // Log when the connection ends. 54 | client.on('end', () => { 55 | console.error(`${logLabel} Redis connection ended.`); 56 | }); 57 | 58 | // Connect asynchronously. 59 | await client.connect(); 60 | } 61 | 62 | // Immediately create Redis clients for both publishing and subscribing. 63 | (async () => { 64 | await createRedisClient('pub'); 65 | await createRedisClient('sub'); 66 | })(); 67 | 68 | /** 69 | * Subscribes to a Redis channel. 70 | * When a message is received, it is parsed and passed to the messenger. 71 | * @param {string} channel The channel to subscribe to. 72 | */ 73 | function subscribe(channel) { 74 | if (!clients.sub) { 75 | return; 76 | } 77 | clients.sub 78 | .subscribe(channel, (messageString, channelName) => { 79 | let message; 80 | try { 81 | message = JSON.parse(messageString); 82 | } catch (err) { 83 | console.error( 84 | `Failed to parse JSON. Channel: ${channelName}, Message: ${messageString}`, 85 | err, 86 | ); 87 | return; 88 | } 89 | // Only process the message if it did not originate from this server. 90 | if (message && message._serverId !== serverId) { 91 | messenger.handleMessage(channelName, message); 92 | } 93 | }) 94 | .catch((err) => { 95 | console.error('Error subscribing to channel:', channel, err); 96 | }); 97 | } 98 | 99 | /** 100 | * Unsubscribes from a Redis channel. 101 | * @param {string} channel The channel to unsubscribe from. 102 | */ 103 | function unsubscribe(channel) { 104 | if (!clients.sub) { 105 | return; 106 | } 107 | clients.sub 108 | .unsubscribe(channel) 109 | .catch((err) => { 110 | console.error('Error unsubscribing from channel:', channel, err); 111 | }); 112 | } 113 | 114 | /** 115 | * Publishes a message to a Redis channel. 116 | * @param {string} channel The channel to publish to. 117 | * @param {string} message The message to publish (JSON string). 118 | */ 119 | function publishMessage(channel, message) { 120 | if (!clients.pub) { 121 | return; 122 | } 123 | clients.pub 124 | .publish(channel, message) 125 | .catch((err) => { 126 | console.error('Error publishing message:', err); 127 | }); 128 | } 129 | 130 | export { 131 | serverId, 132 | subscribe, 133 | unsubscribe, 134 | publishMessage, 135 | }; 136 | -------------------------------------------------------------------------------- /write-client.js: -------------------------------------------------------------------------------- 1 | import { _write } from './write'; 2 | 3 | /** 4 | * Performs a client-side write operation. 5 | * It wraps the _write function and sets the selector from doc if not provided. 6 | * @param {Mongo.Collection} collection The collection to write to. 7 | * @param {string} method The write method ('insert', 'remove', 'update', 'upsert'). 8 | * @param {Object=} options Options for the write operation. 9 | * @return {Promise} A promise that resolves with the result. 10 | */ 11 | async function write(collection, method, options = {}) { 12 | // For convenience, if no selector is provided, use options.doc. 13 | options.selector = options.selector || options.doc; 14 | return _write(collection, method, options); 15 | } 16 | 17 | export { write }; 18 | -------------------------------------------------------------------------------- /write-server.js: -------------------------------------------------------------------------------- 1 | import { Random } from 'meteor/random'; 2 | import { Mongo } from 'meteor/mongo'; 3 | import { _write } from './write'; 4 | import { serverId, publishMessage } from './redis'; 5 | import { RPS } from './main-server'; 6 | import { messenger } from './messenger'; 7 | 8 | /** 9 | * Performs a server-side write operation and publishes changes. 10 | * @param {Mongo.Collection} collection The collection to write to. 11 | * @param {string} method The method ('insert', 'remove', 'update', 'upsert'). 12 | * @param {Object=} options The options for the write operation. 13 | * @return {Promise} A promise that resolves with the result. 14 | */ 15 | async function write(collection, method, options = {}) { 16 | // If a selector is provided in options, rewrite it; otherwise, use the document from options. 17 | options.selector = options.selector 18 | ? Mongo.Collection._rewriteSelector(options.selector) 19 | : options.doc || {}; 20 | 21 | // Destructure _id from the selector. 22 | const { _id } = options.selector; 23 | // Determine if _id is a non-empty string. 24 | const _idIsId = !!_id && typeof _id === 'string'; 25 | // Get the collection name. 26 | const collectionName = collection._name; 27 | // Retrieve configuration for this collection, or use an empty object if none exists. 28 | const config = RPS.config[collectionName] || {}; 29 | // Determine the channels for publishing. If noPublish is true, channels will be false. 30 | // Otherwise, use options.channels, or the channels defined in the config, or default to the collection name. 31 | const channels = !options.noPublish && (options.channels || config.channels || collectionName); 32 | 33 | // Arrays to store document IDs and documents for later publishing 34 | let idMap = []; 35 | let docs = []; 36 | 37 | // Async function to publish a message to all determined channels for a document 38 | async function publish(doc, id) { 39 | let channelsForDoc; 40 | // If channels is a function, call it to determine channels based on the document, selector, and fields. 41 | if (typeof channels === 'function') { 42 | channelsForDoc = channels(doc, options.selector, options.fields); 43 | } else { 44 | channelsForDoc = channels; 45 | } 46 | // If no channels are returned, skip publishing. 47 | if (!channelsForDoc) { 48 | return; 49 | } 50 | // Build the message object to send. 51 | const message = { 52 | _serverId: serverId, // Identifier for the server sending the message. 53 | doc: method !== 'remove' && doc, // Include the document unless the method is 'remove'. 54 | method, // The write method (e.g., insert, update, remove). 55 | selector: options.selector, // The selector used in the write operation. 56 | modifier: options.redModifier || options.modifier, // Modifier used for update operations. 57 | withoutMongo: options.withoutMongo, // Indicates if MongoDB is bypassed. 58 | id: id || (doc && doc._id), // Use the provided id, or extract from the document. 59 | ts: Date.now(), // Timestamp for the message. 60 | }; 61 | // Serialize the message to a JSON string for transmission. 62 | const messageString = JSON.stringify(message); 63 | // Ensure channelsForDoc is in array form (even if a single channel is returned). 64 | const channelsArray = Array.isArray(channelsForDoc) ? channelsForDoc : [channelsForDoc]; 65 | 66 | // Publish the message to each channel. 67 | channelsArray.forEach((channel) => { 68 | if (!channel) { 69 | return; 70 | } 71 | // Handle the message through the messenger. 72 | messenger.handleMessage(channel, message); 73 | // Send out the message string via publishMessage. 74 | publishMessage(channel, messageString); 75 | }); 76 | } 77 | 78 | // Async function to be called after the write operation, 79 | // which handles the publishing of changes. 80 | async function afterWrite(result) { 81 | // If channels are not configured, skip publishing and return the result immediately. 82 | if (!channels) { 83 | return result; 84 | } 85 | // If the write is done without MongoDB, publish using a generated or provided id. 86 | if (options.withoutMongo) { 87 | // Generate an id if necessary: use _id if it's a valid string or generate a random id for insert/upsert. 88 | const id = _idIsId ? _id : ((method === 'insert' || method === 'upsert') && Random.id()); 89 | await publish(null, id); 90 | } else if (method === 'remove') { 91 | // If the method is 'remove', publish each document in parallel. 92 | await Promise.all(docs.map((doc) => publish(doc))); 93 | } else { 94 | // For other methods (insert, update, upsert), fetch the latest documents to publish. 95 | if (idMap.length) { 96 | // Fetch documents with ids in idMap. 97 | const cursor = collection.find({ _id: { $in: idMap } }); 98 | docs = await cursor.fetchAsync(); 99 | } else if (method === 'upsert' && result.insertedId) { 100 | // For upsert, if an insertedId is provided, fetch that document. 101 | const cursor = collection.find({ _id: result.insertedId }); 102 | docs = await cursor.fetchAsync(); 103 | } else if (method === 'insert') { 104 | // For insert, use the selector as the document and update idMap accordingly. 105 | const doc = options.selector; 106 | docs = [doc]; 107 | idMap = [doc._id = doc._id || result]; 108 | } 109 | // Publish all the documents concurrently. 110 | await Promise.all(docs.map((doc) => publish(doc))); 111 | } 112 | // Return the result from the write operation after publishing is complete. 113 | return result; 114 | } 115 | 116 | // If the noWrite option is set, skip the write operation and only publish the provided document. 117 | if (options.noWrite) { 118 | await publish(options.doc); 119 | return void 0; 120 | } 121 | 122 | // Pre-fetch document ids and documents for publishing if channels are configured, 123 | // the method is not 'insert', and MongoDB write is not bypassed. 124 | if (channels && method !== 'insert' && !options.withoutMongo) { 125 | const findOptions = {}; 126 | if (method !== 'remove') { 127 | if (_idIsId) { 128 | // If a valid _id exists, add it directly to the idMap. 129 | idMap.push(_id); 130 | } else { 131 | // Otherwise, set findOptions to fetch only the _id field. 132 | findOptions.fields = { _id: 1 }; 133 | // If the update is not multi, limit the query to 1 document. 134 | if (!options.options || !options.options.multi) { 135 | findOptions.limit = 1; 136 | } 137 | } 138 | } 139 | // If idMap is empty, perform a query to fetch the documents matching the selector. 140 | if (idMap.length === 0) { 141 | const cursor = collection.find(options.selector, findOptions); 142 | const foundDocs = await cursor.fetchAsync(); 143 | for (const doc of foundDocs) { 144 | idMap.push(doc._id); 145 | docs.push(doc); 146 | } 147 | } 148 | } 149 | 150 | // If withoutMongo is set, skip the actual database write and directly publish. 151 | if (options.withoutMongo) { 152 | return afterWrite(void 0); 153 | } 154 | 155 | // Perform the actual write operation (insert, update, remove, etc.) 156 | const writeResult = await _write(collection, method, options); 157 | // After the write, call afterWrite to handle publishing and then return the result. 158 | return afterWrite(writeResult); 159 | } 160 | 161 | export { write }; 162 | -------------------------------------------------------------------------------- /write.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Internal function that performs a database write operation. 3 | * This function uses asynchronous methods on the collection. 4 | * @param {Mongo.Collection} collection The collection to write to. 5 | * @param {string} method The method to use ('insert', 'remove', 'update', 'upsert'). 6 | * @param {Object} options Options for the write operation. 7 | * @return {Promise} A promise resolving with the result of the operation. 8 | */ 9 | async function _write(collection, method, options) { 10 | switch (method) { 11 | case 'insert': 12 | return collection.insertAsync(options.selector); 13 | case 'remove': 14 | return collection.removeAsync(options.selector); 15 | case 'update': 16 | return collection.updateAsync(options.selector, options.modifier, options.options); 17 | case 'upsert': 18 | return collection.upsertAsync(options.selector, options.modifier, options.options); 19 | default: 20 | throw new Error(`Unknown method: ${method}`); 21 | } 22 | } 23 | 24 | export { _write }; 25 | --------------------------------------------------------------------------------