From 9c5254179369f7c9ef8852960bccbc5aacb4fd21 Mon Sep 17 00:00:00 2001 From: filipenevola Date: Wed, 8 Nov 2023 08:48:24 -0500 Subject: [PATCH 1/6] Starts Meteor 3 migration - all tests are passing but we still need to test in an actual project --- .gitignore | 2 + .npm/package/npm-shrinkwrap.json | 10 +- .versions | 47 ----- LICENSE | 20 -- README.md | 14 +- example/.meteor/.finished-upgraders | 8 - example/.meteor/.gitignore | 1 - example/.meteor/.id | 7 - example/.meteor/packages | 9 - example/.meteor/platforms | 2 - example/.meteor/release | 1 - example/.meteor/versions | 50 ----- example/example.css | 1 - example/example.html | 13 -- example/example.js | 41 ---- package-lock.json | 30 +++ package.js | 32 +-- package.json | 8 + synced-cron-server.js | 287 +++++++++++++------------- synced-cron-tests.js | 309 +++++++++++++++------------- versions.json | 83 -------- 21 files changed, 380 insertions(+), 595 deletions(-) delete mode 100644 .versions delete mode 100644 LICENSE delete mode 100644 example/.meteor/.finished-upgraders delete mode 100644 example/.meteor/.gitignore delete mode 100644 example/.meteor/.id delete mode 100644 example/.meteor/packages delete mode 100644 example/.meteor/platforms delete mode 100644 example/.meteor/release delete mode 100644 example/.meteor/versions delete mode 100644 example/example.css delete mode 100644 example/example.html delete mode 100644 example/example.js create mode 100644 package-lock.json create mode 100644 package.json delete mode 100644 versions.json diff --git a/.gitignore b/.gitignore index 677a6fc..23c7573 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ .build* +node_modules +.idea \ No newline at end of file diff --git a/.npm/package/npm-shrinkwrap.json b/.npm/package/npm-shrinkwrap.json index a734887..73d6b9e 100644 --- a/.npm/package/npm-shrinkwrap.json +++ b/.npm/package/npm-shrinkwrap.json @@ -1,10 +1,10 @@ { - "lockfileVersion": 1, + "lockfileVersion": 4, "dependencies": { - "later": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/later/-/later-1.1.6.tgz", - "integrity": "sha1-Wvg61IJjk8VvEO4u4ekQlkRb5Os=" + "@breejs/later": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@breejs/later/-/later-4.1.0.tgz", + "integrity": "sha512-QgGnZ9b7o4k0Ai1ZbTJWwZpZcFK9d+Gb+DyNt4UT9x6IEIs5HVu0iIlmgzGqN+t9MoJSpSPo9S/Mm51UtHr3JA==" } } } diff --git a/.versions b/.versions deleted file mode 100644 index 721c659..0000000 --- a/.versions +++ /dev/null @@ -1,47 +0,0 @@ -allow-deny@1.1.0 -babel-compiler@7.1.1 -babel-runtime@1.2.6 -base64@1.0.11 -binary-heap@1.0.10 -boilerplate-generator@1.5.0 -callback-hook@1.1.0 -check@1.3.1 -ddp@1.4.0 -ddp-client@2.3.3 -ddp-common@1.4.0 -ddp-server@2.2.0 -diff-sequence@1.1.0 -dynamic-import@0.4.2 -ecmascript@0.11.1 -ecmascript-runtime@0.7.0 -ecmascript-runtime-client@0.7.2 -ecmascript-runtime-server@0.7.1 -ejson@1.1.0 -geojson-utils@1.0.10 -http@1.4.1 -id-map@1.1.0 -littledata:synced-cron@1.5.0 -local-test:littledata:synced-cron@1.5.0 -logging@1.1.20 -meteor@1.9.0 -minimongo@1.4.4 -modern-browsers@0.1.2 -modules@0.12.2 -modules-runtime@0.10.0 -mongo@1.5.0 -mongo-dev-server@1.1.0 -mongo-id@1.0.7 -npm-mongo@3.0.11 -ordered-dict@1.1.0 -promise@0.11.1 -random@1.1.0 -reload@1.2.0 -retry@1.1.0 -routepolicy@1.0.13 -socket-stream-client@0.2.2 -tinytest@1.1.0 -tracker@1.2.0 -underscore@1.0.10 -url@1.2.0 -webapp@1.6.0 -webapp-hashing@1.0.9 diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 8485972..0000000 --- a/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Percolate Studio - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 1538434..b7c8c0c 100644 --- a/README.md +++ b/README.md @@ -2,20 +2,20 @@ A simple cron system for [Meteor](http://meteor.com). It supports syncronizing jobs between multiple processes. In other words, if you add a job that runs every hour and your deployment consists of multiple app servers, only one of the app servers will execute the job each time (whichever tries first). -## Migrated from percolate:synced-cron littledata:synced-cron +## Migrated from littledata:synced-cron -Since the original creator of the project could no longer maintain it, we had to migrate the package to another organisation to allow further maintenance and updates. +Quave version is compatible with Meteor 3.0 and forward. To migrate you can simply run ``` sh -$ meteor remove percolate:synced-cron && meteor add littledata:synced-cron +$ meteor remove littledata:synced-cron && meteor add quave:synced-cron ``` ## Installation ``` sh -$ meteor add littledata:synced-cron +$ meteor add quave:synced-cron ``` ## API @@ -141,9 +141,3 @@ Write some code. Write some tests. To run the tests, do: ``` sh $ meteor test-packages ./ ``` - -## License - -MIT. (c) Percolate Studio, originally designed and built by Zoltan Olah (@zol), now community maintained. - -Synced Cron was developed as part of the [Verso](http://versoapp.com) project. diff --git a/example/.meteor/.finished-upgraders b/example/.meteor/.finished-upgraders deleted file mode 100644 index 8a76103..0000000 --- a/example/.meteor/.finished-upgraders +++ /dev/null @@ -1,8 +0,0 @@ -# This file contains information which helps Meteor properly upgrade your -# app when you run 'meteor update'. You should check it into version control -# with your project. - -notices-for-0.9.0 -notices-for-0.9.1 -0.9.4-platform-file -notices-for-facebook-graph-api-2 diff --git a/example/.meteor/.gitignore b/example/.meteor/.gitignore deleted file mode 100644 index 4083037..0000000 --- a/example/.meteor/.gitignore +++ /dev/null @@ -1 +0,0 @@ -local diff --git a/example/.meteor/.id b/example/.meteor/.id deleted file mode 100644 index 536ae72..0000000 --- a/example/.meteor/.id +++ /dev/null @@ -1,7 +0,0 @@ -# This file contains a token that is unique to your project. -# Check it into your repository along with the rest of this directory. -# It can be used for purposes such as: -# - ensuring you don't accidentally deploy one app on top of another -# - providing package authors with aggregated statistics - -18n88nbddjnt450w00w diff --git a/example/.meteor/packages b/example/.meteor/packages deleted file mode 100644 index afc9e5d..0000000 --- a/example/.meteor/packages +++ /dev/null @@ -1,9 +0,0 @@ -# Meteor packages used by this project, one per line. -# -# 'meteor add' and 'meteor remove' will edit this file for you, -# but you can also edit it by hand. - -standard-app-packages -autopublish -insecure -percolate:synced-cron diff --git a/example/.meteor/platforms b/example/.meteor/platforms deleted file mode 100644 index 8a3a35f..0000000 --- a/example/.meteor/platforms +++ /dev/null @@ -1,2 +0,0 @@ -browser -server diff --git a/example/.meteor/release b/example/.meteor/release deleted file mode 100644 index 4fd7a93..0000000 --- a/example/.meteor/release +++ /dev/null @@ -1 +0,0 @@ -METEOR@1.3 diff --git a/example/.meteor/versions b/example/.meteor/versions deleted file mode 100644 index 2358b9f..0000000 --- a/example/.meteor/versions +++ /dev/null @@ -1,50 +0,0 @@ -autopublish@1.0.3 -autoupdate@1.2.1 -base64@1.0.3 -binary-heap@1.0.3 -blaze@2.1.2 -blaze-tools@1.0.3 -boilerplate-generator@1.0.3 -callback-hook@1.0.3 -check@1.0.5 -ddp@1.1.0 -deps@1.0.7 -ejson@1.0.6 -fastclick@1.0.3 -geojson-utils@1.0.3 -html-tools@1.0.4 -htmljs@1.0.4 -http@1.1.0 -id-map@1.0.3 -insecure@1.0.3 -jquery@1.11.3_2 -json@1.0.3 -launch-screen@1.0.2 -livedata@1.0.13 -logging@1.0.7 -meteor@1.1.6 -meteor-platform@1.2.2 -minifiers@1.1.5 -minimongo@1.0.8 -mobile-status-bar@1.0.3 -mongo@1.1.0 -observe-sequence@1.0.6 -ordered-dict@1.0.3 -percolate:synced-cron@1.2.2 -random@1.0.3 -reactive-dict@1.1.0 -reactive-var@1.0.5 -reload@1.1.3 -retry@1.0.3 -routepolicy@1.0.5 -session@1.1.0 -spacebars@1.0.6 -spacebars-compiler@1.0.6 -standard-app-packages@1.0.5 -templating@1.1.1 -tracker@1.0.7 -ui@1.0.6 -underscore@1.0.3 -url@1.0.4 -webapp@1.2.0 -webapp-hashing@1.0.3 diff --git a/example/example.css b/example/example.css deleted file mode 100644 index b6b4052..0000000 --- a/example/example.css +++ /dev/null @@ -1 +0,0 @@ -/* CSS declarations go here */ diff --git a/example/example.html b/example/example.html deleted file mode 100644 index 3f05c83..0000000 --- a/example/example.html +++ /dev/null @@ -1,13 +0,0 @@ - - example - - - - {{> hello}} - - - diff --git a/example/example.js b/example/example.js deleted file mode 100644 index 9f4a86d..0000000 --- a/example/example.js +++ /dev/null @@ -1,41 +0,0 @@ -if (Meteor.isClient) { - Template.hello.greeting = function () { - return "Welcome to example."; - }; - - Template.hello.events({ - 'click input': function () { - // template data, if any, is available in 'this' - if (typeof console !== 'undefined') - console.log("You pressed the button"); - } - }); -} - -if (Meteor.isServer) { - // optionally set the collection's name that synced cron will use - SyncedCron.config({ - collectionName: 'somethingDifferent' - }); - - SyncedCron.add({ - name: 'Crunch some important numbers for the marketing department', - schedule: function(parser) { - // parser is a later.parse object - return parser.text('every 5 seconds'); - }, - job: function(intendedAt) { - console.log('crunching numbers'); - console.log('job should be running at:'); - console.log(intendedAt); - } - }); - - Meteor.startup(function () { - // code to run on server at startup - SyncedCron.start(); - - // Stop jobs after 15 seconds - Meteor.setTimeout(function() { SyncedCron.stop(); }, 15 * 1000); - }); -} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..52e06be --- /dev/null +++ b/package-lock.json @@ -0,0 +1,30 @@ +{ + "name": "meteor-synced-cron", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "meteor-synced-cron", + "version": "1.0.0", + "devDependencies": { + "prettier": "^3.0.3" + } + }, + "node_modules/prettier": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", + "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + } + } +} diff --git a/package.js b/package.js index f7aa1a2..e354ba9 100644 --- a/package.js +++ b/package.js @@ -1,21 +1,29 @@ Package.describe({ - summary: "Allows you to define and run scheduled jobs across multiple servers.", - version: "1.5.1", - name: "littledata:synced-cron", - git: "https://github.com/percolatestudio/meteor-synced-cron.git" + summary: + "Allows you to define and run scheduled jobs across multiple servers.", + version: "2.0.0", + name: "quave:synced-cron", + git: "https://github.com/percolatestudio/meteor-synced-cron.git", }); -Npm.depends({later: "1.1.6"}); +Npm.depends({ "@breejs/later": "4.1.0" }); Package.onUse(function (api) { - api.versionsFrom('METEOR@1.3'); - api.use(['underscore', 'check', 'mongo', 'logging'], 'server'); - api.add_files(['synced-cron-server.js'], "server"); - api.export('SyncedCron', 'server'); + api.versionsFrom("METEOR@3.0-alpha.17"); + + api.use( + ["check", "mongo@1.0.0||2.0.0||2.0.0-alpha300.17", "logging"], + "server", + ); + + api.addFiles(["synced-cron-server.js"], "server"); + + api.export("SyncedCron", "server"); }); Package.onTest(function (api) { - api.use(['check', 'mongo'], 'server'); - api.use(['tinytest', 'underscore', 'logging']); - api.add_files(['synced-cron-server.js', 'synced-cron-tests.js'], ['server']); + api.use(["check", "mongo"], "server"); + api.use(["tinytest", "logging"]); + + api.addFiles(["synced-cron-server.js", "synced-cron-tests.js"], ["server"]); }); diff --git a/package.json b/package.json new file mode 100644 index 0000000..5e75321 --- /dev/null +++ b/package.json @@ -0,0 +1,8 @@ +{ + "name": "meteor-synced-cron", + "description": "Meteor package for SyncedCron. package.json only to install prettier", + "version": "1.0.0", + "devDependencies": { + "prettier": "^3.0.3" + } +} diff --git a/synced-cron-server.js b/synced-cron-server.js index 7b80f09..2e05237 100644 --- a/synced-cron-server.js +++ b/synced-cron-server.js @@ -9,7 +9,7 @@ SyncedCron = { logger: null, //Name of collection to use for synchronisation and logging - collectionName: 'cronHistory', + collectionName: "cronHistory", //Default to using localTime utc: false, @@ -17,14 +17,14 @@ SyncedCron = { //TTL in seconds for history records in collection to expire //NOTE: Unset to remove expiry but ensure you remove the index from //mongo by hand - collectionTTL: 172800 + collectionTTL: 172800, }, - config: function(opts) { - this.options = _.extend({}, this.options, opts); - } -} + config: function (opts) { + this.options = Object.assign({}, this.options, opts); + }, +}; -Later = Npm.require('later'); +Later = Npm.require("@breejs/later"); /* Logger factory function. Takes a prefix string and options object @@ -41,71 +41,79 @@ function createLogger(prefix) { check(prefix, String); // Return noop if logging is disabled. - if(SyncedCron.options.log === false) { - return function() {}; + if (SyncedCron.options.log === false) { + return function () {}; } - return function(level, message) { - check(level, Match.OneOf('info', 'error', 'warn', 'debug')); + return function (level, message) { + check(level, Match.OneOf("info", "error", "warn", "debug")); check(message, String); - var logger = SyncedCron.options && SyncedCron.options.logger; - - if(logger && _.isFunction(logger)) { + const logger = SyncedCron.options && SyncedCron.options.logger; + if (logger && typeof logger === "function") { logger({ level: level, message: message, - tag: prefix + tag: prefix, }); - } else { - Log[level]({ message: prefix + ': ' + message }); + Log[level]({ message: prefix + ": " + message }); } - } + }; } -var log; +let log; + +const partial = (func, ...boundArgs) => (...remainingArgs) => func(...boundArgs, ...remainingArgs) -Meteor.startup(function() { - var options = SyncedCron.options; +Meteor.startup(async function syncedCronStartup() { + const options = SyncedCron.options; - log = createLogger('SyncedCron'); + log = createLogger("SyncedCron"); - ['info', 'warn', 'error', 'debug'].forEach(function(level) { - log[level] = _.partial(log, level); + ["info", "warn", "error", "debug"].forEach(function (level) { + log[level] = partial(log, level); }); // Don't allow TTL less than 5 minutes so we don't break synchronization - var minTTL = 300; + const minTTL = 300; // Use UTC or localtime for evaluating schedules - if (options.utc) - Later.date.UTC(); - else - Later.date.localTime(); + if (options.utc) Later.date.UTC(); + else Later.date.localTime(); // collection holding the job history records SyncedCron._collection = new Mongo.Collection(options.collectionName); - SyncedCron._collection._ensureIndex({intendedAt: 1, name: 1}, {unique: true}); + await SyncedCron._collection.createIndexAsync( + { intendedAt: 1, name: 1 }, + { unique: true }, + ); if (options.collectionTTL) { if (options.collectionTTL > minTTL) - SyncedCron._collection._ensureIndex({startedAt: 1 }, - { expireAfterSeconds: options.collectionTTL } ); - else - log.warn('Not going to use a TTL that is shorter than:' + minTTL); + await SyncedCron._collection.createIndexAsync( + { startedAt: 1 }, + { expireAfterSeconds: options.collectionTTL }, + ); + else log.warn("Not going to use a TTL that is shorter than:" + minTTL); } }); -var scheduleEntry = function(entry) { - var schedule = entry.schedule(Later.parse); - entry._timer = - SyncedCron._laterSetInterval(SyncedCron._entryWrapper(entry), schedule); - - log.info('Scheduled "' + entry.name + '" next run @' - + Later.schedule(schedule).next(1)); -} +const scheduleEntry = function (entry) { + const schedule = entry.schedule(Later.parse); + entry._timer = SyncedCron._laterSetInterval( + SyncedCron._entryWrapper(entry), + schedule, + ); + + log.info( + 'Scheduled "' + + entry.name + + '" next run @' + + Later.schedule(schedule).next(1), + ); +}; // add a scheduled job // SyncedCron.add({ @@ -113,7 +121,7 @@ var scheduleEntry = function(entry) { // schedule: function(laterParser) {},//*required* when to run the job // job: function() {}, //*required* the code to run // }); -SyncedCron.add = function(entry) { +SyncedCron.add = function (entry) { check(entry.name, String); check(entry.schedule, Function); check(entry.job, Function); @@ -132,84 +140,82 @@ SyncedCron.add = function(entry) { scheduleEntry(entry); } } -} +}; // Start processing added jobs -SyncedCron.start = function() { - var self = this; +SyncedCron.start = function () { + const self = this; - Meteor.startup(function() { + Meteor.startup(function () { // Schedule each job with later.js - _.each(self._entries, function(entry) { + Object.values(self._entries).forEach(function scheduleEachEntry(entry) { scheduleEntry(entry); }); self.running = true; }); -} +}; // Return the next scheduled date of the first matching entry or undefined -SyncedCron.nextScheduledAtDate = function(jobName) { - var entry = this._entries[jobName]; +SyncedCron.nextScheduledAtDate = function (jobName) { + const entry = this._entries[jobName]; - if (entry) - return Later.schedule(entry.schedule(Later.parse)).next(1); -} + if (entry) return Later.schedule(entry.schedule(Later.parse)).next(1); +}; // Remove and stop the entry referenced by jobName -SyncedCron.remove = function(jobName) { - var entry = this._entries[jobName]; +SyncedCron.remove = function (jobName) { + const entry = this._entries[jobName]; if (entry) { - if (entry._timer) - entry._timer.clear(); + if (entry._timer) entry._timer.clear(); delete this._entries[jobName]; log.info('Removed "' + entry.name + '"'); } -} +}; // Pause processing, but do not remove jobs so that the start method will // restart existing jobs -SyncedCron.pause = function() { +SyncedCron.pause = function () { if (this.running) { - _.each(this._entries, function(entry) { + Object.values(this._entries).forEach(function pauseEntry(entry) { entry._timer.clear(); }); this.running = false; } -} +}; // Stop processing and remove ALL jobs -SyncedCron.stop = function() { - _.each(this._entries, function(entry, name) { - SyncedCron.remove(name); +SyncedCron.stop = function () { + Object.values(this._entries).forEach(function stopEntry(entry) { + SyncedCron.remove(entry.name); }); this.running = false; -} +}; // The meat of our logic. Checks if the specified has already run. If not, // records that it's running the job, runs it, and records the output -SyncedCron._entryWrapper = function(entry) { - var self = this; +SyncedCron._entryWrapper = function (entry) { + const self = this; - return function(intendedAt) { + return async function syncedCronRun(intendedAt) { intendedAt = new Date(intendedAt.getTime()); intendedAt.setMilliseconds(0); - var jobHistory; + let jobHistory; if (entry.persist) { jobHistory = { intendedAt: intendedAt, name: entry.name, - startedAt: new Date() + startedAt: new Date(), }; // If we have a dup key error, another instance has already tried to run // this job. try { - jobHistory._id = self._collection.insert(jobHistory); - } catch(e) { + jobHistory._id = await self._collection.insertAsync(jobHistory); + } catch (e) { // http://www.mongodb.org/about/contributors/error-codes/ // 11000 == duplicate key error if (e.code === 11000) { @@ -218,43 +224,51 @@ SyncedCron._entryWrapper = function(entry) { } throw e; - }; + } } // run and record the job try { log.info('Starting "' + entry.name + '".'); - var output = entry.job(intendedAt,entry.name); // <- Run the actual job + const output = entry.job(intendedAt, entry.name); // <- Run the actual job log.info('Finished "' + entry.name + '".'); - if(entry.persist) { - self._collection.update({_id: jobHistory._id}, { - $set: { - finishedAt: new Date(), - result: output - } - }); + if (entry.persist) { + await self._collection.updateAsync( + { _id: jobHistory._id }, + { + $set: { + finishedAt: new Date(), + result: output, + }, + }, + ); } - } catch(e) { - log.info('Exception "' + entry.name +'" ' + ((e && e.stack) ? e.stack : e)); - if(entry.persist) { - self._collection.update({_id: jobHistory._id}, { - $set: { - finishedAt: new Date(), - error: (e && e.stack) ? e.stack : e - } - }); + } catch (e) { + log.info( + 'Exception "' + entry.name + '" ' + (e && e.stack ? e.stack : e), + ); + if (entry.persist) { + await self._collection.updateAsync( + { _id: jobHistory._id }, + { + $set: { + finishedAt: new Date(), + error: e && e.stack ? e.stack : e, + }, + }, + ); } } }; -} +}; // for tests -SyncedCron._reset = function() { +SyncedCron._reset = async function () { this._entries = {}; - this._collection.remove({}); + await this._collection.removeAsync({}); this.running = false; -} +}; // --------------------------------------------------------------------------- // The following two functions are lifted from the later.js package, however @@ -265,21 +279,22 @@ SyncedCron._reset = function() { // between multiple, potentially laggy and unsynced machines // From: https://github.com/bunkat/later/blob/master/src/core/setinterval.js -SyncedCron._laterSetInterval = function(fn, sched) { - - var t = SyncedCron._laterSetTimeout(scheduleTimeout, sched), - done = false; +SyncedCron._laterSetInterval = function (fn, sched) { + let t = SyncedCron._laterSetTimeout(scheduleTimeout, sched), + done = false; /** - * Executes the specified function and then sets the timeout for the next - * interval. - */ - function scheduleTimeout(intendedAt) { - if(!done) { + * Executes the specified function and then sets the timeout for the next + * interval. + */ + async function scheduleTimeout(intendedAt) { + if (!done) { try { - fn(intendedAt); - } catch(e) { - log.info('Exception running scheduled job ' + ((e && e.stack) ? e.stack : e)); + await fn(intendedAt); + } catch (e) { + log.info( + "Exception running scheduled job " + (e && e.stack ? e.stack : e), + ); } t = SyncedCron._laterSetTimeout(scheduleTimeout, sched); @@ -287,65 +302,59 @@ SyncedCron._laterSetInterval = function(fn, sched) { } return { - /** - * Clears the timeout. - */ - clear: function() { + * Clears the timeout. + */ + clear: function () { done = true; t.clear(); - } - + }, }; - }; // From: https://github.com/bunkat/later/blob/master/src/core/settimeout.js -SyncedCron._laterSetTimeout = function(fn, sched) { - - var s = Later.schedule(sched), t; +SyncedCron._laterSetTimeout = function (fn, sched) { + const s = Later.schedule(sched); + let t; scheduleTimeout(); /** - * Schedules the timeout to occur. If the next occurrence is greater than the - * max supported delay (2147483647 ms) than we delay for that amount before - * attempting to schedule the timeout again. - */ + * Schedules the timeout to occur. If the next occurrence is greater than the + * max supported delay (2147483647 ms) than we delay for that amount before + * attempting to schedule the timeout again. + */ function scheduleTimeout() { - var now = Date.now(), - next = s.next(2, now); + const now = Date.now(); + const next = s.next(2, now); // don't schedlue another occurence if no more exist synced-cron#41 - if (! next[0]) - return; + if (!next[0]) return; - var diff = next[0].getTime() - now, - intendedAt = next[0]; + let diff = next[0].getTime() - now; + let intendedAt = next[0]; // minimum time to fire is one second, use next occurrence instead - if(diff < 1000) { + if (diff < 1000) { diff = next[1].getTime() - now; intendedAt = next[1]; } - if(diff < 2147483647) { - t = Meteor.setTimeout(function() { fn(intendedAt); }, diff); - } - else { + if (diff < 2147483647) { + t = Meteor.setTimeout(async function () { + await fn(intendedAt); + }, diff); + } else { t = Meteor.setTimeout(scheduleTimeout, 2147483647); } } return { - /** - * Clears the timeout. - */ - clear: function() { + * Clears the timeout. + */ + clear: function () { Meteor.clearTimeout(t); - } - + }, }; - }; // --------------------------------------------------------------------------- diff --git a/synced-cron-tests.js b/synced-cron-tests.js index e3ee6b8..47f86f9 100644 --- a/synced-cron-tests.js +++ b/synced-cron-tests.js @@ -1,242 +1,259 @@ -Later = Npm.require('later'); +Later = Npm.require("@breejs/later"); Later.date.localTime(); // corresponds to SyncedCron.options.utc: true; -var TestEntry = { - name: 'Test Job', - schedule: function(parser) { - return parser.cron('15 10 * * ? *'); // not required +const TestEntry = { + name: "Test Job", + schedule: function (parser) { + return parser.cron("15 10 * * ? *"); // not required + }, + job: function () { + return "ran"; }, - job: function() { - return 'ran'; - } }; -Tinytest.add('Syncing works', function(test) { - SyncedCron._reset(); - test.equal(SyncedCron._collection.find().count(), 0); +Tinytest.addAsync("Syncing works", async function (test) { + await SyncedCron._reset(); + test.equal(await SyncedCron._collection.find().countAsync(), 0); // added the entry ok SyncedCron.add(TestEntry); - test.equal(_.keys(SyncedCron._entries).length, 1); + test.equal(Object.keys(SyncedCron._entries).length, 1); - var entry = SyncedCron._entries[TestEntry.name]; - var intendedAt = new Date(); //whatever + const entry = SyncedCron._entries[TestEntry.name]; + const intendedAt = new Date(); //whatever + console.log(`entry`, entry); // first run - SyncedCron._entryWrapper(entry)(intendedAt); - test.equal(SyncedCron._collection.find().count(), 1); - var jobHistory1 = SyncedCron._collection.findOne(); - test.equal(jobHistory1.result, 'ran'); + await SyncedCron._entryWrapper(entry)(intendedAt); + test.equal(await SyncedCron._collection.find().countAsync(), 1); + const jobHistory1 = await SyncedCron._collection.findOneAsync(); + test.equal(jobHistory1.result, "ran"); // second run - SyncedCron._entryWrapper(entry)(intendedAt); - test.equal(SyncedCron._collection.find().count(), 1); // should still be 1 - var jobHistory2 = SyncedCron._collection.findOne(); + await SyncedCron._entryWrapper(entry)(intendedAt); + test.equal(await SyncedCron._collection.find().countAsync(), 1); // should still be 1 + const jobHistory2 = await SyncedCron._collection.findOneAsync(); test.equal(jobHistory1._id, jobHistory2._id); }); -Tinytest.add('Exceptions work', function(test) { - SyncedCron._reset(); - SyncedCron.add(_.extend({}, TestEntry, { - job: function() { - throw new Meteor.Error('Haha, gotcha!'); - } - }) +Tinytest.addAsync("Exceptions work", async function (test) { + await SyncedCron._reset(); + SyncedCron.add( + Object.assign({}, TestEntry, { + job: function () { + throw new Meteor.Error("Haha, gotcha!"); + }, + }), ); - var entry = SyncedCron._entries[TestEntry.name]; - var intendedAt = new Date(); //whatever + const entry = SyncedCron._entries[TestEntry.name]; + const intendedAt = new Date(); //whatever // error without result - SyncedCron._entryWrapper(entry)(intendedAt); - test.equal(SyncedCron._collection.find().count(), 1); - var jobHistory1 = SyncedCron._collection.findOne(); + await SyncedCron._entryWrapper(entry)(intendedAt); + test.equal(await SyncedCron._collection.find().countAsync(), 1); + const jobHistory1 = await SyncedCron._collection.findOneAsync(); test.equal(jobHistory1.result, undefined); test.matches(jobHistory1.error, /Haha, gotcha/); }); -Tinytest.add('SyncedCron.nextScheduledAtDate works', function(test) { - SyncedCron._reset(); - test.equal(SyncedCron._collection.find().count(), 0); +Tinytest.addAsync( + "SyncedCron.nextScheduledAtDate works", + async function (test) { + await SyncedCron._reset(); + test.equal(await SyncedCron._collection.find().countAsync(), 0); - // addd 2 entries - SyncedCron.add(TestEntry); + // addd 2 entries + SyncedCron.add(TestEntry); - var entry2 = _.extend({}, TestEntry, { - name: 'Test Job2', - schedule: function(parser) { - return parser.cron('30 11 * * ? *'); - } - }); - SyncedCron.add(entry2); + const entry2 = Object.assign({}, TestEntry, { + name: "Test Job2", + schedule: function (parser) { + return parser.cron("30 11 * * ? *"); + }, + }); + SyncedCron.add(entry2); - test.equal(_.keys(SyncedCron._entries).length, 2); + test.equal(Object.keys(SyncedCron._entries).length, 2); - SyncedCron.start(); + SyncedCron.start(); - var date = SyncedCron.nextScheduledAtDate(entry2.name); - var correctDate = Later.schedule(entry2.schedule(Later.parse)).next(1); + const date = SyncedCron.nextScheduledAtDate(entry2.name); + const correctDate = Later.schedule(entry2.schedule(Later.parse)).next(1); - test.equal(date, correctDate); -}); + test.equal(date, correctDate); + }, +); // Tests SyncedCron.remove in the process -Tinytest.add('SyncedCron.stop works', function(test) { - SyncedCron._reset(); - test.equal(SyncedCron._collection.find().count(), 0); +Tinytest.addAsync("SyncedCron.stop works", async function (test) { + await SyncedCron._reset(); + test.equal(await SyncedCron._collection.find().countAsync(), 0); // addd 2 entries SyncedCron.add(TestEntry); - var entry2 = _.extend({}, TestEntry, { - name: 'Test Job2', - schedule: function(parser) { - return parser.cron('30 11 * * ? *'); - } + const entry2 = Object.assign({}, TestEntry, { + name: "Test Job2", + schedule: function (parser) { + return parser.cron("30 11 * * ? *"); + }, }); SyncedCron.add(entry2); SyncedCron.start(); - test.equal(_.keys(SyncedCron._entries).length, 2); + test.equal(Object.keys(SyncedCron._entries).length, 2); SyncedCron.stop(); - test.equal(_.keys(SyncedCron._entries).length, 0); + test.equal(Object.keys(SyncedCron._entries).length, 0); }); -Tinytest.add('SyncedCron.pause works', function(test) { - SyncedCron._reset(); - test.equal(SyncedCron._collection.find().count(), 0); +Tinytest.addAsync("SyncedCron.pause works", async function (test) { + await SyncedCron._reset(); + test.equal(await SyncedCron._collection.find().countAsync(), 0); // addd 2 entries SyncedCron.add(TestEntry); - var entry2 = _.extend({}, TestEntry, { - name: 'Test Job2', - schedule: function(parser) { - return parser.cron('30 11 * * ? *'); - } + const entry2 = Object.assign({}, TestEntry, { + name: "Test Job2", + schedule: function (parser) { + return parser.cron("30 11 * * ? *"); + }, }); SyncedCron.add(entry2); SyncedCron.start(); - test.equal(_.keys(SyncedCron._entries).length, 2); + test.equal(Object.keys(SyncedCron._entries).length, 2); SyncedCron.pause(); - test.equal(_.keys(SyncedCron._entries).length, 2); + test.equal(Object.keys(SyncedCron._entries).length, 2); test.isFalse(SyncedCron.running); SyncedCron.start(); - test.equal(_.keys(SyncedCron._entries).length, 2); + test.equal(Object.keys(SyncedCron._entries).length, 2); test.isTrue(SyncedCron.running); - }); // Tests SyncedCron.remove in the process -Tinytest.add('SyncedCron.add starts by it self when running', function(test) { - SyncedCron._reset(); +Tinytest.addAsync( + "SyncedCron.add starts by it self when running", + async function (test) { + await SyncedCron._reset(); - test.equal(SyncedCron._collection.find().count(), 0); - test.equal(SyncedCron.running, false); - Log._intercept(2); + test.equal(await SyncedCron._collection.find().countAsync(), 0); + test.equal(SyncedCron.running, false); + Log._intercept(2); - SyncedCron.start(); - - test.equal(SyncedCron.running, true); - - // addd 1 entries - SyncedCron.add(TestEntry); + SyncedCron.start(); - test.equal(_.keys(SyncedCron._entries).length, 1); + test.equal(SyncedCron.running, true); - SyncedCron.stop(); - - var intercepted = Log._intercepted(); - test.equal(intercepted.length, 2); - - test.equal(SyncedCron.running, false); - test.equal(_.keys(SyncedCron._entries).length, 0); -}); + // addd 1 entries + SyncedCron.add(TestEntry); -Tinytest.add('SyncedCron.config can customize the options object', function(test) { - SyncedCron._reset(); + test.equal(Object.keys(SyncedCron._entries).length, 1); - SyncedCron.config({ - log: false, - collectionName: 'foo', - utc: true, - collectionTTL: 0 - }); + SyncedCron.stop(); - test.equal(SyncedCron.options.log, false); - test.equal(SyncedCron.options.collectionName, 'foo'); - test.equal(SyncedCron.options.utc, true); - test.equal(SyncedCron.options.collectionTTL, 0); -}); + const intercepted = Log._intercepted(); + test.equal(intercepted.length, 2); -Tinytest.addAsync('SyncedCron can log to injected logger', function(test, done) { - SyncedCron._reset(); + test.equal(SyncedCron.running, false); + test.equal(Object.keys(SyncedCron._entries).length, 0); + }, +); + +Tinytest.addAsync( + "SyncedCron.config can customize the options object", + async function (test) { + await SyncedCron._reset(); + + SyncedCron.config({ + log: false, + collectionName: "foo", + utc: true, + collectionTTL: 0, + }); + + test.equal(SyncedCron.options.log, false); + test.equal(SyncedCron.options.collectionName, "foo"); + test.equal(SyncedCron.options.utc, true); + test.equal(SyncedCron.options.collectionTTL, 0); + }, +); - var logger = function() { - test.isTrue(true); +Tinytest.addAsync( + "SyncedCron can log to injected logger", + async function (test, done) { + await SyncedCron._reset(); - SyncedCron.stop(); - done(); - }; + const logger = function () { + test.isTrue(true); - SyncedCron.options.logger = logger; + SyncedCron.stop(); + done(); + }; - SyncedCron.add(TestEntry); - SyncedCron.start(); + SyncedCron.options.logger = logger; - SyncedCron.options.logger = null; -}); + SyncedCron.add(TestEntry); + SyncedCron.start(); -Tinytest.addAsync('SyncedCron should pass correct arguments to logger', function(test, done) { - SyncedCron._reset(); + SyncedCron.options.logger = null; + }, +); - var logger = function(opts) { - test.include(opts, 'level'); - test.include(opts, 'message'); - test.include(opts, 'tag'); - test.equal(opts.tag, 'SyncedCron'); +Tinytest.addAsync( + "SyncedCron should pass correct arguments to logger", + async function (test, done) { + await SyncedCron._reset(); - SyncedCron.stop(); - done(); - }; + const logger = function (opts) { + test.include(opts, "level"); + test.include(opts, "message"); + test.include(opts, "tag"); + test.equal(opts.tag, "SyncedCron"); - SyncedCron.options.logger = logger; + SyncedCron.stop(); + done(); + }; - SyncedCron.add(TestEntry); - SyncedCron.start(); + SyncedCron.options.logger = logger; - SyncedCron.options.logger = null; + SyncedCron.add(TestEntry); + SyncedCron.start(); -}); + SyncedCron.options.logger = null; + }, +); -Tinytest.add('Single time schedules don\'t break', function(test) { +Tinytest.addAsync("Single time schedules don't break", async function () { // create a once off date 1 sec in the future - var date = new Date(new Date().valueOf() + 1 * 1000); - var schedule = Later.parse.recur().on(date).fullDate(); + const date = new Date(new Date().valueOf() + 1000); + const schedule = Later.parse.recur().on(date).fullDate(); // this would throw without our patch for #41 - SyncedCron._laterSetTimeout(_.identity, schedule); + SyncedCron._laterSetTimeout(() => {}, schedule); }); +Tinytest.addAsync( + "Do not persist when flag is set to false", + async function (test) { + await SyncedCron._reset(); -Tinytest.add('Do not persist when flag is set to false', function (test) { - SyncedCron._reset(); + const testEntryNoPersist = Object.assign({}, TestEntry, { persist: false }); - var testEntryNoPersist = _.extend({}, TestEntry, {persist: false}); + SyncedCron.add(testEntryNoPersist); - SyncedCron.add(testEntryNoPersist); - - const now = new Date(); - SyncedCron._entryWrapper(testEntryNoPersist)(now); - test.equal(SyncedCron._collection.find().count(), 0); -}); \ No newline at end of file + const now = new Date(); + await SyncedCron._entryWrapper(testEntryNoPersist)(now); + test.equal(await SyncedCron._collection.find().countAsync(), 0); + }, +); diff --git a/versions.json b/versions.json deleted file mode 100644 index 5711dab..0000000 --- a/versions.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "dependencies": [ - [ - "application-configuration", - "1.0.1" - ], - [ - "binary-heap", - "1.0.0" - ], - [ - "callback-hook", - "1.0.0" - ], - [ - "check", - "1.0.0" - ], - [ - "ddp", - "1.0.8" - ], - [ - "ejson", - "1.0.1" - ], - [ - "follower-livedata", - "1.0.1" - ], - [ - "geojson-utils", - "1.0.0" - ], - [ - "id-map", - "1.0.0" - ], - [ - "json", - "1.0.0" - ], - [ - "logging", - "1.0.2" - ], - [ - "meteor", - "1.0.3" - ], - [ - "minimongo", - "1.0.2" - ], - [ - "mongo", - "1.0.4" - ], - [ - "ordered-dict", - "1.0.0" - ], - [ - "random", - "1.0.0" - ], - [ - "retry", - "1.0.0" - ], - [ - "tracker", - "1.0.2" - ], - [ - "underscore", - "1.0.0" - ] - ], - "pluginDependencies": [], - "toolVersion": "meteor-tool@1.0.28", - "format": "1.0" -} \ No newline at end of file From 0b36869105e7182401d50568244adeca649261d4 Mon Sep 17 00:00:00 2001 From: filipenevola Date: Wed, 8 Nov 2023 09:09:49 -0500 Subject: [PATCH 2/6] 2.0.0 (2023-11-8) - Migrates `later` to `@breejs/later@4.1.0` - Moves away from `underscore` - Moves away from `var` usage - Upgrades code to Meteor 3 - Upgrades tests to Meteor 3 (async tests) --- CHANGELOG.md | 13 +++++++++++++ README.md | 7 +++---- package.js | 2 +- 3 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..718b0fc --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,13 @@ +# Changelog + +## 2.0.0 (2023-11-8) + +- Migrates `later` to `@breejs/later@4.1.0` +- Moves away from `underscore` +- Moves away from `var` usage +- Upgrades code to Meteor 3 +- Upgrades tests to Meteor 3 (async tests) + +## 1.5.1 - littledata:synced-cron + +- Initial [version](https://github.com/percolatestudio/meteor-synced-cron). diff --git a/README.md b/README.md index b7c8c0c..1ded0d7 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ $ meteor add quave:synced-cron To write a cron job, give it a unique name, a schedule and a function to run like below. SyncedCron uses the fantastic [later.js](http://bunkat.github.io/later/) library behind the scenes. A Later.js `parse` object is passed into the schedule call that gives you a huge amount of flexibility for scheduling your jobs, see the [documentation](http://bunkat.github.io/later/parsers.html#overview). -``` js +```js SyncedCron.add({ name: 'Crunch some important numbers for the marketing department', schedule: function(parser) { @@ -32,8 +32,7 @@ SyncedCron.add({ return parser.text('every 2 hours'); }, job: function() { - var numbersCrunched = CrushSomeNumbers(); - return numbersCrunched; + crushSomeNumbers(); } }); ``` @@ -109,7 +108,7 @@ SyncedCron uses Meteor's `logging` package by default. If you want to use your o SyncedCron expects a function as `logger`, and will pass arguments to it for you to take action on. ```js -var MyLogger = function(opts) { +const MyLogger = function(opts) { console.log('Level', opts.level); console.log('Message', opts.message); console.log('Tag', opts.tag); diff --git a/package.js b/package.js index e354ba9..131bec3 100644 --- a/package.js +++ b/package.js @@ -3,7 +3,7 @@ Package.describe({ "Allows you to define and run scheduled jobs across multiple servers.", version: "2.0.0", name: "quave:synced-cron", - git: "https://github.com/percolatestudio/meteor-synced-cron.git", + git: "https://github.com/quavedev/meteor-synced-cron.git", }); Npm.depends({ "@breejs/later": "4.1.0" }); From 150ad19bc700385467ad03bc078ba71c20845110 Mon Sep 17 00:00:00 2001 From: filipenevola Date: Wed, 8 Nov 2023 16:21:38 -0500 Subject: [PATCH 3/6] 2.0.2 - Meteor 3 release issues, I had to run `chmod +rw .npm/package` for it to work. --- .versions | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ CHANGELOG.md | 10 ++++++++++ package.js | 4 ++-- 3 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 .versions diff --git a/.versions b/.versions new file mode 100644 index 0000000..a805e4a --- /dev/null +++ b/.versions @@ -0,0 +1,51 @@ +allow-deny@2.0.0-alpha300.17 +babel-compiler@7.11.0-alpha300.17 +babel-runtime@1.5.2-alpha300.17 +base64@1.0.13-alpha300.17 +binary-heap@1.0.12-alpha300.17 +boilerplate-generator@2.0.0-alpha300.17 +callback-hook@1.6.0-alpha300.17 +check@1.3.3-alpha300.17 +core-runtime@1.0.0-alpha300.17 +ddp@1.4.2-alpha300.17 +ddp-client@3.0.0-alpha300.17 +ddp-common@1.4.1-alpha300.17 +ddp-server@3.0.0-alpha300.17 +diff-sequence@1.1.3-alpha300.17 +dynamic-import@0.7.4-alpha300.17 +ecmascript@0.16.8-alpha300.17 +ecmascript-runtime@0.8.2-alpha300.17 +ecmascript-runtime-client@0.12.2-alpha300.17 +ecmascript-runtime-server@0.11.1-alpha300.17 +ejson@1.1.4-alpha300.17 +facts-base@1.0.2-alpha300.17 +fetch@0.1.4-alpha300.17 +geojson-utils@1.0.12-alpha300.17 +id-map@1.2.0-alpha300.17 +inter-process-messaging@0.1.2-alpha300.17 +local-test:quave:synced-cron@2.0.2 +logging@1.3.3-alpha300.17 +meteor@2.0.0-alpha300.17 +minimongo@2.0.0-alpha300.17 +modern-browsers@0.1.10-alpha300.17 +modules@0.19.1-alpha300.17 +modules-runtime@0.13.2-alpha300.17 +mongo@2.0.0-alpha300.17 +mongo-decimal@0.1.4-alpha300.17 +mongo-dev-server@1.1.1-alpha300.17 +mongo-id@1.0.9-alpha300.17 +npm-mongo@4.16.1-alpha300.17 +ordered-dict@1.2.0-alpha300.17 +promise@1.0.0-alpha300.17 +quave:synced-cron@2.0.2 +random@1.2.2-alpha300.17 +react-fast-refresh@0.2.8-alpha300.17 +reload@1.3.2-alpha300.17 +retry@1.1.1-alpha300.17 +routepolicy@1.1.2-alpha300.17 +socket-stream-client@0.5.2-alpha300.17 +tinytest@2.0.0-alpha300.17 +tracker@1.3.3-alpha300.17 +underscore@1.0.14-alpha300.17 +webapp@2.0.0-alpha300.17 +webapp-hashing@1.1.2-alpha300.17 diff --git a/CHANGELOG.md b/CHANGELOG.md index 718b0fc..d25bab0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,17 @@ # Changelog +## 2.0.2 (2023-11-8) + +- Meteor 3 release issues, I had to run `chmod +rw .npm/package` for it to work. + +## 2.0.1 (2023-11-8) + +This release failed but the content is present in the next. + ## 2.0.0 (2023-11-8) +This release failed but the content is present in the next. + - Migrates `later` to `@breejs/later@4.1.0` - Moves away from `underscore` - Moves away from `var` usage diff --git a/package.js b/package.js index 131bec3..974d93d 100644 --- a/package.js +++ b/package.js @@ -1,7 +1,7 @@ Package.describe({ summary: "Allows you to define and run scheduled jobs across multiple servers.", - version: "2.0.0", + version: "2.0.2", name: "quave:synced-cron", git: "https://github.com/quavedev/meteor-synced-cron.git", }); @@ -12,7 +12,7 @@ Package.onUse(function (api) { api.versionsFrom("METEOR@3.0-alpha.17"); api.use( - ["check", "mongo@1.0.0||2.0.0||2.0.0-alpha300.17", "logging"], + ["check@1.3.2||1.3.3-alpha300.17", "mongo@1.0.0||2.0.0||2.0.0-alpha300.17", "logging@1.3.2||1.3.3-alpha300.17"], "server", ); From bc678df2f5c66c932c311d8b76dff891386c3f3c Mon Sep 17 00:00:00 2001 From: filipenevola Date: Wed, 8 Nov 2023 16:29:02 -0500 Subject: [PATCH 4/6] Adds ecmascript --- package.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.js b/package.js index 974d93d..9aad564 100644 --- a/package.js +++ b/package.js @@ -11,6 +11,8 @@ Npm.depends({ "@breejs/later": "4.1.0" }); Package.onUse(function (api) { api.versionsFrom("METEOR@3.0-alpha.17"); + api.use('ecmascript@0.16.7||0.16.8-alpha300.17'); + api.use( ["check@1.3.2||1.3.3-alpha300.17", "mongo@1.0.0||2.0.0||2.0.0-alpha300.17", "logging@1.3.2||1.3.3-alpha300.17"], "server", From fd949aacc3d68be5a521032bd6cd5bd6b463a21a Mon Sep 17 00:00:00 2001 From: filipenevola Date: Sun, 12 Nov 2023 16:16:42 -0500 Subject: [PATCH 5/6] Removes console.log --- synced-cron-tests.js | 1 - 1 file changed, 1 deletion(-) diff --git a/synced-cron-tests.js b/synced-cron-tests.js index 47f86f9..15affeb 100644 --- a/synced-cron-tests.js +++ b/synced-cron-tests.js @@ -22,7 +22,6 @@ Tinytest.addAsync("Syncing works", async function (test) { const entry = SyncedCron._entries[TestEntry.name]; const intendedAt = new Date(); //whatever - console.log(`entry`, entry); // first run await SyncedCron._entryWrapper(entry)(intendedAt); From bfcf8536c14856f1878d2e0f94445f3eb7cc87e5 Mon Sep 17 00:00:00 2001 From: harryadel Date: Mon, 8 Jan 2024 08:41:34 +0200 Subject: [PATCH 6/6] Update package setup --- .github/workflows/codeql.yml | 41 + .github/workflows/comment-issue.yml | 31 + .github/workflows/testsuite.yml | 30 + package/synced-cron/.npm/package/.gitignore | 1 + package/synced-cron/.npm/package/README | 7 + .../.npm/package/npm-shrinkwrap.json | 10 + package.js => package/synced-cron/package.js | 10 +- .../synced-cron/synced-cron-server.js | 2 +- synced-cron-tests.js | 258 -- tests/.meteor/.finished-upgraders | 19 + tests/.meteor/.gitignore | 1 + tests/.meteor/.id | 7 + tests/.meteor/packages | 30 + tests/.meteor/platforms | 2 + tests/.meteor/release | 1 + tests/.meteor/versions | 70 + tests/package-lock.json | 2557 +++++++++++++++++ tests/package.json | 19 + tests/synced-cron.tests.js | 268 ++ 19 files changed, 3100 insertions(+), 264 deletions(-) create mode 100644 .github/workflows/codeql.yml create mode 100644 .github/workflows/comment-issue.yml create mode 100644 .github/workflows/testsuite.yml create mode 100644 package/synced-cron/.npm/package/.gitignore create mode 100644 package/synced-cron/.npm/package/README create mode 100644 package/synced-cron/.npm/package/npm-shrinkwrap.json rename package.js => package/synced-cron/package.js (75%) rename synced-cron-server.js => package/synced-cron/synced-cron-server.js (99%) delete mode 100644 synced-cron-tests.js create mode 100644 tests/.meteor/.finished-upgraders create mode 100644 tests/.meteor/.gitignore create mode 100644 tests/.meteor/.id create mode 100644 tests/.meteor/packages create mode 100644 tests/.meteor/platforms create mode 100644 tests/.meteor/release create mode 100644 tests/.meteor/versions create mode 100644 tests/package-lock.json create mode 100644 tests/package.json create mode 100644 tests/synced-cron.tests.js diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..a7676ce --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,41 @@ +name: "CodeQL" + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + schedule: + - cron: "34 22 * * 4" + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ javascript ] + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + queries: +security-and-quality + + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/comment-issue.yml b/.github/workflows/comment-issue.yml new file mode 100644 index 0000000..f71d991 --- /dev/null +++ b/.github/workflows/comment-issue.yml @@ -0,0 +1,31 @@ +name: Add immediate comment on new issues + +on: + issues: + types: [opened] + +jobs: + createComment: + runs-on: ubuntu-latest + steps: + - name: Create Comment + uses: peter-evans/create-or-update-comment@v1.4.2 + with: + issue-number: ${{ github.event.issue.number }} + body: | + Thank you for submitting this issue! + + We, the Members of Meteor Community Packages take every issue seriously. + Our goal is to provide long-term lifecycles for packages and keep up + with the newest changes in Meteor and the overall NodeJs/JavaScript ecosystem. + + However, we contribute to these packages mostly in our free time. + Therefore, we can't guarantee you issues to be solved within certain time. + + If you think this issue is trivial to solve, don't hesitate to submit + a pull request, too! We will accompany you in the process with reviews and hints + on how to get development set up. + + Please also consider sponsoring the maintainers of the package. + If you don't know who is currently maintaining this package, just leave a comment + and we'll let you know diff --git a/.github/workflows/testsuite.yml b/.github/workflows/testsuite.yml new file mode 100644 index 0000000..58197ec --- /dev/null +++ b/.github/workflows/testsuite.yml @@ -0,0 +1,30 @@ +# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions + +name: Test suite + +on: [push, pull_request] + +jobs: + tests: + name: tests + runs-on: ubuntu-latest + # needs: [lintcode,lintstyle,lintdocs] # we could add prior jobs for linting, if desired + steps: + - name: checkout + uses: actions/checkout@v3 + + - name: Setup meteor + uses: meteorengineer/setup-meteor@v1 + with: + meteor-release: '2.13.3' + + - name: cache dependencies + uses: actions/cache@v1 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + - run: cd tests && meteor npm install && meteor npm run test + diff --git a/package/synced-cron/.npm/package/.gitignore b/package/synced-cron/.npm/package/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/package/synced-cron/.npm/package/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/package/synced-cron/.npm/package/README b/package/synced-cron/.npm/package/README new file mode 100644 index 0000000..3d49255 --- /dev/null +++ b/package/synced-cron/.npm/package/README @@ -0,0 +1,7 @@ +This directory and the files immediately inside it are automatically generated +when you change this package's NPM dependencies. Commit the files in this +directory (npm-shrinkwrap.json, .gitignore, and this README) to source control +so that others run the same versions of sub-dependencies. + +You should NOT check in the node_modules directory that Meteor automatically +creates; if you are using git, the .gitignore file tells git to ignore it. diff --git a/package/synced-cron/.npm/package/npm-shrinkwrap.json b/package/synced-cron/.npm/package/npm-shrinkwrap.json new file mode 100644 index 0000000..73d6b9e --- /dev/null +++ b/package/synced-cron/.npm/package/npm-shrinkwrap.json @@ -0,0 +1,10 @@ +{ + "lockfileVersion": 4, + "dependencies": { + "@breejs/later": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@breejs/later/-/later-4.1.0.tgz", + "integrity": "sha512-QgGnZ9b7o4k0Ai1ZbTJWwZpZcFK9d+Gb+DyNt4UT9x6IEIs5HVu0iIlmgzGqN+t9MoJSpSPo9S/Mm51UtHr3JA==" + } + } +} diff --git a/package.js b/package/synced-cron/package.js similarity index 75% rename from package.js rename to package/synced-cron/package.js index 9aad564..12a4181 100644 --- a/package.js +++ b/package/synced-cron/package.js @@ -9,7 +9,7 @@ Package.describe({ Npm.depends({ "@breejs/later": "4.1.0" }); Package.onUse(function (api) { - api.versionsFrom("METEOR@3.0-alpha.17"); + api.versionsFrom("3.0-beta.0"); api.use('ecmascript@0.16.7||0.16.8-alpha300.17'); @@ -24,8 +24,8 @@ Package.onUse(function (api) { }); Package.onTest(function (api) { - api.use(["check", "mongo"], "server"); - api.use(["tinytest", "logging"]); - - api.addFiles(["synced-cron-server.js", "synced-cron-tests.js"], ["server"]); + api.use([ + // 'meteortesting:mocha@3.1.0-beta300.0', + 'quave:synced-cron@2.0.2' + ]) }); diff --git a/synced-cron-server.js b/package/synced-cron/synced-cron-server.js similarity index 99% rename from synced-cron-server.js rename to package/synced-cron/synced-cron-server.js index 2e05237..1af72c6 100644 --- a/synced-cron-server.js +++ b/package/synced-cron/synced-cron-server.js @@ -329,7 +329,7 @@ SyncedCron._laterSetTimeout = function (fn, sched) { // don't schedlue another occurence if no more exist synced-cron#41 if (!next[0]) return; - + let diff = next[0].getTime() - now; let intendedAt = next[0]; diff --git a/synced-cron-tests.js b/synced-cron-tests.js deleted file mode 100644 index 15affeb..0000000 --- a/synced-cron-tests.js +++ /dev/null @@ -1,258 +0,0 @@ -Later = Npm.require("@breejs/later"); - -Later.date.localTime(); // corresponds to SyncedCron.options.utc: true; - -const TestEntry = { - name: "Test Job", - schedule: function (parser) { - return parser.cron("15 10 * * ? *"); // not required - }, - job: function () { - return "ran"; - }, -}; - -Tinytest.addAsync("Syncing works", async function (test) { - await SyncedCron._reset(); - test.equal(await SyncedCron._collection.find().countAsync(), 0); - - // added the entry ok - SyncedCron.add(TestEntry); - test.equal(Object.keys(SyncedCron._entries).length, 1); - - const entry = SyncedCron._entries[TestEntry.name]; - const intendedAt = new Date(); //whatever - - // first run - await SyncedCron._entryWrapper(entry)(intendedAt); - test.equal(await SyncedCron._collection.find().countAsync(), 1); - const jobHistory1 = await SyncedCron._collection.findOneAsync(); - test.equal(jobHistory1.result, "ran"); - - // second run - await SyncedCron._entryWrapper(entry)(intendedAt); - test.equal(await SyncedCron._collection.find().countAsync(), 1); // should still be 1 - const jobHistory2 = await SyncedCron._collection.findOneAsync(); - test.equal(jobHistory1._id, jobHistory2._id); -}); - -Tinytest.addAsync("Exceptions work", async function (test) { - await SyncedCron._reset(); - SyncedCron.add( - Object.assign({}, TestEntry, { - job: function () { - throw new Meteor.Error("Haha, gotcha!"); - }, - }), - ); - - const entry = SyncedCron._entries[TestEntry.name]; - const intendedAt = new Date(); //whatever - - // error without result - await SyncedCron._entryWrapper(entry)(intendedAt); - test.equal(await SyncedCron._collection.find().countAsync(), 1); - const jobHistory1 = await SyncedCron._collection.findOneAsync(); - test.equal(jobHistory1.result, undefined); - test.matches(jobHistory1.error, /Haha, gotcha/); -}); - -Tinytest.addAsync( - "SyncedCron.nextScheduledAtDate works", - async function (test) { - await SyncedCron._reset(); - test.equal(await SyncedCron._collection.find().countAsync(), 0); - - // addd 2 entries - SyncedCron.add(TestEntry); - - const entry2 = Object.assign({}, TestEntry, { - name: "Test Job2", - schedule: function (parser) { - return parser.cron("30 11 * * ? *"); - }, - }); - SyncedCron.add(entry2); - - test.equal(Object.keys(SyncedCron._entries).length, 2); - - SyncedCron.start(); - - const date = SyncedCron.nextScheduledAtDate(entry2.name); - const correctDate = Later.schedule(entry2.schedule(Later.parse)).next(1); - - test.equal(date, correctDate); - }, -); - -// Tests SyncedCron.remove in the process -Tinytest.addAsync("SyncedCron.stop works", async function (test) { - await SyncedCron._reset(); - test.equal(await SyncedCron._collection.find().countAsync(), 0); - - // addd 2 entries - SyncedCron.add(TestEntry); - - const entry2 = Object.assign({}, TestEntry, { - name: "Test Job2", - schedule: function (parser) { - return parser.cron("30 11 * * ? *"); - }, - }); - SyncedCron.add(entry2); - - SyncedCron.start(); - - test.equal(Object.keys(SyncedCron._entries).length, 2); - - SyncedCron.stop(); - - test.equal(Object.keys(SyncedCron._entries).length, 0); -}); - -Tinytest.addAsync("SyncedCron.pause works", async function (test) { - await SyncedCron._reset(); - test.equal(await SyncedCron._collection.find().countAsync(), 0); - - // addd 2 entries - SyncedCron.add(TestEntry); - - const entry2 = Object.assign({}, TestEntry, { - name: "Test Job2", - schedule: function (parser) { - return parser.cron("30 11 * * ? *"); - }, - }); - SyncedCron.add(entry2); - - SyncedCron.start(); - - test.equal(Object.keys(SyncedCron._entries).length, 2); - - SyncedCron.pause(); - - test.equal(Object.keys(SyncedCron._entries).length, 2); - test.isFalse(SyncedCron.running); - - SyncedCron.start(); - - test.equal(Object.keys(SyncedCron._entries).length, 2); - test.isTrue(SyncedCron.running); -}); - -// Tests SyncedCron.remove in the process -Tinytest.addAsync( - "SyncedCron.add starts by it self when running", - async function (test) { - await SyncedCron._reset(); - - test.equal(await SyncedCron._collection.find().countAsync(), 0); - test.equal(SyncedCron.running, false); - Log._intercept(2); - - SyncedCron.start(); - - test.equal(SyncedCron.running, true); - - // addd 1 entries - SyncedCron.add(TestEntry); - - test.equal(Object.keys(SyncedCron._entries).length, 1); - - SyncedCron.stop(); - - const intercepted = Log._intercepted(); - test.equal(intercepted.length, 2); - - test.equal(SyncedCron.running, false); - test.equal(Object.keys(SyncedCron._entries).length, 0); - }, -); - -Tinytest.addAsync( - "SyncedCron.config can customize the options object", - async function (test) { - await SyncedCron._reset(); - - SyncedCron.config({ - log: false, - collectionName: "foo", - utc: true, - collectionTTL: 0, - }); - - test.equal(SyncedCron.options.log, false); - test.equal(SyncedCron.options.collectionName, "foo"); - test.equal(SyncedCron.options.utc, true); - test.equal(SyncedCron.options.collectionTTL, 0); - }, -); - -Tinytest.addAsync( - "SyncedCron can log to injected logger", - async function (test, done) { - await SyncedCron._reset(); - - const logger = function () { - test.isTrue(true); - - SyncedCron.stop(); - done(); - }; - - SyncedCron.options.logger = logger; - - SyncedCron.add(TestEntry); - SyncedCron.start(); - - SyncedCron.options.logger = null; - }, -); - -Tinytest.addAsync( - "SyncedCron should pass correct arguments to logger", - async function (test, done) { - await SyncedCron._reset(); - - const logger = function (opts) { - test.include(opts, "level"); - test.include(opts, "message"); - test.include(opts, "tag"); - test.equal(opts.tag, "SyncedCron"); - - SyncedCron.stop(); - done(); - }; - - SyncedCron.options.logger = logger; - - SyncedCron.add(TestEntry); - SyncedCron.start(); - - SyncedCron.options.logger = null; - }, -); - -Tinytest.addAsync("Single time schedules don't break", async function () { - // create a once off date 1 sec in the future - const date = new Date(new Date().valueOf() + 1000); - const schedule = Later.parse.recur().on(date).fullDate(); - - // this would throw without our patch for #41 - SyncedCron._laterSetTimeout(() => {}, schedule); -}); - -Tinytest.addAsync( - "Do not persist when flag is set to false", - async function (test) { - await SyncedCron._reset(); - - const testEntryNoPersist = Object.assign({}, TestEntry, { persist: false }); - - SyncedCron.add(testEntryNoPersist); - - const now = new Date(); - await SyncedCron._entryWrapper(testEntryNoPersist)(now); - test.equal(await SyncedCron._collection.find().countAsync(), 0); - }, -); diff --git a/tests/.meteor/.finished-upgraders b/tests/.meteor/.finished-upgraders new file mode 100644 index 0000000..c07b6ff --- /dev/null +++ b/tests/.meteor/.finished-upgraders @@ -0,0 +1,19 @@ +# This file contains information which helps Meteor properly upgrade your +# app when you run 'meteor update'. You should check it into version control +# with your project. + +notices-for-0.9.0 +notices-for-0.9.1 +0.9.4-platform-file +notices-for-facebook-graph-api-2 +1.2.0-standard-minifiers-package +1.2.0-meteor-platform-split +1.2.0-cordova-changes +1.2.0-breaking-changes +1.3.0-split-minifiers-package +1.4.0-remove-old-dev-bundle-link +1.4.1-add-shell-server-package +1.4.3-split-account-service-packages +1.5-add-dynamic-import-package +1.7-split-underscore-from-meteor-base +1.8.3-split-jquery-from-blaze diff --git a/tests/.meteor/.gitignore b/tests/.meteor/.gitignore new file mode 100644 index 0000000..4083037 --- /dev/null +++ b/tests/.meteor/.gitignore @@ -0,0 +1 @@ +local diff --git a/tests/.meteor/.id b/tests/.meteor/.id new file mode 100644 index 0000000..d4ab15b --- /dev/null +++ b/tests/.meteor/.id @@ -0,0 +1,7 @@ +# This file contains a token that is unique to your project. +# Check it into your repository along with the rest of this directory. +# It can be used for purposes such as: +# - ensuring you don't accidentally deploy one app on top of another +# - providing package authors with aggregated statistics + +1nydo23oqnttp22v79u diff --git a/tests/.meteor/packages b/tests/.meteor/packages new file mode 100644 index 0000000..62ffbce --- /dev/null +++ b/tests/.meteor/packages @@ -0,0 +1,30 @@ +# Meteor packages used by this project, one per line. +# Check this file (and the other files in this directory) into your repository. +# +# 'meteor add' and 'meteor remove' will edit this file for you, +# but you can also edit it by hand. + +meteor-base@1.5.2-beta300.0 # Packages every Meteor app needs to have +mongo@2.0.0-beta300.0 # The database Meteor supports right now +reactive-var@1.0.13-beta300.0 # Reactive variable for tracker +jquery # Helpful client-side library +tracker@1.3.3-beta300.0 # Meteor's client-side reactive programming library + +standard-minifier-css@1.9.3-beta300.0 # CSS minifier run for production mode +standard-minifier-js@3.0.0-beta300.0 # JS minifier run for production mode +es5-shim@4.8.1-beta300.0 # ECMAScript 5 compatibility for older browsers. +ecmascript@0.16.8-beta300.0 # Enable ECMAScript2015+ syntax in app code +shell-server@0.6.0-beta300.0 # Server-side component of the `meteor shell` command + +autopublish@1.0.8-beta300.0 # Publish all data to the clients (for prototyping) +insecure@1.0.8-beta300.0 # Allow all DB writes from clients (for prototyping) + +underscore@1.0.14-beta300.0 +dynamic-import@0.7.4-beta300.0 + +logging +quave:synced-cron +aldeed:simple-schema@1.13.1 +aldeed:collection2@4.0.0-beta.6 +meteortesting:mocha@3.1.0-beta300.0 +meteortesting:mocha-core@8.3.0-beta300.0 diff --git a/tests/.meteor/platforms b/tests/.meteor/platforms new file mode 100644 index 0000000..efeba1b --- /dev/null +++ b/tests/.meteor/platforms @@ -0,0 +1,2 @@ +server +browser diff --git a/tests/.meteor/release b/tests/.meteor/release new file mode 100644 index 0000000..3952621 --- /dev/null +++ b/tests/.meteor/release @@ -0,0 +1 @@ +METEOR@3.0-beta.0 diff --git a/tests/.meteor/versions b/tests/.meteor/versions new file mode 100644 index 0000000..5d7effc --- /dev/null +++ b/tests/.meteor/versions @@ -0,0 +1,70 @@ +aldeed:collection2@4.0.0-beta.6 +aldeed:simple-schema@1.13.1 +allow-deny@2.0.0-beta300.0 +autopublish@1.0.8-beta300.0 +autoupdate@2.0.0-beta300.0 +babel-compiler@7.11.0-beta300.0 +babel-runtime@1.5.2-beta300.0 +base64@1.0.13-beta300.0 +binary-heap@1.0.12-beta300.0 +boilerplate-generator@2.0.0-beta300.0 +callback-hook@1.6.0-beta300.0 +check@1.3.3-beta300.0 +core-runtime@1.0.0-beta300.0 +ddp@1.4.2-beta300.0 +ddp-client@3.0.0-beta300.0 +ddp-common@1.4.1-beta300.0 +ddp-server@3.0.0-beta300.0 +diff-sequence@1.1.3-beta300.0 +dynamic-import@0.7.4-beta300.0 +ecmascript@0.16.8-beta300.0 +ecmascript-runtime@0.8.2-beta300.0 +ecmascript-runtime-client@0.12.2-beta300.0 +ecmascript-runtime-server@0.11.1-beta300.0 +ejson@1.1.4-beta300.0 +es5-shim@4.8.1-beta300.0 +facts-base@1.0.2-beta300.0 +fetch@0.1.4-beta300.0 +geojson-utils@1.0.12-beta300.0 +hot-code-push@1.0.5-beta300.0 +http@1.0.1 +id-map@1.2.0-beta300.0 +insecure@1.0.8-beta300.0 +inter-process-messaging@0.1.2-beta300.0 +jquery@3.0.0 +logging@1.3.3-beta300.0 +meteor@2.0.0-beta300.0 +meteor-base@1.5.2-beta300.0 +meteortesting:browser-tests@1.6.0-beta300.0 +meteortesting:mocha@2.1.0 +meteortesting:mocha-core@8.3.1-beta300.0 +minifier-css@2.0.0-beta300.0 +minifier-js@3.0.0-beta300.0 +minimongo@2.0.0-beta300.0 +modern-browsers@0.1.10-beta300.0 +modules@0.19.1-beta300.0 +modules-runtime@0.13.2-beta300.0 +mongo@2.0.0-beta300.0 +mongo-decimal@0.1.4-beta300.0 +mongo-dev-server@1.1.1-beta300.0 +mongo-id@1.0.9-beta300.0 +npm-mongo@4.16.1-beta300.0 +ordered-dict@1.2.0-beta300.0 +promise@1.0.0-beta300.0 +quave:synced-cron@2.0.2 +raix:eventemitter@1.0.0 +random@1.2.2-beta300.0 +react-fast-refresh@0.2.8-beta300.0 +reactive-var@1.0.13-beta300.0 +reload@1.3.2-beta300.0 +retry@1.1.1-beta300.0 +routepolicy@1.1.2-beta300.0 +shell-server@0.6.0-beta300.0 +socket-stream-client@0.5.2-beta300.0 +standard-minifier-css@1.9.3-beta300.0 +standard-minifier-js@3.0.0-beta300.0 +tracker@1.3.3-beta300.0 +typescript@4.9.5-beta300.0 +underscore@1.0.14-beta300.0 +webapp@2.0.0-beta300.0 +webapp-hashing@1.1.2-beta300.0 diff --git a/tests/package-lock.json b/tests/package-lock.json new file mode 100644 index 0000000..92aec89 --- /dev/null +++ b/tests/package-lock.json @@ -0,0 +1,2557 @@ +{ + "name": "tests", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "tests", + "dependencies": { + "@babel/runtime": "^7.23.1", + "@breejs/later": "^4.1.0", + "jquery": "^3.5.1", + "meteor-node-stubs": "^1.2.7" + }, + "devDependencies": { + "expect": "^26.6.2", + "puppeteer": "^19.11.1" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/runtime": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.7.tgz", + "integrity": "sha512-w06OXVOFso7LcbzMiDGt+3X7Rh7Ho8MmgPoWU3rarH+8upf+wSU/grlGbWzQyr3DkdN6ZeuMFjpdwW0Q+HxobA==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@breejs/later": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@breejs/later/-/later-4.2.0.tgz", + "integrity": "sha512-EVMD0SgJtOuFeg0lAVbCwa+qeTKILb87jqvLyUtQswGD9+ce2nB52Y5zbTF1Hc0MDFfbydcMcxb47jSdhikVHA==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/@puppeteer/browsers": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-0.5.0.tgz", + "integrity": "sha512-Uw6oB7VvmPRLE4iKsjuOh8zgDabhNX67dzo8U/BB0f9527qx+4eeUs+korU98OhG5C4ubg7ufBgVi63XYwS6TQ==", + "dev": true, + "dependencies": { + "debug": "4.3.4", + "extract-zip": "2.0.1", + "https-proxy-agent": "5.0.1", + "progress": "2.0.3", + "proxy-from-env": "1.1.0", + "tar-fs": "2.1.1", + "unbzip2-stream": "1.4.3", + "yargs": "17.7.1" + }, + "bin": { + "browsers": "lib/cjs/main-cli.js" + }, + "engines": { + "node": ">=14.1.0" + }, + "peerDependencies": { + "typescript": ">= 4.7.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/node": { + "version": "20.10.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.6.tgz", + "integrity": "sha512-Vac8H+NlRNNlAmDfGUP7b5h/KA+AtWIzuXy0E6OyP8f1tCLYAtPvKRRDJjAPqhpCb0t6U2j7/xqAuLEebW2kiw==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "15.0.19", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", + "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/chromium-bidi": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.7.tgz", + "integrity": "sha512-6+mJuFXwTMU6I3vYLs6IL8A1DyQTPjCfIL971X0aMPVGRbGnNfl6i6Cl0NMbxi2bRYLGESt9T2ZIMRM5PAEcIQ==", + "dev": true, + "dependencies": { + "mitt": "3.0.0" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/cosmiconfig": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", + "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", + "dev": true, + "dependencies": { + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "dev": true, + "dependencies": { + "node-fetch": "2.6.7" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/devtools-protocol": { + "version": "0.0.1107588", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1107588.tgz", + "integrity": "sha512-yIR+pG9x65Xko7bErCUSQaDLrO/P1p3JUzEk7JCU4DowPcGHkTGUGQapcfcLc4qj0UaALwZ+cr0riFgiqpixcg==", + "dev": true + }, + "node_modules/diff-sequences": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz", + "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==", + "dev": true, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/expect": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-26.6.2.tgz", + "integrity": "sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA==", + "dev": true, + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-styles": "^4.0.0", + "jest-get-type": "^26.3.0", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-regex-util": "^26.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/jest-diff": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz", + "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^26.6.2", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/jest-get-type": { + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz", + "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==", + "dev": true, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/jest-matcher-utils": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz", + "integrity": "sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^26.6.2", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.6.2" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/jest-message-util": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.6.2.tgz", + "integrity": "sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "@jest/types": "^26.6.2", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.2", + "pretty-format": "^26.6.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.2" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/jest-regex-util": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz", + "integrity": "sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==", + "dev": true, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/jquery": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/meteor-node-stubs": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/meteor-node-stubs/-/meteor-node-stubs-1.2.7.tgz", + "integrity": "sha512-20bAFUhEIOD/Cos2nmvhqf2NOKpTf63WVQ+nwuaX2OFj31sU6GL4KkNylkWum8McwsH0LsMr/F+UHhduTX7KRg==", + "bundleDependencies": [ + "assert", + "browserify-zlib", + "buffer", + "console-browserify", + "constants-browserify", + "crypto-browserify", + "domain-browser", + "events", + "https-browserify", + "os-browserify", + "path-browserify", + "process", + "punycode", + "querystring-es3", + "readable-stream", + "stream-browserify", + "stream-http", + "string_decoder", + "timers-browserify", + "tty-browserify", + "url", + "util", + "vm-browserify" + ], + "dependencies": { + "assert": "^2.0.0", + "browserify-zlib": "^0.2.0", + "buffer": "^5.7.1", + "console-browserify": "^1.2.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.12.0", + "domain-browser": "^4.22.0", + "elliptic": "^6.5.4", + "events": "^3.3.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "^1.0.0", + "process": "^0.11.10", + "punycode": "^1.4.1", + "querystring-es3": "^0.2.1", + "readable-stream": "^3.6.0", + "stream-browserify": "^3.0.0", + "stream-http": "^3.2.0", + "string_decoder": "^1.3.0", + "timers-browserify": "^2.0.12", + "tty-browserify": "0.0.1", + "url": "^0.11.0", + "util": "^0.12.4", + "vm-browserify": "^1.1.2" + } + }, + "node_modules/meteor-node-stubs/node_modules/asn1.js": { + "version": "5.4.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/assert": { + "version": "2.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "es6-object-assign": "^1.1.0", + "is-nan": "^1.2.1", + "object-is": "^1.0.1", + "util": "^0.12.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/available-typed-arrays": { + "version": "1.0.4", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/base64-js": { + "version": "1.5.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/bn.js": { + "version": "5.2.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/brorand": { + "version": "1.1.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/browserify-aes": { + "version": "1.2.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/meteor-node-stubs/node_modules/browserify-cipher": { + "version": "1.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/browserify-des": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/meteor-node-stubs/node_modules/browserify-rsa": { + "version": "4.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/meteor-node-stubs/node_modules/browserify-sign": { + "version": "4.2.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/browserify-zlib": { + "version": "0.2.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "pako": "~1.0.5" + } + }, + "node_modules/meteor-node-stubs/node_modules/buffer": { + "version": "5.7.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "inBundle": true, + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/meteor-node-stubs/node_modules/buffer-xor": { + "version": "1.0.3", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/builtin-status-codes": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/call-bind": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/cipher-base": { + "version": "1.0.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/meteor-node-stubs/node_modules/console-browserify": { + "version": "1.2.0", + "inBundle": true + }, + "node_modules/meteor-node-stubs/node_modules/constants-browserify": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/create-ecdh": { + "version": "4.0.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/meteor-node-stubs/node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/create-hash": { + "version": "1.2.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/create-hmac": { + "version": "1.1.7", + "inBundle": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/meteor-node-stubs/node_modules/crypto-browserify": { + "version": "3.12.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/meteor-node-stubs/node_modules/define-properties": { + "version": "1.1.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/meteor-node-stubs/node_modules/des.js": { + "version": "1.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/diffie-hellman": { + "version": "5.0.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/domain-browser": { + "version": "4.22.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/meteor-node-stubs/node_modules/elliptic": { + "version": "6.5.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/meteor-node-stubs/node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/es-abstract": { + "version": "1.18.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.3", + "is-string": "^1.0.6", + "object-inspect": "^1.10.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/es-to-primitive": { + "version": "1.2.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/es6-object-assign": { + "version": "1.1.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/events": { + "version": "3.3.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/meteor-node-stubs/node_modules/evp_bytestokey": { + "version": "1.0.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/meteor-node-stubs/node_modules/foreach": { + "version": "2.0.5", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/function-bind": { + "version": "1.1.1", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/get-intrinsic": { + "version": "1.1.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/has": { + "version": "1.0.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/has-bigints": { + "version": "1.0.1", + "inBundle": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/has-symbols": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/hash-base": { + "version": "3.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/meteor-node-stubs/node_modules/hash.js": { + "version": "1.1.7", + "inBundle": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/meteor-node-stubs/node_modules/hmac-drbg": { + "version": "1.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/meteor-node-stubs/node_modules/https-browserify": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/ieee754": { + "version": "1.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "inBundle": true, + "license": "BSD-3-Clause" + }, + "node_modules/meteor-node-stubs/node_modules/inherits": { + "version": "2.0.4", + "inBundle": true, + "license": "ISC" + }, + "node_modules/meteor-node-stubs/node_modules/is-arguments": { + "version": "1.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/is-bigint": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/is-boolean-object": { + "version": "1.1.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/is-callable": { + "version": "1.2.3", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/is-date-object": { + "version": "1.0.4", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/is-generator-function": { + "version": "1.0.9", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/is-nan": { + "version": "1.3.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/is-negative-zero": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/is-number-object": { + "version": "1.0.5", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/is-regex": { + "version": "1.1.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/is-string": { + "version": "1.0.6", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/is-symbol": { + "version": "1.0.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/is-typed-array": { + "version": "1.1.5", + "inBundle": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.2", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.0-next.2", + "foreach": "^2.0.5", + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/md5.js": { + "version": "1.3.5", + "inBundle": true, + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/meteor-node-stubs/node_modules/miller-rabin": { + "version": "4.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/meteor-node-stubs/node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/minimalistic-assert": { + "version": "1.0.1", + "inBundle": true, + "license": "ISC" + }, + "node_modules/meteor-node-stubs/node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/object-inspect": { + "version": "1.10.3", + "inBundle": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/object-is": { + "version": "1.1.5", + "inBundle": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/object-keys": { + "version": "1.1.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/meteor-node-stubs/node_modules/object.assign": { + "version": "4.1.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/os-browserify": { + "version": "0.3.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/pako": { + "version": "1.0.11", + "inBundle": true, + "license": "(MIT AND Zlib)" + }, + "node_modules/meteor-node-stubs/node_modules/parse-asn1": { + "version": "5.1.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/meteor-node-stubs/node_modules/path-browserify": { + "version": "1.0.1", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/pbkdf2": { + "version": "3.1.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/meteor-node-stubs/node_modules/process": { + "version": "0.11.10", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/public-encrypt": { + "version": "4.0.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/meteor-node-stubs/node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/punycode": { + "version": "1.4.1", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/querystring": { + "version": "0.2.0", + "inBundle": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/meteor-node-stubs/node_modules/querystring-es3": { + "version": "0.2.1", + "inBundle": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/meteor-node-stubs/node_modules/randombytes": { + "version": "2.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/randomfill": { + "version": "1.0.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/readable-stream": { + "version": "3.6.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/meteor-node-stubs/node_modules/ripemd160": { + "version": "2.0.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/meteor-node-stubs/node_modules/safe-buffer": { + "version": "5.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/safer-buffer": { + "version": "2.1.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/setimmediate": { + "version": "1.0.5", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/sha.js": { + "version": "2.4.11", + "inBundle": true, + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/meteor-node-stubs/node_modules/stream-browserify": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/stream-http": { + "version": "3.2.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + } + }, + "node_modules/meteor-node-stubs/node_modules/string_decoder": { + "version": "1.3.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/string.prototype.trimend": { + "version": "1.0.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/string.prototype.trimstart": { + "version": "1.0.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/timers-browserify": { + "version": "2.0.12", + "inBundle": true, + "license": "MIT", + "dependencies": { + "setimmediate": "^1.0.4" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/tty-browserify": { + "version": "0.0.1", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/unbox-primitive": { + "version": "1.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/url": { + "version": "0.11.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/util": { + "version": "0.12.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/meteor-node-stubs/node_modules/util-deprecate": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/vm-browserify": { + "version": "1.1.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/meteor-node-stubs/node_modules/which-boxed-primitive": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/which-typed-array": { + "version": "1.1.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.2", + "call-bind": "^1.0.0", + "es-abstract": "^1.18.0-next.1", + "foreach": "^2.0.5", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.1", + "is-typed-array": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/meteor-node-stubs/node_modules/xtend": { + "version": "4.0.2", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mitt": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz", + "integrity": "sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==", + "dev": true + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "dev": true, + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/puppeteer": { + "version": "19.11.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-19.11.1.tgz", + "integrity": "sha512-39olGaX2djYUdhaQQHDZ0T0GwEp+5f9UB9HmEP0qHfdQHIq0xGQZuAZ5TLnJIc/88SrPLpEflPC+xUqOTv3c5g==", + "deprecated": "< 21.3.7 is no longer supported", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@puppeteer/browsers": "0.5.0", + "cosmiconfig": "8.1.3", + "https-proxy-agent": "5.0.1", + "progress": "2.0.3", + "proxy-from-env": "1.1.0", + "puppeteer-core": "19.11.1" + } + }, + "node_modules/puppeteer-core": { + "version": "19.11.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-19.11.1.tgz", + "integrity": "sha512-qcuC2Uf0Fwdj9wNtaTZ2OvYRraXpAK+puwwVW8ofOhOgLPZyz1c68tsorfIZyCUOpyBisjr+xByu7BMbEYMepA==", + "dev": true, + "dependencies": { + "@puppeteer/browsers": "0.5.0", + "chromium-bidi": "0.4.7", + "cross-fetch": "3.1.5", + "debug": "4.3.4", + "devtools-protocol": "0.0.1107588", + "extract-zip": "2.0.1", + "https-proxy-agent": "5.0.1", + "proxy-from-env": "1.1.0", + "tar-fs": "2.1.1", + "unbzip2-stream": "1.4.3", + "ws": "8.13.0" + }, + "engines": { + "node": ">=14.14.0" + }, + "peerDependencies": { + "typescript": ">= 4.7.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dev": true, + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + } +} diff --git a/tests/package.json b/tests/package.json new file mode 100644 index 0000000..a43c5e5 --- /dev/null +++ b/tests/package.json @@ -0,0 +1,19 @@ +{ + "name": "tests", + "private": true, + "scripts": { + "test": "TEST_CLIENT=0 METEOR_PACKAGE_DIRS=../package TEST_BROWSER_DRIVER=puppeteer meteor test --once --driver-package meteortesting:mocha --raw-logs", + "test:watch": "TEST_CLIENT=0 METEOR_PACKAGE_DIRS=../package:../../ TEST_BROWSER_DRIVER=puppeteer TEST_WATCH=1 meteor test --inspect --driver-package meteortesting:mocha --raw-logs", + "test:watch:browser": "METEOR_PACKAGE_DIRS=../package TEST_WATCH=1 meteor test --driver-package meteortesting:mocha --raw-logs" + }, + "dependencies": { + "@babel/runtime": "^7.23.1", + "jquery": "^3.5.1", + "meteor-node-stubs": "^1.2.7", + "@breejs/later": "^4.1.0" + }, + "devDependencies": { + "expect": "^26.6.2", + "puppeteer": "^19.11.1" + } +} diff --git a/tests/synced-cron.tests.js b/tests/synced-cron.tests.js new file mode 100644 index 0000000..955332e --- /dev/null +++ b/tests/synced-cron.tests.js @@ -0,0 +1,268 @@ +import expect from 'expect'; +import Later from "@breejs/later"; +import 'meteor/aldeed:collection2/dynamic' + +Collection2.load(); + +Later.date.localTime(); // corresponds to SyncedCron.options.utc: true; + +const TestEntry = { + name: "Test Job", + schedule: function (parser) { + return parser.cron("15 10 * * ? *"); // not required + }, + job: function () { + return "ran"; + }, +}; + +describe("Synced-Cron", function() { + + before(async function() { + await SyncedCron._collection.removeAsync({}) + }) + + it("Syncing works", async function () { + await SyncedCron._reset(); + expect(await SyncedCron._collection.find().countAsync()).toEqual(0); + + // added the entry ok + SyncedCron.add(TestEntry); + expect(Object.keys(SyncedCron._entries).length).toEqual(1); + + const entry = SyncedCron._entries[TestEntry.name]; + const intendedAt = new Date(); //whatever + + // first run + await SyncedCron._entryWrapper(entry)(intendedAt); + expect(await SyncedCron._collection.find().countAsync()).toEqual(1); + const jobHistory1 = await SyncedCron._collection.findOneAsync(); + expect(jobHistory1.result).toEqual("ran"); + + // second run + await SyncedCron._entryWrapper(entry)(intendedAt); + expect(await SyncedCron._collection.find().countAsync()).toEqual(1); // should still be 1 + const jobHistory2 = await SyncedCron._collection.findOneAsync(); + expect(jobHistory1._id).toEqual(jobHistory2._id); + }); + + it("Exceptions work", async function () { + await SyncedCron._reset(); + SyncedCron.add( + Object.assign({}, TestEntry, { + job: function () { + throw new Meteor.Error("Haha, gotcha!"); + }, + }), + ); + + const entry = SyncedCron._entries[TestEntry.name]; + const intendedAt = new Date(); //whatever + + // error without result + await SyncedCron._entryWrapper(entry)(intendedAt); + expect(await SyncedCron._collection.find().countAsync()).toEqual(1); + const jobHistory1 = await SyncedCron._collection.findOneAsync(); + expect(jobHistory1.result).toEqual(undefined); + expect(jobHistory1.error).toMatch(/Haha, gotcha/); + }); + + it( + "SyncedCron.nextScheduledAtDate works", + async function () { + await SyncedCron._reset(); + expect(await SyncedCron._collection.find().countAsync()).toEqual(0); + + // addd 2 entries + SyncedCron.add(TestEntry); + + const entry2 = Object.assign({}, TestEntry, { + name: "Test Job2", + schedule: function (parser) { + return parser.cron("30 11 * * ? *"); + }, + }); + SyncedCron.add(entry2); + + expect(Object.keys(SyncedCron._entries).length).toEqual(2); + + SyncedCron.start(); + + const date = SyncedCron.nextScheduledAtDate(entry2.name); + const correctDate = Later.schedule(entry2.schedule(Later.parse)).next(1); + + expect(date).toEqual(correctDate); + }, + ); + + // Tests SyncedCron.remove in the process + it("SyncedCron.stop works", async function () { + await SyncedCron._reset(); + expect(await SyncedCron._collection.find().countAsync()).toEqual(0); + + // addd 2 entries + SyncedCron.add(TestEntry); + + const entry2 = Object.assign({}, TestEntry, { + name: "Test Job2", + schedule: function (parser) { + return parser.cron("30 11 * * ? *"); + }, + }); + SyncedCron.add(entry2); + + SyncedCron.start(); + + expect(Object.keys(SyncedCron._entries).length).toEqual(2); + + SyncedCron.stop(); + + expect(Object.keys(SyncedCron._entries).length).toEqual(0); + }); + + it("SyncedCron.pause works", async function () { + await SyncedCron._reset(); + expect(await SyncedCron._collection.find().countAsync()).toEqual(0); + + // addd 2 entries + SyncedCron.add(TestEntry); + + const entry2 = Object.assign({}, TestEntry, { + name: "Test Job2", + schedule: function (parser) { + return parser.cron("30 11 * * ? *"); + }, + }); + SyncedCron.add(entry2); + + SyncedCron.start(); + + expect(Object.keys(SyncedCron._entries).length).toEqual(2); + + SyncedCron.pause(); + + expect(Object.keys(SyncedCron._entries).length).toEqual(2); + expect(SyncedCron.running).toBeFalsy(); + + SyncedCron.start(); + + expect(Object.keys(SyncedCron._entries).length).toEqual(2); + expect(SyncedCron.running).toBeTruthy(); + }); + + // Tests SyncedCron.remove in the process + it( + "SyncedCron.add starts by it self when running", + async function () { + await SyncedCron._reset(); + + expect(await SyncedCron._collection.find().countAsync()).toEqual(0); + expect(SyncedCron.running).toEqual(false); + Log._intercept(2); + + SyncedCron.start(); + + expect(SyncedCron.running).toEqual(true); + + // addd 1 entries + SyncedCron.add(TestEntry); + + expect(Object.keys(SyncedCron._entries).length).toEqual(1); + + SyncedCron.stop(); + + const intercepted = Log._intercepted(); + expect(intercepted.length).toEqual(2); + + expect(SyncedCron.running).toEqual(false); + expect(Object.keys(SyncedCron._entries).length).toEqual(0); + }, + ); + + it( + "SyncedCron.config can customize the options object", + async function () { + await SyncedCron._reset(); + + SyncedCron.config({ + log: false, + collectionName: "foo", + utc: true, + collectionTTL: 0, + }); + + expect(SyncedCron.options.log).toEqual(false); + expect(SyncedCron.options.collectionName).toEqual("foo"); + expect(SyncedCron.options.utc).toEqual(true); + expect(SyncedCron.options.collectionTTL).toEqual(0); + }, + ); + + it( + "SyncedCron can log to injected logger", + async function () { + await SyncedCron._reset(); + + const logger = function () { + SyncedCron.stop(); + }; + + SyncedCron.options.logger = logger; + + SyncedCron.add(TestEntry); + SyncedCron.start(); + + SyncedCron.options.logger = null; + }, + ); + + it("SyncedCron should pass correct arguments to logger", + async function () { + await SyncedCron._reset(); + + const logger = function (opts) { + expect(opts).toHaveProperty("level"); + expect(opts).toHaveProperty("message"); + expect(opts).toHaveProperty("tag"); + expect(opts.tag).toEqual("SyncedCron"); + + SyncedCron.stop(); + }; + + SyncedCron.options.logger = logger; + + SyncedCron.add(TestEntry); + SyncedCron.start(); + + SyncedCron.options.logger = null; + }, + ); + + it("Single time schedules don't break", async function () { + // create a once off date 1 sec in the future + const date = new Date(new Date().valueOf() + 1000); + const schedule = Later.parse.recur().on(date).fullDate(); + + // this would throw without our patch for #41 + SyncedCron._laterSetTimeout(() => {}, schedule); + }); + + it( + "Do not persist when flag is set to false", + async function () { + await SyncedCron._reset(); + + const testEntryNoPersist = Object.assign({}, TestEntry, { persist: false }); + + SyncedCron.add(testEntryNoPersist); + + const now = new Date(); + await SyncedCron._entryWrapper(testEntryNoPersist)(now); + const count = await SyncedCron._collection.find().countAsync(); + expect(count).toEqual(0); + }, + ); + + +}) +