From 74c6a423eeb3e653a6586c5824b8466c8e47efaf Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Tue, 28 Aug 2018 09:59:10 +0200 Subject: [PATCH 001/247] Allowed owners to give their characters to new owners, no UI yet. --- app/Model/Character/Characters.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Model/Character/Characters.js b/app/Model/Character/Characters.js index 7ba2ac97..1a1ae3a2 100644 --- a/app/Model/Character/Characters.js +++ b/app/Model/Character/Characters.js @@ -583,7 +583,7 @@ Characters.allow({ Characters.deny({ update: function(userId, docs, fields, modifier) { - // can't change owners - return _.contains(fields, "owner"); + // can't change owners unless you are the current owner + return _.contains(fields, "owner") && doc.owner !== userId; } }); From 06ffc94b4cec53fde864c0036d0f95c5db93ac8c Mon Sep 17 00:00:00 2001 From: Andrew Zhu Date: Fri, 7 Sep 2018 14:07:55 -0700 Subject: [PATCH 002/247] fix error in Characters.deny() Renamed `docs` to `doc`, since `doc.owner` was undefined. --- app/Model/Character/Characters.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Model/Character/Characters.js b/app/Model/Character/Characters.js index 1a1ae3a2..f60ef969 100644 --- a/app/Model/Character/Characters.js +++ b/app/Model/Character/Characters.js @@ -582,7 +582,7 @@ Characters.allow({ }); Characters.deny({ - update: function(userId, docs, fields, modifier) { + update: function(userId, doc, fields, modifier) { // can't change owners unless you are the current owner return _.contains(fields, "owner") && doc.owner !== userId; } From f4d3368fb478a6b20a95027a725e3fed87aa532a Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Tue, 25 Sep 2018 10:58:01 +0200 Subject: [PATCH 003/247] Updated cron job to clean database of soft removed documents --- app/.meteor/packages | 2 +- app/.meteor/versions | 2 +- app/server/lib/cron/deleteRemovedDocuments.js | 18 +++++++++++------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/app/.meteor/packages b/app/.meteor/packages index d28447d3..b0f17e3d 100644 --- a/app/.meteor/packages +++ b/app/.meteor/packages @@ -46,7 +46,6 @@ ecmascript@0.11.1 es5-shim@4.8.0 differential:vulcanize reactive-dict@1.2.0 -percolate:synced-cron ongoworks:speakingurl service-configuration@1.0.11 google-config-ui@1.0.0 @@ -54,3 +53,4 @@ dynamic-import@0.4.0 ddp-rate-limiter@1.0.7 rate-limit@1.0.9 iron:router +littledata:synced-cron diff --git a/app/.meteor/versions b/app/.meteor/versions index e5c754a6..80766fa9 100644 --- a/app/.meteor/versions +++ b/app/.meteor/versions @@ -64,6 +64,7 @@ jquery@1.11.11 lai:collection-extensions@0.2.1_1 launch-screen@1.1.1 less@2.7.12 +littledata:synced-cron@1.5.1 livedata@1.0.18 localstorage@1.2.0 logging@1.1.20 @@ -93,7 +94,6 @@ observe-sequence@1.0.16 ongoworks:speakingurl@9.0.0 ordered-dict@1.1.0 percolate:migrations@0.9.8 -percolate:synced-cron@1.3.2 promise@0.11.1 raix:eventemitter@0.1.3 random@1.1.0 diff --git a/app/server/lib/cron/deleteRemovedDocuments.js b/app/server/lib/cron/deleteRemovedDocuments.js index d450aaec..4be8aa27 100644 --- a/app/server/lib/cron/deleteRemovedDocuments.js +++ b/app/server/lib/cron/deleteRemovedDocuments.js @@ -15,29 +15,33 @@ Meteor.startup(() => { const now = new Date(); const thirtyMinutesAgo = new Date(now.getTime() - 30*60000); _.each(collections, (collection) => { - numRemoved += collection.remove({ + collection.remove({ removed: true, removedAt: {$lt: thirtyMinutesAgo} // dates *before* 30 minutes ago + }, function(error, result){ + if (error){ + console.error(error); + } }); }); - return numRemoved; }; SyncedCron.add({ - name: "Delete all soft removed items that haven't been restored", + name: "deleteSoftRemovedDocs", schedule: function(parser) { - return parser.text('every 6 hours'); + return parser.text('every 2 hours'); }, - job: function() { - deleteOldSoftRemovedDocs(); - } + job: deleteOldSoftRemovedDocs, }); + SyncedCron.start(); + // Add a method to manually trigger removal Meteor.methods({ deleteOldSoftRemovedDocs() { const user = Meteor.users.findOne(this.userId); if (user && _.contains(user.roles, "admin")){ + this.unblock(); return deleteOldSoftRemovedDocs(); } }, From f5a32cb50ac242d334548e47ab3a818fd6fb7e7e Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Tue, 2 Oct 2018 15:43:10 +0200 Subject: [PATCH 004/247] Cobbled together some semblance of an item library UI --- app/Model/Library/Library.js | 38 +++- app/Model/Library/LibraryAttacks.js | 2 +- app/Model/Library/LibraryEffects.js | 1 - app/Model/Library/LibraryItems.js | 47 ++++ app/Model/Users/Users.js | 4 + app/Routes/Routes.js | 2 +- .../itemLibraryDialog/itemLibraryDialog.html | 19 ++ .../itemLibraryDialog/itemLibraryDialog.js | 37 +++- .../library/itemLibrary/itemLibrary.html | 28 ++- .../views/library/itemLibrary/itemLibrary.js | 95 +++++++- .../libraryItemDialog/libraryItemDialog.html | 88 ++++++++ .../libraryItemDialog/libraryItemDialog.js | 204 ++++++++++++++++++ app/client/views/library/library.css | 19 ++ app/client/views/library/library.html | 20 +- app/client/views/library/library.js | 29 +++ .../library/libraryDialog/libraryDialog.html | 58 +++++ .../library/libraryDialog/libraryDialog.js | 95 ++++++++ app/server/publications/library.js | 15 ++ app/server/publications/user.js | 1 + 19 files changed, 775 insertions(+), 27 deletions(-) create mode 100644 app/client/views/library/itemLibrary/libraryItemDialog/libraryItemDialog.html create mode 100644 app/client/views/library/itemLibrary/libraryItemDialog/libraryItemDialog.js create mode 100644 app/client/views/library/library.css create mode 100644 app/client/views/library/library.js create mode 100644 app/client/views/library/libraryDialog/libraryDialog.html create mode 100644 app/client/views/library/libraryDialog/libraryDialog.js diff --git a/app/Model/Library/Library.js b/app/Model/Library/Library.js index 6688d0e5..edcb8cc1 100644 --- a/app/Model/Library/Library.js +++ b/app/Model/Library/Library.js @@ -2,14 +2,38 @@ Libraries = new Mongo.Collection("library"); Schemas.Library = new SimpleSchema({ name: {type: String}, - owner: {type: String, regEx: SimpleSchema.RegEx.Id}, - readers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: []}, - writers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: []}, - public: {type: Boolean, defaultValue: false}, + owner: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1}, + readers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: [], index: 1}, + writers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: [], index: 1}, + public: {type: Boolean, defaultValue: false, index: 1}, }); Libraries.attachSchema(Schemas.Library); +Libraries.after.remove(function(userId, library) { + LibraryItems.remove({library: library._id}); + LibrarySpells.remove({library: library._id}); +}); + +Meteor.methods({ + removeLibrary: function(libraryId) { + let library = Libraries.findOne(libraryId); + let userId = Meteor.userId(); + + if (!library) return; + if (library.owner === userId){ + Libraries.remove(libraryId); + } else { + if (_.contains(library.readers, userId)){ + Libraries.update(libraryId, {$pull: {"readers": userId}}); + } + if (_.contains(library.writers, userId)){ + Libraries.update(libraryId, {$pull: {"writers": userId}}); + } + } + }, +}); + Libraries.allow({ insert(userId, doc) { return userId && doc.owner === userId; @@ -18,16 +42,14 @@ Libraries.allow({ return canEdit(userId, doc); }, remove(userId, doc) { - return canEdit(userId, doc); + return userId && doc.owner === userId; }, fetch: ["owner", "writers"], }); Libraries.deny({ - // For now, only admins can manage libraries insert(userId, doc){ - var user = Meteor.users.findOne(userId); - return !user || !_.contains(user.roles, "admin"); + return !Meteor.users.findOne(userId); }, update(userId, doc, fields, modifier) { // Can't change owners diff --git a/app/Model/Library/LibraryAttacks.js b/app/Model/Library/LibraryAttacks.js index d606acd5..9d111498 100644 --- a/app/Model/Library/LibraryAttacks.js +++ b/app/Model/Library/LibraryAttacks.js @@ -1,7 +1,7 @@ Schemas.LibraryAttacks = new SimpleSchema({ name: { type: String, - defaultValue: "New Attack", + optional: true, trim: false, }, details: { diff --git a/app/Model/Library/LibraryEffects.js b/app/Model/Library/LibraryEffects.js index 4abcb1ef..38389d53 100644 --- a/app/Model/Library/LibraryEffects.js +++ b/app/Model/Library/LibraryEffects.js @@ -9,7 +9,6 @@ Schemas.LibraryEffects = new SimpleSchema({ defaultValue: "add", allowedValues: [ "base", - "proficiency", "add", "mul", "min", diff --git a/app/Model/Library/LibraryItems.js b/app/Model/Library/LibraryItems.js index 569e1df9..f95cd95e 100644 --- a/app/Model/Library/LibraryItems.js +++ b/app/Model/Library/LibraryItems.js @@ -42,3 +42,50 @@ LibraryItems.allow({ }, fetch: ["library"], }); + +Meteor.methods({ + updateLibraryItemEffect: function({itemId, effectIndex, field, value, unsetField}){ + let libraryId = LibraryItems.findOne(itemId).library; + let userId = Meteor.userId(); + if (!Libraries.canEdit(userId, libraryId)) return; + let modifier = { + $set: { + [`effects.${effectIndex}.${field}`]: value, + } + }; + if (unsetField){ + modifier.$unset = { + [`effects.${effectIndex}.${unsetField}`]: 1, + } + } + LibraryItems.update(itemId, modifier); + }, + removeLibraryItemEffect: function({itemId, effectIndex}){ + let libraryId = LibraryItems.findOne(itemId).library; + let userId = Meteor.userId(); + if (!Libraries.canEdit(userId, libraryId)) return; + LibraryItems.update(itemId, {$unset : { + [`effects.${effectIndex}`] : 1, + }}); + LibraryItems.update(itemId, {$pull : {"effects" : null}}); + }, + updateLibraryItemAttack: function({itemId, attackIndex, field, value}){ + let libraryId = LibraryItems.findOne(itemId).library; + let userId = Meteor.userId(); + if (!Libraries.canEdit(userId, libraryId)) return; + LibraryItems.update(itemId, { + $set: { + [`attacks.${attackIndex}.${field}`]: value, + } + }); + }, + removeLibraryItemAttack: function({itemId, attackIndex}){ + let libraryId = LibraryItems.findOne(itemId).library; + let userId = Meteor.userId(); + if (!Libraries.canEdit(userId, libraryId)) return; + LibraryItems.update(itemId, {$unset : { + [`attacks.${attackIndex}`] : 1, + }}); + LibraryItems.update(itemId, {$pull : {"attacks" : null}}); + }, +}) diff --git a/app/Model/Users/Users.js b/app/Model/Users/Users.js index bdbbdda4..5f6b2a7e 100644 --- a/app/Model/Users/Users.js +++ b/app/Model/Users/Users.js @@ -3,6 +3,10 @@ Schemas.UserProfile = new SimpleSchema({ type: String, optional: true, }, + librarySubscriptions: { + type: [String], + defaultValue: [], + }, }); Schemas.User = new SimpleSchema({ diff --git a/app/Routes/Routes.js b/app/Routes/Routes.js index 5d67332a..49accc2a 100644 --- a/app/Routes/Routes.js +++ b/app/Routes/Routes.js @@ -121,7 +121,7 @@ Router.map(function() { this.route("library", { path: "/library", waitOn: function(){ - return subsManager.subscribe("standardLibraries"); + return subsManager.subscribe("customLibraries"); }, onAfterAction: function() { document.title = appName + " - Library"; diff --git a/app/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.html b/app/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.html index 1dcb352e..50d6189f 100644 --- a/app/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.html +++ b/app/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.html @@ -48,6 +48,25 @@ {{/unless}} {{/each}} + {{#each customLibraries}} +
+ + + {{name}} +
+ + + + {{#each item in (itemsInLibrary _id)}} + {{>libraryItem item=item selected=(isSelected item)}} + {{/each}} + +
+ {{#unless ready _id}} + + {{/unless}} +
+ {{/each}} {{/if}} diff --git a/app/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.js b/app/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.js index 7ca93920..c21a9aba 100644 --- a/app/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.js +++ b/app/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.js @@ -7,6 +7,13 @@ const categories = [ {name: "Tools", key: "tools"}, ]; +const categoryKeys = [ + "weapons", + "armor", + "adventuringGear", + "tools", +]; + Template.itemLibraryDialog.onCreated(function(){ this.selectedItem = new ReactiveVar(); this.searchTerm = new ReactiveVar(); @@ -14,10 +21,17 @@ Template.itemLibraryDialog.onCreated(function(){ this.readyDict = new ReactiveDict(); this.searchReady = new ReactiveVar(); librarySubs.subscribe("standardLibraries"); + librarySubs.subscribe("customLibraries"); + this.autorun(() => { // Subscribe to all open categories _.each(this.categoriesOpen.get(), (key) => { - var handle = librarySubs.subscribe("standardLibraryItems", key); + let handle; + if (_.contains(categoryKeys, key)){ + handle = librarySubs.subscribe("standardLibraryItems", key); + } else { + handle = librarySubs.subscribe("libraryItems", key); + } this.autorun(() => { this.readyDict.set(key, handle.ready()); }); @@ -70,12 +84,29 @@ Template.itemLibraryDialog.helpers({ const searchTerm = Template.instance().searchTerm.get(); if (!searchTerm) return; return LibraryItems.find({ - library: "SRDLibraryGA3XWsd", name: { $regex: new RegExp(".*" + searchTerm + ".*", "gi") }, }); }, + customLibraries(){ + let userId = Meteor.userId(); + return Libraries.find({ + $or: [ + {readers: userId}, + {writers: userId}, + {owner: userId}, + ], + }); + }, + itemsInLibrary(libraryId){ + return LibraryItems.find({ + library: libraryId, + }, { + sort: {name: 1}, + }); + }, + }); Template.itemLibraryDialog.events({ @@ -93,7 +124,7 @@ Template.itemLibraryDialog.events({ }, "click .category-header": function(event, template){ let cats = template.categoriesOpen.get(); - const key = this.key; + const key = this.key || this._id; // Toggle whether this key is in the array or not if (_.contains(cats, key)){ cats = _.without(cats, key); diff --git a/app/client/views/library/itemLibrary/itemLibrary.html b/app/client/views/library/itemLibrary/itemLibrary.html index 5fbf353b..87047681 100644 --- a/app/client/views/library/itemLibrary/itemLibrary.html +++ b/app/client/views/library/itemLibrary/itemLibrary.html @@ -1,5 +1,29 @@ diff --git a/app/client/views/library/itemLibrary/itemLibrary.js b/app/client/views/library/itemLibrary/itemLibrary.js index 480effcc..06c733db 100644 --- a/app/client/views/library/itemLibrary/itemLibrary.js +++ b/app/client/views/library/itemLibrary/itemLibrary.js @@ -1,7 +1,94 @@ +const librarySubs = new SubsManager(); + +Template.itemLibrary.onCreated(function(){ + this.selectedTab = new ReactiveVar("0"); + this.librariesOpen = new ReactiveVar([]); + this.readyDict = new ReactiveDict(); + this.autorun(() => { + // Subscribe to all open libraries + _.each(this.librariesOpen.get(), (libraryId) => { + var handle = librarySubs.subscribe("libraryItems", libraryId); + this.autorun(() => { + this.readyDict.set(libraryId, handle.ready()); + }); + }); + }); +}); + Template.itemLibrary.helpers({ - items(){ - return Items.find({charId: {$in: [ - "SRDLibrary", - ]}}); + selectedTab(){ + return Template.instance().selectedTab.get(); + }, + libraries(){ + let userId = Meteor.userId(); + return Libraries.find({ + $or: [ + {readers: userId}, + {writers: userId}, + {owner: userId}, + ], + }); + }, + libraryItems(){ + return LibraryItems.find({ + library: this._id + },{ + sort: {name: 1} + }); + }, + ready(libraryId){ + return Template.instance().readyDict.get(libraryId); + }, + isOpen(libraryId){ + const librariesOpen = Template.instance().librariesOpen.get(); + return _.contains(librariesOpen, libraryId); }, }); + +Template.itemLibrary.events({ + "click .library-header": function(event, template){ + let libs = template.librariesOpen.get(); + const libraryId = this._id; + // Toggle whether this key is in the array or not + if (_.contains(libs, libraryId)){ + libs = _.without(libs, libraryId); + } else { + libs.push(libraryId); + } + template.librariesOpen.set(libs); + }, + "click .editLibrary": function(event, instance){ + event.stopPropagation(); + var libraryId = this._id; + pushDialogStack({ + template: "libraryDialog", + data: {libraryId}, + element: event.currentTarget.parentElement.parentElement, + returnElement: () => instance.find(`.library-header[data-id='${libraryId}']`), + }); + }, + "click .addItem": function(event, instance){ + event.stopPropagation(); + var libraryId = this._id; + var itemId = LibraryItems.insert({ + name: "New Library Item", + library: libraryId, + }); + pushDialogStack({ + template: "libraryItemDialog", + data: {itemId}, + element: event.currentTarget, + returnElement: () => instance.find(`.item-name[data-id='${itemId}']`), + }); + }, + "click .item-name": function(event, instance){ + event.stopPropagation(); + var itemId = this._id; + pushDialogStack({ + template: "libraryItemDialog", + data: {itemId}, + element: event.currentTarget, + returnElement: () => instance.find(`.item-name[data-id='${itemId}']`), + }); + }, +}) diff --git a/app/client/views/library/itemLibrary/libraryItemDialog/libraryItemDialog.html b/app/client/views/library/itemLibrary/libraryItemDialog/libraryItemDialog.html new file mode 100644 index 00000000..8fcfce0d --- /dev/null +++ b/app/client/views/library/itemLibrary/libraryItemDialog/libraryItemDialog.html @@ -0,0 +1,88 @@ + diff --git a/app/client/views/library/itemLibrary/libraryItemDialog/libraryItemDialog.js b/app/client/views/library/itemLibrary/libraryItemDialog/libraryItemDialog.js new file mode 100644 index 00000000..c258705d --- /dev/null +++ b/app/client/views/library/itemLibrary/libraryItemDialog/libraryItemDialog.js @@ -0,0 +1,204 @@ +Template.libraryItemDialog.helpers({ + item(){ + return LibraryItems.findOne(this.itemId); + }, + calculationOrValue(){ + return this.calculation || this.value; + }, + indexedEffects(){ + let item = LibraryItems.findOne(this.itemId); + if (!item) return; + return _.map(item.effects, (effect, index) => { + if (!effect) return; + effect.index = index; + return effect; + }); + }, + indexedAttacks(){ + let item = LibraryItems.findOne(this.itemId); + if (!item) return; + return _.map(item.attacks, (attack, index) => { + if (!attack) return; + attack.index = index; + return attack; + }); + }, + operationIndex(operation){ + const ref = { + base: 0, + add: 1, + mul: 2, + min: 3, + max: 4, + advantage: 5, + disadvantage: 6, + passiveAdd: 7, + fail: 8, + conditional: 9, + }; + return ref[operation]; + }, + damageTypeIndex(damageType){ + const ref = { + bludgeoning: 0, + piercing: 1, + slashing: 2, + acid: 3, + cold: 4, + fire: 5, + force: 6, + lightning: 7, + necrotic: 8, + poison: 9, + psychic: 10, + radiant: 11, + thunder: 12, + }; + return ref[damageType]; + } +}); + +const bind = function(field){ + return _.debounce(function(event){ + const input = event.currentTarget; + var value = input.value; + LibraryItems.update(this.itemId, { + $set: {[field]: value} + }, { + removeEmptyStrings: false, + trimStrings: false, + }); + }, 300); +}; + +Template.libraryItemDialog.events({ + "click #backButton": function(){ + popDialogStack(); + }, + "click #deleteButton": function(){ + LibraryItems.remove(this.itemId); + popDialogStack(); + }, + "input #libraryItemLibraryNameInput": bind("libraryName"), + "input #libraryItemNameInput": bind("name"), + "input #libraryItemPluralInput": bind("plural"), + "input #libraryItemQuantityInput": bind("quantity"), + "input #libraryItemValueInput": bind("value"), + "input #libraryItemWeightInput": bind("weight"), + "change #attunementCheckbox": function(event){ + LibraryItems.update(this.itemId, { + $set: {requiresAttunement: event.currentTarget.checked} + }); + }, + "change #incrementCheckbox": function(event){ + LibraryItems.update(this.itemId, { + $set: {"settings.showIncrement": event.currentTarget.checked} + }); + }, + "input #libraryItemDescriptionInput": bind("description"), + + // Effects + "click #addEffect": function(event, template){ + LibraryItems.update(template.data.itemId, { + $push: { + effects: {operation: "add"} + } + }); + }, + "iron-select .operationMenu": function(event, template){ + var detail = event.originalEvent.detail; + var opName = detail.item.getAttribute("name"); + if (opName == this.operation) return; + Meteor.call("updateLibraryItemEffect", { + itemId: template.data.itemId, + effectIndex: this.index, + field: "operation", + value: opName, + }); + }, + "input .LibraryItemEffectStat": _.debounce(function(event, template){ + Meteor.call("updateLibraryItemEffect", { + itemId: template.data.itemId, + effectIndex: this.index, + field: "stat", + value: event.currentTarget.value, + }); + }, 300), + "input .LibraryItemEffectValue": _.debounce(function(event, template){ + let value = event.currentTarget.value; + if (value && _.isFinite(+value)){ + Meteor.call("updateLibraryItemEffect", { + itemId: template.data.itemId, + effectIndex: this.index, + field: "value", + unsetField: "calculation", + value, + }); + } else { + Meteor.call("updateLibraryItemEffect", { + itemId: template.data.itemId, + effectIndex: this.index, + field: "calculation", + unsetField: "value", + value, + }); + } + }, 300), + "click .deleteEffect": function (event, template) { + Meteor.call("removeLibraryItemEffect", { + itemId: template.data.itemId, + effectIndex: this.index, + }); + }, + + // Attacks + "click #addAttack": function(event, template){ + LibraryItems.update(template.data.itemId, { + $push: { + attacks: {damageType: "slashing"} + } + }); + }, + "iron-select .damageTypeMenu": function(event, template){ + var detail = event.originalEvent.detail; + var damageType = detail.item.getAttribute("name"); + if (damageType == this.damageType) return; + Meteor.call("updateLibraryItemAttack", { + itemId: template.data.itemId, + attackIndex: this.index, + field: "damageType", + value: damageType, + }); + }, + "input .LibraryItemAttackBonusInput": _.debounce(function(event, template){ + Meteor.call("updateLibraryItemAttack", { + itemId: template.data.itemId, + attackIndex: this.index, + field: "attackBonus", + value: event.currentTarget.value, + }); + }, 300), + "input .LibraryItemAttackDamageInput": _.debounce(function(event, template){ + Meteor.call("updateLibraryItemAttack", { + itemId: template.data.itemId, + attackIndex: this.index, + field: "damage", + value: event.currentTarget.value, + }); + }, 300), + "input .LibraryItemAttackDetailsInput": _.debounce(function(event, template){ + Meteor.call("updateLibraryItemAttack", { + itemId: template.data.itemId, + attackIndex: this.index, + field: "details", + value: event.currentTarget.value, + }); + }, 300), + + "click .deleteAttack": function (event, template) { + Meteor.call("removeLibraryItemAttack", { + itemId: template.data.itemId, + attackIndex: this.index, + }); + }, +}); diff --git a/app/client/views/library/library.css b/app/client/views/library/library.css new file mode 100644 index 00000000..731d8036 --- /dev/null +++ b/app/client/views/library/library.css @@ -0,0 +1,19 @@ +.library .item-name { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + cursor: pointer; +} + +.library .library-header { + font-weight: 500; + cursor: pointer; +} + +.library .library-header iron-icon { + transition: transform 0.3s ease; +} + +.library .library-header iron-icon.open { + transform: rotate(90deg); +} diff --git a/app/client/views/library/library.html b/app/client/views/library/library.html index e22c9a84..b01f46ff 100644 --- a/app/client/views/library/library.html +++ b/app/client/views/library/library.html @@ -1,26 +1,32 @@ diff --git a/app/client/views/library/library.js b/app/client/views/library/library.js new file mode 100644 index 00000000..70d0e89d --- /dev/null +++ b/app/client/views/library/library.js @@ -0,0 +1,29 @@ +const librarySubs = new SubsManager(); + +Template.library.onCreated(function(){ + this.selectedTab = new ReactiveVar("0"); +}); + +Template.library.helpers({ + selectedTab(){ + return Template.instance().selectedTab.get(); + }, +}); + +Template.library.events({ + "iron-select #libraryTabs": function(event, instance){ + instance.selectedTab.set(event.target.selected); + }, + "click #addLibrary": function(event, instance){ + var libraryId = Libraries.insert({ + name: "New Library", + owner: Meteor.userId(), + }); + pushDialogStack({ + template: "libraryDialog", + data: {libraryId}, + element: event.currentTarget, + returnElement: () => instance.find(`.library-header[data-id='${libraryId}']`), + }); + }, +}) diff --git a/app/client/views/library/libraryDialog/libraryDialog.html b/app/client/views/library/libraryDialog/libraryDialog.html new file mode 100644 index 00000000..3fc83637 --- /dev/null +++ b/app/client/views/library/libraryDialog/libraryDialog.html @@ -0,0 +1,58 @@ + diff --git a/app/client/views/library/libraryDialog/libraryDialog.js b/app/client/views/library/libraryDialog/libraryDialog.js new file mode 100644 index 00000000..6c22b871 --- /dev/null +++ b/app/client/views/library/libraryDialog/libraryDialog.js @@ -0,0 +1,95 @@ +Template.libraryDialog.onCreated(function(){ + this.userId = new ReactiveVar(); + this.autorun(() => { + var library = Libraries.findOne(Template.currentData().libraryId, { + fields: {readers: 1, writers: 1, owner: 1} + }); + if (!library) return; + this.subscribe("userNames", _.union(library.readers, library.writers, [library.owner])); + }); +}); + +Template.libraryDialog.helpers({ + library(){ + return Libraries.findOne(this.libraryId); + }, + readers: function(){ + var library = Libraries.findOne(this.libraryId, {fields: {readers: 1}}); + return library && library.readers; + }, + writers: function(){ + var library = Libraries.findOne(this.libraryId, {fields: {writers: 1}}); + return library && library.writers + }, + username: function(id){ + const user = Meteor.users.findOne(id); + return user && user.username || "user: " + id; + }, + shareButtonDisabled: function(){ + return !Template.instance().userId.get(); + }, + userFindError: function(){ + if (!Template.instance().userId.get()){ + return "User not found"; + } + }, +}); + +Template.libraryDialog.events({ + "input #libraryNameInput": _.debounce(function(event){ + const input = event.currentTarget; + var name = input.value; + if (!name){ + input.invalid = true; + input.errorMessage = "Name is required"; + } else { + input.invalid = false; + Libraries.update(this.libraryId, { + $set: {name} + }, { + removeEmptyStrings: false, + trimStrings: false, + }); + } + }, 300), + "click #deleteButton": function(){ + Meteor.call("removeLibrary", this.libraryId); + popDialogStack(); + }, + "input #userNameOrEmailInput": + function(event, instance){ + var userName = instance.find("#userNameOrEmailInput").value; + instance.userId.set(undefined); + Meteor.call("getUserId", userName, function(err, result) { + if (err){ + console.error(err); + } else { + console.log(result); + instance.userId.set(result); + } + }); + }, + "click #shareButton": function(event, instance){ + var self = this; + var permission = instance.find("#accessLevelMenu").selected; + if (!permission) throw "no permission set"; + var userId = instance.userId.get(); + if (!userId) return; + if (permission === "write"){ + Libraries.update(self.libraryId, { + $addToSet: {writers: userId}, + $pull: {readers: userId}, + }); + } else { + Libraries.update(self.libraryId, { + $addToSet: {readers: userId}, + $pull: {writers: userId}, + }); + } + }, + "click .deleteShare": function(event, instance) { + Libraries.update(instance.data.libraryId, { + $pull: {writers: this.id, readers: this.id} + }); + }, +}); diff --git a/app/server/publications/library.js b/app/server/publications/library.js index 1e6a6441..3ab18ce3 100644 --- a/app/server/publications/library.js +++ b/app/server/publications/library.js @@ -23,3 +23,18 @@ Meteor.publish("standardLibrarySpells", function(level){ sort: {name: 1}, }); }); + +Meteor.publish("customLibraries", function(){ + userId = this.userId; + return Libraries.find({ + $or: [ + {readers: userId}, + {writers: userId}, + {owner: userId}, + ], + }); +}); + +Meteor.publish("libraryItems", function(libraryId){ + return LibraryItems.find({library: libraryId}); +}); diff --git a/app/server/publications/user.js b/app/server/publications/user.js index ceb648ff..799539fd 100644 --- a/app/server/publications/user.js +++ b/app/server/publications/user.js @@ -4,5 +4,6 @@ Meteor.publish("user", function(){ username: 1, profile: 1, apiKey: 1, + librarySubscriptions: 1, }}); }); From 1c00f5aa04960434d6f31a18ab4bc532d64898f1 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 4 Oct 2018 10:05:02 +0200 Subject: [PATCH 005/247] Hotfix iOS sign in issues (maybe) --- app/.gitignore | 1 + app/client/style/iosButtonFix.css | 8 ++++++++ 2 files changed, 9 insertions(+) create mode 100644 app/client/style/iosButtonFix.css diff --git a/app/.gitignore b/app/.gitignore index 88a0a828..086ca397 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -4,6 +4,7 @@ settings.json public/components public/_imports.html +private/oldClient nohup.out node_modules dump diff --git a/app/client/style/iosButtonFix.css b/app/client/style/iosButtonFix.css new file mode 100644 index 00000000..fa3799ec --- /dev/null +++ b/app/client/style/iosButtonFix.css @@ -0,0 +1,8 @@ +/* + * iOS doens't believe in click events for some elements. + * This is here to convince it to allow buttons to be clickable + */ + button { + cursor: pointer; + } + From 3f81d419f7e9186cc37e0205bcb7cb17cd54929b Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Wed, 10 Oct 2018 14:00:46 +0200 Subject: [PATCH 006/247] updated meteor --- app/.meteor/packages | 2 +- app/.meteor/release | 2 +- app/.meteor/versions | 67 +++++++++++++++++++++++--------------------- 3 files changed, 37 insertions(+), 34 deletions(-) diff --git a/app/.meteor/packages b/app/.meteor/packages index b0f17e3d..59ab11bd 100644 --- a/app/.meteor/packages +++ b/app/.meteor/packages @@ -49,7 +49,7 @@ reactive-dict@1.2.0 ongoworks:speakingurl service-configuration@1.0.11 google-config-ui@1.0.0 -dynamic-import@0.4.0 +dynamic-import@0.4.2 ddp-rate-limiter@1.0.7 rate-limit@1.0.9 iron:router diff --git a/app/.meteor/release b/app/.meteor/release index 04fe8b4f..4c71956e 100644 --- a/app/.meteor/release +++ b/app/.meteor/release @@ -1 +1 @@ -METEOR@1.7.0.3 +METEOR@1.7.0.5 diff --git a/app/.meteor/versions b/app/.meteor/versions index 80766fa9..f75ea35c 100644 --- a/app/.meteor/versions +++ b/app/.meteor/versions @@ -1,8 +1,8 @@ -accounts-base@1.4.2 -accounts-google@1.3.1 -accounts-oauth@1.1.15 +accounts-base@1.4.3 +accounts-google@1.3.2 +accounts-oauth@1.1.16 accounts-password@1.5.1 -accounts-ui@1.3.0 +accounts-ui@1.3.1 accounts-ui-unstyled@1.4.1 aldeed:collection2@2.10.0 aldeed:collection2-core@1.2.0 @@ -10,16 +10,16 @@ aldeed:schema-deny@1.1.0 aldeed:schema-index@1.1.1 aldeed:simple-schema@1.5.4 allow-deny@1.1.0 -autoupdate@1.4.1 -babel-compiler@7.1.1 -babel-runtime@1.2.2 +autoupdate@1.5.0 +babel-compiler@7.2.0 +babel-runtime@1.3.0 base64@1.0.11 -binary-heap@1.0.10 -blaze@2.3.2 +binary-heap@1.0.11 +blaze@2.3.3 blaze-html-templates@1.1.2 blaze-tools@1.0.10 -boilerplate-generator@1.5.0 -caching-compiler@1.1.12 +boilerplate-generator@1.6.0 +caching-compiler@1.2.0 caching-html-compiler@1.1.3 callback-hook@1.1.0 check@1.3.1 @@ -35,23 +35,25 @@ ddp-server@2.2.0 deps@1.0.12 diff-sequence@1.1.0 differential:vulcanize@3.0.0 -dynamic-import@0.4.1 -ecmascript@0.11.1 +dynamic-import@0.5.0 +ecmascript@0.12.0 ecmascript-runtime@0.7.0 -ecmascript-runtime-client@0.7.1 -ecmascript-runtime-server@0.7.0 +ecmascript-runtime-client@0.8.0 +ecmascript-runtime-server@0.7.1 ecwyne:mathjs@0.25.0 ejson@1.1.0 email@1.2.3 es5-shim@4.8.0 +fetch@0.1.0 geojson-utils@1.0.10 -google-config-ui@1.0.0 -google-oauth@1.2.5 +google-config-ui@1.0.1 +google-oauth@1.2.6 hot-code-push@1.0.4 html-tools@1.0.11 htmljs@1.0.11 http@1.4.1 id-map@1.1.0 +inter-process-messaging@0.1.0 iron:controller@1.0.12 iron:core@1.0.11 iron:dynamic-template@1.0.12 @@ -63,7 +65,7 @@ iron:url@1.1.0 jquery@1.11.11 lai:collection-extensions@0.2.1_1 launch-screen@1.1.1 -less@2.7.12 +less@2.8.0 littledata:synced-cron@1.5.1 livedata@1.0.18 localstorage@1.2.0 @@ -73,23 +75,24 @@ mdg:validation-error@0.5.1 meteor@1.9.2 meteor-base@1.4.0 meteorhacks:subs-manager@1.6.4 -minifier-css@1.3.1 -minifier-js@2.3.5 -minimongo@1.4.4 +minifier-css@1.4.0 +minifier-js@2.4.0 +minimongo@1.4.5 mobile-experience@1.0.5 mobile-status-bar@1.0.14 modern-browsers@0.1.2 -modules@0.12.2 +modules@0.13.0 modules-runtime@0.10.2 momentjs:moment@2.22.2 -mongo@1.5.1 +mongo@1.6.0 +mongo-decimal@0.1.0 mongo-dev-server@1.1.0 mongo-id@1.0.7 nikogosovd:multiple-uihooks@0.1.8 npm-bcrypt@0.9.3 -npm-mongo@3.0.11 +npm-mongo@3.1.1 oauth@1.2.3 -oauth2@1.2.0 +oauth2@1.2.1 observe-sequence@1.0.16 ongoworks:speakingurl@9.0.0 ordered-dict@1.1.0 @@ -98,25 +101,25 @@ promise@0.11.1 raix:eventemitter@0.1.3 random@1.1.0 rate-limit@1.0.9 -reactive-dict@1.2.0 +reactive-dict@1.2.1 reactive-var@1.0.11 reload@1.2.0 retry@1.1.0 reywood:iron-router-ga@0.7.1 -routepolicy@1.0.13 +routepolicy@1.1.0 seba:minifiers-autoprefixer@1.0.1 service-configuration@1.0.11 -session@1.1.7 +session@1.1.8 sha@1.0.9 -shell-server@0.3.1 +shell-server@0.4.0 socket-stream-client@0.2.2 softwarerero:accounts-t9n@1.3.11 spacebars@1.0.15 spacebars-compiler@1.1.3 splendido:accounts-emails-field@1.2.0 splendido:accounts-meld@1.3.1 -srp@1.0.10 -standard-minifier-js@2.3.4 +srp@1.0.12 +standard-minifier-js@2.4.0 templates:array@1.0.3 templating@1.3.2 templating-compiler@1.3.3 @@ -129,7 +132,7 @@ url@1.2.0 useraccounts:core@1.14.2 useraccounts:iron-routing@1.14.2 useraccounts:polymer@1.14.2 -webapp@1.6.2 +webapp@1.7.0 webapp-hashing@1.0.9 wizonesolutions:canonical@0.0.5 zimme:collection-behaviours@1.1.3 From e17dbf6601c660b1ecb9f07d31f33564684d75f0 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Wed, 10 Oct 2018 14:28:48 +0200 Subject: [PATCH 007/247] Upgrade to meteor 1.8 --- app/.meteor/packages | 20 +- app/.meteor/release | 2 +- app/.meteor/versions | 2 +- app/bower.json | 4 +- app/package-lock.json | 988 +++++++++++++++++++++--------------------- app/package.json | 9 +- 6 files changed, 514 insertions(+), 511 deletions(-) diff --git a/app/.meteor/packages b/app/.meteor/packages index 59ab11bd..e48d58c7 100644 --- a/app/.meteor/packages +++ b/app/.meteor/packages @@ -4,7 +4,7 @@ # but you can also edit it by hand. accounts-password@1.5.1 -accounts-ui@1.3.0 +accounts-ui@1.3.1 random@1.1.0 dburles:collection-helpers reactive-var@1.0.11 @@ -17,7 +17,7 @@ dburles:mongo-collection-instances percolate:migrations ecwyne:mathjs useraccounts:polymer -accounts-google@1.3.1 +accounts-google@1.3.2 splendido:accounts-meld email@1.2.3 meteorhacks:subs-manager @@ -25,9 +25,9 @@ chuangbo:marked reywood:iron-router-ga meteor-base@1.4.0 mobile-experience@1.0.5 -mongo@1.5.0 +mongo@1.6.0 blaze-html-templates -session@1.1.7 +session@1.1.8 jquery@1.11.10 tracker@1.2.0 logging@1.1.20 @@ -37,19 +37,19 @@ spacebars check@1.3.1 useraccounts:iron-routing wizonesolutions:canonical -standard-minifier-js@2.3.4 -shell-server@0.3.1 +standard-minifier-js@2.4.0 +shell-server@0.4.0 seba:minifiers-autoprefixer nikogosovd:multiple-uihooks templates:array -ecmascript@0.11.1 +ecmascript@0.12.0 es5-shim@4.8.0 differential:vulcanize -reactive-dict@1.2.0 +reactive-dict@1.2.1 ongoworks:speakingurl service-configuration@1.0.11 -google-config-ui@1.0.0 -dynamic-import@0.4.2 +google-config-ui@1.0.1 +dynamic-import@0.5.0 ddp-rate-limiter@1.0.7 rate-limit@1.0.9 iron:router diff --git a/app/.meteor/release b/app/.meteor/release index 4c71956e..e76dedee 100644 --- a/app/.meteor/release +++ b/app/.meteor/release @@ -1 +1 @@ -METEOR@1.7.0.5 +METEOR@1.8 diff --git a/app/.meteor/versions b/app/.meteor/versions index f75ea35c..be46ee81 100644 --- a/app/.meteor/versions +++ b/app/.meteor/versions @@ -107,7 +107,7 @@ reload@1.2.0 retry@1.1.0 reywood:iron-router-ga@0.7.1 routepolicy@1.1.0 -seba:minifiers-autoprefixer@1.0.1 +seba:minifiers-autoprefixer@1.1.1 service-configuration@1.0.11 session@1.1.8 sha@1.0.9 diff --git a/app/bower.json b/app/bower.json index b6299b5d..1ce65cf0 100644 --- a/app/bower.json +++ b/app/bower.json @@ -1,6 +1,6 @@ { - "name": "RPG Docs", - "version": "0.0.0", + "name": "dicecloud", + "version": "1", "homepage": "", "authors": [ "Stefan Zermatten" diff --git a/app/package-lock.json b/app/package-lock.json index e5c83ad5..12e5ed0b 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -1,16 +1,15 @@ { - "name": "rpg-docs", + "name": "dicecloud", "version": "0.10.0", "lockfileVersion": 1, "requires": true, "dependencies": { "@babel/runtime": { - "version": "7.0.0-beta.49", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0-beta.49.tgz", - "integrity": "sha1-A7O/B+uYIHLI6FHdLd1RECguYb8=", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.1.2.tgz", + "integrity": "sha512-Y3SCjmhSupzFB6wcv1KmmFucH6gDVnI30WjOcicV10ju0cZjak3Jcs67YLIXBrmZYw1xCrVeJPbycFwrqNyxpg==", "requires": { - "core-js": "2.5.7", - "regenerator-runtime": "0.11.1" + "regenerator-runtime": "^0.12.0" } }, "@polymer/polymer": { @@ -18,7 +17,7 @@ "resolved": "https://registry.npmjs.org/@polymer/polymer/-/polymer-1.2.5-npm-test.2.tgz", "integrity": "sha1-eTD1ZjwvaGkVRR0hHmY6qZl9czY=", "requires": { - "webcomponents.js": "0.7.24" + "webcomponents.js": "^0.7.20" } }, "abbrev": { @@ -31,10 +30,10 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" }, "dependencies": { "co": { @@ -45,7 +44,8 @@ } }, "ansi-regex": { - "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "aproba": { @@ -63,22 +63,6 @@ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "requires": { - "core-js": "2.5.7", - "regenerator-runtime": "0.11.1" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" - } - } - }, "bcrypt": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-1.0.3.tgz", @@ -89,10 +73,10 @@ } }, "block-stream": { - "version": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "version": "0.0.9", "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", "requires": { - "inherits": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + "inherits": "~2.0.0" } }, "bower": { @@ -101,9 +85,9 @@ "integrity": "sha1-54dqB23rgTf30GUl3F6MZtuC8oo=" }, "buffer-from": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", - "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" }, "builtin-modules": { "version": "1.1.1", @@ -120,7 +104,7 @@ "resolved": "https://registry.npmjs.org/can-promise/-/can-promise-0.0.1.tgz", "integrity": "sha512-gzVrHyyrvgt0YpDm7pn04MQt8gjh0ZAhN4ZDyCRtGl6YnuuK6b4aiUTD7G52r9l4YNmxfTtEscb92vxtAlL6XQ==", "requires": { - "window-or-global": "1.0.1" + "window-or-global": "^1.0.1" } }, "cliui": { @@ -128,13 +112,26 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "requires": { - "string-width": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "wrap-ansi": "2.1.0" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } } }, "code-point-at": { - "version": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "core-js": { @@ -147,9 +144,9 @@ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "requires": { - "lru-cache": "4.1.1", - "shebang-command": "1.2.0", - "which": "1.3.0" + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" } }, "debug": { @@ -171,11 +168,11 @@ "integrity": "sha1-082BIh4+pAdCz83lVtTpnpjdxxs=" }, "error-ex": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "requires": { - "is-arrayish": "0.2.1" + "is-arrayish": "^0.2.1" } }, "execa": { @@ -183,13 +180,13 @@ "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "strip-eof": "1.0.0" + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" } }, "extsprintf": { @@ -217,7 +214,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "requires": { - "locate-path": "2.0.0" + "locate-path": "^2.0.0" } }, "form-data": { @@ -225,9 +222,9 @@ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "requires": { - "asynckit": "0.4.0", + "asynckit": "^0.4.0", "combined-stream": "1.0.6", - "mime-types": "2.1.18" + "mime-types": "^2.1.12" }, "dependencies": { "asynckit": { @@ -240,7 +237,7 @@ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "requires": { - "delayed-stream": "1.0.0" + "delayed-stream": "~1.0.0" } }, "delayed-stream": { @@ -251,17 +248,18 @@ } }, "get-caller-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" }, "get-stream": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" }, "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, "har-schema": { @@ -274,23 +272,23 @@ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", "requires": { - "ajv": "5.5.2", - "har-schema": "2.0.0" + "ajv": "^5.1.0", + "har-schema": "^2.0.0" } }, "hosted-git-info": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==" + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.14.1" + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" }, "dependencies": { "asn1": { @@ -304,7 +302,7 @@ "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", "optional": true, "requires": { - "tweetnacl": "0.14.5" + "tweetnacl": "^0.14.3" } }, "dashdash": { @@ -312,7 +310,7 @@ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" } }, "ecc-jsbn": { @@ -321,7 +319,7 @@ "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", "optional": true, "requires": { - "jsbn": "0.1.1" + "jsbn": "~0.1.0" } }, "getpass": { @@ -329,7 +327,7 @@ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" } }, "jsbn": { @@ -343,14 +341,14 @@ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "tweetnacl": "~0.14.0" } }, "tweetnacl": { @@ -362,7 +360,7 @@ } }, "inherits": { - "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "version": "2.0.3", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "invert-kv": { @@ -377,17 +375,18 @@ }, "is-builtin-module": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "requires": { - "builtin-modules": "1.1.1" + "builtin-modules": "^1.0.0" } }, "is-fullwidth-code-point": { - "version": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "requires": { - "number-is-nan": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" + "number-is-nan": "^1.0.0" } }, "is-stream": { @@ -395,6 +394,11 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, + "isarray": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.4.tgz", + "integrity": "sha512-GMxXOiUirWg1xTKRipM0Ek07rX+ubx4nNVElTJdNLYmNO/2YrDkgJGw9CljXn+r4EWiDQg/8lsRdHyg2PJuUaA==" + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -428,18 +432,18 @@ "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "requires": { - "invert-kv": "1.0.0" + "invert-kv": "^1.0.0" } }, "load-json-file": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "requires": { - "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "parse-json": "2.2.0", - "pify": "2.3.0", - "strip-bom": "3.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" } }, "locate-path": { @@ -447,17 +451,17 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" } }, "lru-cache": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } }, "mem": { @@ -465,7 +469,7 @@ "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", "requires": { - "mimic-fn": "1.2.0" + "mimic-fn": "^1.0.0" } }, "meteor-node-stubs": { @@ -473,28 +477,28 @@ "resolved": "https://registry.npmjs.org/meteor-node-stubs/-/meteor-node-stubs-0.3.3.tgz", "integrity": "sha512-TI1aQRK0vqs94OCkUMkmf5lXNWfIsjSaEDP1inUuwRGt9w8/S2V+HdRikz9r1k/gew+7NcJieaqHsHX7pSTEgA==", "requires": { - "assert": "1.4.1", - "browserify-zlib": "0.1.4", - "buffer": "4.9.1", - "console-browserify": "1.1.0", - "constants-browserify": "1.0.0", - "crypto-browserify": "3.12.0", - "domain-browser": "1.2.0", - "events": "1.1.1", + "assert": "^1.4.1", + "browserify-zlib": "^0.1.4", + "buffer": "^4.9.1", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.7", + "events": "^1.1.1", "https-browserify": "0.0.1", - "os-browserify": "0.2.1", + "os-browserify": "^0.2.1", "path-browserify": "0.0.0", - "process": "0.11.10", - "punycode": "1.4.1", - "querystring-es3": "0.2.1", + "process": "^0.11.9", + "punycode": "^1.4.1", + "querystring-es3": "^0.2.1", "readable-stream": "git+https://github.com/meteor/readable-stream.git#c688cdd193549919b840e8d72a86682d91961e12", - "stream-browserify": "2.0.1", - "stream-http": "2.8.0", - "string_decoder": "1.1.0", - "timers-browserify": "1.4.2", + "stream-browserify": "^2.0.1", + "stream-http": "^2.8.0", + "string_decoder": "^1.1.0", + "timers-browserify": "^1.4.2", "tty-browserify": "0.0.0", - "url": "0.11.0", - "util": "0.10.3", + "url": "^0.11.0", + "util": "^0.10.3", "vm-browserify": "0.0.4" }, "dependencies": { @@ -503,9 +507,9 @@ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", "requires": { - "bn.js": "4.11.8", - "inherits": "2.0.1", - "minimalistic-assert": "1.0.0" + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" } }, "assert": { @@ -536,7 +540,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -550,12 +554,12 @@ "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==", "requires": { - "buffer-xor": "1.0.3", - "cipher-base": "1.0.4", - "create-hash": "1.1.3", - "evp_bytestokey": "1.0.3", - "inherits": "2.0.1", - "safe-buffer": "5.1.1" + "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" } }, "browserify-cipher": { @@ -563,9 +567,9 @@ "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", "requires": { - "browserify-aes": "1.1.1", - "browserify-des": "1.0.0", - "evp_bytestokey": "1.0.3" + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" } }, "browserify-des": { @@ -573,9 +577,9 @@ "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", "requires": { - "cipher-base": "1.0.4", - "des.js": "1.0.0", - "inherits": "2.0.1" + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1" } }, "browserify-rsa": { @@ -583,8 +587,8 @@ "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "requires": { - "bn.js": "4.11.8", - "randombytes": "2.0.6" + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" } }, "browserify-sign": { @@ -592,13 +596,13 @@ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", "requires": { - "bn.js": "4.11.8", - "browserify-rsa": "4.0.1", - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "elliptic": "6.4.0", - "inherits": "2.0.1", - "parse-asn1": "5.1.0" + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" } }, "browserify-zlib": { @@ -606,7 +610,7 @@ "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", "requires": { - "pako": "0.2.9" + "pako": "~0.2.0" } }, "buffer": { @@ -614,9 +618,9 @@ "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "requires": { - "base64-js": "1.2.3", - "ieee754": "1.1.8", - "isarray": "1.0.0" + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" } }, "buffer-xor": { @@ -634,8 +638,8 @@ "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "requires": { - "inherits": "2.0.1", - "safe-buffer": "5.1.1" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "concat-map": { @@ -648,7 +652,7 @@ "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", "requires": { - "date-now": "0.1.4" + "date-now": "^0.1.4" } }, "constants-browserify": { @@ -661,8 +665,8 @@ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", "requires": { - "bn.js": "4.11.8", - "elliptic": "6.4.0" + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" } }, "create-hash": { @@ -670,10 +674,10 @@ "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", "requires": { - "cipher-base": "1.0.4", - "inherits": "2.0.1", - "ripemd160": "2.0.1", - "sha.js": "2.4.10" + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "sha.js": "^2.4.0" } }, "create-hmac": { @@ -681,12 +685,12 @@ "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", "requires": { - "cipher-base": "1.0.4", - "create-hash": "1.1.3", - "inherits": "2.0.1", - "ripemd160": "2.0.1", - "safe-buffer": "5.1.1", - "sha.js": "2.4.10" + "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" } }, "crypto-browserify": { @@ -694,17 +698,17 @@ "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", "requires": { - "browserify-cipher": "1.0.0", - "browserify-sign": "4.0.4", - "create-ecdh": "4.0.0", - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "diffie-hellman": "5.0.2", - "inherits": "2.0.1", - "pbkdf2": "3.0.14", - "public-encrypt": "4.0.0", - "randombytes": "2.0.6", - "randomfill": "1.0.4" + "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" } }, "date-now": { @@ -717,8 +721,8 @@ "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", "requires": { - "inherits": "2.0.1", - "minimalistic-assert": "1.0.0" + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" } }, "diffie-hellman": { @@ -726,9 +730,9 @@ "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", "requires": { - "bn.js": "4.11.8", - "miller-rabin": "4.0.1", - "randombytes": "2.0.6" + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" } }, "domain-browser": { @@ -741,13 +745,13 @@ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0", - "hash.js": "1.1.3", - "hmac-drbg": "1.0.1", - "inherits": "2.0.1", - "minimalistic-assert": "1.0.0", - "minimalistic-crypto-utils": "1.0.1" + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" } }, "events": { @@ -760,8 +764,8 @@ "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "requires": { - "md5.js": "1.3.4", - "safe-buffer": "5.1.1" + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" } }, "fs.realpath": { @@ -774,12 +778,12 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.1", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "hash-base": { @@ -787,7 +791,7 @@ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", "requires": { - "inherits": "2.0.1" + "inherits": "^2.0.1" } }, "hash.js": { @@ -795,8 +799,8 @@ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" }, "dependencies": { "inherits": { @@ -811,9 +815,9 @@ "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "requires": { - "hash.js": "1.1.3", - "minimalistic-assert": "1.0.0", - "minimalistic-crypto-utils": "1.0.1" + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" } }, "https-browserify": { @@ -836,8 +840,8 @@ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -855,8 +859,8 @@ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.1" + "hash-base": "^3.0.0", + "inherits": "^2.0.1" }, "dependencies": { "hash-base": { @@ -864,8 +868,8 @@ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "requires": { - "inherits": "2.0.1", - "safe-buffer": "5.1.1" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } } } @@ -875,8 +879,8 @@ "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0" + "bn.js": "^4.0.0", + "brorand": "^1.0.1" } }, "minimalistic-assert": { @@ -894,7 +898,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "^1.1.7" } }, "once": { @@ -902,7 +906,7 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "os-browserify": { @@ -920,11 +924,11 @@ "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", "requires": { - "asn1.js": "4.10.1", - "browserify-aes": "1.1.1", - "create-hash": "1.1.3", - "evp_bytestokey": "1.0.3", - "pbkdf2": "3.0.14" + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3" } }, "path-browserify": { @@ -942,11 +946,11 @@ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", "requires": { - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "ripemd160": "2.0.1", - "safe-buffer": "5.1.1", - "sha.js": "2.4.10" + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" } }, "process": { @@ -964,11 +968,11 @@ "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", "requires": { - "bn.js": "4.11.8", - "browserify-rsa": "4.0.1", - "create-hash": "1.1.3", - "parse-asn1": "5.1.0", - "randombytes": "2.0.6" + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1" } }, "punycode": { @@ -991,7 +995,7 @@ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "^5.1.0" } }, "randomfill": { @@ -999,19 +1003,20 @@ "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", "requires": { - "randombytes": "2.0.6", - "safe-buffer": "5.1.1" + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" } }, "readable-stream": { "version": "git+https://github.com/meteor/readable-stream.git#c688cdd193549919b840e8d72a86682d91961e12", + "from": "git+https://github.com/meteor/readable-stream.git", "requires": { - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.1.0", - "util-deprecate": "1.0.2" + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.0", + "util-deprecate": "~1.0.1" }, "dependencies": { "inherits": { @@ -1026,7 +1031,7 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" } }, "ripemd160": { @@ -1034,8 +1039,8 @@ "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", "requires": { - "hash-base": "2.0.2", - "inherits": "2.0.1" + "hash-base": "^2.0.0", + "inherits": "^2.0.1" } }, "safe-buffer": { @@ -1048,8 +1053,8 @@ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz", "integrity": "sha512-vnwmrFDlOExK4Nm16J2KMWHLrp14lBrjxMxBJpu++EnsuBmpiYaM/MEs46Vxxm/4FvdP5yTwuCTO9it5FSjrqA==", "requires": { - "inherits": "2.0.1", - "safe-buffer": "5.1.1" + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" } }, "stream-browserify": { @@ -1057,8 +1062,8 @@ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", "requires": { - "inherits": "2.0.1", - "readable-stream": "git+https://github.com/meteor/readable-stream.git#c688cdd193549919b840e8d72a86682d91961e12" + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" } }, "stream-http": { @@ -1066,11 +1071,11 @@ "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", "integrity": "sha512-sZOFxI/5xw058XIRHl4dU3dZ+TTOIGJR78Dvo0oEAejIt4ou27k+3ne1zYmCV+v7UucbxIFQuOgnkTVHh8YPnw==", "requires": { - "builtin-status-codes": "3.0.0", - "inherits": "2.0.1", - "readable-stream": "git+https://github.com/meteor/readable-stream.git#c688cdd193549919b840e8d72a86682d91961e12", - "to-arraybuffer": "1.0.1", - "xtend": "4.0.1" + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.3", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" } }, "string_decoder": { @@ -1078,7 +1083,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.0.tgz", "integrity": "sha512-8zQpRF6juocE69ae7CSPmYEGJe4VCXwP6S6dxUWI7i53Gwv54/ec41fiUA+X7BPGGv7fRSQJjBQVa0gomGaOgg==", "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } }, "timers-browserify": { @@ -1086,7 +1091,7 @@ "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", "requires": { - "process": "0.11.10" + "process": "~0.11.0" } }, "to-arraybuffer": { @@ -1158,7 +1163,7 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", "requires": { - "mime-db": "1.33.0" + "mime-db": "~1.33.0" } }, "mimic-fn": { @@ -1181,15 +1186,15 @@ "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz", "integrity": "sha1-22BBEst04NR3VU6bUFsXq936t4Y=", "requires": { - "mkdirp": "0.5.1", - "nopt": "4.0.1", - "npmlog": "4.1.2", - "rc": "1.2.8", - "request": "2.87.0", - "rimraf": "2.6.2", - "semver": "5.4.1", - "tar": "2.2.1", - "tar-pack": "3.4.1" + "mkdirp": "^0.5.1", + "nopt": "^4.0.1", + "npmlog": "^4.0.2", + "rc": "^1.1.7", + "request": "^2.81.0", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^2.2.1", + "tar-pack": "^3.4.0" }, "dependencies": { "ansi-regex": { @@ -1202,8 +1207,8 @@ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.6" + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" } }, "code-point-at": { @@ -1231,10 +1236,10 @@ "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.2" + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" } }, "gauge": { @@ -1242,14 +1247,14 @@ "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.3" + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" } }, "graceful-fs": { @@ -1272,7 +1277,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, "isarray": { @@ -1298,10 +1303,10 @@ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "requires": { - "are-we-there-yet": "1.1.5", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" } }, "number-is-nan": { @@ -1324,13 +1329,13 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.2", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, "safe-buffer": { @@ -1353,9 +1358,9 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string_decoder": { @@ -1363,7 +1368,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "~5.1.0" } }, "strip-ansi": { @@ -1371,7 +1376,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "tar": { @@ -1379,9 +1384,9 @@ "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", "requires": { - "block-stream": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "fstream": "1.0.11", - "inherits": "2.0.3" + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" } }, "util-deprecate": { @@ -1394,7 +1399,7 @@ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "requires": { - "string-width": "1.0.2" + "string-width": "^1.0.2 || 2" } } } @@ -1404,8 +1409,8 @@ "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "requires": { - "abbrev": "1.1.1", - "osenv": "0.1.5" + "abbrev": "1", + "osenv": "^0.1.4" } }, "normalize-package-data": { @@ -1413,10 +1418,10 @@ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "requires": { - "hosted-git-info": "2.5.0", - "is-builtin-module": "1.0.0", - "semver": "5.4.1", - "validate-npm-package-license": "3.0.3" + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, "npm-run-path": { @@ -1424,11 +1429,12 @@ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "requires": { - "path-key": "2.0.1" + "path-key": "^2.0.0" } }, "number-is-nan": { - "version": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "os-homedir": { @@ -1441,9 +1447,9 @@ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" } }, "os-tmpdir": { @@ -1456,8 +1462,8 @@ "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } }, "p-finally": { @@ -1466,11 +1472,11 @@ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" }, "p-limit": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", - "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "requires": { - "p-try": "1.0.0" + "p-try": "^1.0.0" } }, "p-locate": { @@ -1478,7 +1484,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "requires": { - "p-limit": "1.2.0" + "p-limit": "^1.1.0" } }, "p-try": { @@ -1491,7 +1497,7 @@ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "requires": { - "error-ex": "1.3.1" + "error-ex": "^1.2.0" } }, "path-exists": { @@ -1509,7 +1515,7 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", "requires": { - "pify": "2.3.0" + "pify": "^2.0.0" } }, "performance-now": { @@ -1523,9 +1529,9 @@ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, "pngjs": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.3.2.tgz", - "integrity": "sha512-bVNd3LMXRzdo6s4ehr4XW2wFMu9cb40nPgHEjSSppm8/++Xc+g0b2QQb+SeDesgfANXbjydOr1or9YQ+pcCZPQ==" + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.3.3.tgz", + "integrity": "sha512-1n3Z4p3IOxArEs1VRXnZ/RXdfEniAUS9jb68g58FIXMNkPJeZd+Qh4Uq7/e0LVxAQGos1eIUrqrt4FpjdnEd+Q==" }, "pseudomap": { "version": "1.0.2", @@ -1533,22 +1539,15 @@ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, "qrcode": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.2.0.tgz", - "integrity": "sha512-wZK0Z0eYmOUDP2tOGzmLdeBn5Npa+4wms9GdvzH7HrywvGUq/Stz0BKUhW4DfmBf1PSrm9dNfdnVDq683Zxvag==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.3.0.tgz", + "integrity": "sha512-HFE7drEGhVoPxL1Ilm/zV+wkNJzUa8zL2nXP30vzo78EXAnHPStVOt2iZUIOfgmELtAbSkw/Z8igqu/TbNDGrQ==", "requires": { - "can-promise": "0.0.1", - "dijkstrajs": "1.0.1", - "isarray": "2.0.4", - "pngjs": "3.3.2", - "yargs": "8.0.2" - }, - "dependencies": { - "isarray": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.4.tgz", - "integrity": "sha512-GMxXOiUirWg1xTKRipM0Ek07rX+ubx4nNVElTJdNLYmNO/2YrDkgJGw9CljXn+r4EWiDQg/8lsRdHyg2PJuUaA==" - } + "can-promise": "^0.0.1", + "dijkstrajs": "^1.0.1", + "isarray": "^2.0.1", + "pngjs": "^3.3.0", + "yargs": "^8.0.2" } }, "qs": { @@ -1561,10 +1560,10 @@ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "requires": { - "deep-extend": "0.6.0", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, "dependencies": { "deep-extend": { @@ -1579,7 +1578,6 @@ }, "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "strip-json-comments": { @@ -1594,9 +1592,9 @@ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", "requires": { - "load-json-file": "2.0.0", - "normalize-package-data": "2.4.0", - "path-type": "2.0.0" + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" } }, "read-pkg-up": { @@ -1604,40 +1602,40 @@ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", "requires": { - "find-up": "2.1.0", - "read-pkg": "2.0.0" + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" } }, "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", + "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==" }, "request": { "version": "2.87.0", "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.7.0", - "caseless": "0.12.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.3.2", - "har-validator": "5.0.3", - "http-signature": "1.2.0", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.18", - "oauth-sign": "0.8.2", - "performance-now": "2.1.0", - "qs": "6.5.2", - "safe-buffer": "5.1.2", - "tough-cookie": "2.3.4", - "tunnel-agent": "0.6.0", - "uuid": "3.2.1" + "aws-sign2": "~0.7.0", + "aws4": "^1.6.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.1", + "forever-agent": "~0.6.1", + "form-data": "~2.3.1", + "har-validator": "~5.0.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.17", + "oauth-sign": "~0.8.2", + "performance-now": "^2.1.0", + "qs": "~6.5.1", + "safe-buffer": "^5.1.1", + "tough-cookie": "~2.3.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.1.0" }, "dependencies": { "aws4": { @@ -1655,7 +1653,7 @@ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "requires": { - "delayed-stream": "1.0.0" + "delayed-stream": "~1.0.0" } }, "delayed-stream": { @@ -1703,7 +1701,7 @@ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "^5.0.1" } }, "uuid": { @@ -1728,7 +1726,7 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" }, "dependencies": { "balanced-match": { @@ -1741,7 +1739,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -1760,12 +1758,12 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "inflight": { @@ -1773,8 +1771,8 @@ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -1787,7 +1785,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "^1.1.7" } }, "once": { @@ -1795,7 +1793,7 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "path-is-absolute": { @@ -1816,7 +1814,8 @@ "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" }, "set-blocking": { - "version": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "shebang-command": { @@ -1824,7 +1823,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "requires": { - "shebang-regex": "1.0.0" + "shebang-regex": "^1.0.0" } }, "shebang-regex": { @@ -1833,7 +1832,8 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" }, "signal-exit": { - "version": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, "source-map": { @@ -1842,56 +1842,77 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-support": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.6.tgz", - "integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", + "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", "requires": { - "buffer-from": "1.1.0", - "source-map": "0.6.1" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, "spdx-correct": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", - "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", + "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", "requires": { - "spdx-expression-parse": "3.0.0", - "spdx-license-ids": "3.0.0" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, "spdx-exceptions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" }, "spdx-expression-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "requires": { - "spdx-exceptions": "2.1.0", - "spdx-license-ids": "3.0.0" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, "spdx-license-ids": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz", + "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==" }, "string-width": { - "version": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "requires": { - "code-point-at": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "is-fullwidth-code-point": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } } }, "strip-ansi": { - "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "version": "3.0.1", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { - "ansi-regex": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" + "ansi-regex": "^2.0.0" } }, "strip-bom": { @@ -1909,14 +1930,14 @@ "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.1.tgz", "integrity": "sha512-PPRybI9+jM5tjtCbN2cxmmRU7YmqT3Zv/UDy48tAh2XRkLa9bAORtSWLkVc13+GJF+cdTh1yEnHEk3cpTaL5Kg==", "requires": { - "debug": "2.6.9", - "fstream": "1.0.11", - "fstream-ignore": "1.0.5", - "once": "1.4.0", - "readable-stream": "2.3.6", - "rimraf": "2.6.2", - "tar": "2.2.1", - "uid-number": "0.0.6" + "debug": "^2.2.0", + "fstream": "^1.0.10", + "fstream-ignore": "^1.0.5", + "once": "^1.3.3", + "readable-stream": "^2.1.4", + "rimraf": "^2.5.1", + "tar": "^2.2.1", + "uid-number": "^0.0.6" }, "dependencies": { "balanced-match": { @@ -1929,7 +1950,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -1948,10 +1969,10 @@ "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.2" + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" } }, "fstream-ignore": { @@ -1959,9 +1980,9 @@ "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", "requires": { - "fstream": "1.0.11", - "inherits": "2.0.3", - "minimatch": "3.0.4" + "fstream": "^1.0.0", + "inherits": "2", + "minimatch": "^3.0.0" } }, "graceful-fs": { @@ -1984,7 +2005,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -2005,7 +2026,7 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "process-nextick-args": { @@ -2018,13 +2039,13 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.2", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, "safe-buffer": { @@ -2037,7 +2058,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "safe-buffer": "5.1.2" + "safe-buffer": "~5.1.0" } }, "tar": { @@ -2045,9 +2066,9 @@ "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", "requires": { - "block-stream": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "fstream": "1.0.11", - "inherits": "2.0.3" + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" } }, "uid-number": { @@ -2072,7 +2093,7 @@ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", "requires": { - "punycode": "1.4.1" + "punycode": "^1.4.1" }, "dependencies": { "punycode": { @@ -2088,12 +2109,12 @@ "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" }, "validate-npm-package-license": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", - "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "requires": { - "spdx-correct": "3.0.0", - "spdx-expression-parse": "3.0.0" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, "verror": { @@ -2101,9 +2122,9 @@ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "requires": { - "assert-plus": "1.0.0", + "assert-plus": "^1.0.0", "core-util-is": "1.0.2", - "extsprintf": "1.3.0" + "extsprintf": "^1.2.0" }, "dependencies": { "core-util-is": { @@ -2119,11 +2140,11 @@ "integrity": "sha1-IRb7+hRo7EFqe+/aozPh0Rj2nAQ=" }, "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "requires": { - "isexe": "2.0.0" + "isexe": "^2.0.0" } }, "which-module": { @@ -2138,11 +2159,23 @@ }, "wrap-ansi": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "requires": { - "string-width": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "strip-ansi": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } } }, "y18n": { @@ -2160,48 +2193,19 @@ "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", "requires": { - "camelcase": "4.1.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "os-locale": "2.1.0", - "read-pkg-up": "2.0.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "3.2.1", - "yargs-parser": "7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "3.0.0" - } - } + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" } }, "yargs-parser": { @@ -2209,7 +2213,7 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", "requires": { - "camelcase": "4.1.0" + "camelcase": "^4.1.0" } } } diff --git a/app/package.json b/app/package.json index b24f5d75..13ecdf36 100644 --- a/app/package.json +++ b/app/package.json @@ -1,5 +1,5 @@ { - "name": "rpg-docs", + "name": "dicecloud", "version": "0.10.0", "description": "Unofficial Online Realtime D&D 5e App", "scripts": { @@ -11,16 +11,15 @@ }, "author": "Stefan Zermatten", "dependencies": { - "@babel/runtime": "^7.0.0-beta.49", + "@babel/runtime": "^7.1.2", "@polymer/polymer": "^1.2.5-npm-test.2", - "babel-runtime": "^6.26.0", "bcrypt": "^1.0.3", "bower": "^1.7.9", "core-js": "^2.5.7", "fibers": "^2.0.2", "meteor-node-stubs": "^0.3.3", - "qrcode": "^1.2.0", - "source-map-support": "^0.5.6", + "qrcode": "^1.3.0", + "source-map-support": "^0.5.9", "underscore": "^1.9.1" } } From 96f4e35e25919eca0333044c1485f7ce9b2bb69c Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Tue, 13 Nov 2018 08:58:42 +0200 Subject: [PATCH 008/247] fixes #187 --- .../views/character/characterSettings/shareDialog.js | 4 ++-- app/lib/functions/shareCharacter.js | 11 +++-------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/app/client/views/character/characterSettings/shareDialog.js b/app/client/views/character/characterSettings/shareDialog.js index 6574fa84..13ad3e50 100644 --- a/app/client/views/character/characterSettings/shareDialog.js +++ b/app/client/views/character/characterSettings/shareDialog.js @@ -53,7 +53,7 @@ Template.shareDialog.events({ Characters.update(this._id, {$set: {"settings.viewPermission": value}}); }, "input #userNameOrEmailInput": - function(event, instance){ + _.debounce(function(event, instance){ var userName = instance.find("#userNameOrEmailInput").value; instance.userId.set(undefined); Meteor.call("getUserId", userName, function(err, result) { @@ -64,7 +64,7 @@ Template.shareDialog.events({ instance.userId.set(result); } }); - }, + }, 300), "click #shareButton": function(event, instance){ var self = this; var permission = instance.find("#accessLevelMenu").selected; diff --git a/app/lib/functions/shareCharacter.js b/app/lib/functions/shareCharacter.js index dcf94447..d206fc0f 100644 --- a/app/lib/functions/shareCharacter.js +++ b/app/lib/functions/shareCharacter.js @@ -1,14 +1,9 @@ Meteor.methods({ "getUserId": function(username){ if (!username) return; - regex = new RegExp("^" + username + "$", "i") - var user = Meteor.users.findOne( - {$or: [ - {username: username}, - {"emails.address": regex}, - {"services.google.email": regex}, - ]} - ); + if (Meteor.isClient) return; + let user = Accounts.findUserByUsername(username) || + Accounts.findUserByEmail(username); return user && user._id; } }); From 6599fe1ef88072764dc02f2ba7ba81b0487098dc Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Tue, 13 Nov 2018 09:26:36 +0200 Subject: [PATCH 009/247] fixes #191 --- app/lib/functions/parenting.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/lib/functions/parenting.js b/app/lib/functions/parenting.js index eb3e01f2..fe62eacb 100644 --- a/app/lib/functions/parenting.js +++ b/app/lib/functions/parenting.js @@ -3,10 +3,12 @@ var childSchema = new SimpleSchema({ "parent.collection": {type: String}, "parent.id": {type: String, regEx: SimpleSchema.RegEx.Id, index: 1}, "parent.group": {type: String, optional: true}, + "removed": {type: Boolean, optional: true, index: 1}, "removedWith": { optional: true, type: String, regEx: SimpleSchema.RegEx.Id, + index: 1, }, }); From 933878e1583d25b9a9b61b9efb3478f8299132c5 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Tue, 13 Nov 2018 09:31:57 +0200 Subject: [PATCH 010/247] fixes #177 --- .../views/character/characterSettings/characterSettings.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/client/views/character/characterSettings/characterSettings.js b/app/client/views/character/characterSettings/characterSettings.js index 773fe2bb..42ff74f0 100644 --- a/app/client/views/character/characterSettings/characterSettings.js +++ b/app/client/views/character/characterSettings/characterSettings.js @@ -17,6 +17,7 @@ Template.characterSettings.events({ "change #hideSpellcasting": function(event, instance){ var value = instance.find("#hideSpellcasting").checked; if (this.settings.hideSpellcasting !== value){ + Session.set(this._id + ".selectedTab", "0"); Characters.update( this._id, {$set: {"settings.hideSpellcasting": value}} From 56f1bd28293cc633ea4657baa5f007d22c7bb2af Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Tue, 13 Nov 2018 10:07:55 +0200 Subject: [PATCH 011/247] Fixes #170 and maybe some other more subtle problems regarding soft removes not cascading properly, orphaning objects --- app/lib/functions/parenting.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/lib/functions/parenting.js b/app/lib/functions/parenting.js index fe62eacb..82ecf204 100644 --- a/app/lib/functions/parenting.js +++ b/app/lib/functions/parenting.js @@ -145,17 +145,17 @@ var checkPermission = function(userId, charId){ return true; }; -var cascadeSoftRemove = function(id, removedWithId){ +var cascadeSoftRemove = function(parentId, removedWithId){ _.each(childCollections, function(treeCollection){ treeCollection.update( - {"parent.id": id}, + {"parent.id": parentId}, {$set: { removed: true, removedWith: removedWithId, }}, {multi: true} ); - treeCollection.find({"parent.id": id}).forEach(function(doc){ + treeCollection.find({"parent.id": parentId, removed: true}).forEach(function(doc){ cascadeSoftRemove(doc._id, removedWithId); }); }); From 261220fdd5b18b42a148dd0431a44a2290c37954 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Tue, 13 Nov 2018 10:39:14 +0200 Subject: [PATCH 012/247] Fixes #155, buffs can now only be applied if you have write access refactored applying buffs to be a method, not a client side operation. You can now only applied if you have write access to the receiving character. --- app/Model/Character/Buffs.js | 34 ++++++++++++++ .../buffs/customBuffView/customBuffView.js | 44 +------------------ 2 files changed, 35 insertions(+), 43 deletions(-) diff --git a/app/Model/Character/Buffs.js b/app/Model/Character/Buffs.js index e6e00710..c73c88eb 100644 --- a/app/Model/Character/Buffs.js +++ b/app/Model/Character/Buffs.js @@ -65,3 +65,37 @@ makeParent(Buffs, ["name", "enabled"]); //parents of effects, attacks, proficien Buffs.allow(CHARACTER_SUBSCHEMA_ALLOW); Buffs.deny(CHARACTER_SUBSCHEMA_DENY); + +Meteor.methods({ + applyBuff: function(buffId, targetId){ + if (!Meteor.call("canWriteCharacter", targetId)){ + throw new Meteor.Error( + "Access denied", + "You do not have permission to buff this character" + ); + } + let buff = CustomBuffs.findOne(buffId); + if (!buff) return; + + var parentCol = Meteor.isClient ? + window[buff.parent.collection] : global[buff.parent.collection] + var parent = parentCol.findOne(buff.parent.id); + + //insert new buff + newBuffId = Buffs.insert({ + charId: targetId, + name: buff.name, + description: buff.description, + lifeTime: {total: buff.lifeTime.total}, + type: "custom", + + appliedBy: buff.charId, + appliedByDetails: { + name: parent && parent.name || "", + collection: buff.parent.collection, + }, + }); + + Meteor.call("cloneChildren", buffId, {id: newBuffId, collection: "Buffs"}) + } +}) diff --git a/app/client/views/character/buffs/customBuffView/customBuffView.js b/app/client/views/character/buffs/customBuffView/customBuffView.js index fdc30712..fb06bc41 100644 --- a/app/client/views/character/buffs/customBuffView/customBuffView.js +++ b/app/client/views/character/buffs/customBuffView/customBuffView.js @@ -1,47 +1,5 @@ const applyBuff = function(targetId, buff) { - var parent = global[buff.parent.collection].findOne(buff.parent.id); - - //insert new buff - newBuffId = Buffs.insert({ - charId: targetId, - name: buff.name, - description: buff.description, - lifeTime: {total: buff.lifeTime.total}, - type: "custom", - - appliedBy: buff.charId, - appliedByDetails: { - name: parent.name, - collection: buff.parent.collection, - }, - }); - - //insert children - Attacks.find({"parent.id": buff._id}).forEach(function(doc){ - temp = _.clone(doc); - temp.parent.id = newBuffId; - temp.parent.collection = "Buffs"; - delete temp._id; - - Attacks.insert(temp); - }); - Effects.find({"parent.id": buff._id}).forEach(function(doc){ - temp = _.clone(doc); - temp.parent.id = newBuffId; - temp.parent.collection = "Buffs"; - delete temp._id; - - Effects.insert(temp); - }); - Proficiencies.find({"parent.id": buff._id}).forEach(function(doc){ - temp = _.clone(doc); - temp.parent.id = newBuffId; - temp.parent.collection = "Buffs"; - delete temp._id; - - Proficiencies.insert(temp); - }); - + Meteor.call("applyBuff", buff._id, targetId) let target; if (targetId == buff.charId) { target = "self"; From 1c953368435de1be49f861d7717471dd28a17992 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Tue, 13 Nov 2018 12:01:40 +0200 Subject: [PATCH 013/247] Spell slot bubbles are limited to 10, overflow is shown numerically fixes #150 --- app/client/views/character/spells/spells.html | 18 ++++++++----- app/client/views/character/spells/spells.js | 26 +++++++++++++++---- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/app/client/views/character/spells/spells.html b/app/client/views/character/spells/spells.html index c992daa4..fb7b2a90 100644 --- a/app/client/views/character/spells/spells.html +++ b/app/client/views/character/spells/spells.html @@ -11,16 +11,20 @@
{{#each levels}}{{#if showSlots ..}}
-
-
+
+
{{name}}
-
+
{{#each slotBubbles ..}} - - + {{#unless overflow}} + + + {{else}} +
+{{overflow}}
+ {{/unless}} {{/each}}
diff --git a/app/client/views/character/spells/spells.js b/app/client/views/character/spells/spells.js index df7a68af..e9839200 100644 --- a/app/client/views/character/spells/spells.js +++ b/app/client/views/character/spells/spells.js @@ -122,6 +122,7 @@ Template.spells.helpers({ return false; }, slotBubbles: function(char){ + const MAX_SLOTS = 10; var baseSlots = Characters.calculate.attributeBase( char._id, "level" + this.level + "SpellSlots" ); @@ -130,16 +131,28 @@ Template.spells.helpers({ ); var slotsUsed = baseSlots - currentSlots; var bubbles = []; - var i; - for (i = 0; i < currentSlots; i++){ + var i, overflowFilled, overflowEmpty; + var filledSlots = currentSlots; + var maxEmptySlots = Math.max(MAX_SLOTS - filledSlots + 1, 1); + var emptySlots = slotsUsed; + if (baseSlots > MAX_SLOTS){ + filledSlots = Math.min(MAX_SLOTS, filledSlots); + overflowFilled = Math.max(currentSlots - MAX_SLOTS, 0); + emptySlots = Math.min(maxEmptySlots, emptySlots); + overflowEmpty = Math.max(slotsUsed - maxEmptySlots, 0); + } + for (i = 0; i < filledSlots; i++){ bubbles.push({ icon: "radio-button-checked", - disabled: i !== currentSlots - 1 || !canEditCharacter(char._id), //last full slot not disabled + disabled: i !== filledSlots - 1 || !canEditCharacter(char._id), //last full slot not disabled attribute: "level" + this.level + "SpellSlots", charId: char._id, }); } - for (i = 0; i < slotsUsed; i++){ + if (overflowFilled){ + bubbles.push({overflow: overflowFilled}); + } + for (i = 0; i < emptySlots; i++){ bubbles.push({ icon: "radio-button-unchecked", disabled: i !== 0 || !canEditCharacter(char._id), //first empty slot not disabled @@ -147,6 +160,9 @@ Template.spells.helpers({ charId: char._id, }); } + if (overflowEmpty){ + bubbles.push({overflow: overflowEmpty}); + } return bubbles; }, slotStatName: function() { @@ -178,7 +194,7 @@ Template.spells.events({ } event.stopPropagation(); }, - "click .spellSlot": function(event, instance) { + "click .spellLevelName": function(event, instance) { var name = "Level " + this.level + " Spell Slots"; var stat = "level" + this.level + "SpellSlots"; var charId = instance.data._id; From 7d364c80c0384a8e7a0f52f106970c45c924fdb0 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Tue, 13 Nov 2018 12:57:02 +0200 Subject: [PATCH 014/247] Added hotfix to fix password button until the relevant package can be updated, fixes #67 --- app/client/lib/fixPasswordButton.js | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 app/client/lib/fixPasswordButton.js diff --git a/app/client/lib/fixPasswordButton.js b/app/client/lib/fixPasswordButton.js new file mode 100644 index 00000000..26fed09d --- /dev/null +++ b/app/client/lib/fixPasswordButton.js @@ -0,0 +1,5 @@ +let pwdFormSubmit = AccountsTemplates.atPwdFormEvents["submit #at-pwd-form"] + +Template.atPwdForm.events({ + "click .at-btn.submit": pwdFormSubmit, +}); From 65d1bac0dc119bd30ca4636650292e8905985e45 Mon Sep 17 00:00:00 2001 From: Frogvall Date: Wed, 14 Nov 2018 06:40:22 +0100 Subject: [PATCH 015/247] Updated heat metal according to SRD/PHB --- dataSources/srd/spells.json | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dataSources/srd/spells.json b/dataSources/srd/spells.json index d4907c6a..6e51208c 100644 --- a/dataSources/srd/spells.json +++ b/dataSources/srd/spells.json @@ -2194,9 +2194,9 @@ } }, { - "castingTime": "bonus action", + "castingTime": "action", "description": "Choose a manufactured metal object, such as a metal weapon or a suit of heavy or medium metal armor, that you can see within range. You cause the object to glow red-hot. Any creature in physical contact with the object takes 2d8 fire damage when you cast the spell. Until the spell ends, you can use a bonus action on each of your subsequent turns to cause this damage again.\n\nIf a creature is holding or wearing the object and takes the damage from it, the creature must succeed on a DC {DC} Constitution saving throw or drop the object if it can. If it doesn’t drop the object, it has disadvantage on attack rolls and ability checks until the start of your next turn.\n\n***At Higher Levels.*** When you cast this spell using a spell slot of 3rd level or higher, the damage increases by 1d8 for each slot level above 2nd.", - "duration": "Instantaneous", + "duration": "Concentration, up to 1 minute", "level": 2, "range": "60 feet", "school": "Transmutation", @@ -2204,8 +2204,9 @@ "name": "Heat Metal", "components": { "verbal": true, - "somatic": false, - "concentration": false + "somatic": true, + "concentration": true, + "material": "a piece of iron and a flame" } }, { From e2822b9f22361303f4d619a4ca549ede23812515 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Mon, 28 Jan 2019 11:35:56 +0200 Subject: [PATCH 016/247] added naive backup restore --- app/.gitignore | 1 + app/lib/functions/backupRestoreCharacter.js | 33 +++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 app/lib/functions/backupRestoreCharacter.js diff --git a/app/.gitignore b/app/.gitignore index 086ca397..2df4ae3a 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -8,3 +8,4 @@ private/oldClient nohup.out node_modules dump +.cache diff --git a/app/lib/functions/backupRestoreCharacter.js b/app/lib/functions/backupRestoreCharacter.js new file mode 100644 index 00000000..ba95f4af --- /dev/null +++ b/app/lib/functions/backupRestoreCharacter.js @@ -0,0 +1,33 @@ +let characterCollections = [ + Actions, + Attacks, + Buffs, + Classes, + CustomBuffs, + Effects, + Experiences, + Features, + Notes, + Proficiencies, + SpellLists, + Items, + Containers, +]; + +function backupCharacter(charId){ + let characterDump = {}; + characterDump.characters = [Characters.findOne(charId)]; + characterCollections.map( + c => characterDump[c._name] = c.find({charId}).fetch() + ); + return characterDump; +}; + +function restoreCharacter(characterDump){ + for (collectionName in characterDump){ + let collection = Meteor.Collection.get(collectionName); + for (doc in characterDump[collectionName]){ + collection.insert(doc); + } + } +}; From b052e8dd196aac86968f2cf308d065fd168cc376 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 31 Jan 2019 10:09:19 +0200 Subject: [PATCH 017/247] Update README.md --- README.md | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f70527ca..12240434 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,71 @@ -RPG Docs +DiceCloud ======== This is the repo for [DiceCloud](dicecloud.com). +DiceCloud is a free, auditable, real-time character sheet for D&D 5e. + +Philosophy +---------- + +Setting up your character on DiceCloud takes a little longer than +just filling it in on a paper character sheet would. The goal of using an +online sheet is to make actually playing the game more streamlined, and +ultimately more fun. So putting a little extra effort into setting up a +character now pays off over and over again once you're playing. + +The idea is to track where each number comes from, and allow you to easily make +changes on the fly. Let's look at a hypothetical example. + +> You need to swim through a sunken section of dungeon to fetch the quest's Thing. +> You'll need to take off your magical Plate Armor of +1 Constitution to swim +> without sinking, of course. +> +> Taking it off will take away that disadvantage on +> stealth checks, change your armor class, your speed and your constitution, and +> which in turn changes your hit points and your constitution saving throw. +> Working out all those changes in the middle of a game will drag the game to a +> halt. +> +> Fortunately you have DiceCloud, so it's a matter of dragging +> your Plate Armor +1 Con from your "equipment" box to your "backpack" box and +> you're done. Your hitpoints change correctly, your saving throws are up to date, +> your armor class goes back to reflecting the fact that you have natural armor +> from being a dragonborn. Your character sheet keeps up and you +> ultimately get more time to play the game. Huzzah! + Getting started --------------- +Running DiceCloud locally, either to host it yourself away from an internet +connection, or to contribute to developing it further, is fairly +straightforward and it should work on Linux, Windows, and Mac. + +You'll need to have installed: + +- [git](https://www.atlassian.com/git/tutorials/install-git) +- [Meteor](https://www.meteor.com/install) +- [Bower](https://bower.io/) + +Then, it's just a matter of cloning this repository into a folder, installing the bower dependencies and running +`meteor` in the app directory. + `git clone https://github.com/ThaumRystra/DiceCloud1 dicecloud` `cd dicecloud` `cd app` `bower install` `meteor` + +You should see this: + +``` +=> Started proxy. +=> Started MongoDB. +=> Started your app. + +=> App running at: http://localhost:3000/ +``` + +Now, visiting [](http://localhost:3000/) should show you an empty instance of +DiceCloud running. + From 4ea02c4fbb6a8c39d952751a3af32a4c523874e3 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 31 Jan 2019 10:10:56 +0200 Subject: [PATCH 018/247] Fixed hidden link to localhost --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 12240434..bed794c7 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,6 @@ You should see this: => App running at: http://localhost:3000/ ``` -Now, visiting [](http://localhost:3000/) should show you an empty instance of +Now, visiting http://localhost:3000/ should show you an empty instance of DiceCloud running. From 3f325356666c4c93838aa15af0938b724bf32b7c Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 31 Jan 2019 10:11:32 +0200 Subject: [PATCH 019/247] fixed link to dicecloud repo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bed794c7..6c81e7ae 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ You'll need to have installed: Then, it's just a matter of cloning this repository into a folder, installing the bower dependencies and running `meteor` in the app directory. -`git clone https://github.com/ThaumRystra/DiceCloud1 dicecloud` +`git clone https://github.com/ThaumRystra/DiceCloud dicecloud` `cd dicecloud` `cd app` `bower install` From b94f5ebb4bf4cf9a5d319d078a5bda1ed783d4f2 Mon Sep 17 00:00:00 2001 From: Andrew Zhu Date: Tue, 5 Feb 2019 13:08:28 -0800 Subject: [PATCH 020/247] add getUserId API endpoint --- app/.gitignore | 1 + app/Routes/API.js | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/app/.gitignore b/app/.gitignore index 086ca397..9e3b6267 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -8,3 +8,4 @@ private/oldClient nohup.out node_modules dump +.idea/ diff --git a/app/Routes/API.js b/app/Routes/API.js index 7df32907..e375c4f0 100644 --- a/app/Routes/API.js +++ b/app/Routes/API.js @@ -42,6 +42,29 @@ Router.map(function() { ); }, }); + + this.route("getUserId", { // GET /api/user?username=:un + path: "/api/user", + where: "server", + action: function () { + this.response.setHeader("Content-Type", "application/json"); + var query = this.params.query; + var key = query && query.key; + var username = query && query.username; + ifKeyValid(key, this.response, "getUserId", () => { + Meteor.call("getUserId", username, (err, result) => { + if (err) { + console.error(err); + this.response.writeHead(404, "User not found"); + this.response.end(); + } else { + console.log(result); + this.response.end(JSON.stringify({id: result})); + } + }); + }); + } + }); }); var ifKeyValid = function(apiKey, response, method, callback){ From d1d22c0d89b2c0d341db5a6c9a8caad6fda5d3ed Mon Sep 17 00:00:00 2001 From: Andrew Zhu Date: Tue, 5 Feb 2019 13:09:56 -0800 Subject: [PATCH 021/247] formatting, add helper func for POST endpoints --- app/Routes/API.js | 167 +++++++++++++++++++++++++--------------------- 1 file changed, 91 insertions(+), 76 deletions(-) diff --git a/app/Routes/API.js b/app/Routes/API.js index e375c4f0..b9cb005a 100644 --- a/app/Routes/API.js +++ b/app/Routes/API.js @@ -1,47 +1,47 @@ -Router.map(function() { - this.route("vmixCharacter", { - path: "/vmix-character/:_id/", - where: "server", - action: function() { - this.response.setHeader("Content-Type", "application/json"); - var query = this.params.query; - var key = query && query.key; - ifKeyValid(key, this.response, "vmixCharacter", () => - this.response.end(vMixCharacter(this.params._id)) - ); - }, - }); - this.route("vmixParty", { - path: "/vmix-party/:_id/", - where: "server", - action: function() { - this.response.setHeader("Content-Type", "application/json"); - var query = this.params.query; - var key = query && query.key; - ifKeyValid(key, this.response, "vmixParty", () => - this.response.end(vMixParty(this.params._id)) - ); - }, - }); +Router.map(function () { + this.route("vmixCharacter", { + path: "/vmix-character/:_id/", + where: "server", + action: function () { + this.response.setHeader("Content-Type", "application/json"); + var query = this.params.query; + var key = query && query.key; + ifKeyValid(key, this.response, "vmixCharacter", () => + this.response.end(vMixCharacter(this.params._id)) + ); + }, + }); + this.route("vmixParty", { + path: "/vmix-party/:_id/", + where: "server", + action: function () { + this.response.setHeader("Content-Type", "application/json"); + var query = this.params.query; + var key = query && query.key; + ifKeyValid(key, this.response, "vmixParty", () => + this.response.end(vMixParty(this.params._id)) + ); + }, + }); - this.route("jsonCharacterSheet", { - path: "/character/:_id/json", - where: "server", - action: function() { - this.response.setHeader("Content-Type", "application/json"); - var query = this.params.query; - var key = query && query.key; - ifKeyValid(key, this.response, "jsonCharacterSheet", () => { - if (canViewCharacter(this.params._id, userIdFromKey(key))){ - this.response.end(JSONExport(this.params._id)) - } else { - this.response.writeHead(403, "You do not have permission to view this character"); - this.response.end(); - } - } - ); - }, - }); + this.route("jsonCharacterSheet", { + path: "/character/:_id/json", + where: "server", + action: function () { + this.response.setHeader("Content-Type", "application/json"); + var query = this.params.query; + var key = query && query.key; + ifKeyValid(key, this.response, "jsonCharacterSheet", () => { + if (canViewCharacter(this.params._id, userIdFromKey(key))) { + this.response.end(JSONExport(this.params._id)) + } else { + this.response.writeHead(403, "You do not have permission to view this character"); + this.response.end(); + } + } + ); + }, + }); this.route("getUserId", { // GET /api/user?username=:un path: "/api/user", @@ -67,35 +67,50 @@ Router.map(function() { }); }); -var ifKeyValid = function(apiKey, response, method, callback){ - if (!apiKey){ - response.writeHead(403, "You must use an api key to access this api"); - response.end(); - } else if (!isKeyValid(apiKey)){ - response.writeHead(403, "API key is invalid"); - response.end(); - } else if (isRateLimited(apiKey, method)){ - response.writeHead(429, "Too many requests"); - response.end(JSON.stringify({ - "timeToReset": rateLimiter.check({apiKey: apiKey, method: method}).timeToReset - })); - } else { - rateLimiter.increment({apiKey: apiKey, method: method}) - callback(); - } +var ifPostOK = function (router, endpoint, callback) { + router.response.setHeader("Content-Type", "application/json"); + var header = router.request.headers; + var key = header && header['Authorization']; + ifKeyValid(key, router.response, endpoint, () => { + if (canEditCharacter(router.params._id, userIdFromKey(key))) { + callback(); + } else { + router.response.writeHead(403, "You do not have permission to edit this character"); + router.response.end(); + } + } + ); }; -var isKeyValid = function(apiKey){ - var user = Meteor.users.findOne({apiKey}); - if (!user) return false; - var blackListed = Blacklist.findOne({userId: user._id}); - return !blackListed; +var ifKeyValid = function (apiKey, response, method, callback) { + if (!apiKey) { + response.writeHead(403, "You must use an api key to access this api"); + response.end(); + } else if (!isKeyValid(apiKey)) { + response.writeHead(403, "API key is invalid"); + response.end(); + } else if (isRateLimited(apiKey, method)) { + response.writeHead(429, "Too many requests"); + response.end(JSON.stringify({ + "timeToReset": rateLimiter.check({apiKey: apiKey, method: method}).timeToReset + })); + } else { + rateLimiter.increment({apiKey: apiKey, method: method}); + callback(); + } }; -var userIdFromKey = function(apiKey){ - var user = Meteor.users.findOne({apiKey}); // we know user exists from isKeyValid - return user._id; -} +var isKeyValid = function (apiKey) { + var user = Meteor.users.findOne({apiKey}); + if (!user) return false; + var blackListed = Blacklist.findOne({userId: user._id}); + return !blackListed; +}; + +var userIdFromKey = function (apiKey) { + var user = Meteor.users.findOne({apiKey}); // we know user exists from isKeyValid + return user._id; +}; var rateLimiter = new RateLimiter(); rateLimiter.addRule({apiKey: String}, 5, 5000); @@ -103,12 +118,12 @@ rateLimiter.addRule({apiKey: String, method: "vmixCharacter"}, 2, 10000); rateLimiter.addRule({apiKey: String, method: "vmixParty"}, 2, 10000); rateLimiter.addRule({apiKey: String, method: "jsonCharacterSheet"}, 5, 5000); -var isRateLimited = function(apiKey, method){ - const limited = !rateLimiter.check({apiKey: apiKey, method: method}).allowed - if (limited) { - console.log(`Rate limit hit by API key ${apiKey}`); - return true; - } else { - return false; - } +var isRateLimited = function (apiKey, method) { + const limited = !rateLimiter.check({apiKey: apiKey, method: method}).allowed; + if (limited) { + console.log(`Rate limit hit by API key ${apiKey}`); + return true; + } else { + return false; + } }; From 612575d0e655056809cae389e95f4b0eb4ba28b2 Mon Sep 17 00:00:00 2001 From: Andrew Zhu Date: Tue, 5 Feb 2019 13:14:09 -0800 Subject: [PATCH 022/247] add skeletons, ratelimits for endpoints --- app/Routes/API.js | 96 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 3 deletions(-) diff --git a/app/Routes/API.js b/app/Routes/API.js index b9cb005a..36d6438c 100644 --- a/app/Routes/API.js +++ b/app/Routes/API.js @@ -24,7 +24,7 @@ Router.map(function () { }, }); - this.route("jsonCharacterSheet", { + this.route("jsonCharacterSheet", { // GET /character/:_id/json?key=:key path: "/character/:_id/json", where: "server", action: function () { @@ -43,7 +43,7 @@ Router.map(function () { }, }); - this.route("getUserId", { // GET /api/user?username=:un + this.route("getUserId", { // GET /api/user?username=:un&key=:key path: "/api/user", where: "server", action: function () { @@ -65,6 +65,83 @@ Router.map(function () { }); } }); + + this.route("addSpellsToCharacter", { // POST /api/character/:_id/spellList/:listId + path: "/api/character/:_id/spellList/:listId", + where: "server" + }).post( + function () { + ifPostOK(this, "addSpellsToCharacter", () => { + + }); + } + ); + + this.route("createCharacter", { // POST /api/character + path: "/api/character", + where: "server" + }).post( + function () { + ifPostOK(this, "createCharacter", () => { + + }); + } + ); + + this.route("transferCharacterOwnership", { // POST /api/character/:_id/owner + path: "/api/character/:_id/owner", + where: "server" + }).post( + function () { + ifPostOK(this, "transferCharacterOwnership", () => { + + }); + } + ); + + this.route("insertFeatures", { // POST /api/character/:_id/feature + path: "/api/character/:_id/feature", + where: "server", + }).post( + function () { + ifPostOK(this, "insertFeatures", () => { + + }); + } + ); + + this.route("insertProfs", { // POST /api/character/:_id/prof + path: "/api/character/:_id/prof", + where: "server", + }).post( + function () { + ifPostOK(this, "insertProfs", () => { + + }); + } + ); + + this.route("insertEffects", { // POST /api/character/:_id/effect + path: "/api/character/:_id/effect", + where: "server", + }).post( + function () { + ifPostOK(this, "insertEffects", () => { + + }); + } + ); + + this.route("insertClasses", { // POST /api/character/:_id/class + path: "/api/character/:_id/class", + where: "server", + }).post( + function () { + ifPostOK(this, "insertClasses", () => { + + }); + } + ); }); var ifPostOK = function (router, endpoint, callback) { @@ -113,10 +190,23 @@ var userIdFromKey = function (apiKey) { }; var rateLimiter = new RateLimiter(); -rateLimiter.addRule({apiKey: String}, 5, 5000); +// global limit +rateLimiter.addRule({apiKey: String}, 10, 1000); + +// vmix stuff rateLimiter.addRule({apiKey: String, method: "vmixCharacter"}, 2, 10000); rateLimiter.addRule({apiKey: String, method: "vmixParty"}, 2, 10000); + +// bot API endpoints rateLimiter.addRule({apiKey: String, method: "jsonCharacterSheet"}, 5, 5000); +rateLimiter.addRule({apiKey: String, method: "getUserId"}, 5, 5000); +rateLimiter.addRule({apiKey: String, method: "addSpellsToCharacter"}, 5, 5000); +rateLimiter.addRule({apiKey: String, method: "createCharacter"}, 5, 5000); +rateLimiter.addRule({apiKey: String, method: "transferCharacterOwnership"}, 5, 5000); +rateLimiter.addRule({apiKey: String, method: "insertFeatures"}, 5, 5000); +rateLimiter.addRule({apiKey: String, method: "insertProfs"}, 5, 5000); +rateLimiter.addRule({apiKey: String, method: "insertEffects"}, 5, 5000); +rateLimiter.addRule({apiKey: String, method: "insertClasses"}, 5, 5000); var isRateLimited = function (apiKey, method) { const limited = !rateLimiter.check({apiKey: apiKey, method: method}).allowed; From fedda62c7c735a522c6471cad5bcbc32d29b9304 Mon Sep 17 00:00:00 2001 From: Andrew Zhu Date: Tue, 5 Feb 2019 13:59:55 -0800 Subject: [PATCH 023/247] add endpoint to add spells --- app/Routes/API.js | 28 +++++++++++++++++--- app/lib/constants/characterAssetAllowDeny.js | 7 ++--- app/lib/functions/parenting.js | 3 +++ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/app/Routes/API.js b/app/Routes/API.js index 36d6438c..2ca20b7c 100644 --- a/app/Routes/API.js +++ b/app/Routes/API.js @@ -71,8 +71,30 @@ Router.map(function () { where: "server" }).post( function () { - ifPostOK(this, "addSpellsToCharacter", () => { - + ifPostOK(this, "addSpellsToList", () => { + const spells = this.request.body; + const charId = this.params._id; + const listId = this.params.listId; + let spellIds = []; + let error; + for (let spell of spells) { + spell.parent = {id: listId, collection: "SpellLists"}; + spell.charId = charId; + let id = Spells.insert(spell, (err, _id) => { + if (err) { + error = err.message; + } + }); + if (error) + break; + spellIds.push(id); + } + if (error) { + this.response.writeHead(400, "Failed to insert one or more spells"); + this.response.end(JSON.stringify({err: error, inserted: spellIds})); + } else { + this.response.end(JSON.stringify(spellIds)); + } }); } ); @@ -147,7 +169,7 @@ Router.map(function () { var ifPostOK = function (router, endpoint, callback) { router.response.setHeader("Content-Type", "application/json"); var header = router.request.headers; - var key = header && header['Authorization']; + var key = header && header['authorization']; ifKeyValid(key, router.response, endpoint, () => { if (canEditCharacter(router.params._id, userIdFromKey(key))) { callback(); diff --git a/app/lib/constants/characterAssetAllowDeny.js b/app/lib/constants/characterAssetAllowDeny.js index 65730cfb..70277148 100644 --- a/app/lib/constants/characterAssetAllowDeny.js +++ b/app/lib/constants/characterAssetAllowDeny.js @@ -12,19 +12,20 @@ Meteor.methods({ CHARACTER_SUBSCHEMA_ALLOW = { // the user must be logged in, and the user must be a writer of the character + // or we must be the server insert: function(userId, doc) { var char = Characters.findOne( doc.charId, {fields: {owner: 1, writers: 1}} ); - return (userId && char.owner === userId || _.contains(char.writers, userId)); + return (userId && char.owner === userId || _.contains(char.writers, userId) || Meteor.isServer); }, update: function(userId, doc, fields, modifier) { var char = Characters.findOne( doc.charId, {fields: {owner: 1, writers: 1}} ); - return (userId && char.owner === userId || _.contains(char.writers, userId)); + return (userId && char.owner === userId || _.contains(char.writers, userId) || Meteor.isServer); }, remove: function(userId, doc) { var char = Characters.findOne( @@ -32,7 +33,7 @@ CHARACTER_SUBSCHEMA_ALLOW = { {fields: {owner: 1, writers: 1}} ); if (!char) return true; - return userId && char.owner === userId || _.contains(char.writers, userId); + return userId && char.owner === userId || _.contains(char.writers, userId) || Meteor.isServer; }, fetch: ["charId"], }; diff --git a/app/lib/functions/parenting.js b/app/lib/functions/parenting.js index 82ecf204..d26dc885 100644 --- a/app/lib/functions/parenting.js +++ b/app/lib/functions/parenting.js @@ -132,6 +132,9 @@ makeParent = function(collection, donatedKeys){ }; var checkPermission = function(userId, charId){ + if (Meteor.isServer) { // we always trust server + return true; + } var char = Characters.findOne(charId, {fields: {owner: 1, writers: 1}}); if (!char) throw new Meteor.Error("Access Denied, no charId", From c9242a95f3b1aa753f13cc7960bc2ef011b50d11 Mon Sep 17 00:00:00 2001 From: Andrew Zhu Date: Tue, 5 Feb 2019 15:14:11 -0800 Subject: [PATCH 024/247] add createCharacter, transferCharacter endpoints --- app/Routes/API.js | 47 +++++++++++++++++++++++++++++--- app/lib/functions/permissions.js | 7 +++++ 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/app/Routes/API.js b/app/Routes/API.js index 2ca20b7c..f041f37a 100644 --- a/app/Routes/API.js +++ b/app/Routes/API.js @@ -104,19 +104,58 @@ Router.map(function () { where: "server" }).post( function () { - ifPostOK(this, "createCharacter", () => { + this.response.setHeader("Content-Type", "application/json"); + const header = this.request.headers; + const key = header && header['authorization']; + ifKeyValid(key, this.response, "createCharacter", () => { + const character = this.request.body; + let error; + character.owner = userIdFromKey(key); + let id = Characters.insert(character, (err) => { + if (err) + error = err.message; + }); + + if (error) { + this.response.writeHead(400, "Failed to insert character"); + this.response.end(JSON.stringify({err: error})); + } else { + this.response.end(JSON.stringify({id: id})); + } }); } ); - this.route("transferCharacterOwnership", { // POST /api/character/:_id/owner + this.route("transferCharacterOwnership", { // PUT /api/character/:_id/owner path: "/api/character/:_id/owner", where: "server" - }).post( + }).put( function () { - ifPostOK(this, "transferCharacterOwnership", () => { + this.response.setHeader("Content-Type", "application/json"); + const header = this.request.headers; + const key = header && header['authorization']; + const charId = this.params._id; + ifKeyValid(key, this.response, "transferCharacterOwnership", () => { + if (isOwner(charId, userIdFromKey(key))) { + const newOwner = this.request.body['id']; + let error; + Characters.update({_id: charId}, {"$set": {owner: newOwner}}, null, + (err) => { + if (err) + error = err.message; + }); + if (error) { + this.response.writeHead(400, "Failed to update character"); + this.response.end(JSON.stringify({err: error})); + } else { + this.response.end(JSON.stringify({success: true})); + } + } else { + this.response.writeHead(403, "You do not have permission to transfer this character"); + this.response.end(); + } }); } ); diff --git a/app/lib/functions/permissions.js b/app/lib/functions/permissions.js index 8f160297..495d429b 100644 --- a/app/lib/functions/permissions.js +++ b/app/lib/functions/permissions.js @@ -1,3 +1,10 @@ +isOwner = function(charId, userId) { + userId = userId || Meteor.userId(); + var char = Characters.findOne(charId, {fields: {owner: 1}}); + if (!char) return true; + return (userId === char.owner); +}; + canEditCharacter = function(charId, userId){ userId = userId || Meteor.userId(); var char = Characters.findOne(charId, {fields: {owner: 1, writers: 1}}); From b890a3b11e4eca39ddf04eb37d2a9e1d1705c9e3 Mon Sep 17 00:00:00 2001 From: Andrew Zhu Date: Tue, 5 Feb 2019 15:21:32 -0800 Subject: [PATCH 025/247] add feature, effect, prof, class insert --- app/Routes/API.js | 88 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 84 insertions(+), 4 deletions(-) diff --git a/app/Routes/API.js b/app/Routes/API.js index f041f37a..373f2f83 100644 --- a/app/Routes/API.js +++ b/app/Routes/API.js @@ -166,7 +166,27 @@ Router.map(function () { }).post( function () { ifPostOK(this, "insertFeatures", () => { - + const features = this.request.body; + const charId = this.params._id; + let ids = []; + let error; + for (let feature of features) { + feature.charId = charId; + let id = Features.insert(feature, (err) => { + if (err) { + error = err.message; + } + }); + if (error) + break; + ids.push(id); + } + if (error) { + this.response.writeHead(400, "Failed to insert one or more features"); + this.response.end(JSON.stringify({err: error, inserted: ids})); + } else { + this.response.end(JSON.stringify(ids)); + } }); } ); @@ -177,7 +197,27 @@ Router.map(function () { }).post( function () { ifPostOK(this, "insertProfs", () => { - + const profs = this.request.body; + const charId = this.params._id; + let ids = []; + let error; + for (let prof of profs) { + prof.charId = charId; // we currently rely on the client to supply parent + let id = Proficiencies.insert(prof, (err) => { + if (err) { + error = err.message; + } + }); + if (error) + break; + ids.push(id); + } + if (error) { + this.response.writeHead(400, "Failed to insert one or more profs"); + this.response.end(JSON.stringify({err: error, inserted: ids})); + } else { + this.response.end(JSON.stringify(ids)); + } }); } ); @@ -188,7 +228,27 @@ Router.map(function () { }).post( function () { ifPostOK(this, "insertEffects", () => { - + const effects = this.request.body; + const charId = this.params._id; + let ids = []; + let error; + for (let effect of effects) { + effect.charId = charId; // we currently rely on the client to supply parent + let id = Effects.insert(effect, (err) => { + if (err) { + error = err.message; + } + }); + if (error) + break; + ids.push(id); + } + if (error) { + this.response.writeHead(400, "Failed to insert one or more effects"); + this.response.end(JSON.stringify({err: error, inserted: ids})); + } else { + this.response.end(JSON.stringify(ids)); + } }); } ); @@ -199,7 +259,27 @@ Router.map(function () { }).post( function () { ifPostOK(this, "insertClasses", () => { - + const klasses = this.request.body; + const charId = this.params._id; + let ids = []; + let error; + for (let klass of klasses) { + klass.charId = charId; // we currently rely on the client to supply parent + let id = Classes.insert(klass, (err) => { + if (err) { + error = err.message; + } + }); + if (error) + break; + ids.push(id); + } + if (error) { + this.response.writeHead(400, "Failed to insert one or more classes"); + this.response.end(JSON.stringify({err: error, inserted: ids})); + } else { + this.response.end(JSON.stringify(ids)); + } }); } ); From 40c54524a7dba3dc2cc1f04a08f22a570a0751f6 Mon Sep 17 00:00:00 2001 From: Andrew Zhu Date: Tue, 5 Feb 2019 15:46:06 -0800 Subject: [PATCH 026/247] add delete character endpoint --- app/Routes/API.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/app/Routes/API.js b/app/Routes/API.js index 373f2f83..2f3deaa7 100644 --- a/app/Routes/API.js +++ b/app/Routes/API.js @@ -127,6 +127,37 @@ Router.map(function () { } ); + this.route("deleteCharacter", { // DELETE /api/character/:_id + path: "/api/character/:_id", + where: "server" + }).delete( + function () { + this.response.setHeader("Content-Type", "application/json"); + const header = this.request.headers; + const key = header && header['authorization']; + const charId = this.params._id; + ifKeyValid(key, this.response, "deleteCharacter", () => { + if (isOwner(charId, userIdFromKey(key))) { + let error; + Characters.remove({_id: charId}, (err) => { + if (err) + error = err.message; + }); + + if (error) { + this.response.writeHead(400, "Failed to delete character"); + this.response.end(JSON.stringify({err: error})); + } else { + this.response.end(JSON.stringify({success: true})); + } + } else { + this.response.writeHead(403, "You do not have permission to delete this character"); + this.response.end(); + } + }); + } + ); + this.route("transferCharacterOwnership", { // PUT /api/character/:_id/owner path: "/api/character/:_id/owner", where: "server" From 2f04d9ec1c52dd89404aad2e479a6b3a06430ab2 Mon Sep 17 00:00:00 2001 From: Andrew Zhu Date: Thu, 7 Feb 2019 15:45:45 -0800 Subject: [PATCH 027/247] remove server check overrides --- app/lib/constants/characterAssetAllowDeny.js | 7 +++---- app/lib/functions/parenting.js | 3 --- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/app/lib/constants/characterAssetAllowDeny.js b/app/lib/constants/characterAssetAllowDeny.js index 70277148..65730cfb 100644 --- a/app/lib/constants/characterAssetAllowDeny.js +++ b/app/lib/constants/characterAssetAllowDeny.js @@ -12,20 +12,19 @@ Meteor.methods({ CHARACTER_SUBSCHEMA_ALLOW = { // the user must be logged in, and the user must be a writer of the character - // or we must be the server insert: function(userId, doc) { var char = Characters.findOne( doc.charId, {fields: {owner: 1, writers: 1}} ); - return (userId && char.owner === userId || _.contains(char.writers, userId) || Meteor.isServer); + return (userId && char.owner === userId || _.contains(char.writers, userId)); }, update: function(userId, doc, fields, modifier) { var char = Characters.findOne( doc.charId, {fields: {owner: 1, writers: 1}} ); - return (userId && char.owner === userId || _.contains(char.writers, userId) || Meteor.isServer); + return (userId && char.owner === userId || _.contains(char.writers, userId)); }, remove: function(userId, doc) { var char = Characters.findOne( @@ -33,7 +32,7 @@ CHARACTER_SUBSCHEMA_ALLOW = { {fields: {owner: 1, writers: 1}} ); if (!char) return true; - return userId && char.owner === userId || _.contains(char.writers, userId) || Meteor.isServer; + return userId && char.owner === userId || _.contains(char.writers, userId); }, fetch: ["charId"], }; diff --git a/app/lib/functions/parenting.js b/app/lib/functions/parenting.js index d26dc885..82ecf204 100644 --- a/app/lib/functions/parenting.js +++ b/app/lib/functions/parenting.js @@ -132,9 +132,6 @@ makeParent = function(collection, donatedKeys){ }; var checkPermission = function(userId, charId){ - if (Meteor.isServer) { // we always trust server - return true; - } var char = Characters.findOne(charId, {fields: {owner: 1, writers: 1}}); if (!char) throw new Meteor.Error("Access Denied, no charId", From cb71f6d38029298fe0ba73fa33ce41caf64cb7b5 Mon Sep 17 00:00:00 2001 From: Andrew Zhu Date: Thu, 7 Feb 2019 22:05:24 -0800 Subject: [PATCH 028/247] move everything to Meteor methods --- app/Routes/API.js | 346 ++++++++++------------------- app/lib/functions/api.js | 241 ++++++++++++++++++++ app/lib/functions/characterJSON.js | 17 -- 3 files changed, 353 insertions(+), 251 deletions(-) create mode 100644 app/lib/functions/api.js delete mode 100644 app/lib/functions/characterJSON.js diff --git a/app/Routes/API.js b/app/Routes/API.js index 2f3deaa7..45453351 100644 --- a/app/Routes/API.js +++ b/app/Routes/API.js @@ -69,266 +69,144 @@ Router.map(function () { this.route("addSpellsToCharacter", { // POST /api/character/:_id/spellList/:listId path: "/api/character/:_id/spellList/:listId", where: "server" - }).post( - function () { - ifPostOK(this, "addSpellsToList", () => { - const spells = this.request.body; - const charId = this.params._id; - const listId = this.params.listId; - let spellIds = []; - let error; - for (let spell of spells) { - spell.parent = {id: listId, collection: "SpellLists"}; - spell.charId = charId; - let id = Spells.insert(spell, (err, _id) => { - if (err) { - error = err.message; - } - }); - if (error) - break; - spellIds.push(id); - } - if (error) { - this.response.writeHead(400, "Failed to insert one or more spells"); - this.response.end(JSON.stringify({err: error, inserted: spellIds})); - } else { - this.response.end(JSON.stringify(spellIds)); - } - }); - } - ); + }).post(function () { + const key = startPOSTResponse(this); + const spells = this.request.body; + const charId = this.params._id; + const listId = this.params.listId; + Meteor.call("insertSpells", key, charId, listId, spells, (err, res) => { + if (err) { + console.log(err); + this.response.writeHead(err.error, err.reason); + this.response.end(err.details); + } else { + this.response.end(JSON.stringify(res)); + } + }); + }); this.route("createCharacter", { // POST /api/character path: "/api/character", where: "server" - }).post( - function () { - this.response.setHeader("Content-Type", "application/json"); - const header = this.request.headers; - const key = header && header['authorization']; - ifKeyValid(key, this.response, "createCharacter", () => { - const character = this.request.body; - let error; - - character.owner = userIdFromKey(key); - let id = Characters.insert(character, (err) => { - if (err) - error = err.message; - }); - - if (error) { - this.response.writeHead(400, "Failed to insert character"); - this.response.end(JSON.stringify({err: error})); - } else { - this.response.end(JSON.stringify({id: id})); - } - }); - } - ); + }).post(function () { + const key = startPOSTResponse(this); + const character = this.request.body; + Meteor.call("insertCharacter", key, character, (err, res) => { + if (err) { + this.response.writeHead(err.error, err.reason); + this.response.end(err.details); + } else { + this.response.end(JSON.stringify(res)); + } + }); + }); this.route("deleteCharacter", { // DELETE /api/character/:_id path: "/api/character/:_id", where: "server" - }).delete( - function () { - this.response.setHeader("Content-Type", "application/json"); - const header = this.request.headers; - const key = header && header['authorization']; - const charId = this.params._id; - ifKeyValid(key, this.response, "deleteCharacter", () => { - if (isOwner(charId, userIdFromKey(key))) { - let error; - Characters.remove({_id: charId}, (err) => { - if (err) - error = err.message; - }); - - if (error) { - this.response.writeHead(400, "Failed to delete character"); - this.response.end(JSON.stringify({err: error})); - } else { - this.response.end(JSON.stringify({success: true})); - } - } else { - this.response.writeHead(403, "You do not have permission to delete this character"); - this.response.end(); - } - }); - } - ); + }).delete(function () { + const key = startPOSTResponse(this); + const charId = this.params._id; + Meteor.call("deleteCharacter", key, charId, (err, res) => { + if (err) { + this.response.writeHead(err.error, err.reason); + this.response.end(err.details); + } else { + this.response.end(JSON.stringify(res)); + } + }); + }); this.route("transferCharacterOwnership", { // PUT /api/character/:_id/owner path: "/api/character/:_id/owner", where: "server" - }).put( - function () { - this.response.setHeader("Content-Type", "application/json"); - const header = this.request.headers; - const key = header && header['authorization']; - const charId = this.params._id; - ifKeyValid(key, this.response, "transferCharacterOwnership", () => { - if (isOwner(charId, userIdFromKey(key))) { - const newOwner = this.request.body['id']; - let error; - Characters.update({_id: charId}, {"$set": {owner: newOwner}}, null, - (err) => { - if (err) - error = err.message; - }); - - if (error) { - this.response.writeHead(400, "Failed to update character"); - this.response.end(JSON.stringify({err: error})); - } else { - this.response.end(JSON.stringify({success: true})); - } - } else { - this.response.writeHead(403, "You do not have permission to transfer this character"); - this.response.end(); - } - }); - } - ); + }).put(function () { + const key = startPOSTResponse(this); + const charId = this.params._id; + const ownerId = this.request.body['id']; + Meteor.call("transferCharacterOwnership", key, charId, ownerId, (err, res) => { + if (err) { + this.response.writeHead(err.error, err.reason); + this.response.end(err.details); + } else { + this.response.end(JSON.stringify(res)); + } + }); + }); this.route("insertFeatures", { // POST /api/character/:_id/feature path: "/api/character/:_id/feature", where: "server", - }).post( - function () { - ifPostOK(this, "insertFeatures", () => { - const features = this.request.body; - const charId = this.params._id; - let ids = []; - let error; - for (let feature of features) { - feature.charId = charId; - let id = Features.insert(feature, (err) => { - if (err) { - error = err.message; - } - }); - if (error) - break; - ids.push(id); - } - if (error) { - this.response.writeHead(400, "Failed to insert one or more features"); - this.response.end(JSON.stringify({err: error, inserted: ids})); - } else { - this.response.end(JSON.stringify(ids)); - } - }); - } - ); + }).post(function () { + const key = startPOSTResponse(this); + const charId = this.params._id; + const features = this.request.body; + Meteor.call("insertFeatures", key, charId, features, (err, res) => { + if (err) { + this.response.writeHead(err.error, err.reason); + this.response.end(err.details); + } else { + this.response.end(JSON.stringify(res)); + } + }); + }); this.route("insertProfs", { // POST /api/character/:_id/prof path: "/api/character/:_id/prof", where: "server", - }).post( - function () { - ifPostOK(this, "insertProfs", () => { - const profs = this.request.body; - const charId = this.params._id; - let ids = []; - let error; - for (let prof of profs) { - prof.charId = charId; // we currently rely on the client to supply parent - let id = Proficiencies.insert(prof, (err) => { - if (err) { - error = err.message; - } - }); - if (error) - break; - ids.push(id); - } - if (error) { - this.response.writeHead(400, "Failed to insert one or more profs"); - this.response.end(JSON.stringify({err: error, inserted: ids})); - } else { - this.response.end(JSON.stringify(ids)); - } - }); - } - ); + }).post(function () { + const key = startPOSTResponse(this); + const charId = this.params._id; + const profs = this.request.body; + Meteor.call("insertProfs", key, charId, profs, (err, res) => { + if (err) { + this.response.writeHead(err.error, err.reason); + this.response.end(err.details); + } else { + this.response.end(JSON.stringify(res)); + } + }); + }); this.route("insertEffects", { // POST /api/character/:_id/effect path: "/api/character/:_id/effect", where: "server", - }).post( - function () { - ifPostOK(this, "insertEffects", () => { - const effects = this.request.body; - const charId = this.params._id; - let ids = []; - let error; - for (let effect of effects) { - effect.charId = charId; // we currently rely on the client to supply parent - let id = Effects.insert(effect, (err) => { - if (err) { - error = err.message; - } - }); - if (error) - break; - ids.push(id); - } - if (error) { - this.response.writeHead(400, "Failed to insert one or more effects"); - this.response.end(JSON.stringify({err: error, inserted: ids})); - } else { - this.response.end(JSON.stringify(ids)); - } - }); - } - ); + }).post(function () { + const key = startPOSTResponse(this); + const charId = this.params._id; + const effects = this.request.body; + Meteor.call("insertEffects", key, charId, effects, (err, res) => { + if (err) { + this.response.writeHead(err.error, err.reason); + this.response.end(err.details); + } else { + this.response.end(JSON.stringify(res)); + } + }); + }); this.route("insertClasses", { // POST /api/character/:_id/class path: "/api/character/:_id/class", where: "server", - }).post( - function () { - ifPostOK(this, "insertClasses", () => { - const klasses = this.request.body; - const charId = this.params._id; - let ids = []; - let error; - for (let klass of klasses) { - klass.charId = charId; // we currently rely on the client to supply parent - let id = Classes.insert(klass, (err) => { - if (err) { - error = err.message; - } - }); - if (error) - break; - ids.push(id); - } - if (error) { - this.response.writeHead(400, "Failed to insert one or more classes"); - this.response.end(JSON.stringify({err: error, inserted: ids})); - } else { - this.response.end(JSON.stringify(ids)); - } - }); - } - ); + }).post(function () { + const key = startPOSTResponse(this); + const charId = this.params._id; + const classes = this.request.body; + Meteor.call("insertClasses", key, charId, classes, (err, res) => { + if (err) { + this.response.writeHead(err.error, err.reason); + this.response.end(err.details); + } else { + this.response.end(JSON.stringify(res)); + } + }); + }); }); -var ifPostOK = function (router, endpoint, callback) { - router.response.setHeader("Content-Type", "application/json"); - var header = router.request.headers; - var key = header && header['authorization']; - ifKeyValid(key, router.response, endpoint, () => { - if (canEditCharacter(router.params._id, userIdFromKey(key))) { - callback(); - } else { - router.response.writeHead(403, "You do not have permission to edit this character"); - router.response.end(); - } - } - ); +const startPOSTResponse = function (request) { + request.response.setHeader("Content-Type", "application/json"); + const header = request.request.headers; + return header && header['authorization']; }; var ifKeyValid = function (apiKey, response, method, callback) { @@ -349,19 +227,19 @@ var ifKeyValid = function (apiKey, response, method, callback) { } }; -var isKeyValid = function (apiKey) { +isKeyValid = function (apiKey) { var user = Meteor.users.findOne({apiKey}); if (!user) return false; var blackListed = Blacklist.findOne({userId: user._id}); return !blackListed; }; -var userIdFromKey = function (apiKey) { +userIdFromKey = function (apiKey) { var user = Meteor.users.findOne({apiKey}); // we know user exists from isKeyValid return user._id; }; -var rateLimiter = new RateLimiter(); +rateLimiter = new RateLimiter(); // global limit rateLimiter.addRule({apiKey: String}, 10, 1000); @@ -380,7 +258,7 @@ rateLimiter.addRule({apiKey: String, method: "insertProfs"}, 5, 5000); rateLimiter.addRule({apiKey: String, method: "insertEffects"}, 5, 5000); rateLimiter.addRule({apiKey: String, method: "insertClasses"}, 5, 5000); -var isRateLimited = function (apiKey, method) { +isRateLimited = function (apiKey, method) { const limited = !rateLimiter.check({apiKey: apiKey, method: method}).allowed; if (limited) { console.log(`Rate limit hit by API key ${apiKey}`); diff --git a/app/lib/functions/api.js b/app/lib/functions/api.js new file mode 100644 index 00000000..e58b5135 --- /dev/null +++ b/app/lib/functions/api.js @@ -0,0 +1,241 @@ +/** + * @return {string} + */ +JSONExport = function (charId) { + const character = { + "attacks": Attacks.find({charId: charId}).fetch(), + "characters": Characters.find({_id: charId}).fetch(), + "classes": Classes.find({charId: charId}).fetch(), + "containers": Containers.find({charId: charId}).fetch(), + "effects": Effects.find({charId: charId}).fetch(), + "experience": Experiences.find({charId: charId}).fetch(), + "features": Features.find({charId: charId}).fetch(), + "items": Items.find({charId: charId}).fetch(), + "notes": Notes.find({charId: charId}).fetch(), + "proficiencies": Proficiencies.find({charId: charId}).fetch(), + "spellLists": SpellLists.find({charId: charId}).fetch(), + "spells": Spells.find({charId: charId}).fetch() + }; + return JSON.stringify(character); +}; + +Meteor.methods({ + "insertSpells": function (key, charId, listId, spells) { + if (Meteor.isClient) return; + ifCanEdit(key, charId, "addSpellsToCharacter", () => { + let ids = []; + let error; + for (let spell of spells) { + spell.parent = {id: listId, collection: "SpellLists"}; + spell.charId = charId; + let id = Spells.insert(spell, (err) => { + if (err) { + error = err.message; + } + }); + ids.push(id); + } + if (error) { + throw new Meteor.Error(400, "Failed to insert one or more spells", JSON.stringify({ + err: error, + inserted: ids + })); + } else { + return ids; + } + }); + }, + + "insertCharacter": function (key, character) { + if (Meteor.isClient) return; + ifAuthorized(key, "createCharacter", () => { + let error; + + character.owner = userIdFromKey(key); + let id = Characters.insert(character, (err) => { + if (err) + error = err.message; + }); + + if (error) { + throw new Meteor.Error(400, "Failed to insert character", JSON.stringify({err: error})); + } else { + return {id: id}; + } + }); + }, + + "deleteCharacter": function (key, charId) { + if (Meteor.isClient) return; + ifAuthorized(key, "deleteCharacter", () => { + if (isOwner(charId, userIdFromKey(key))) { + let error; + + Characters.remove({_id: charId}, (err) => { + if (err) + error = err.message; + }); + if (error) { + throw new Meteor.Error(400, "Failed to delete character", JSON.stringify({err: error})); + } else { + return {success: true}; + } + } else { + throw new Meteor.Error(403, "You do not have permission to delete the requested character"); + } + }); + }, + + "transferCharacterOwnership": function (key, charId, newOwner) { + if (Meteor.isClient) return; + ifAuthorized(key, "transferCharacterOwnership", () => { + if (isOwner(charId, userIdFromKey(key))) { + let error; + Characters.update({_id: charId}, {"$set": {owner: newOwner}}, null, + (err) => { + if (err) + error = err.message; + }); + + if (error) { + throw new Meteor.Error(400, "Failed to update character", JSON.stringify({err: error})); + } else { + return {success: true}; + } + } else { + throw new Meteor.Error(403, "You do not have permission to transfer the requested character"); + } + }); + }, + + "insertFeatures": function (key, charId, features) { + if (Meteor.isClient) return; + ifCanEdit(key, charId, "insertFeatures", () => { + let ids = []; + let error; + for (let feature of features) { + feature.charId = charId; + let id = Features.insert(feature, (err) => { + if (err) { + error = err.message; + } + }); + if (error) + break; + ids.push(id); + } + if (error) { + throw new Meteor.Error(400, "Failed to insert one or more features", JSON.stringify({ + err: error, + inserted: ids + })); + } else { + return ids; + } + }); + }, + + "insertProfs": function (key, charId, profs) { + if (Meteor.isClient) return; + ifCanEdit(key, charId, "insertProfs", () => { + let ids = []; + let error; + for (let prof of profs) { + prof.charId = charId; // we currently rely on the client to supply parent + let id = Proficiencies.insert(prof, (err) => { + if (err) { + error = err.message; + } + }); + if (error) + break; + ids.push(id); + } + if (error) { + throw new Meteor.Error(400, "Failed to insert one or more profs", JSON.stringify({ + err: error, + inserted: ids + })); + } else { + return ids; + } + }); + }, + + "insertEffects": function (key, charId, effects) { + if (Meteor.isClient) return; + ifCanEdit(key, charId, "insertEffects", () => { + let ids = []; + let error; + for (let effect of effects) { + effect.charId = charId; // we currently rely on the client to supply parent + let id = Effects.insert(effect, (err) => { + if (err) { + error = err.message; + } + }); + if (error) + break; + ids.push(id); + } + if (error) { + throw new Meteor.Error(400, "Failed to insert one or more effects", JSON.stringify({ + err: error, + inserted: ids + })); + } else { + return ids; + } + }); + }, + + "insertClasses": function (key, charId, klasses) { + if (Meteor.isClient) return; + ifCanEdit(key, charId, "insertClasses", () => { + let ids = []; + let error; + for (let klass of klasses) { + klass.charId = charId; // we currently rely on the client to supply parent + let id = Classes.insert(klass, (err) => { + if (err) { + error = err.message; + } + }); + if (error) + break; + ids.push(id); + } + if (error) { + throw new Meteor.Error(400, "Failed to insert one or more classes", JSON.stringify({ + err: error, + inserted: ids + })); + } else { + return ids; + } + }); + } +}); + +var ifCanEdit = function (key, charId, method, callback) { + if (canEditCharacter(charId, userIdFromKey(key))) { + ifAuthorized(key, method, callback); + } else { + throw new Meteor.Error(403, "You do not have permission to edit the requested character"); + } +}; + +var ifAuthorized = function (apiKey, method, callback) { + if (!apiKey) { + throw new Meteor.Error(403, "You must use an api key to access this api"); + } else if (!isKeyValid(apiKey)) { + throw new Meteor.Error(403, "API key is invalid"); + } else if (isRateLimited(apiKey, method)) { + throw new Meteor.Error(429, "Too many requests", JSON.stringify({ + "timeToReset": rateLimiter.check({apiKey: apiKey, method: method}).timeToReset + })); + } else { + rateLimiter.increment({apiKey: apiKey, method: method}); + callback(); + } +}; diff --git a/app/lib/functions/characterJSON.js b/app/lib/functions/characterJSON.js deleted file mode 100644 index 861bb796..00000000 --- a/app/lib/functions/characterJSON.js +++ /dev/null @@ -1,17 +0,0 @@ -JSONExport = function(charId) { - var character = { - "attacks": Attacks.find({charId: charId}).fetch(), - "characters": Characters.find({_id: charId}).fetch(), - "classes": Classes.find({charId: charId}).fetch(), - "containers": Containers.find({charId: charId}).fetch(), - "effects": Effects.find({charId: charId}).fetch(), - "experience": Experiences.find({charId: charId}).fetch(), - "features": Features.find({charId: charId}).fetch(), - "items": Items.find({charId: charId}).fetch(), - "notes": Notes.find({charId: charId}).fetch(), - "proficiencies": Proficiencies.find({charId: charId}).fetch(), - "spellLists": SpellLists.find({charId: charId}).fetch(), - "spells": Spells.find({charId: charId}).fetch() - }; - return JSON.stringify(character); -} From 0260824c2f13cf8307a5edab282483ccf02ff6f0 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Mon, 11 Feb 2019 10:09:18 +0200 Subject: [PATCH 029/247] Made gave backup and restore the ability to change ids for all docs --- app/lib/functions/backupRestoreCharacter.js | 47 ++++++++++++++++++--- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/app/lib/functions/backupRestoreCharacter.js b/app/lib/functions/backupRestoreCharacter.js index ba95f4af..d08ef919 100644 --- a/app/lib/functions/backupRestoreCharacter.js +++ b/app/lib/functions/backupRestoreCharacter.js @@ -3,6 +3,7 @@ let characterCollections = [ Attacks, Buffs, Classes, + Conditions, CustomBuffs, Effects, Experiences, @@ -10,21 +11,55 @@ let characterCollections = [ Notes, Proficiencies, SpellLists, + Spells, + TemporaryHitPoints, Items, Containers, ]; -function backupCharacter(charId){ +function dumpCharacter(charId){ let characterDump = {}; - characterDump.characters = [Characters.findOne(charId)]; - characterCollections.map( - c => characterDump[c._name] = c.find({charId}).fetch() - ); + characterDump.character = Characters.findOne(charId); + characterCollections.forEach(c => { + characterDump.collections[c._name] = c.find({charId}).fetch(); + }); return characterDump; }; +function giveCharacterDumpNewIds(characterDump){ + // Give the character a new Id + const newCharId = Random.id(); + characterDump.character._id = newCharId; + + // Give all documents a new Id, and store the mapping from old to new + let idMap = {}; // {oldId: newId} + for (let colName in characterDump.collections){ + for (let doc of characterDump.collections[colName]){ + let oldId = doc._id; + let newId = Random.id(); + doc._id = newId; + idMap[oldId] = newId; + } + } + + // Replace all references to old Ids with new ones + for (let colName in characterDump.collections){ + for (let doc of characterDump.collections[colName]){ + // Replace the character Id with the new one + doc.charId = newCharId; + // Replace the parent reference id with a new id + if (doc.parent && doc.parent.id){ + let newParentId = idMap[doc.parent.id]; + if(!newParentId) throw `Can't find the mapping for id ${doc.parent.id}`; + doc.parent.id = newParentId; + } + } + } +} + function restoreCharacter(characterDump){ - for (collectionName in characterDump){ + Characters.insert(characterDump.character); + for (collectionName in characterDump.collections){ let collection = Meteor.Collection.get(collectionName); for (doc in characterDump[collectionName]){ collection.insert(doc); From 3343f8a8135506f6d1e099b44aa2e0443e73721b Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Mon, 11 Feb 2019 10:17:43 +0200 Subject: [PATCH 030/247] Allowed canViewCharacter to take in a character instead of a charId to save a database read --- app/lib/functions/permissions.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/app/lib/functions/permissions.js b/app/lib/functions/permissions.js index 8f160297..37b4ff73 100644 --- a/app/lib/functions/permissions.js +++ b/app/lib/functions/permissions.js @@ -5,12 +5,14 @@ canEditCharacter = function(charId, userId){ return (userId === char.owner || _.contains(char.writers, userId)); }; -canViewCharacter = function(charId, userId){ +canViewCharacter = function(char, userId){ userId = userId || Meteor.userId(); - var char = Characters.findOne( - charId, - {fields: {owner: 1, writers: 1, readers: 1, "settings.viewPermission": 1}} - ); + if (typeof char !== 'object'){ + char = Characters.findOne( + charId, + {fields: {owner: 1, writers: 1, readers: 1, "settings.viewPermission": 1}} + ); + } if (!char) return true; return userId === char.owner || char.settings.viewPermission === "public" || From 9d86cb8bee1a8590bc285fdab37569689940d384 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Mon, 11 Feb 2019 10:21:11 +0200 Subject: [PATCH 031/247] Added the copy character method --- app/lib/methods/characterCopyPaste.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 app/lib/methods/characterCopyPaste.js diff --git a/app/lib/methods/characterCopyPaste.js b/app/lib/methods/characterCopyPaste.js new file mode 100644 index 00000000..d078b45b --- /dev/null +++ b/app/lib/methods/characterCopyPaste.js @@ -0,0 +1,22 @@ +// Uses '/lib/functions/backupRestoreCharacter.js' to do most the work + +Meteor.methods({ + copyCharacter: function(charId) { + const userId = Meteor.userId(); + let character = Characters.findOne(charId); + + // Need at least view level permission to make a copy for yourself + if (!canViewCharacter(character, userId)) return; + + let characterDump = dumpCharacter(charId); + giveCharacterDumpNewIds(characterDump); + + // Remove all readers and writers, make this user the new owner + characterDump.character.readers = []; + characterDump.character.writers = []; + characterDump.character.owner = userId; + + // Write the character back to the database + restoreCharacter(characterDump); + }, +}); From 1ebb0d25275b8f37fc5648480cbf54b50d1410ff Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Mon, 11 Feb 2019 11:11:51 +0200 Subject: [PATCH 032/247] Got character copying working --- .../views/character/characterSheet.html | 10 +- app/client/views/character/characterSheet.js | 12 +++ app/lib/functions/backupRestoreCharacter.js | 61 +++++++----- app/lib/methods/characterCopyPaste.js | 4 + app/package-lock.json | 93 +++++++++++++++++-- app/package.json | 1 + 6 files changed, 148 insertions(+), 33 deletions(-) diff --git a/app/client/views/character/characterSheet.html b/app/client/views/character/characterSheet.html index 8785892b..efc54123 100644 --- a/app/client/views/character/characterSheet.html +++ b/app/client/views/character/characterSheet.html @@ -31,9 +31,17 @@ Settings - + Export to Improved Initiative + + + Make a copy + + + + Download a backup + {{else}} diff --git a/app/client/views/character/characterSheet.js b/app/client/views/character/characterSheet.js index a2a549f4..0c43d387 100644 --- a/app/client/views/character/characterSheet.js +++ b/app/client/views/character/characterSheet.js @@ -234,6 +234,18 @@ Template.characterSheet.events({ element: event.currentTarget.parentElement.parentElement, }); }, + "click #characterCopy": function(event, instance){ + Meteor.call("copyCharacter", this._id, (error, char) => { + if (error){ + console.error(error); + } else { + Router.go(`/character/${char._id}/${char.urlName || "-"}`); + } + }); + }, + "click #characterDump": function(event, instance){ + saveCharacterDump(this._id); + }, "click #unshareCharacter": function(event, instance){ pushDialogStack({ data: this, diff --git a/app/lib/functions/backupRestoreCharacter.js b/app/lib/functions/backupRestoreCharacter.js index d08ef919..9863d12f 100644 --- a/app/lib/functions/backupRestoreCharacter.js +++ b/app/lib/functions/backupRestoreCharacter.js @@ -1,24 +1,29 @@ -let characterCollections = [ - Actions, - Attacks, - Buffs, - Classes, - Conditions, - CustomBuffs, - Effects, - Experiences, - Features, - Notes, - Proficiencies, - SpellLists, - Spells, - TemporaryHitPoints, - Items, - Containers, -]; +import { saveAs } from 'file-saver'; -function dumpCharacter(charId){ - let characterDump = {}; +let characterCollections = []; +Meteor.startup(() => { + characterCollections = [ + Actions, + Attacks, + Buffs, + Classes, + Conditions, + CustomBuffs, + Effects, + Experiences, + Features, + Notes, + Proficiencies, + SpellLists, + Spells, + TemporaryHitPoints, + Items, + Containers, + ]; +}); + +dumpCharacter = function(charId){ + let characterDump = {collections: {}}; characterDump.character = Characters.findOne(charId); characterCollections.forEach(c => { characterDump.collections[c._name] = c.find({charId}).fetch(); @@ -26,13 +31,23 @@ function dumpCharacter(charId){ return characterDump; }; -function giveCharacterDumpNewIds(characterDump){ +saveCharacterDump = function(charId){ + let dump = dumpCharacter(charId); + let textDump = JSON.stringify(dump, null, 2); + let charName = dump.character.name; + let blob = new Blob([textDump], {type: "application/json;charset=utf-8"}); + saveAs(blob, `${charName}.JSON`); +}; + +giveCharacterDumpNewIds = function(characterDump){ // Give the character a new Id + const oldCharId = characterDump.character._id; const newCharId = Random.id(); characterDump.character._id = newCharId; + let idMap = {[oldCharId]: newCharId}; // {oldId: newId} + // Give all documents a new Id, and store the mapping from old to new - let idMap = {}; // {oldId: newId} for (let colName in characterDump.collections){ for (let doc of characterDump.collections[colName]){ let oldId = doc._id; @@ -57,7 +72,7 @@ function giveCharacterDumpNewIds(characterDump){ } } -function restoreCharacter(characterDump){ +restoreCharacter = function(characterDump){ Characters.insert(characterDump.character); for (collectionName in characterDump.collections){ let collection = Meteor.Collection.get(collectionName); diff --git a/app/lib/methods/characterCopyPaste.js b/app/lib/methods/characterCopyPaste.js index d078b45b..76173202 100644 --- a/app/lib/methods/characterCopyPaste.js +++ b/app/lib/methods/characterCopyPaste.js @@ -16,7 +16,11 @@ Meteor.methods({ characterDump.character.writers = []; characterDump.character.owner = userId; + // Rename the character so it's obviously a copy + characterDump.character.name += " - Copy"; + // Write the character back to the database restoreCharacter(characterDump); + return characterDump.character; }, }); diff --git a/app/package-lock.json b/app/package-lock.json index 12e5ed0b..3c606c15 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -45,7 +45,7 @@ }, "ansi-regex": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "resolved": false, "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "aproba": { @@ -74,6 +74,7 @@ }, "block-stream": { "version": "0.0.9", + "resolved": false, "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", "requires": { "inherits": "~2.0.0" @@ -131,7 +132,7 @@ }, "code-point-at": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "resolved": false, "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "core-js": { @@ -139,6 +140,11 @@ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, "cross-spawn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", @@ -209,6 +215,11 @@ "resolved": "https://registry.npmjs.org/fibers/-/fibers-2.0.2.tgz", "integrity": "sha512-HfVRxhYG7C8Jl9FqtrlElMR2z/8YiLQVDKf67MLY25Ic+ILx3ecmklfT1v3u+7P5/4vEFjuxaAFXhr2/Afwk5g==" }, + "file-saver": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.0.tgz", + "integrity": "sha512-cYM1ic5DAkg25pHKgi5f10ziAM7RJU37gaH1XQlyNDrtUnzhC/dfoV9zf2OmF0RMKi42jG5B0JWBnPQqyj/G6g==" + }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -259,7 +270,7 @@ }, "graceful-fs": { "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "resolved": false, "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, "har-schema": { @@ -361,6 +372,7 @@ }, "inherits": { "version": "2.0.3", + "resolved": false, "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "invert-kv": { @@ -383,7 +395,7 @@ }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "resolved": false, "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "requires": { "number-is-nan": "^1.0.0" @@ -1064,6 +1076,37 @@ "requires": { "inherits": "~2.0.1", "readable-stream": "^2.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "stream-http": { @@ -1076,6 +1119,37 @@ "readable-stream": "^2.3.3", "to-arraybuffer": "^1.0.0", "xtend": "^4.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "string_decoder": { @@ -1434,7 +1508,7 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "resolved": false, "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "os-homedir": { @@ -1578,6 +1652,7 @@ }, "minimist": { "version": "1.2.0", + "resolved": false, "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "strip-json-comments": { @@ -1815,7 +1890,7 @@ }, "set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "resolved": false, "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "shebang-command": { @@ -1833,7 +1908,7 @@ }, "signal-exit": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "resolved": false, "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, "source-map": { @@ -1909,7 +1984,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": false, "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { "ansi-regex": "^2.0.0" @@ -2159,7 +2234,7 @@ }, "wrap-ansi": { "version": "2.1.0", - "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "requires": { "string-width": "^1.0.1", diff --git a/app/package.json b/app/package.json index 13ecdf36..fbbadeae 100644 --- a/app/package.json +++ b/app/package.json @@ -17,6 +17,7 @@ "bower": "^1.7.9", "core-js": "^2.5.7", "fibers": "^2.0.2", + "file-saver": "^2.0.0", "meteor-node-stubs": "^0.3.3", "qrcode": "^1.3.0", "source-map-support": "^0.5.9", From 23d43f7d4332420016f44fb29fb6a1efcf561af3 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Mon, 11 Feb 2019 11:58:45 +0200 Subject: [PATCH 033/247] Added character restore functionality --- .../views/characterList/characterList.html | 7 +++ .../views/characterList/characterList.js | 16 ++++++ .../characterRestoreDialog.html | 31 ++++++++++++ .../characterRestoreDialog.js | 49 +++++++++++++++++++ 4 files changed, 103 insertions(+) create mode 100644 app/client/views/characterList/characterRestoreDialog/characterRestoreDialog.html create mode 100644 app/client/views/characterList/characterRestoreDialog/characterRestoreDialog.js diff --git a/app/client/views/characterList/characterList.html b/app/client/views/characterList/characterList.html index 94962a5b..c6bc6c97 100644 --- a/app/client/views/characterList/characterList.html +++ b/app/client/views/characterList/characterList.html @@ -58,6 +58,13 @@ {{#simpleTooltip class="always"}} New Character {{/simpleTooltip}}
+
+ + + {{#simpleTooltip class="always"}} Restore from backup {{/simpleTooltip}} +
{{/fabMenu}}
diff --git a/app/client/views/characterList/characterList.js b/app/client/views/characterList/characterList.js index 5bdee54b..47ba3abe 100644 --- a/app/client/views/characterList/characterList.js +++ b/app/client/views/characterList/characterList.js @@ -81,4 +81,20 @@ Template.characterList.events({ returnElement: instance.find(`.party[data-id='${partyId}']`), }); }, + "click .restoreCharacter": function(event, instance) { + pushDialogStack({ + template: "characterRestoreDialog", + element: event.currentTarget, + callback(dump){ + if (!dump) return; + dump.character.name += " - Restored" + giveCharacterDumpNewIds(dump); + restoreCharacter(dump); + Router.go("characterSheet", { + _id: dump.character._id, + urlName: dump.character.urlName || '-', + }); + }, + }) + }, }); diff --git a/app/client/views/characterList/characterRestoreDialog/characterRestoreDialog.html b/app/client/views/characterList/characterRestoreDialog/characterRestoreDialog.html new file mode 100644 index 00000000..d37292cb --- /dev/null +++ b/app/client/views/characterList/characterRestoreDialog/characterRestoreDialog.html @@ -0,0 +1,31 @@ + diff --git a/app/client/views/characterList/characterRestoreDialog/characterRestoreDialog.js b/app/client/views/characterList/characterRestoreDialog/characterRestoreDialog.js new file mode 100644 index 00000000..560a2429 --- /dev/null +++ b/app/client/views/characterList/characterRestoreDialog/characterRestoreDialog.js @@ -0,0 +1,49 @@ +Template.characterRestoreDialog.onCreated(function(){ + this.dump = {}; + this.valid = new ReactiveVar(false); + this.error = new ReactiveVar(null); +}); + +Template.characterRestoreDialog.helpers({ + invalid(){ + return !Template.instance().valid.get(); + }, + error(){ + return Template.instance().error.get(); + }, +}); + +const fail = function(instance){ + instance.valid.set(false); + instance.error.set("Failed to convert file into a valid character"); + instance.dump = undefined; +}; + +Template.characterRestoreDialog.events({ + "input .fileInput": function(event, instance){ + let input = event.currentTarget.$.input; + let reader = new FileReader(); + reader.onload = function(){ + let dumpString = reader.result; + try { + let dump = JSON.parse(dumpString); + if (dump && dump.character && dump.collections){ + instance.valid.set(true); + instance.error.set(null); + instance.dump = dump; + } else { + fail(instance); + } + } catch (e) { + fail(instance); + } + }; + reader.readAsText(input.files[0]); + }, + "click .cancelButton": function(event, instance){ + popDialogStack(); + }, + "click .addButton": function(event, instance){ + popDialogStack(instance.dump); + }, +}); From c9710bdb09aa25da4a8d15f24a860e0f63785b7f Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Mon, 11 Feb 2019 12:10:04 +0200 Subject: [PATCH 034/247] Fixed restored characters not belonging to the user restoring them --- app/client/views/characterList/characterList.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/client/views/characterList/characterList.js b/app/client/views/characterList/characterList.js index 47ba3abe..53f6940b 100644 --- a/app/client/views/characterList/characterList.js +++ b/app/client/views/characterList/characterList.js @@ -88,6 +88,9 @@ Template.characterList.events({ callback(dump){ if (!dump) return; dump.character.name += " - Restored" + dump.character.owner = Meteor.userId(); + dump.character.readers = []; + dump.character.writers = []; giveCharacterDumpNewIds(dump); restoreCharacter(dump); Router.go("characterSheet", { From 8489ef5ec0f1fae7a7f3947fe5b50b6eef18b76e Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Mon, 11 Feb 2019 13:04:14 +0200 Subject: [PATCH 035/247] Fixed restoring characters not working correctly for sub documents --- .../views/characterList/characterList.js | 12 +--------- .../characterRestoreDialog.html | 3 +++ .../characterRestoreDialog.js | 21 ++++++++++++++++-- app/lib/functions/backupRestoreCharacter.js | 22 ++++++++++++++++--- 4 files changed, 42 insertions(+), 16 deletions(-) diff --git a/app/client/views/characterList/characterList.js b/app/client/views/characterList/characterList.js index 53f6940b..f1113243 100644 --- a/app/client/views/characterList/characterList.js +++ b/app/client/views/characterList/characterList.js @@ -86,17 +86,7 @@ Template.characterList.events({ template: "characterRestoreDialog", element: event.currentTarget, callback(dump){ - if (!dump) return; - dump.character.name += " - Restored" - dump.character.owner = Meteor.userId(); - dump.character.readers = []; - dump.character.writers = []; - giveCharacterDumpNewIds(dump); - restoreCharacter(dump); - Router.go("characterSheet", { - _id: dump.character._id, - urlName: dump.character.urlName || '-', - }); + return; }, }) }, diff --git a/app/client/views/characterList/characterRestoreDialog/characterRestoreDialog.html b/app/client/views/characterList/characterRestoreDialog/characterRestoreDialog.html index d37292cb..5ff68c04 100644 --- a/app/client/views/characterList/characterRestoreDialog/characterRestoreDialog.html +++ b/app/client/views/characterList/characterRestoreDialog/characterRestoreDialog.html @@ -17,6 +17,9 @@ {{error}}

{{/if}} + {{#if loading}} + + {{/if}}
diff --git a/app/client/views/characterList/characterRestoreDialog/characterRestoreDialog.js b/app/client/views/characterList/characterRestoreDialog/characterRestoreDialog.js index 560a2429..ebc6a4dd 100644 --- a/app/client/views/characterList/characterRestoreDialog/characterRestoreDialog.js +++ b/app/client/views/characterList/characterRestoreDialog/characterRestoreDialog.js @@ -2,14 +2,18 @@ Template.characterRestoreDialog.onCreated(function(){ this.dump = {}; this.valid = new ReactiveVar(false); this.error = new ReactiveVar(null); + this.loading = new ReactiveVar(false); }); Template.characterRestoreDialog.helpers({ invalid(){ return !Template.instance().valid.get(); }, - error(){ + error(){ return Template.instance().error.get(); + }, + loading(){ + return Template.instance().loading.get(); }, }); @@ -44,6 +48,19 @@ Template.characterRestoreDialog.events({ popDialogStack(); }, "click .addButton": function(event, instance){ - popDialogStack(instance.dump); + let dump = instance.dump; + if (!dump) return; + Meteor.call('restoreCharacter', dump, (e, char) => { + instance.loading.set(false); + if (!char){ + instance.error.set(e.message) + } else { + popDialogStack(); + Router.go("characterSheet", { + _id: char._id, + urlName: char.urlName || '-', + }); + } + }); }, }); diff --git a/app/lib/functions/backupRestoreCharacter.js b/app/lib/functions/backupRestoreCharacter.js index 9863d12f..31fced03 100644 --- a/app/lib/functions/backupRestoreCharacter.js +++ b/app/lib/functions/backupRestoreCharacter.js @@ -73,11 +73,27 @@ giveCharacterDumpNewIds = function(characterDump){ } restoreCharacter = function(characterDump){ - Characters.insert(characterDump.character); + Characters.direct.insert(characterDump.character); for (collectionName in characterDump.collections){ let collection = Meteor.Collection.get(collectionName); - for (doc in characterDump[collectionName]){ - collection.insert(doc); + for (doc of characterDump.collections[collectionName]){ + // delete problematic keys that shouldn't ever be available on insert + delete doc.restoredAt; + delete doc.restoredBy; + // Insert the doc with no hooks + collection.direct.insert(doc); } } }; + +Meteor.methods({ + restoreCharacter(characterDump){ + characterDump.character.name += " - Restored" + characterDump.character.owner = Meteor.userId(); + characterDump.character.readers = []; + characterDump.character.writers = []; + giveCharacterDumpNewIds(characterDump); + restoreCharacter(characterDump); + return characterDump.character + }, +}); From 436c5bb785c077df7e8b86d13682665a13dd0542 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Tue, 12 Feb 2019 09:53:29 +0200 Subject: [PATCH 036/247] Fixed bug in view permission causing 500 errors for Avrae --- app/lib/functions/permissions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/lib/functions/permissions.js b/app/lib/functions/permissions.js index 37b4ff73..c6b72ff1 100644 --- a/app/lib/functions/permissions.js +++ b/app/lib/functions/permissions.js @@ -9,7 +9,7 @@ canViewCharacter = function(char, userId){ userId = userId || Meteor.userId(); if (typeof char !== 'object'){ char = Characters.findOne( - charId, + char, {fields: {owner: 1, writers: 1, readers: 1, "settings.viewPermission": 1}} ); } From 4d642b56bb7e7ed84064900f612dab282b83d37a Mon Sep 17 00:00:00 2001 From: Andrew Zhu Date: Tue, 12 Feb 2019 13:51:39 -0800 Subject: [PATCH 037/247] use direct insert, add schema check --- app/Routes/API.js | 1 - app/lib/functions/api.js | 474 +++++++++++++++++++++++++++++---------- 2 files changed, 352 insertions(+), 123 deletions(-) diff --git a/app/Routes/API.js b/app/Routes/API.js index 45453351..863fdf91 100644 --- a/app/Routes/API.js +++ b/app/Routes/API.js @@ -76,7 +76,6 @@ Router.map(function () { const listId = this.params.listId; Meteor.call("insertSpells", key, charId, listId, spells, (err, res) => { if (err) { - console.log(err); this.response.writeHead(err.error, err.reason); this.response.end(err.details); } else { diff --git a/app/lib/functions/api.js b/app/lib/functions/api.js index e58b5135..34022cd6 100644 --- a/app/lib/functions/api.js +++ b/app/lib/functions/api.js @@ -22,210 +22,248 @@ JSONExport = function (charId) { Meteor.methods({ "insertSpells": function (key, charId, listId, spells) { if (Meteor.isClient) return; - ifCanEdit(key, charId, "addSpellsToCharacter", () => { - let ids = []; - let error; - for (let spell of spells) { + assertCanEdit(key, charId, "addSpellsToCharacter"); + let ids = []; + let error; + for (let spell of spells) { + spell.charId = charId; + try { + Schemas.Spell.clean(spell); + } catch (e) { + // console.log(e); + error = e.error; + } + if (!error) { spell.parent = {id: listId, collection: "SpellLists"}; - spell.charId = charId; - let id = Spells.insert(spell, (err) => { + let id = Spells.direct.insert(spell, (err) => { if (err) { error = err.message; } }); + // console.log(id); ids.push(id); - } - if (error) { - throw new Meteor.Error(400, "Failed to insert one or more spells", JSON.stringify({ - err: error, - inserted: ids - })); } else { - return ids; + break; } - }); + } + if (error) { + throw new Meteor.Error(400, "Failed to insert one or more spells", JSON.stringify({ + err: error, + inserted: ids + })); + } else { + return ids; + } }, "insertCharacter": function (key, character) { if (Meteor.isClient) return; - ifAuthorized(key, "createCharacter", () => { - let error; + assertAuthorized(key, "createCharacter"); + let error, id; - character.owner = userIdFromKey(key); - let id = Characters.insert(character, (err) => { + character.owner = userIdFromKey(key); + try { + Schemas.Character.clean(character); + } catch (e) { + console.log(e); + error = e.error; + } + if (!error) { + id = Characters.direct.insert(character, (err) => { if (err) error = err.message; }); - - if (error) { - throw new Meteor.Error(400, "Failed to insert character", JSON.stringify({err: error})); - } else { - return {id: id}; - } - }); + afterCharacterInsert(id); + return {id: id}; + } else { + throw new Meteor.Error(400, "Failed to insert character", JSON.stringify({err: error})); + } }, "deleteCharacter": function (key, charId) { if (Meteor.isClient) return; - ifAuthorized(key, "deleteCharacter", () => { - if (isOwner(charId, userIdFromKey(key))) { - let error; + assertAuthorized(key, "deleteCharacter"); + if (isOwner(charId, userIdFromKey(key))) { + let error; - Characters.remove({_id: charId}, (err) => { - if (err) - error = err.message; - }); - if (error) { - throw new Meteor.Error(400, "Failed to delete character", JSON.stringify({err: error})); - } else { - return {success: true}; - } + Characters.direct.remove({_id: charId}, (err) => { + if (err) + error = err.message; + }); + if (error) { + throw new Meteor.Error(400, "Failed to delete character", JSON.stringify({err: error})); } else { - throw new Meteor.Error(403, "You do not have permission to delete the requested character"); + return {success: true}; } - }); + } else { + throw new Meteor.Error(403, "You do not have permission to delete the requested character"); + } }, "transferCharacterOwnership": function (key, charId, newOwner) { if (Meteor.isClient) return; - ifAuthorized(key, "transferCharacterOwnership", () => { - if (isOwner(charId, userIdFromKey(key))) { - let error; - Characters.update({_id: charId}, {"$set": {owner: newOwner}}, null, - (err) => { - if (err) - error = err.message; - }); + assertAuthorized(key, "transferCharacterOwnership"); + if (isOwner(charId, userIdFromKey(key))) { + let error; + Characters.direct.update({_id: charId}, {"$set": {owner: newOwner}}, null, + (err) => { + if (err) + error = err.message; + }); - if (error) { - throw new Meteor.Error(400, "Failed to update character", JSON.stringify({err: error})); - } else { - return {success: true}; - } + if (error) { + throw new Meteor.Error(400, "Failed to update character", JSON.stringify({err: error})); } else { - throw new Meteor.Error(403, "You do not have permission to transfer the requested character"); + return {success: true}; } - }); + } else { + throw new Meteor.Error(403, "You do not have permission to transfer the requested character"); + } }, "insertFeatures": function (key, charId, features) { if (Meteor.isClient) return; - ifCanEdit(key, charId, "insertFeatures", () => { - let ids = []; - let error; - for (let feature of features) { - feature.charId = charId; - let id = Features.insert(feature, (err) => { + assertCanEdit(key, charId, "insertFeatures"); + let ids = []; + let error; + for (let feature of features) { + feature.charId = charId; + try { + Schemas.Feature.clean(feature); + } catch (e) { + error = e.error; + } + if (!error) { + let id = Features.direct.insert(feature, (err) => { if (err) { error = err.message; } }); - if (error) - break; ids.push(id); - } - if (error) { - throw new Meteor.Error(400, "Failed to insert one or more features", JSON.stringify({ - err: error, - inserted: ids - })); } else { - return ids; + break; } - }); + } + if (error) { + throw new Meteor.Error(400, "Failed to insert one or more features", JSON.stringify({ + err: error, + inserted: ids + })); + } else { + return ids; + } + }, "insertProfs": function (key, charId, profs) { if (Meteor.isClient) return; - ifCanEdit(key, charId, "insertProfs", () => { - let ids = []; - let error; - for (let prof of profs) { - prof.charId = charId; // we currently rely on the client to supply parent - let id = Proficiencies.insert(prof, (err) => { + assertCanEdit(key, charId, "insertProfs"); + let ids = []; + let error; + for (let prof of profs) { + prof.charId = charId; + try { + Schemas.Proficiency.clean(prof, {filter: false}); + } catch (e) { + error = e.error; + } + if (!error) { + let id = Proficiencies.direct.insert(prof, (err) => { if (err) { error = err.message; } }); - if (error) - break; ids.push(id); - } - if (error) { - throw new Meteor.Error(400, "Failed to insert one or more profs", JSON.stringify({ - err: error, - inserted: ids - })); } else { - return ids; + break; } - }); + } + if (error) { + throw new Meteor.Error(400, "Failed to insert one or more profs", JSON.stringify({ + err: error, + inserted: ids + })); + } else { + return ids; + } }, "insertEffects": function (key, charId, effects) { if (Meteor.isClient) return; - ifCanEdit(key, charId, "insertEffects", () => { - let ids = []; - let error; - for (let effect of effects) { - effect.charId = charId; // we currently rely on the client to supply parent - let id = Effects.insert(effect, (err) => { + assertCanEdit(key, charId, "insertEffects"); + let ids = []; + let error; + for (let effect of effects) { + effect.charId = charId; + try { + Schemas.Effect.clean(effect, {filter: false}); + } catch (e) { + error = e.error; + } + if (!error) { + let id = Effects.direct.insert(effect, (err) => { if (err) { error = err.message; } }); - if (error) - break; ids.push(id); - } - if (error) { - throw new Meteor.Error(400, "Failed to insert one or more effects", JSON.stringify({ - err: error, - inserted: ids - })); } else { - return ids; + break; } - }); + } + if (error) { + throw new Meteor.Error(400, "Failed to insert one or more effects", JSON.stringify({ + err: error, + inserted: ids + })); + } else { + return ids; + } }, "insertClasses": function (key, charId, klasses) { if (Meteor.isClient) return; - ifCanEdit(key, charId, "insertClasses", () => { - let ids = []; - let error; - for (let klass of klasses) { - klass.charId = charId; // we currently rely on the client to supply parent - let id = Classes.insert(klass, (err) => { + assertCanEdit(key, charId, "insertClasses"); + let ids = []; + let error; + for (let klass of klasses) { + klass.charId = charId; + try { + Schemas.Class.clean(klass); + } catch (e) { + error = e.error; + } + if (!error) { + let id = Classes.direct.insert(klass, (err) => { if (err) { error = err.message; } }); - if (error) - break; ids.push(id); - } - if (error) { - throw new Meteor.Error(400, "Failed to insert one or more classes", JSON.stringify({ - err: error, - inserted: ids - })); } else { - return ids; + break; } - }); + } + if (error) { + throw new Meteor.Error(400, "Failed to insert one or more classes", JSON.stringify({ + err: error, + inserted: ids + })); + } else { + return ids; + } } }); -var ifCanEdit = function (key, charId, method, callback) { +var assertCanEdit = function (key, charId, method) { if (canEditCharacter(charId, userIdFromKey(key))) { - ifAuthorized(key, method, callback); + assertAuthorized(key, method); } else { throw new Meteor.Error(403, "You do not have permission to edit the requested character"); } }; -var ifAuthorized = function (apiKey, method, callback) { +var assertAuthorized = function (apiKey, method) { if (!apiKey) { throw new Meteor.Error(403, "You must use an api key to access this api"); } else if (!isKeyValid(apiKey)) { @@ -236,6 +274,198 @@ var ifAuthorized = function (apiKey, method, callback) { })); } else { rateLimiter.increment({apiKey: apiKey, method: method}); - callback(); } }; + +var afterCharacterInsert = function (charId) { + // Effects + Effects.direct.insert({ + charId: charId, + name: "Constitution modifier for each level", + stat: "hitPoints", + operation: "add", + calculation: "level * constitutionMod", + parent: { + id: charId, + collection: "Characters", + group: "Inate", + }, + }); + Effects.direct.insert({ + charId: charId, + name: "Proficiency bonus by level", + stat: "proficiencyBonus", + operation: "add", + calculation: "floor(level / 4 + 1.75)", + parent: { + id: charId, + collection: "Characters", + group: "Inate", + }, + }); + Effects.direct.insert({ + charId: charId, + name: "Dexterity Armor Bonus", + stat: "armor", + operation: "add", + calculation: "dexterityArmor", + parent: { + id: charId, + collection: "Characters", + group: "Inate", + }, + }); + Effects.direct.insert({ + charId: charId, + name: "Natural Armor", + stat: "armor", + operation: "base", + value: 10, + parent: { + id: charId, + collection: "Characters", + group: "Inate", + }, + }); + Effects.direct.insert({ + charId: charId, + name: "Natural Carrying Capacity", + stat: "carryMultiplier", + operation: "base", + value: "1", + parent: { + id: charId, + collection: "Characters", + group: "Inate", + }, + }); + // Features + let featureId = Features.direct.insert({ + name: "Base Ability Scores", + charId: charId, + enabled: true, + alwaysEnabled: true, + }); + Effects.direct.insert({ + stat: "strength", + charId: charId, + parent: { + id: featureId, + collection: "Features", + }, + operation: "base", + value: 10, + enabled: true, + }); + Effects.direct.insert({ + stat: "dexterity", + charId: charId, + parent: { + id: featureId, + collection: "Features", + }, + operation: "base", + value: 10, + enabled: true, + }); + Effects.direct.insert({ + stat: "constitution", + charId: charId, + parent: { + id: featureId, + collection: "Features", + }, + operation: "base", + value: 10, + enabled: true, + }); + Effects.direct.insert({ + stat: "intelligence", + charId: charId, + parent: { + id: featureId, + collection: "Features", + }, + operation: "base", + value: 10, + enabled: true, + }); + Effects.direct.insert({ + stat: "wisdom", + charId: charId, + parent: { + id: featureId, + collection: "Features", + }, + operation: "base", + value: 10, + enabled: true, + }); + Effects.direct.insert({ + stat: "charisma", + charId: charId, + parent: { + id: featureId, + collection: "Features", + }, + operation: "base", + value: 10, + enabled: true, + }); + // Items + let containerId = Containers.direct.insert({ + name: "Coin Pouch", + charId: charId, + isCarried: true, + description: "A sturdy pouch for coins", + color: "d", + }); + Items.direct.insert({ + name: "Gold piece", + plural: "Gold pieces", + charId: charId, + quantity: 0, + weight: 0.02, + value: 1, + color: "n", + parent: { + id: containerId, + collection: "Containers", + }, + settings: { + showIncrement: true, + }, + }); + Items.direct.insert({ + name: "Silver piece", + plural: "Silver pieces", + charId: charId, + quantity: 0, + weight: 0.02, + value: 0.1, + color: "q", + parent: { + id: containerId, + collection: "Containers", + }, + settings: { + showIncrement: true, + }, + }); + Items.direct.insert({ + name: "Copper piece", + plural: "Copper pieces", + charId: charId, + quantity: 0, + weight: 0.02, + value: 0.01, + color: "s", + parent: { + id: containerId, + collection: "Containers", + }, + settings: { + showIncrement: true, + }, + }); +}; From 3fbb0067830c66235f4a3b4cb5ec1bd8b7c0dd66 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 21 Feb 2019 11:51:46 +0200 Subject: [PATCH 038/247] Added Patreon notification badge for new patreon posts --- app/Model/Meta/PatreonPosts.js | 26 ++++++++++++++++++++++++++ app/Model/Users/Users.js | 12 ++++++++++++ app/client/views/layout/layout.html | 11 +++++++++-- app/client/views/layout/layout.js | 13 +++++++++++++ app/config.vulcanize | 9 +++++---- app/package-lock.json | 6 +++--- app/package.json | 2 +- app/server/publications/user.js | 18 +++++++++++------- 8 files changed, 80 insertions(+), 17 deletions(-) create mode 100644 app/Model/Meta/PatreonPosts.js diff --git a/app/Model/Meta/PatreonPosts.js b/app/Model/Meta/PatreonPosts.js new file mode 100644 index 00000000..8cd96287 --- /dev/null +++ b/app/Model/Meta/PatreonPosts.js @@ -0,0 +1,26 @@ +PatreonPosts = new Mongo.Collection("patreonPosts"); + +Schemas.PatreonPosts = new SimpleSchema({ + link: { + type: String, + }, + dateAdded: { + type: Date, + autoValue(){ + return new Date(); + }, + }, +}); + +PatreonPosts.attachSchema(Schemas.PatreonPosts); + +PatreonPosts.allow({ + insert: function(userId, doc) { + var user = Meteor.users.findOne(userId); + if (user) return _.contains(user.roles, "admin"); + }, + remove: function(userId, doc) { + var user = Meteor.users.findOne(userId); + if (user) return _.contains(user.roles, "admin"); + }, +}); diff --git a/app/Model/Users/Users.js b/app/Model/Users/Users.js index 5f6b2a7e..6878df1d 100644 --- a/app/Model/Users/Users.js +++ b/app/Model/Users/Users.js @@ -70,6 +70,10 @@ Schemas.User = new SimpleSchema({ index: 1, optional: true, }, + lastPatreonPostClicked: { + type: String, + optional: true, + }, }); Meteor.users.attachSchema(Schemas.User); @@ -107,3 +111,11 @@ if (Meteor.isServer) Meteor.methods({ Meteor.users.update(this.userId, {$set: {apiKey}}); }, }); + +Meteor.methods({ + clickPatreonPost(link) { + Meteor.users.update(this.userId, {$set: { + lastPatreonPostClicked: link + }}); + }, +}); diff --git a/app/client/views/layout/layout.html b/app/client/views/layout/layout.html index 1997308d..50d6cb0c 100644 --- a/app/client/views/layout/layout.html +++ b/app/client/views/layout/layout.html @@ -51,9 +51,16 @@ Send Feedback - + - + + {{#if showPatreonBadge}} + + + {{/if}} Patreon diff --git a/app/client/views/layout/layout.js b/app/client/views/layout/layout.js index 0d24a237..f4937071 100644 --- a/app/client/views/layout/layout.js +++ b/app/client/views/layout/layout.js @@ -7,6 +7,16 @@ Template.appDrawer.helpers({ var user = Meteor.user(); return user.profile && user.profile.username || user.username || "My Account"; }, + showPatreonBadge: function(){ + let post = PatreonPosts.findOne({}, {sort: {date: -1}}); + let user = Meteor.user(); + if (!post || !user) return false; + return post.link !== user.lastPatreonPostClicked; + }, + patreonLink: function(){ + let post = PatreonPosts.findOne({}, {sort: {date: -1}}); + return (post && post.link) || 'https://www.patreon.com/dicecloud'; + }, }); let drawerLayout; @@ -37,6 +47,9 @@ Template.appDrawer.events({ closeDrawer(instance); }, "click .patreon": function(event, instance){ + let post = PatreonPosts.findOne({}, {sort: {date: -1}}); + let link = (post && post.link) || 'https://www.patreon.com/dicecloud'; + Meteor.call('clickPatreonPost', link); ga("send", "event", "externalLink", "patreon"); }, "click .github": function(event, instance){ diff --git a/app/config.vulcanize b/app/config.vulcanize index fbdd8a9c..01f1cbf9 100644 --- a/app/config.vulcanize +++ b/app/config.vulcanize @@ -2,13 +2,13 @@ "polyfill": "/components/webcomponentsjs/webcomponents.min.js", "useShadowDom": true, "imports": [ - "/components/app-layout/app-layout.html", - "/components/app-layout/app-layout.html", + "/components/app-layout/app-layout.html", + "/components/app-layout/app-layout.html", "/components/app-layout/app-scroll-effects/effects/waterfall.html", "/components/app-layout/app-scroll-effects/effects/parallax-background.html", "/components/app-layout/app-scroll-effects/effects/resize-title.html", - "/components/iron-collapse/iron-collapse.html", + "/components/iron-collapse/iron-collapse.html", "/components/iron-icon/iron-icon.html", "/components/iron-icons/av-icons.html", "/components/iron-icons/editor-icons.html", @@ -21,7 +21,8 @@ "/components/neon-animation/neon-animation.html", - "/components/paper-button/paper-button.html", + "/components/paper-button/paper-button.html", + "/components/paper-badge/paper-badge.html", "/components/paper-swatch-picker/paper-swatch-picker.html", "/components/paper-dialog/paper-dialog.html", "/components/paper-dropdown-menu/paper-dropdown-menu.html", diff --git a/app/package-lock.json b/app/package-lock.json index 3c606c15..b7b60acc 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -216,9 +216,9 @@ "integrity": "sha512-HfVRxhYG7C8Jl9FqtrlElMR2z/8YiLQVDKf67MLY25Ic+ILx3ecmklfT1v3u+7P5/4vEFjuxaAFXhr2/Afwk5g==" }, "file-saver": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.0.tgz", - "integrity": "sha512-cYM1ic5DAkg25pHKgi5f10ziAM7RJU37gaH1XQlyNDrtUnzhC/dfoV9zf2OmF0RMKi42jG5B0JWBnPQqyj/G6g==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.1.tgz", + "integrity": "sha512-dCB3K7/BvAcUmtmh1DzFdv0eXSVJ9IAFt1mw3XZfAexodNRoE29l3xB2EX4wH2q8m/UTzwzEPq/ArYk98kUkBQ==" }, "find-up": { "version": "2.1.0", diff --git a/app/package.json b/app/package.json index fbbadeae..29cbefcc 100644 --- a/app/package.json +++ b/app/package.json @@ -17,7 +17,7 @@ "bower": "^1.7.9", "core-js": "^2.5.7", "fibers": "^2.0.2", - "file-saver": "^2.0.0", + "file-saver": "^2.0.1", "meteor-node-stubs": "^0.3.3", "qrcode": "^1.3.0", "source-map-support": "^0.5.9", diff --git a/app/server/publications/user.js b/app/server/publications/user.js index 799539fd..ab979722 100644 --- a/app/server/publications/user.js +++ b/app/server/publications/user.js @@ -1,9 +1,13 @@ Meteor.publish("user", function(){ - return Meteor.users.find(this.userId, {fields: { - roles: 1, - username: 1, - profile: 1, - apiKey: 1, - librarySubscriptions: 1, - }}); + return [ + Meteor.users.find(this.userId, {fields: { + roles: 1, + username: 1, + profile: 1, + apiKey: 1, + librarySubscriptions: 1, + lastPatreonPostClicked: 1, + }}), + PatreonPosts.find({},{sort: {dateAdded: -1}, limit: 1}) + ]; }); From b3371fca534c03a8a0f00990c714cc9391cc1523 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Wed, 6 Mar 2019 17:05:44 +0200 Subject: [PATCH 039/247] Added fetching User data from patreon and writing it to the DiceCloud user database --- app/Model/Users/Users.js | 30 ++ app/client/views/user/profile/profile.html | 6 + app/client/views/user/profile/profile.js | 31 ++ app/package-lock.json | 515 ++++++++++++--------- app/package.json | 2 + app/server/patreon/patreon.js | 135 ++++++ app/server/publications/user.js | 1 + 7 files changed, 494 insertions(+), 226 deletions(-) create mode 100644 app/server/patreon/patreon.js diff --git a/app/Model/Users/Users.js b/app/Model/Users/Users.js index 6878df1d..82a2ccae 100644 --- a/app/Model/Users/Users.js +++ b/app/Model/Users/Users.js @@ -74,6 +74,36 @@ Schemas.User = new SimpleSchema({ type: String, optional: true, }, + patreon: { + type: Object, + optional: true, + }, + "patreon.accessToken": { + type: String, + optional: true, + }, + "patreon.refreshToken": { + type: String, + optional: true, + }, + "patreon.userId": { + type: String, + optional: true, + }, + "patreon.entitledCents": { + type: Number, + decimal: false, + optional: true, + }, + "patreon.entitledCentsOverride": { + type: Number, + decimal: false, + optional: true, + }, + "patreon.error": { + type: String, + optional: true, + }, }); Meteor.users.attachSchema(Schemas.User); diff --git a/app/client/views/user/profile/profile.html b/app/client/views/user/profile/profile.html index 5a8e6a50..488ec1f7 100644 --- a/app/client/views/user/profile/profile.html +++ b/app/client/views/user/profile/profile.html @@ -66,6 +66,12 @@
{{> atForm state="signIn"}}
+
+ Tier: {{tier}} + + Connect Patreon Account + +
{{> atNavButton }}
diff --git a/app/client/views/user/profile/profile.js b/app/client/views/user/profile/profile.js index ca64f6ea..c1e63b09 100644 --- a/app/client/views/user/profile/profile.js +++ b/app/client/views/user/profile/profile.js @@ -1,3 +1,7 @@ +import { format as formatUrl } from 'url'; + +const CLIENT_ID = "zv38izfGZDf8s_Z9BI5kICjGGnvs45PawHYu6cqsTqftwZ_5DZFqEGKZfdP8Q6I2"; + Template.profile.onCreated(function(){ this.showApiKey = new ReactiveVar(false); }); @@ -12,6 +16,33 @@ Template.profile.helpers({ showApiKey: function(){ return Template.instance().showApiKey.get(); }, + patreonLoginUrl: function(){ + return formatUrl({ + protocol: 'https', + host: 'patreon.com', + pathname: '/oauth2/authorize', + query: { + response_type: 'code', + client_id: CLIENT_ID, + redirect_uri: Meteor.absoluteUrl() + 'patreon-redirect', + state: Meteor.userId(), + scope: 'identity', + }, + }); + }, + patreon: function(){ + let user = Meteor.user(); + return user && user.patreon || {}; + }, + tier: function(){ + let user = Meteor.user(); + if (!user) return; + patreon = user.patreon; + if (!patreon) return; + let tier = patreon.entitledCents || 0; + if (patreon.entitledCentsOverride > tier) tier = patreon.entitledCentsOverride; + return tier; + } }); Template.profile.events({ diff --git a/app/package-lock.json b/app/package-lock.json index b7b60acc..486bfe7c 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -26,21 +26,14 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", + "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - }, - "dependencies": { - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" - } + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, "ansi-regex": { @@ -53,16 +46,34 @@ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, "bcrypt": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-1.0.3.tgz", @@ -72,6 +83,14 @@ "node-pre-gyp": "0.6.36" } }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, "block-stream": { "version": "0.0.9", "resolved": false, @@ -108,6 +127,11 @@ "window-or-global": "^1.0.1" } }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, "cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", @@ -135,6 +159,14 @@ "resolved": false, "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "core-js": { "version": "2.5.7", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", @@ -155,6 +187,14 @@ "which": "^1.2.9" } }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -168,11 +208,33 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, "dijkstrajs": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.1.tgz", "integrity": "sha1-082BIh4+pAdCz83lVtTpnpjdxxs=" }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "~0.4.13" + } + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -195,15 +257,20 @@ "strip-eof": "^1.0.0" } }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" }, "fast-json-stable-stringify": { "version": "2.0.0", @@ -228,36 +295,26 @@ "locate-path": "^2.0.0" } }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, "form-data": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "requires": { "asynckit": "^0.4.0", - "combined-stream": "1.0.6", + "combined-stream": "^1.0.6", "mime-types": "^2.1.12" - }, - "dependencies": { - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - } } }, + "form-urlencoded": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/form-urlencoded/-/form-urlencoded-2.0.9.tgz", + "integrity": "sha512-fWUzNiOnYa126vFAT6TFXd1mhJrvD8IqmQ9ilZPjkLYQfaRreBr5fIUoOpPlWtqaAG64nzoE7u5zSetifab9IA==" + }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", @@ -268,6 +325,14 @@ "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, "graceful-fs": { "version": "4.1.11", "resolved": false, @@ -279,11 +344,11 @@ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", "requires": { - "ajv": "^5.1.0", + "ajv": "^6.5.5", "har-schema": "^2.0.0" } }, @@ -300,74 +365,14 @@ "assert-plus": "^1.0.0", "jsprim": "^1.2.2", "sshpk": "^1.7.0" - }, - "dependencies": { - "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "optional": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "optional": true, - "requires": { - "jsbn": "~0.1.0" - } - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "optional": true - }, - "sshpk": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", - "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "tweetnacl": "~0.14.0" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "optional": true - } + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" } }, "inherits": { @@ -401,11 +406,24 @@ "number-is-nan": "^1.0.0" } }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, "isarray": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.4.tgz", @@ -416,10 +434,49 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "requires": { + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonapi-datastore": { + "version": "0.4.0-beta", + "resolved": "https://registry.npmjs.org/jsonapi-datastore/-/jsonapi-datastore-0.4.0-beta.tgz", + "integrity": "sha1-tJn86STUXivDxheGgVIAY+I2HxA=" }, "jsprim": { "version": "1.4.1", @@ -430,13 +487,6 @@ "extsprintf": "1.3.0", "json-schema": "0.2.3", "verror": "1.10.0" - }, - "dependencies": { - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - } } }, "lcid": { @@ -1228,16 +1278,16 @@ } }, "mime-db": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", + "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==" }, "mime-types": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", + "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", "requires": { - "mime-db": "~1.33.0" + "mime-db": "~1.38.0" } }, "mimic-fn": { @@ -1255,6 +1305,15 @@ "resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz", "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=" }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, "node-pre-gyp": { "version": "0.6.36", "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz", @@ -1511,6 +1570,11 @@ "resolved": false, "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -1592,6 +1656,17 @@ "pify": "^2.0.0" } }, + "patreon": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/patreon/-/patreon-0.4.1.tgz", + "integrity": "sha512-aLhjx4rg2BArTq0Kg61MrM4dkJnTQ9kPN8F6a2IlQoYVEtIH7kUK/dprClTx+QYQKlXMfKksN9NCux1YarQJsQ==", + "requires": { + "form-urlencoded": "^2.0.4", + "is-plain-object": "^2.0.4", + "isomorphic-fetch": "^2.2.1", + "jsonapi-datastore": "^0.4.0-beta" + } + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -1612,6 +1687,16 @@ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, + "psl": { + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, "qrcode": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.3.0.tgz", @@ -1687,103 +1772,30 @@ "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==" }, "request": { - "version": "2.87.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", - "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", "requires": { "aws-sign2": "~0.7.0", - "aws4": "^1.6.0", + "aws4": "^1.8.0", "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.1", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", "forever-agent": "~0.6.1", - "form-data": "~2.3.1", - "har-validator": "~5.0.3", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.17", - "oauth-sign": "~0.8.2", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", "performance-now": "^2.1.0", - "qs": "~6.5.1", - "safe-buffer": "^5.1.1", - "tough-cookie": "~2.3.3", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", "tunnel-agent": "^0.6.0", - "uuid": "^3.1.0" - }, - "dependencies": { - "aws4": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", - "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==" - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" - } + "uuid": "^3.3.2" } }, "require-directory": { @@ -1883,6 +1895,16 @@ } } }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, "semver": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", @@ -1953,6 +1975,22 @@ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz", "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==" }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -2164,10 +2202,11 @@ } }, "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "requires": { + "psl": "^1.1.24", "punycode": "^1.4.1" }, "dependencies": { @@ -2178,11 +2217,37 @@ } } }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, "underscore": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -2200,13 +2265,6 @@ "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" - }, - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - } } }, "webcomponents.js": { @@ -2214,6 +2272,11 @@ "resolved": "https://registry.npmjs.org/webcomponents.js/-/webcomponents.js-0.7.24.tgz", "integrity": "sha1-IRb7+hRo7EFqe+/aozPh0Rj2nAQ=" }, + "whatwg-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", + "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", diff --git a/app/package.json b/app/package.json index 29cbefcc..bfc69dbf 100644 --- a/app/package.json +++ b/app/package.json @@ -19,7 +19,9 @@ "fibers": "^2.0.2", "file-saver": "^2.0.1", "meteor-node-stubs": "^0.3.3", + "patreon": "^0.4.1", "qrcode": "^1.3.0", + "request": "^2.88.0", "source-map-support": "^0.5.9", "underscore": "^1.9.1" } diff --git a/app/server/patreon/patreon.js b/app/server/patreon/patreon.js new file mode 100644 index 00000000..feb03927 --- /dev/null +++ b/app/server/patreon/patreon.js @@ -0,0 +1,135 @@ +import request from 'request'; + +const CLIENT_ID = "zv38izfGZDf8s_Z9BI5kICjGGnvs45PawHYu6cqsTqftwZ_5DZFqEGKZfdP8Q6I2"; +const CLIENT_SECRET = Meteor.settings.patreon.clientSecret; + +// Handle redirects from patreon +Router.map(function () { + this.route("patreon-redirect", { + path: "/patreon-redirect", + where: "server", + action: function () { + let route = this; + let userId = route.params.query.state; + let singleUseCode = route.params.query.code; + requestToken(singleUseCode, Meteor.bindEnvironment((error, response, body) => { + // Should return an access token, valid for 1 month, which needs to be + // stored and used to make requests on behalf of the user + if (error){ + writePatreonError(userId, error); + return; + } + let token; + try { + token = JSON.parse(body); + writePatreonToken(userId, token); + } catch(error) { + writePatreonError(userId, error); + return; + } + getIdentity(token.access_token, Meteor.bindEnvironment((error, response, body) => { + if (error){ + writePatreonError(userId, error); + return; + } + try { + let identity = JSON.parse(body); + let entitledAmount = +identity.included[0].attributes + .currently_entitled_amount_cents; + //TODO also write the patreon userId + writeEntitledCents(userId, entitledAmount); + } catch(error) { + writePatreonError(userId, error); + } + })); + })); + route.response.writeHead(302, { + 'Location': Meteor.absoluteUrl() + "account", + }); + route.response.end(); + }, + }); +}); + +const requestToken = function(singleUseCode, callback){ + request({ + method: "POST", + uri: "https://www.patreon.com/api/oauth2/token", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + qs: { + code: singleUseCode, + grant_type: "authorization_code", + client_id: CLIENT_ID, + client_secret: CLIENT_SECRET, + redirect_uri: Meteor.absoluteUrl() + 'patreon-redirect', + }, + }, callback); +} + +// Should return a new access token for the user +// callback is called with (error, response, body) +const refreshAccessToken = function(refreshToken, callback){ + request({ + method: "POST", + uri: "https://www.patreon.com/api/oauth2/token", + qs: { + grant_type: "refresh_token", + refresh_token: refreshToken, + client_id: CLIENT_ID, + client_secret: CLIENT_SECRET, + } + }, callback); +}; + +const getIdentity = function(accessToken, callback){ + request({ + uri: "https://www.patreon.com/api/oauth2/v2/identity", + headers:{ + Authorization: "Bearer " + accessToken, + }, + qs: { + "include": "memberships", + "fields[member]": "currently_entitled_amount_cents", + } + }, callback); +}; + +const writePatreonToken = function(userId, {access_token, refresh_token}){ + console.log('Writing token ') + console.log({access_token, refresh_token}); + Meteor.users.update(userId, { + $set: { + "patreon.accessToken": access_token, + "patreon.refreshToken": refresh_token, + }, + $unset: { + "patreon.error": 1, + }, + }); + console.log(Meteor.users.findOne(userId).patreon); +}; + +const writeEntitledCents = function(userId, amount){ + console.log('Writing cents ') + console.log(arguments); + Meteor.users.update(userId, { + $set: { + "patreon.entitledCents": amount, + }, + $unset: { + "patreon.error": 1, + }, + }); + console.log(Meteor.users.findOne(userId).patreon); +}; + +const writePatreonError = function(userId, error){ + console.error(error); + Meteor.users.update(userId, { + $set: { + "patreon.error": error.toString(), + }, + }); +} diff --git a/app/server/publications/user.js b/app/server/publications/user.js index ab979722..fc6c9c6a 100644 --- a/app/server/publications/user.js +++ b/app/server/publications/user.js @@ -7,6 +7,7 @@ Meteor.publish("user", function(){ apiKey: 1, librarySubscriptions: 1, lastPatreonPostClicked: 1, + patreon: 1, }}), PatreonPosts.find({},{sort: {dateAdded: -1}, limit: 1}) ]; From 857213f157129abca38253d9cd040d36e2307e1e Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 7 Mar 2019 13:35:31 +0200 Subject: [PATCH 040/247] Improved Patreon linking --- app/Model/Users/Users.js | 5 + app/client/views/layout/layout.html | 3 + app/client/views/layout/layout.js | 14 ++ app/client/views/user/profile/profile.html | 28 ++- app/client/views/user/profile/profile.js | 24 ++- app/server/patreon/patreon.js | 201 +++++++++++++++++---- 6 files changed, 224 insertions(+), 51 deletions(-) diff --git a/app/Model/Users/Users.js b/app/Model/Users/Users.js index 82a2ccae..4f4aaa38 100644 --- a/app/Model/Users/Users.js +++ b/app/Model/Users/Users.js @@ -86,9 +86,14 @@ Schemas.User = new SimpleSchema({ type: String, optional: true, }, + "patreon.tokenExpiryDate": { + type: Date, + optional: true, + }, "patreon.userId": { type: String, optional: true, + index: 1, }, "patreon.entitledCents": { type: Number, diff --git a/app/client/views/layout/layout.html b/app/client/views/layout/layout.html index 50d6cb0c..9bb47c02 100644 --- a/app/client/views/layout/layout.html +++ b/app/client/views/layout/layout.html @@ -21,6 +21,9 @@ {{profileLink}} + + {{patreonTier}} tier + {{else}} Sign in diff --git a/app/client/views/layout/layout.js b/app/client/views/layout/layout.js index f4937071..a18c74c8 100644 --- a/app/client/views/layout/layout.js +++ b/app/client/views/layout/layout.js @@ -17,6 +17,20 @@ Template.appDrawer.helpers({ let post = PatreonPosts.findOne({}, {sort: {date: -1}}); return (post && post.link) || 'https://www.patreon.com/dicecloud'; }, + patreonTier: function(){ + let user = Meteor.user(); + if (!user) return; + patreon = user.patreon; + if (!patreon) return "$0"; + let entitledCents = patreon.entitledCents || 0; + if (patreon.entitledCentsOverride > entitledCents){ + return "$" + (patreon.entitledCentsOverride / 100).toFixed(0); + } else if (patreon.entitledCents === undefined){ + return "$0"; + } else { + return "$" + (patreon.entitledCents / 100).toFixed(0); + } + }, }); let drawerLayout; diff --git a/app/client/views/user/profile/profile.html b/app/client/views/user/profile/profile.html index 488ec1f7..c8b455f4 100644 --- a/app/client/views/user/profile/profile.html +++ b/app/client/views/user/profile/profile.html @@ -62,16 +62,32 @@ {{/if}} + + + Patreon + + {{#if patreon.accessToken}} + + {{tier}} tier + + + + + + {{else}} + + + + Connect Patreon account + + + + {{/if}} +
{{> atForm state="signIn"}}
-
- Tier: {{tier}} - - Connect Patreon Account - -
{{> atNavButton }}
diff --git a/app/client/views/user/profile/profile.js b/app/client/views/user/profile/profile.js index c1e63b09..18e303fe 100644 --- a/app/client/views/user/profile/profile.js +++ b/app/client/views/user/profile/profile.js @@ -1,9 +1,10 @@ import { format as formatUrl } from 'url'; -const CLIENT_ID = "zv38izfGZDf8s_Z9BI5kICjGGnvs45PawHYu6cqsTqftwZ_5DZFqEGKZfdP8Q6I2"; +const CLIENT_ID = Meteor.settings.public.patreon.clientId; Template.profile.onCreated(function(){ this.showApiKey = new ReactiveVar(false); + this.loadingPatreon = new ReactiveVar(false); }); Template.profile.helpers({ @@ -39,10 +40,17 @@ Template.profile.helpers({ if (!user) return; patreon = user.patreon; if (!patreon) return; - let tier = patreon.entitledCents || 0; - if (patreon.entitledCentsOverride > tier) tier = patreon.entitledCentsOverride; - return tier; - } + let entitledCents = patreon.entitledCents || 0; + if (Template.instance().loadingPatreon.get()){ + return "loading..." + } else if (patreon.entitledCentsOverride > entitledCents){ + return `$ ${(patreon.entitledCentsOverride / 100).toFixed(0)} (Overridden)"`; + } else if (patreon.entitledCents === undefined){ + return "?"; + } else { + return "$" + (patreon.entitledCents / 100).toFixed(0); + } + }, }); Template.profile.events({ @@ -70,4 +78,10 @@ Template.profile.events({ Meteor.call("generateMyApiKey"); instance.showApiKey.set(true); }, + "click .refreshPatreon": function(event, instance){ + instance.loadingPatreon.set(true); + Meteor.call("updateMyPatreonDetails", (error) => { + instance.loadingPatreon.set(false); + }); + }, }); diff --git a/app/server/patreon/patreon.js b/app/server/patreon/patreon.js index feb03927..71d77ad7 100644 --- a/app/server/patreon/patreon.js +++ b/app/server/patreon/patreon.js @@ -1,7 +1,9 @@ import request from 'request'; -const CLIENT_ID = "zv38izfGZDf8s_Z9BI5kICjGGnvs45PawHYu6cqsTqftwZ_5DZFqEGKZfdP8Q6I2"; +const CLIENT_ID = Meteor.settings.public.patreon.clientId; const CLIENT_SECRET = Meteor.settings.patreon.clientSecret; +const CREATOR_ACCESS_TOKEN = Meteor.settings.patreon.creatorAccessToken; +const CAMPAIGN_ID = Meteor.settings.public.patreon.campaignId; // Handle redirects from patreon Router.map(function () { @@ -27,21 +29,7 @@ Router.map(function () { writePatreonError(userId, error); return; } - getIdentity(token.access_token, Meteor.bindEnvironment((error, response, body) => { - if (error){ - writePatreonError(userId, error); - return; - } - try { - let identity = JSON.parse(body); - let entitledAmount = +identity.included[0].attributes - .currently_entitled_amount_cents; - //TODO also write the patreon userId - writeEntitledCents(userId, entitledAmount); - } catch(error) { - writePatreonError(userId, error); - } - })); + updateIdentity(token.access_token, userId); })); route.response.writeHead(302, { 'Location': Meteor.absoluteUrl() + "account", @@ -68,21 +56,6 @@ const requestToken = function(singleUseCode, callback){ }, callback); } -// Should return a new access token for the user -// callback is called with (error, response, body) -const refreshAccessToken = function(refreshToken, callback){ - request({ - method: "POST", - uri: "https://www.patreon.com/api/oauth2/token", - qs: { - grant_type: "refresh_token", - refresh_token: refreshToken, - client_id: CLIENT_ID, - client_secret: CLIENT_SECRET, - } - }, callback); -}; - const getIdentity = function(accessToken, callback){ request({ uri: "https://www.patreon.com/api/oauth2/v2/identity", @@ -96,40 +69,188 @@ const getIdentity = function(accessToken, callback){ }, callback); }; -const writePatreonToken = function(userId, {access_token, refresh_token}){ - console.log('Writing token ') - console.log({access_token, refresh_token}); +// Should return a new access token for the user +// callback is called with (error, response, body) +const refreshAccessToken = Meteor.wrapAsync(function(refreshToken, userId, callback){ + request({ + method: "POST", + uri: "https://www.patreon.com/api/oauth2/token", + qs: { + grant_type: "refresh_token", + refresh_token: refreshToken, + client_id: CLIENT_ID, + client_secret: CLIENT_SECRET, + } + }, Meteor.bindEnvironment((error, response, body) => { + // Should return an access token, valid for 1 month, which needs to be + // stored and used to make requests on behalf of the user + if (error){ + callback(error) + return; + } + let token; + try { + token = JSON.parse(body); + writePatreonToken(userId, token); + callback(undefined, token.access_token); + } catch(error) { + callback(error); + } + })); +}); + +const updateIdentity = Meteor.wrapAsync(function(accessToken, userId, callback){ + getIdentity(accessToken, Meteor.bindEnvironment((error, response, body) => { + if (error){ + writePatreonError(userId, error); + return; + } + try { + let identity = JSON.parse(body); + let membership = identity.included[0]; + let entitledAmount = membership && membership.attributes + .currently_entitled_amount_cents || 0; + let patreonUserId = identity.data.id; + writeEntitledCentsAndId(userId, entitledAmount, patreonUserId); + if (callback) callback(); + } catch(error) { + writePatreonError(userId, error); + if(callback) callback(error); + } + })); +}); + +Meteor.methods({ + updateMyPatreonDetails(){ + const userId = this.userId; + if (!userId) throw new Meteor.Error("not-logged-in", "You must be logged in to update Patreon details"); + const user = Meteor.users.findOne(userId, {fields: {patreon: 1}}); + Meteor.users.update(userId, {$unset: {"patreon.entitledCents": 1}}); + if (!user.patreon || !user.patreon.accessToken){ + throw new Meteor.Error("no-patreon-access", "Patreon access token not found for this user"); + } + let accessToken = user.patreon.accessToken; + if (user.patreon.tokenExpiryDate < new Date()){ + // Token expired, refresh it before continuing + accessToken = refreshAccessToken(user.patreon.refreshToken, userId); + } + updateIdentity(accessToken, userId); + }, +}); + +const writePatreonToken = function(userId, { + access_token, refresh_token, expires_in +}){ + // The expiry date is now plus `expires_in` seconds + let expiryDate = new Date(); + expiryDate.setSeconds(expiryDate.getSeconds() + expires_in); + // Expire a day early so we don't accidentally miss it + expiryDate.setDate(expiryDate.getDate() - 1); + + // Write Meteor.users.update(userId, { $set: { "patreon.accessToken": access_token, "patreon.refreshToken": refresh_token, + "patreon.tokenExpiryDate": expiryDate, }, $unset: { "patreon.error": 1, }, }); - console.log(Meteor.users.findOne(userId).patreon); }; -const writeEntitledCents = function(userId, amount){ - console.log('Writing cents ') - console.log(arguments); +const writeEntitledCentsAndId = function(userId, amount, patreonUserId){ Meteor.users.update(userId, { $set: { "patreon.entitledCents": amount, + "patreon.userId": patreonUserId, }, $unset: { "patreon.error": 1, }, }); - console.log(Meteor.users.findOne(userId).patreon); }; const writePatreonError = function(userId, error){ - console.error(error); + console.error({patreonError: error}); Meteor.users.update(userId, { $set: { "patreon.error": error.toString(), }, }); } + + +const requestMembers = Meteor.wrapAsync(function(cursor, members, callback){ + request({ + uri: `https://www.patreon.com/api/oauth2/v2/campaigns/${CAMPAIGN_ID}/members`, + headers:{ + Authorization: "Bearer " + CREATOR_ACCESS_TOKEN, + }, + qs: { + "include": "user", + "fields[member]": "currently_entitled_amount_cents", + "page[cursor]": cursor, + } + }, (error, reponse, body) => { + if (error){ + callback(error); + return; + } + let json = JSON.parse(body); + if (json.errors) { + callback(json.errors); + return; + } + let newMembers = json.data.map(member => ({ + id: member.relationships.user.data.id, + entitledCents: member.attributes.currently_entitled_amount_cents, + })); + members.push(...newMembers); + let next = json.meta.pagination.cursors && json.meta.pagination.cursors.next; + if (next){ + callback(undefined, next); + } else { + callback(undefined); + } + }); +}); + +const updatePatreonMembersEntitledCents = function(){ + let next = ""; + let members = []; + do { + next = requestMembers(next, members); + } while (next) + members.forEach(({id, entitledCents}) => { + Meteor.users.update({ + "patreon.userId": id + }, {$set: { + "patreon.entitledCents":entitledCents, + }}); + }); + return members; +} + +// Method to run a manual update +Meteor.methods({ + updatePatreonMembersEntitledCents(){ + const user = Meteor.users.findOne(this.userId); + if (!user || !_.contains(user.roles, "admin")) throw new Meteor.Error( + "permission-error", "You need to be logged in as an admin to run this method" + ); + return updatePatreonMembersEntitledCents(); + }, +}); + +// Cron job to run the update automatically +Meteor.startup(() => { + SyncedCron.add({ + name: "updatePatreonMembersEntitledCents", + schedule: function(parser) { + return parser.text('every 4 hours'); + }, + job: updatePatreonMembersEntitledCents, + }); +}) From 0a22073d672912e309048ed76edcae9a9264b9cb Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 7 Mar 2019 13:44:35 +0200 Subject: [PATCH 041/247] Added library link for $5 patrons --- app/client/views/layout/layout.html | 8 ++++++++ app/client/views/layout/layout.js | 13 ++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/app/client/views/layout/layout.html b/app/client/views/layout/layout.html index 9bb47c02..14f287e8 100644 --- a/app/client/views/layout/layout.html +++ b/app/client/views/layout/layout.html @@ -44,6 +44,14 @@ Characters + {{#if isTier5}} + + + + Library (beta) + + + {{/if}} diff --git a/app/client/views/layout/layout.js b/app/client/views/layout/layout.js index a18c74c8..a1d0945d 100644 --- a/app/client/views/layout/layout.js +++ b/app/client/views/layout/layout.js @@ -17,16 +17,23 @@ Template.appDrawer.helpers({ let post = PatreonPosts.findOne({}, {sort: {date: -1}}); return (post && post.link) || 'https://www.patreon.com/dicecloud'; }, + isTier5: function(){ + let user = Meteor.user(); + if (!user) return false; + patreon = user.patreon; + if (!patreon) return false; + return patreon.entitledCents >= 500 || patreon.entitledCentsOverride >= 500; + }, patreonTier: function(){ let user = Meteor.user(); if (!user) return; patreon = user.patreon; - if (!patreon) return "$0"; + if (!patreon) return "free"; let entitledCents = patreon.entitledCents || 0; if (patreon.entitledCentsOverride > entitledCents){ return "$" + (patreon.entitledCentsOverride / 100).toFixed(0); - } else if (patreon.entitledCents === undefined){ - return "$0"; + } else if (!patreon.entitledCents){ + return "free"; } else { return "$" + (patreon.entitledCents / 100).toFixed(0); } From bc6dfbe498a8e36e9d06157695d499ee99bb9f94 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 7 Mar 2019 13:45:38 +0200 Subject: [PATCH 042/247] Fixed stray quotation mark --- app/client/views/user/profile/profile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/client/views/user/profile/profile.js b/app/client/views/user/profile/profile.js index 18e303fe..e8e0d1fc 100644 --- a/app/client/views/user/profile/profile.js +++ b/app/client/views/user/profile/profile.js @@ -44,7 +44,7 @@ Template.profile.helpers({ if (Template.instance().loadingPatreon.get()){ return "loading..." } else if (patreon.entitledCentsOverride > entitledCents){ - return `$ ${(patreon.entitledCentsOverride / 100).toFixed(0)} (Overridden)"`; + return `$ ${(patreon.entitledCentsOverride / 100).toFixed(0)} (Overridden)`; } else if (patreon.entitledCents === undefined){ return "?"; } else { From 721300700eb3a87fb4476a390ecdec5abc797076 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 7 Mar 2019 13:46:56 +0200 Subject: [PATCH 043/247] Fixed capitalization error --- app/client/views/user/profile/profile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/client/views/user/profile/profile.js b/app/client/views/user/profile/profile.js index e8e0d1fc..90234d86 100644 --- a/app/client/views/user/profile/profile.js +++ b/app/client/views/user/profile/profile.js @@ -44,7 +44,7 @@ Template.profile.helpers({ if (Template.instance().loadingPatreon.get()){ return "loading..." } else if (patreon.entitledCentsOverride > entitledCents){ - return `$ ${(patreon.entitledCentsOverride / 100).toFixed(0)} (Overridden)`; + return `$ ${(patreon.entitledCentsOverride / 100).toFixed(0)} (overridden)`; } else if (patreon.entitledCents === undefined){ return "?"; } else { From 41731212ef69be73bb696b768f07cd1d1b0bdb85 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 7 Mar 2019 14:53:52 +0200 Subject: [PATCH 044/247] Added application performance monitoring --- app/.meteor/packages | 3 ++- app/.meteor/versions | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/.meteor/packages b/app/.meteor/packages index e48d58c7..ba4fce08 100644 --- a/app/.meteor/packages +++ b/app/.meteor/packages @@ -37,7 +37,6 @@ spacebars check@1.3.1 useraccounts:iron-routing wizonesolutions:canonical -standard-minifier-js@2.4.0 shell-server@0.4.0 seba:minifiers-autoprefixer nikogosovd:multiple-uihooks @@ -54,3 +53,5 @@ ddp-rate-limiter@1.0.7 rate-limit@1.0.9 iron:router littledata:synced-cron +montiapm:agent +zodern:standard-minifier-js diff --git a/app/.meteor/versions b/app/.meteor/versions index be46ee81..f8a3d460 100644 --- a/app/.meteor/versions +++ b/app/.meteor/versions @@ -64,6 +64,7 @@ iron:router@1.1.2 iron:url@1.1.0 jquery@1.11.11 lai:collection-extensions@0.2.1_1 +lamhieu:meteorx@2.0.1 launch-screen@1.1.1 less@2.8.0 littledata:synced-cron@1.5.1 @@ -76,7 +77,6 @@ meteor@1.9.2 meteor-base@1.4.0 meteorhacks:subs-manager@1.6.4 minifier-css@1.4.0 -minifier-js@2.4.0 minimongo@1.4.5 mobile-experience@1.0.5 mobile-status-bar@1.0.14 @@ -88,6 +88,8 @@ mongo@1.6.0 mongo-decimal@0.1.0 mongo-dev-server@1.1.0 mongo-id@1.0.7 +mongo-livedata@1.0.12 +montiapm:agent@2.34.3 nikogosovd:multiple-uihooks@0.1.8 npm-bcrypt@0.9.3 npm-mongo@3.1.1 @@ -119,7 +121,6 @@ spacebars-compiler@1.1.3 splendido:accounts-emails-field@1.2.0 splendido:accounts-meld@1.3.1 srp@1.0.12 -standard-minifier-js@2.4.0 templates:array@1.0.3 templating@1.3.2 templating-compiler@1.3.3 @@ -137,3 +138,5 @@ webapp-hashing@1.0.9 wizonesolutions:canonical@0.0.5 zimme:collection-behaviours@1.1.3 zimme:collection-softremovable@1.0.5 +zodern:minifier-js@3.0.0 +zodern:standard-minifier-js@3.0.0 From 5ce1b6aff8c6a514ed3121f14b691b62cdcffc7d Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Wed, 3 Apr 2019 10:16:24 +0200 Subject: [PATCH 045/247] closes #210 closes #211 --- README.md | 34 ++- app/.meteor/packages | 5 +- app/.meteor/release | 2 +- app/.meteor/versions | 47 ++-- app/package-lock.json | 68 +---- app/package.json | 2 +- app/server/patreon/patreon.js | 494 +++++++++++++++++----------------- dataSources/srd/srdimport.js | 17 +- 8 files changed, 320 insertions(+), 349 deletions(-) diff --git a/README.md b/README.md index 6c81e7ae..6616df90 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ changes on the fly. Let's look at a hypothetical example. Getting started --------------- -Running DiceCloud locally, either to host it yourself away from an internet +Running DiceCloud locally, either to run it locally, away from an internet connection, or to contribute to developing it further, is fairly straightforward and it should work on Linux, Windows, and Mac. @@ -45,18 +45,29 @@ You'll need to have installed: - [git](https://www.atlassian.com/git/tutorials/install-git) - [Meteor](https://www.meteor.com/install) -- [Bower](https://bower.io/) -Then, it's just a matter of cloning this repository into a folder, installing the bower dependencies and running -`meteor` in the app directory. +Then, it's just a matter of cloning this repository into a folder, installing the dependencies and running +`meteor` in the app directory: `git clone https://github.com/ThaumRystra/DiceCloud dicecloud` `cd dicecloud` `cd app` -`bower install` +`meteor npm install` `meteor` -You should see this: +If you edit the source code at this point, Meteor will rebuild the server with +your changes. + +If you want to simulate a production environment, run `meteor --production` + +This will minimize all the files served to your browser, and load a lot faster, +in exchange for not watching the source code for changes. + +Note that this is not how you should deploy Meteor to your own web server, that +is documented here: https://guide.meteor.com/deployment.html + +After running `meteor` or `meteor --production`, you should see this, possibly +mixed with other logged text: ``` => Started proxy. @@ -69,3 +80,14 @@ You should see this: Now, visiting http://localhost:3000/ should show you an empty instance of DiceCloud running. +To stop the process when you are done (or if it gets stuck) press `ctrl-c` + +## Adding default documents + +Navigate to `/dataSources/srd/srdimport.js`, and follow the steps under +'First Setup', running the code in your browser's console, while logged in to +your own instance of DiceCloud. + +Do not run code in your browser console on the live version of DiceCloud hosted +at dicecloud.com, as doing so could result in a large number of denied requests +to the server, and may get your account permanently banned. diff --git a/app/.meteor/packages b/app/.meteor/packages index ba4fce08..815922ae 100644 --- a/app/.meteor/packages +++ b/app/.meteor/packages @@ -27,7 +27,7 @@ meteor-base@1.4.0 mobile-experience@1.0.5 mongo@1.6.0 blaze-html-templates -session@1.1.8 +session@1.2.0 jquery@1.11.10 tracker@1.2.0 logging@1.1.20 @@ -36,12 +36,11 @@ ejson@1.1.0 spacebars check@1.3.1 useraccounts:iron-routing -wizonesolutions:canonical shell-server@0.4.0 seba:minifiers-autoprefixer nikogosovd:multiple-uihooks templates:array -ecmascript@0.12.0 +ecmascript@0.12.4 es5-shim@4.8.0 differential:vulcanize reactive-dict@1.2.1 diff --git a/app/.meteor/release b/app/.meteor/release index e76dedee..91e05fc1 100644 --- a/app/.meteor/release +++ b/app/.meteor/release @@ -1 +1 @@ -METEOR@1.8 +METEOR@1.8.0.2 diff --git a/app/.meteor/versions b/app/.meteor/versions index f8a3d460..73460e95 100644 --- a/app/.meteor/versions +++ b/app/.meteor/versions @@ -3,15 +3,15 @@ accounts-google@1.3.2 accounts-oauth@1.1.16 accounts-password@1.5.1 accounts-ui@1.3.1 -accounts-ui-unstyled@1.4.1 +accounts-ui-unstyled@1.4.2 aldeed:collection2@2.10.0 aldeed:collection2-core@1.2.0 aldeed:schema-deny@1.1.0 aldeed:schema-index@1.1.1 aldeed:simple-schema@1.5.4 allow-deny@1.1.0 -autoupdate@1.5.0 -babel-compiler@7.2.0 +autoupdate@1.5.1 +babel-compiler@7.2.4 babel-runtime@1.3.0 base64@1.0.11 binary-heap@1.0.11 @@ -19,7 +19,7 @@ blaze@2.3.3 blaze-html-templates@1.1.2 blaze-tools@1.0.10 boilerplate-generator@1.6.0 -caching-compiler@1.2.0 +caching-compiler@1.2.1 caching-html-compiler@1.1.3 callback-hook@1.1.0 check@1.3.1 @@ -33,10 +33,10 @@ ddp-common@1.4.0 ddp-rate-limiter@1.0.7 ddp-server@2.2.0 deps@1.0.12 -diff-sequence@1.1.0 +diff-sequence@1.1.1 differential:vulcanize@3.0.0 -dynamic-import@0.5.0 -ecmascript@0.12.0 +dynamic-import@0.5.1 +ecmascript@0.12.6 ecmascript-runtime@0.7.0 ecmascript-runtime-client@0.8.0 ecmascript-runtime-server@0.7.1 @@ -44,14 +44,14 @@ ecwyne:mathjs@0.25.0 ejson@1.1.0 email@1.2.3 es5-shim@4.8.0 -fetch@0.1.0 +fetch@0.1.1 geojson-utils@1.0.10 google-config-ui@1.0.1 google-oauth@1.2.6 hot-code-push@1.0.4 html-tools@1.0.11 htmljs@1.0.11 -http@1.4.1 +http@1.4.2 id-map@1.1.0 inter-process-messaging@0.1.0 iron:controller@1.0.12 @@ -73,33 +73,33 @@ localstorage@1.2.0 logging@1.1.20 matb33:collection-hooks@0.8.4 mdg:validation-error@0.5.1 -meteor@1.9.2 +meteor@1.9.3 meteor-base@1.4.0 meteorhacks:subs-manager@1.6.4 -minifier-css@1.4.0 +minifier-css@1.4.2 minimongo@1.4.5 mobile-experience@1.0.5 mobile-status-bar@1.0.14 -modern-browsers@0.1.2 +modern-browsers@0.1.4 modules@0.13.0 -modules-runtime@0.10.2 -momentjs:moment@2.22.2 -mongo@1.6.0 -mongo-decimal@0.1.0 +modules-runtime@0.10.3 +momentjs:moment@2.24.0 +mongo@1.6.2 +mongo-decimal@0.1.1 mongo-dev-server@1.1.0 mongo-id@1.0.7 mongo-livedata@1.0.12 -montiapm:agent@2.34.3 +montiapm:agent@2.35.0 nikogosovd:multiple-uihooks@0.1.8 npm-bcrypt@0.9.3 -npm-mongo@3.1.1 -oauth@1.2.3 +npm-mongo@3.1.2 +oauth@1.2.8 oauth2@1.2.1 observe-sequence@1.0.16 ongoworks:speakingurl@9.0.0 ordered-dict@1.1.0 percolate:migrations@0.9.8 -promise@0.11.1 +promise@0.11.2 raix:eventemitter@0.1.3 random@1.1.0 rate-limit@1.0.9 @@ -109,9 +109,9 @@ reload@1.2.0 retry@1.1.0 reywood:iron-router-ga@0.7.1 routepolicy@1.1.0 -seba:minifiers-autoprefixer@1.1.1 +seba:minifiers-autoprefixer@1.1.2 service-configuration@1.0.11 -session@1.1.8 +session@1.2.0 sha@1.0.9 shell-server@0.4.0 socket-stream-client@0.2.2 @@ -133,9 +133,8 @@ url@1.2.0 useraccounts:core@1.14.2 useraccounts:iron-routing@1.14.2 useraccounts:polymer@1.14.2 -webapp@1.7.0 +webapp@1.7.3 webapp-hashing@1.0.9 -wizonesolutions:canonical@0.0.5 zimme:collection-behaviours@1.1.3 zimme:collection-softremovable@1.0.5 zodern:minifier-js@3.0.0 diff --git a/app/package-lock.json b/app/package-lock.json index 486bfe7c..b6dc3891 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -100,9 +100,9 @@ } }, "bower": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.4.tgz", - "integrity": "sha1-54dqB23rgTf30GUl3F6MZtuC8oo=" + "version": "1.8.8", + "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.8.tgz", + "integrity": "sha512-1SrJnXnkP9soITHptSO+ahx3QKp3cVzn8poI6ujqc5SeOkg5iqM1pK9H+DSc2OQ8SnO0jC/NG4Ur/UIwy7574A==" }, "buffer-from": { "version": "1.1.1", @@ -1126,37 +1126,6 @@ "requires": { "inherits": "~2.0.1", "readable-stream": "^2.0.2" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - } - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "stream-http": { @@ -1169,37 +1138,6 @@ "readable-stream": "^2.3.3", "to-arraybuffer": "^1.0.0", "xtend": "^4.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - } - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "string_decoder": { diff --git a/app/package.json b/app/package.json index bfc69dbf..559c5aef 100644 --- a/app/package.json +++ b/app/package.json @@ -14,7 +14,7 @@ "@babel/runtime": "^7.1.2", "@polymer/polymer": "^1.2.5-npm-test.2", "bcrypt": "^1.0.3", - "bower": "^1.7.9", + "bower": "^1.8.8", "core-js": "^2.5.7", "fibers": "^2.0.2", "file-saver": "^2.0.1", diff --git a/app/server/patreon/patreon.js b/app/server/patreon/patreon.js index 71d77ad7..27e98522 100644 --- a/app/server/patreon/patreon.js +++ b/app/server/patreon/patreon.js @@ -1,256 +1,262 @@ import request from 'request'; -const CLIENT_ID = Meteor.settings.public.patreon.clientId; -const CLIENT_SECRET = Meteor.settings.patreon.clientSecret; -const CREATOR_ACCESS_TOKEN = Meteor.settings.patreon.creatorAccessToken; -const CAMPAIGN_ID = Meteor.settings.public.patreon.campaignId; +if ( + Meteor.settings && + Meteor.settings.public && + Meteor.settings.public.patreon +) { + const CLIENT_ID = Meteor.settings.public.patreon.clientId; + const CLIENT_SECRET = Meteor.settings.patreon.clientSecret; + const CREATOR_ACCESS_TOKEN = Meteor.settings.patreon.creatorAccessToken; + const CAMPAIGN_ID = Meteor.settings.public.patreon.campaignId; -// Handle redirects from patreon -Router.map(function () { - this.route("patreon-redirect", { - path: "/patreon-redirect", - where: "server", - action: function () { - let route = this; - let userId = route.params.query.state; - let singleUseCode = route.params.query.code; - requestToken(singleUseCode, Meteor.bindEnvironment((error, response, body) => { - // Should return an access token, valid for 1 month, which needs to be - // stored and used to make requests on behalf of the user - if (error){ - writePatreonError(userId, error); - return; - } - let token; - try { - token = JSON.parse(body); - writePatreonToken(userId, token); - } catch(error) { - writePatreonError(userId, error); - return; - } - updateIdentity(token.access_token, userId); - })); - route.response.writeHead(302, { - 'Location': Meteor.absoluteUrl() + "account", - }); - route.response.end(); - }, + // Handle redirects from patreon + Router.map(function () { + this.route("patreon-redirect", { + path: "/patreon-redirect", + where: "server", + action: function () { + let route = this; + let userId = route.params.query.state; + let singleUseCode = route.params.query.code; + requestToken(singleUseCode, Meteor.bindEnvironment((error, response, body) => { + // Should return an access token, valid for 1 month, which needs to be + // stored and used to make requests on behalf of the user + if (error){ + writePatreonError(userId, error); + return; + } + let token; + try { + token = JSON.parse(body); + writePatreonToken(userId, token); + } catch(error) { + writePatreonError(userId, error); + return; + } + updateIdentity(token.access_token, userId); + })); + route.response.writeHead(302, { + 'Location': Meteor.absoluteUrl() + "account", + }); + route.response.end(); + }, + }); }); -}); -const requestToken = function(singleUseCode, callback){ - request({ - method: "POST", - uri: "https://www.patreon.com/api/oauth2/token", - headers: { - "Content-Type": "application/x-www-form-urlencoded", - }, - qs: { - code: singleUseCode, - grant_type: "authorization_code", - client_id: CLIENT_ID, - client_secret: CLIENT_SECRET, - redirect_uri: Meteor.absoluteUrl() + 'patreon-redirect', - }, - }, callback); -} + const requestToken = function(singleUseCode, callback){ + request({ + method: "POST", + uri: "https://www.patreon.com/api/oauth2/token", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + qs: { + code: singleUseCode, + grant_type: "authorization_code", + client_id: CLIENT_ID, + client_secret: CLIENT_SECRET, + redirect_uri: Meteor.absoluteUrl() + 'patreon-redirect', + }, + }, callback); + } -const getIdentity = function(accessToken, callback){ - request({ - uri: "https://www.patreon.com/api/oauth2/v2/identity", - headers:{ - Authorization: "Bearer " + accessToken, - }, - qs: { - "include": "memberships", - "fields[member]": "currently_entitled_amount_cents", - } - }, callback); -}; + const getIdentity = function(accessToken, callback){ + request({ + uri: "https://www.patreon.com/api/oauth2/v2/identity", + headers:{ + Authorization: "Bearer " + accessToken, + }, + qs: { + "include": "memberships", + "fields[member]": "currently_entitled_amount_cents", + } + }, callback); + }; -// Should return a new access token for the user -// callback is called with (error, response, body) -const refreshAccessToken = Meteor.wrapAsync(function(refreshToken, userId, callback){ - request({ - method: "POST", - uri: "https://www.patreon.com/api/oauth2/token", - qs: { - grant_type: "refresh_token", - refresh_token: refreshToken, - client_id: CLIENT_ID, - client_secret: CLIENT_SECRET, - } - }, Meteor.bindEnvironment((error, response, body) => { - // Should return an access token, valid for 1 month, which needs to be - // stored and used to make requests on behalf of the user - if (error){ - callback(error) - return; - } - let token; - try { - token = JSON.parse(body); - writePatreonToken(userId, token); - callback(undefined, token.access_token); - } catch(error) { - callback(error); - } - })); -}); - -const updateIdentity = Meteor.wrapAsync(function(accessToken, userId, callback){ - getIdentity(accessToken, Meteor.bindEnvironment((error, response, body) => { - if (error){ - writePatreonError(userId, error); - return; - } - try { - let identity = JSON.parse(body); - let membership = identity.included[0]; - let entitledAmount = membership && membership.attributes - .currently_entitled_amount_cents || 0; - let patreonUserId = identity.data.id; - writeEntitledCentsAndId(userId, entitledAmount, patreonUserId); - if (callback) callback(); - } catch(error) { - writePatreonError(userId, error); - if(callback) callback(error); - } - })); -}); - -Meteor.methods({ - updateMyPatreonDetails(){ - const userId = this.userId; - if (!userId) throw new Meteor.Error("not-logged-in", "You must be logged in to update Patreon details"); - const user = Meteor.users.findOne(userId, {fields: {patreon: 1}}); - Meteor.users.update(userId, {$unset: {"patreon.entitledCents": 1}}); - if (!user.patreon || !user.patreon.accessToken){ - throw new Meteor.Error("no-patreon-access", "Patreon access token not found for this user"); - } - let accessToken = user.patreon.accessToken; - if (user.patreon.tokenExpiryDate < new Date()){ - // Token expired, refresh it before continuing - accessToken = refreshAccessToken(user.patreon.refreshToken, userId); - } - updateIdentity(accessToken, userId); - }, -}); - -const writePatreonToken = function(userId, { - access_token, refresh_token, expires_in -}){ - // The expiry date is now plus `expires_in` seconds - let expiryDate = new Date(); - expiryDate.setSeconds(expiryDate.getSeconds() + expires_in); - // Expire a day early so we don't accidentally miss it - expiryDate.setDate(expiryDate.getDate() - 1); - - // Write - Meteor.users.update(userId, { - $set: { - "patreon.accessToken": access_token, - "patreon.refreshToken": refresh_token, - "patreon.tokenExpiryDate": expiryDate, - }, - $unset: { - "patreon.error": 1, - }, - }); -}; - -const writeEntitledCentsAndId = function(userId, amount, patreonUserId){ - Meteor.users.update(userId, { - $set: { - "patreon.entitledCents": amount, - "patreon.userId": patreonUserId, - }, - $unset: { - "patreon.error": 1, - }, - }); -}; - -const writePatreonError = function(userId, error){ - console.error({patreonError: error}); - Meteor.users.update(userId, { - $set: { - "patreon.error": error.toString(), - }, - }); -} - - -const requestMembers = Meteor.wrapAsync(function(cursor, members, callback){ - request({ - uri: `https://www.patreon.com/api/oauth2/v2/campaigns/${CAMPAIGN_ID}/members`, - headers:{ - Authorization: "Bearer " + CREATOR_ACCESS_TOKEN, - }, - qs: { - "include": "user", - "fields[member]": "currently_entitled_amount_cents", - "page[cursor]": cursor, - } - }, (error, reponse, body) => { - if (error){ - callback(error); - return; - } - let json = JSON.parse(body); - if (json.errors) { - callback(json.errors); - return; - } - let newMembers = json.data.map(member => ({ - id: member.relationships.user.data.id, - entitledCents: member.attributes.currently_entitled_amount_cents, + // Should return a new access token for the user + // callback is called with (error, response, body) + const refreshAccessToken = Meteor.wrapAsync(function(refreshToken, userId, callback){ + request({ + method: "POST", + uri: "https://www.patreon.com/api/oauth2/token", + qs: { + grant_type: "refresh_token", + refresh_token: refreshToken, + client_id: CLIENT_ID, + client_secret: CLIENT_SECRET, + } + }, Meteor.bindEnvironment((error, response, body) => { + // Should return an access token, valid for 1 month, which needs to be + // stored and used to make requests on behalf of the user + if (error){ + callback(error) + return; + } + let token; + try { + token = JSON.parse(body); + writePatreonToken(userId, token); + callback(undefined, token.access_token); + } catch(error) { + callback(error); + } })); - members.push(...newMembers); - let next = json.meta.pagination.cursors && json.meta.pagination.cursors.next; - if (next){ - callback(undefined, next); - } else { - callback(undefined); - } }); -}); -const updatePatreonMembersEntitledCents = function(){ - let next = ""; - let members = []; - do { - next = requestMembers(next, members); - } while (next) - members.forEach(({id, entitledCents}) => { - Meteor.users.update({ - "patreon.userId": id - }, {$set: { - "patreon.entitledCents":entitledCents, - }}); + const updateIdentity = Meteor.wrapAsync(function(accessToken, userId, callback){ + getIdentity(accessToken, Meteor.bindEnvironment((error, response, body) => { + if (error){ + writePatreonError(userId, error); + return; + } + try { + let identity = JSON.parse(body); + let membership = identity.included[0]; + let entitledAmount = membership && membership.attributes + .currently_entitled_amount_cents || 0; + let patreonUserId = identity.data.id; + writeEntitledCentsAndId(userId, entitledAmount, patreonUserId); + if (callback) callback(); + } catch(error) { + writePatreonError(userId, error); + if(callback) callback(error); + } + })); }); - return members; + + Meteor.methods({ + updateMyPatreonDetails(){ + const userId = this.userId; + if (!userId) throw new Meteor.Error("not-logged-in", "You must be logged in to update Patreon details"); + const user = Meteor.users.findOne(userId, {fields: {patreon: 1}}); + Meteor.users.update(userId, {$unset: {"patreon.entitledCents": 1}}); + if (!user.patreon || !user.patreon.accessToken){ + throw new Meteor.Error("no-patreon-access", "Patreon access token not found for this user"); + } + let accessToken = user.patreon.accessToken; + if (user.patreon.tokenExpiryDate < new Date()){ + // Token expired, refresh it before continuing + accessToken = refreshAccessToken(user.patreon.refreshToken, userId); + } + updateIdentity(accessToken, userId); + }, + }); + + const writePatreonToken = function(userId, { + access_token, refresh_token, expires_in + }){ + // The expiry date is now plus `expires_in` seconds + let expiryDate = new Date(); + expiryDate.setSeconds(expiryDate.getSeconds() + expires_in); + // Expire a day early so we don't accidentally miss it + expiryDate.setDate(expiryDate.getDate() - 1); + + // Write + Meteor.users.update(userId, { + $set: { + "patreon.accessToken": access_token, + "patreon.refreshToken": refresh_token, + "patreon.tokenExpiryDate": expiryDate, + }, + $unset: { + "patreon.error": 1, + }, + }); + }; + + const writeEntitledCentsAndId = function(userId, amount, patreonUserId){ + Meteor.users.update(userId, { + $set: { + "patreon.entitledCents": amount, + "patreon.userId": patreonUserId, + }, + $unset: { + "patreon.error": 1, + }, + }); + }; + + const writePatreonError = function(userId, error){ + console.error({patreonError: error}); + Meteor.users.update(userId, { + $set: { + "patreon.error": error.toString(), + }, + }); + } + + + const requestMembers = Meteor.wrapAsync(function(cursor, members, callback){ + request({ + uri: `https://www.patreon.com/api/oauth2/v2/campaigns/${CAMPAIGN_ID}/members`, + headers:{ + Authorization: "Bearer " + CREATOR_ACCESS_TOKEN, + }, + qs: { + "include": "user", + "fields[member]": "currently_entitled_amount_cents", + "page[cursor]": cursor, + } + }, (error, reponse, body) => { + if (error){ + callback(error); + return; + } + let json = JSON.parse(body); + if (json.errors) { + callback(json.errors); + return; + } + let newMembers = json.data.map(member => ({ + id: member.relationships.user.data.id, + entitledCents: member.attributes.currently_entitled_amount_cents, + })); + members.push(...newMembers); + let next = json.meta.pagination.cursors && json.meta.pagination.cursors.next; + if (next){ + callback(undefined, next); + } else { + callback(undefined); + } + }); + }); + + const updatePatreonMembersEntitledCents = function(){ + let next = ""; + let members = []; + do { + next = requestMembers(next, members); + } while (next) + members.forEach(({id, entitledCents}) => { + Meteor.users.update({ + "patreon.userId": id + }, {$set: { + "patreon.entitledCents":entitledCents, + }}); + }); + return members; + } + + // Method to run a manual update + Meteor.methods({ + updatePatreonMembersEntitledCents(){ + const user = Meteor.users.findOne(this.userId); + if (!user || !_.contains(user.roles, "admin")) throw new Meteor.Error( + "permission-error", "You need to be logged in as an admin to run this method" + ); + return updatePatreonMembersEntitledCents(); + }, + }); + + // Cron job to run the update automatically + Meteor.startup(() => { + SyncedCron.add({ + name: "updatePatreonMembersEntitledCents", + schedule: function(parser) { + return parser.text('every 4 hours'); + }, + job: updatePatreonMembersEntitledCents, + }); + }) } - -// Method to run a manual update -Meteor.methods({ - updatePatreonMembersEntitledCents(){ - const user = Meteor.users.findOne(this.userId); - if (!user || !_.contains(user.roles, "admin")) throw new Meteor.Error( - "permission-error", "You need to be logged in as an admin to run this method" - ); - return updatePatreonMembersEntitledCents(); - }, -}); - -// Cron job to run the update automatically -Meteor.startup(() => { - SyncedCron.add({ - name: "updatePatreonMembersEntitledCents", - schedule: function(parser) { - return parser.text('every 4 hours'); - }, - job: updatePatreonMembersEntitledCents, - }); -}) diff --git a/dataSources/srd/srdimport.js b/dataSources/srd/srdimport.js index a788b8be..8c5fdb48 100644 --- a/dataSources/srd/srdimport.js +++ b/dataSources/srd/srdimport.js @@ -1,6 +1,9 @@ // This all gets run in the console by an admin. -// Probably a good idea to reset the server after running big updates -// Only do if the library doesn't exist yet + +// First Setup +// ----------- + +// Add the SRD library with the correct static ID: id = Libraries.insert({ _id: "SRDLibraryGA3XWsd", owner: Meteor.userId(), @@ -8,19 +11,23 @@ id = Libraries.insert({ }); // First copy-paste the JSON into your console like `items = ` -// First import, don't do this if the library is already populated _.each(items, (item) => { - item.settings = {category: }; // "adventuringGear", "armor", "weapons", "tools" + // replace "adventuringGear" with appropriate category: "armor", "weapons", "tools" + // if needed + item.settings = {category: "adventuringGear"}; item.library = "SRDLibraryGA3XWsd" LibraryItems.insert(item) }); +// First copy-paste the JSON into your console like `spells = ` _.each(spells, (spell) => { spell.library = "SRDLibraryGA3XWsd" LibrarySpells.insert(spell) }); -// Update the library using names as keys +// Updating the Libary +// ------------------- + // Make sure you're subscribed to all item categories handles = _.map(["weapons", "armor", "adventuringGear", "tools"], category => Meteor.subscribe("standardLibraryItems", category) From d4864dda5fa9e45c67811d378524acb5711c6034 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Fri, 3 May 2019 13:41:49 +0200 Subject: [PATCH 046/247] Fixed error on no meteor.settings file, updated meteor --- app/.meteor/packages | 8 ++++---- app/.meteor/release | 2 +- app/.meteor/versions | 16 ++++++++-------- app/client/views/user/profile/profile.js | 5 ++++- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/app/.meteor/packages b/app/.meteor/packages index 815922ae..6244d270 100644 --- a/app/.meteor/packages +++ b/app/.meteor/packages @@ -25,13 +25,13 @@ chuangbo:marked reywood:iron-router-ga meteor-base@1.4.0 mobile-experience@1.0.5 -mongo@1.6.0 +mongo@1.6.2 blaze-html-templates session@1.2.0 jquery@1.11.10 tracker@1.2.0 logging@1.1.20 -reload@1.2.0 +reload@1.3.0 ejson@1.1.0 spacebars check@1.3.1 @@ -43,11 +43,11 @@ templates:array ecmascript@0.12.4 es5-shim@4.8.0 differential:vulcanize -reactive-dict@1.2.1 +reactive-dict@1.3.0 ongoworks:speakingurl service-configuration@1.0.11 google-config-ui@1.0.1 -dynamic-import@0.5.0 +dynamic-import@0.5.1 ddp-rate-limiter@1.0.7 rate-limit@1.0.9 iron:router diff --git a/app/.meteor/release b/app/.meteor/release index 91e05fc1..97064e19 100644 --- a/app/.meteor/release +++ b/app/.meteor/release @@ -1 +1 @@ -METEOR@1.8.0.2 +METEOR@1.8.1 diff --git a/app/.meteor/versions b/app/.meteor/versions index 73460e95..eecfcb54 100644 --- a/app/.meteor/versions +++ b/app/.meteor/versions @@ -1,4 +1,4 @@ -accounts-base@1.4.3 +accounts-base@1.4.4 accounts-google@1.3.2 accounts-oauth@1.1.16 accounts-password@1.5.1 @@ -10,8 +10,8 @@ aldeed:schema-deny@1.1.0 aldeed:schema-index@1.1.1 aldeed:simple-schema@1.5.4 allow-deny@1.1.0 -autoupdate@1.5.1 -babel-compiler@7.2.4 +autoupdate@1.6.0 +babel-compiler@7.3.4 babel-runtime@1.3.0 base64@1.0.11 binary-heap@1.0.11 @@ -31,12 +31,12 @@ ddp@1.4.0 ddp-client@2.3.3 ddp-common@1.4.0 ddp-rate-limiter@1.0.7 -ddp-server@2.2.0 +ddp-server@2.3.0 deps@1.0.12 diff-sequence@1.1.1 differential:vulcanize@3.0.0 dynamic-import@0.5.1 -ecmascript@0.12.6 +ecmascript@0.12.7 ecmascript-runtime@0.7.0 ecmascript-runtime-client@0.8.0 ecmascript-runtime-server@0.7.1 @@ -103,9 +103,9 @@ promise@0.11.2 raix:eventemitter@0.1.3 random@1.1.0 rate-limit@1.0.9 -reactive-dict@1.2.1 +reactive-dict@1.3.0 reactive-var@1.0.11 -reload@1.2.0 +reload@1.3.0 retry@1.1.0 reywood:iron-router-ga@0.7.1 routepolicy@1.1.0 @@ -133,7 +133,7 @@ url@1.2.0 useraccounts:core@1.14.2 useraccounts:iron-routing@1.14.2 useraccounts:polymer@1.14.2 -webapp@1.7.3 +webapp@1.7.4 webapp-hashing@1.0.9 zimme:collection-behaviours@1.1.3 zimme:collection-softremovable@1.0.5 diff --git a/app/client/views/user/profile/profile.js b/app/client/views/user/profile/profile.js index 90234d86..e0dcde84 100644 --- a/app/client/views/user/profile/profile.js +++ b/app/client/views/user/profile/profile.js @@ -1,6 +1,8 @@ import { format as formatUrl } from 'url'; -const CLIENT_ID = Meteor.settings.public.patreon.clientId; +const CLIENT_ID = Meteor.settings && + Meteor.settings.public.patreon && + Meteor.settings.public.patreon.clientId; Template.profile.onCreated(function(){ this.showApiKey = new ReactiveVar(false); @@ -18,6 +20,7 @@ Template.profile.helpers({ return Template.instance().showApiKey.get(); }, patreonLoginUrl: function(){ + if (!CLIENT_ID) return; return formatUrl({ protocol: 'https', host: 'patreon.com', From 81a3ede86e9d2e86505c72ab971fb1741414d54e Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Mon, 6 May 2019 14:51:48 +0200 Subject: [PATCH 047/247] Substantially improved item libraries UI, locked behind Patreon tier 5 --- app/Model/Library/Library.js | 16 +-- app/Routes/Routes.js | 21 +++- app/client/globalHelpers/isTier5.js | 7 ++ app/client/globalHelpers/patreonLoginUrl.js | 19 +++ app/client/views/layout/layout.html | 14 +-- app/client/views/layout/layout.js | 7 -- .../library/itemLibrary/itemLibrary.html | 29 ----- .../views/library/itemLibrary/itemLibrary.js | 94 -------------- app/client/views/library/libraries.css | 1 + app/client/views/library/libraries.html | 35 ++++++ app/client/views/library/libraries.js | 38 ++++++ app/client/views/library/library.css | 19 --- app/client/views/library/library.html | 64 +++++++--- app/client/views/library/library.js | 117 ++++++++++++++++-- .../library/libraryDeleteConfirmation.html | 18 +++ .../library/libraryDeleteConfirmation.js | 8 ++ .../library/libraryDialog/libraryDialog.html | 34 ++++- .../library/libraryDialog/libraryDialog.js | 34 ++++- .../libraryItemDialog/libraryItemDialog.html | 47 +++---- .../libraryItemDialog/libraryItemDialog.js | 20 +++ app/client/views/patreon/patronsOnly.html | 27 ++++ app/client/views/user/profile/profile.js | 19 --- app/public/custom_components/app-theme.html | 4 + app/server/publications/library.js | 49 +++++++- 24 files changed, 493 insertions(+), 248 deletions(-) create mode 100644 app/client/globalHelpers/isTier5.js create mode 100644 app/client/globalHelpers/patreonLoginUrl.js delete mode 100644 app/client/views/library/itemLibrary/itemLibrary.html delete mode 100644 app/client/views/library/itemLibrary/itemLibrary.js create mode 100644 app/client/views/library/libraries.css create mode 100644 app/client/views/library/libraries.html create mode 100644 app/client/views/library/libraries.js delete mode 100644 app/client/views/library/library.css create mode 100644 app/client/views/library/libraryDeleteConfirmation.html create mode 100644 app/client/views/library/libraryDeleteConfirmation.js rename app/client/views/library/{itemLibrary => }/libraryItemDialog/libraryItemDialog.html (74%) rename app/client/views/library/{itemLibrary => }/libraryItemDialog/libraryItemDialog.js (91%) create mode 100644 app/client/views/patreon/patronsOnly.html diff --git a/app/Model/Library/Library.js b/app/Model/Library/Library.js index edcb8cc1..c8f15706 100644 --- a/app/Model/Library/Library.js +++ b/app/Model/Library/Library.js @@ -10,19 +10,21 @@ Schemas.Library = new SimpleSchema({ Libraries.attachSchema(Schemas.Library); -Libraries.after.remove(function(userId, library) { - LibraryItems.remove({library: library._id}); - LibrarySpells.remove({library: library._id}); -}); +if (Meteor.isServer){ + Libraries.after.remove(function(userId, library) { + LibraryItems.remove({library: library._id}); + LibrarySpells.remove({library: library._id}); + }); +} Meteor.methods({ - removeLibrary: function(libraryId) { + unshareLibraryWithMe: function(libraryId) { let library = Libraries.findOne(libraryId); - let userId = Meteor.userId(); + let userId = Meteor.userId(); if (!library) return; if (library.owner === userId){ - Libraries.remove(libraryId); + throw new Meteor.error("Can't unshare, you own this") } else { if (_.contains(library.readers, userId)){ Libraries.update(libraryId, {$pull: {"readers": userId}}); diff --git a/app/Routes/Routes.js b/app/Routes/Routes.js index 49accc2a..b6803480 100644 --- a/app/Routes/Routes.js +++ b/app/Routes/Routes.js @@ -8,6 +8,8 @@ Router.plugin("ensureSignedIn", { only: [ "profile", "characterList", + "library", + "libraries", ] }); @@ -118,11 +120,28 @@ Router.map(function() { }, }); - this.route("library", { + this.route("libraries", { path: "/library", waitOn: function(){ return subsManager.subscribe("customLibraries"); }, + onAfterAction: function() { + document.title = appName + " - Libraries"; + }, + fastRender: true, + }); + + this.route("library", { + path: "/library/:_id", + waitOn: function(){ + return [ + subsManager.subscribe("libraryItems", this.params._id), + subsManager.subscribe("singleLibrary", this.params._id), + ]; + }, + data: function() { + return Libraries.findOne(this.params._id); + }, onAfterAction: function() { document.title = appName + " - Library"; }, diff --git a/app/client/globalHelpers/isTier5.js b/app/client/globalHelpers/isTier5.js new file mode 100644 index 00000000..1802364f --- /dev/null +++ b/app/client/globalHelpers/isTier5.js @@ -0,0 +1,7 @@ +Template.registerHelper("isTier5", function(){ + let user = Meteor.user(); + if (!user) return false; + patreon = user.patreon; + if (!patreon) return false; + return patreon.entitledCents >= 500 || patreon.entitledCentsOverride >= 500; +}); diff --git a/app/client/globalHelpers/patreonLoginUrl.js b/app/client/globalHelpers/patreonLoginUrl.js new file mode 100644 index 00000000..dbce866d --- /dev/null +++ b/app/client/globalHelpers/patreonLoginUrl.js @@ -0,0 +1,19 @@ +const CLIENT_ID = Meteor.settings && + Meteor.settings.public.patreon && + Meteor.settings.public.patreon.clientId; + +Template.registerHelper("patreonLoginUrl", function() { + if (!CLIENT_ID) return; + return formatUrl({ + protocol: 'https', + host: 'patreon.com', + pathname: '/oauth2/authorize', + query: { + response_type: 'code', + client_id: CLIENT_ID, + redirect_uri: Meteor.absoluteUrl() + 'patreon-redirect', + state: Meteor.userId(), + scope: 'identity', + }, + }); +}); diff --git a/app/client/views/layout/layout.html b/app/client/views/layout/layout.html index 14f287e8..1a84ff81 100644 --- a/app/client/views/layout/layout.html +++ b/app/client/views/layout/layout.html @@ -44,14 +44,12 @@ Characters - {{#if isTier5}} - - - - Library (beta) - - - {{/if}} + + + + Libraries (beta) + + diff --git a/app/client/views/layout/layout.js b/app/client/views/layout/layout.js index a1d0945d..c1480d44 100644 --- a/app/client/views/layout/layout.js +++ b/app/client/views/layout/layout.js @@ -17,13 +17,6 @@ Template.appDrawer.helpers({ let post = PatreonPosts.findOne({}, {sort: {date: -1}}); return (post && post.link) || 'https://www.patreon.com/dicecloud'; }, - isTier5: function(){ - let user = Meteor.user(); - if (!user) return false; - patreon = user.patreon; - if (!patreon) return false; - return patreon.entitledCents >= 500 || patreon.entitledCentsOverride >= 500; - }, patreonTier: function(){ let user = Meteor.user(); if (!user) return; diff --git a/app/client/views/library/itemLibrary/itemLibrary.html b/app/client/views/library/itemLibrary/itemLibrary.html deleted file mode 100644 index 87047681..00000000 --- a/app/client/views/library/itemLibrary/itemLibrary.html +++ /dev/null @@ -1,29 +0,0 @@ - diff --git a/app/client/views/library/itemLibrary/itemLibrary.js b/app/client/views/library/itemLibrary/itemLibrary.js deleted file mode 100644 index 06c733db..00000000 --- a/app/client/views/library/itemLibrary/itemLibrary.js +++ /dev/null @@ -1,94 +0,0 @@ -const librarySubs = new SubsManager(); - -Template.itemLibrary.onCreated(function(){ - this.selectedTab = new ReactiveVar("0"); - this.librariesOpen = new ReactiveVar([]); - this.readyDict = new ReactiveDict(); - this.autorun(() => { - // Subscribe to all open libraries - _.each(this.librariesOpen.get(), (libraryId) => { - var handle = librarySubs.subscribe("libraryItems", libraryId); - this.autorun(() => { - this.readyDict.set(libraryId, handle.ready()); - }); - }); - }); -}); - -Template.itemLibrary.helpers({ - selectedTab(){ - return Template.instance().selectedTab.get(); - }, - libraries(){ - let userId = Meteor.userId(); - return Libraries.find({ - $or: [ - {readers: userId}, - {writers: userId}, - {owner: userId}, - ], - }); - }, - libraryItems(){ - return LibraryItems.find({ - library: this._id - },{ - sort: {name: 1} - }); - }, - ready(libraryId){ - return Template.instance().readyDict.get(libraryId); - }, - isOpen(libraryId){ - const librariesOpen = Template.instance().librariesOpen.get(); - return _.contains(librariesOpen, libraryId); - }, -}); - -Template.itemLibrary.events({ - "click .library-header": function(event, template){ - let libs = template.librariesOpen.get(); - const libraryId = this._id; - // Toggle whether this key is in the array or not - if (_.contains(libs, libraryId)){ - libs = _.without(libs, libraryId); - } else { - libs.push(libraryId); - } - template.librariesOpen.set(libs); - }, - "click .editLibrary": function(event, instance){ - event.stopPropagation(); - var libraryId = this._id; - pushDialogStack({ - template: "libraryDialog", - data: {libraryId}, - element: event.currentTarget.parentElement.parentElement, - returnElement: () => instance.find(`.library-header[data-id='${libraryId}']`), - }); - }, - "click .addItem": function(event, instance){ - event.stopPropagation(); - var libraryId = this._id; - var itemId = LibraryItems.insert({ - name: "New Library Item", - library: libraryId, - }); - pushDialogStack({ - template: "libraryItemDialog", - data: {itemId}, - element: event.currentTarget, - returnElement: () => instance.find(`.item-name[data-id='${itemId}']`), - }); - }, - "click .item-name": function(event, instance){ - event.stopPropagation(); - var itemId = this._id; - pushDialogStack({ - template: "libraryItemDialog", - data: {itemId}, - element: event.currentTarget, - returnElement: () => instance.find(`.item-name[data-id='${itemId}']`), - }); - }, -}) diff --git a/app/client/views/library/libraries.css b/app/client/views/library/libraries.css new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/app/client/views/library/libraries.css @@ -0,0 +1 @@ + diff --git a/app/client/views/library/libraries.html b/app/client/views/library/libraries.html new file mode 100644 index 00000000..62f3c1a4 --- /dev/null +++ b/app/client/views/library/libraries.html @@ -0,0 +1,35 @@ + diff --git a/app/client/views/library/libraries.js b/app/client/views/library/libraries.js new file mode 100644 index 00000000..28756241 --- /dev/null +++ b/app/client/views/library/libraries.js @@ -0,0 +1,38 @@ +const librarySubs = new SubsManager(); + +Template.libraries.helpers({ + libraries(){ + let userId = Meteor.userId(); + let subs = Meteor.user() && Meteor.user().profile.librarySubscriptions; + return Libraries.find({ + $or: [ + {readers: userId}, + {writers: userId}, + {owner: userId}, + {_id: {$in: subs}} + ], + }, { + sort: {name: 1}, + }); + }, +}); + +Template.libraries.events({ + "click #addLibrary": function(event, instance){ + var libraryId = Libraries.insert({ + name: "New Library", + owner: Meteor.userId(), + }); + pushDialogStack({ + template: "libraryDialog", + data: {libraryId}, + element: event.currentTarget, + returnElement: () => instance.find(`.library[data-id='${libraryId}']`), + callback(data){ + if (data && data.delete){ + Libraries.remove(libraryId); + } + } + }); + }, +}) diff --git a/app/client/views/library/library.css b/app/client/views/library/library.css deleted file mode 100644 index 731d8036..00000000 --- a/app/client/views/library/library.css +++ /dev/null @@ -1,19 +0,0 @@ -.library .item-name { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - cursor: pointer; -} - -.library .library-header { - font-weight: 500; - cursor: pointer; -} - -.library .library-header iron-icon { - transition: transform 0.3s ease; -} - -.library .library-header iron-icon.open { - transform: rotate(90deg); -} diff --git a/app/client/views/library/library.html b/app/client/views/library/library.html index b01f46ff..d5c52035 100644 --- a/app/client/views/library/library.html +++ b/app/client/views/library/library.html @@ -2,31 +2,55 @@
-
+
+
- Item Library + {{name}}
+ {{#if isTier5}}{{#if canUserEdit}} + + {{/if}}{{/if}}
- + {{#if isTier5}} +
+ + + +
+ {{#if canUserSubscribe}} + + + Subscribe + + {{else if canUserUnsubscribe}} + + + Unsubscribe + + {{/if}} +
+ {{/if}} -
- -
{{> itemLibrary}}
- -
-
- - {{#simpleTooltip}}Add Library{{/simpleTooltip}} -
+ {{#if isTier5}} +
+ + {{#each items}} + + +
{{displayName}}
+
+
+ {{/each}} +
+
+
+ + {{#simpleTooltip}}Add Library Item{{/simpleTooltip}} +
+ {{else}} + {{> patronsOnly }} + {{/if}}
diff --git a/app/client/views/library/library.js b/app/client/views/library/library.js index 70d0e89d..5f1e889e 100644 --- a/app/client/views/library/library.js +++ b/app/client/views/library/library.js @@ -1,29 +1,120 @@ const librarySubs = new SubsManager(); Template.library.onCreated(function(){ - this.selectedTab = new ReactiveVar("0"); + this.searchTerm = new ReactiveVar(""); }); Template.library.helpers({ - selectedTab(){ - return Template.instance().selectedTab.get(); + items(){ + let search = Template.instance().searchTerm.get(); + if (search){ + return LibraryItems.find( + { + library: this._id, + $or: [ + { + name: {$regex: new RegExp(".*" + search + ".*", "gi")} + }, + { + libraryname: {$regex: new RegExp(".*" + search + ".*", "gi")} + }, + ], + }, + {sort: {name: 1}}, + ); + } else { + return LibraryItems.find( + {library: this._id}, + {sort: {name: 1}}, + ); + } + }, + displayName(){ + return this.libraryName || this.name; + }, + canUserSubscribe(){ + let user = Meteor.user(); + let userId = user._id; + return !( + _.contains(this.readers, userId) || + _.contains(this.writers, userId) || + this.owner === userId || + _.contains(user.profile.librarySubscriptions, this._id) + ); + }, + canUserUnsubscribe(){ + let user = Meteor.user(); + let userId = user._id; + return ( + _.contains(user.profile.librarySubscriptions, this._id) || + _.contains(this.readers, userId) + ); + }, + canUserEdit(){ + let userId = Meteor.userId(); + return ( + _.contains(this.writers, userId) || + this.owner === userId + ); }, }); Template.library.events({ - "iron-select #libraryTabs": function(event, instance){ - instance.selectedTab.set(event.target.selected); + "input .search-input, change .search-input": function(event, template){ + const value = event.currentTarget.value; + template.searchTerm.set(value); }, - "click #addLibrary": function(event, instance){ - var libraryId = Libraries.insert({ - name: "New Library", - owner: Meteor.userId(), - }); + "click #edit": function(event, instance){ + event.stopPropagation(); + var libraryId = this._id; pushDialogStack({ template: "libraryDialog", data: {libraryId}, - element: event.currentTarget, - returnElement: () => instance.find(`.library-header[data-id='${libraryId}']`), + element: event.currentTarget.parentElement.parentElement, + callback(data){ + if (data && data.delete){ + Router.go('/library'); + Tracker.afterFlush(function(){ + Libraries.remove(libraryId); + }); + } + }, }); }, -}) + "click #addLibraryItem": function(event, instance){ + event.stopPropagation(); + var libraryId = this._id; + var itemId = LibraryItems.insert({ + name: "New Library Item", + library: libraryId, + }); + pushDialogStack({ + template: "libraryItemDialog", + data: {itemId}, + element: event.currentTarget, + returnElement: () => instance.find(`.item[data-id='${itemId}']`), + }); + }, + "click .item": function(event, instance){ + event.stopPropagation(); + var itemId = this._id; + pushDialogStack({ + template: "libraryItemDialog", + data: {itemId}, + element: event.currentTarget, + returnElement: () => instance.find(`.item[data-id='${itemId}']`), + }); + }, + "click #subscribe": function(event, instance){ + Meteor.users.update(Meteor.userId(), { + $addToSet: {"profile.librarySubscriptions": this._id}, + }); + }, + "click #unsubscribe": function(event, instance){ + let userId = Meteor.userId(); + Meteor.users.update(userId, { + $pull: {"profile.librarySubscriptions": this._id}, + }); + Meteor.call("unshareLibraryWithMe", this._id); + }, +}); diff --git a/app/client/views/library/libraryDeleteConfirmation.html b/app/client/views/library/libraryDeleteConfirmation.html new file mode 100644 index 00000000..3068e090 --- /dev/null +++ b/app/client/views/library/libraryDeleteConfirmation.html @@ -0,0 +1,18 @@ + diff --git a/app/client/views/library/libraryDeleteConfirmation.js b/app/client/views/library/libraryDeleteConfirmation.js new file mode 100644 index 00000000..20ef660a --- /dev/null +++ b/app/client/views/library/libraryDeleteConfirmation.js @@ -0,0 +1,8 @@ +Template.libraryDeleteConfirmation.events({ + "click #deleteButton": function(event, instance) { + popDialogStack(true); + }, + "click .cancelButton": function(event, instance){ + popDialogStack(); + }, +}); diff --git a/app/client/views/library/libraryDialog/libraryDialog.html b/app/client/views/library/libraryDialog/libraryDialog.html index 3fc83637..1eff7433 100644 --- a/app/client/views/library/libraryDialog/libraryDialog.html +++ b/app/client/views/library/libraryDialog/libraryDialog.html @@ -1,15 +1,39 @@ diff --git a/app/client/views/library/itemLibrary/libraryItemDialog/libraryItemDialog.js b/app/client/views/library/libraryItemDialog/libraryItemDialog.js similarity index 91% rename from app/client/views/library/itemLibrary/libraryItemDialog/libraryItemDialog.js rename to app/client/views/library/libraryItemDialog/libraryItemDialog.js index c258705d..3f82c681 100644 --- a/app/client/views/library/itemLibrary/libraryItemDialog/libraryItemDialog.js +++ b/app/client/views/library/libraryItemDialog/libraryItemDialog.js @@ -1,3 +1,9 @@ +Template.libraryItemDialog.onCreated(function(){ + this.autorun(() => { + this.subscribe('libraryItem', Template.currentData().itemId); + }); +}); + Template.libraryItemDialog.helpers({ item(){ return LibraryItems.findOne(this.itemId); @@ -55,6 +61,20 @@ Template.libraryItemDialog.helpers({ thunder: 12, }; return ref[damageType]; + }, + ready(){ + return Template.instance().subscriptionsReady(); + }, + cantEdit(){ + let item = LibraryItems.findOne(this.itemId); + if (!item) return; + let library = Libraries.findOne(item.library); + if (!library) return; + let userId = Meteor.userId(); + return !( + library.owner === userId || + _.contains(library.writers, userId) + ); } }); diff --git a/app/client/views/patreon/patronsOnly.html b/app/client/views/patreon/patronsOnly.html new file mode 100644 index 00000000..27c55c05 --- /dev/null +++ b/app/client/views/patreon/patronsOnly.html @@ -0,0 +1,27 @@ + diff --git a/app/client/views/user/profile/profile.js b/app/client/views/user/profile/profile.js index e0dcde84..f3df5f10 100644 --- a/app/client/views/user/profile/profile.js +++ b/app/client/views/user/profile/profile.js @@ -1,9 +1,5 @@ import { format as formatUrl } from 'url'; -const CLIENT_ID = Meteor.settings && - Meteor.settings.public.patreon && - Meteor.settings.public.patreon.clientId; - Template.profile.onCreated(function(){ this.showApiKey = new ReactiveVar(false); this.loadingPatreon = new ReactiveVar(false); @@ -19,21 +15,6 @@ Template.profile.helpers({ showApiKey: function(){ return Template.instance().showApiKey.get(); }, - patreonLoginUrl: function(){ - if (!CLIENT_ID) return; - return formatUrl({ - protocol: 'https', - host: 'patreon.com', - pathname: '/oauth2/authorize', - query: { - response_type: 'code', - client_id: CLIENT_ID, - redirect_uri: Meteor.absoluteUrl() + 'patreon-redirect', - state: Meteor.userId(), - scope: 'identity', - }, - }); - }, patreon: function(){ let user = Meteor.user(); return user && user.patreon || {}; diff --git a/app/public/custom_components/app-theme.html b/app/public/custom_components/app-theme.html index e84c18cb..aff91794 100644 --- a/app/public/custom_components/app-theme.html +++ b/app/public/custom_components/app-theme.html @@ -70,4 +70,8 @@ --paper-diff-slider-knob-color: #00BCD4; --paper-diff-slider-pin-color: #00BCD4; } + .white-text paper-input { + /* Input foreground color */ + --paper-input-container-input-color: rgba(255,255,255,0.87); + } diff --git a/app/server/publications/library.js b/app/server/publications/library.js index 3ab18ce3..94d9df78 100644 --- a/app/server/publications/library.js +++ b/app/server/publications/library.js @@ -25,16 +25,61 @@ Meteor.publish("standardLibrarySpells", function(level){ }); Meteor.publish("customLibraries", function(){ - userId = this.userId; + const userId = this.userId; + let user = Meteor.user() + let subs = user && user.profile && user.profile.librarySubscriptions; return Libraries.find({ $or: [ {readers: userId}, {writers: userId}, {owner: userId}, + {public: true, _id: {$in: subs || []}}, + ], + }); +}); + +Meteor.publish("singleLibrary", function(id){ + const userId = this.userId; + return Libraries.find({ + _id: id, + $or: [ + {readers: userId}, + {writers: userId}, + {owner: userId}, + {public: true}, ], }); }); Meteor.publish("libraryItems", function(libraryId){ - return LibraryItems.find({library: libraryId}); + return LibraryItems.find({ + library: libraryId + }, { + fields: { + name: 1, + libraryName: 1, + library: 1, + }, + }); +}); + +Meteor.publish("libraryItem", function(itemId){ + let cursor = LibraryItems.find(itemId); + let item = cursor.fetch()[0]; + let userId = Meteor.userId(); + if (!item) return []; + let library = Libraries.findOne(item.library); + if (!library) { + throw new Meteor.Error("Library item " + item._id + " is an orphan"); + } + if ( + library.public || + library.owner === userId || + _.contains(library.readers, userId) || + _.contains(library.writers, userId) + ) { + return cursor; + } else { + return []; + } }); From 85e3b0724a9855d630920056a921b0ad272299b6 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Mon, 6 May 2019 14:51:58 +0200 Subject: [PATCH 048/247] Added a skip button to the new user experience --- .../character/newUserStepper/newUserStepper.html | 13 ++++++++++++- .../character/newUserStepper/newUserStepper.js | 4 ++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/app/client/views/character/newUserStepper/newUserStepper.html b/app/client/views/character/newUserStepper/newUserStepper.html index e4cce0e4..444817e3 100644 --- a/app/client/views/character/newUserStepper/newUserStepper.html +++ b/app/client/views/character/newUserStepper/newUserStepper.html @@ -4,19 +4,30 @@

To get started, add a feature

+
+ Skip +

Add a racial effect to set your speed

+
+ Skip +

View your speed stat

+
+ Skip +
- Done! If you get stuck, be sure to check out the guide, or ask for help using the feedback form +

+ Done! If you get stuck, be sure to check out the guide, or ask for help using the feedback form +

Finish
diff --git a/app/client/views/character/newUserStepper/newUserStepper.js b/app/client/views/character/newUserStepper/newUserStepper.js index c45acd9a..a11becdb 100644 --- a/app/client/views/character/newUserStepper/newUserStepper.js +++ b/app/client/views/character/newUserStepper/newUserStepper.js @@ -46,6 +46,10 @@ Template.newUserStepper.events({ const stepper = instance.find("paper-stepper"); stepper.continue(); }, + "click .skip-button": function(event, instance){ + const stepper = instance.find("paper-stepper"); + stepper.continue(); + }, }); Template.stats.events({ From b3aeaf06eacfbf7800627b870527eaa8b611f0f5 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Mon, 6 May 2019 14:54:30 +0200 Subject: [PATCH 049/247] Fixed an error when deleting categories from library items without any settings --- app/client/views/character/inventory/inventory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/client/views/character/inventory/inventory.js b/app/client/views/character/inventory/inventory.js index 4234ecff..de5c62ab 100644 --- a/app/client/views/character/inventory/inventory.js +++ b/app/client/views/character/inventory/inventory.js @@ -157,7 +157,7 @@ Template.inventory.events({ } // Make the library item into a regular item let item = _.omit(result, "libraryName", "library", "attacks", "effects"); - delete item.settings.category; + if (item.settings && item.settings.category) delete item.settings.category; // Update the item to match library item Items.update(itemId, {$set: item}); // Copy over attacks and effects From e7f3f669dd0e2098203afdf262d7cffeac7fd976 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Mon, 6 May 2019 15:12:54 +0200 Subject: [PATCH 050/247] Fixed an issue where users without user profiles would fail to load their libraries --- app/client/views/library/libraries.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/client/views/library/libraries.js b/app/client/views/library/libraries.js index 28756241..b8dbf11d 100644 --- a/app/client/views/library/libraries.js +++ b/app/client/views/library/libraries.js @@ -9,7 +9,7 @@ Template.libraries.helpers({ {readers: userId}, {writers: userId}, {owner: userId}, - {_id: {$in: subs}} + {_id: {$in: subs || []}} ], }, { sort: {name: 1}, From 0b11595657519c9d074e7522cca77686660989fb Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Mon, 6 May 2019 15:55:45 +0200 Subject: [PATCH 051/247] Fixed an issue where adding items from libraries didn't get all their properties --- .../inventory/itemLibraryDialog/itemLibraryDialog.js | 2 +- app/server/publications/library.js | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.js b/app/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.js index c21a9aba..9df2c381 100644 --- a/app/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.js +++ b/app/client/views/character/inventory/itemLibraryDialog/itemLibraryDialog.js @@ -30,7 +30,7 @@ Template.itemLibraryDialog.onCreated(function(){ if (_.contains(categoryKeys, key)){ handle = librarySubs.subscribe("standardLibraryItems", key); } else { - handle = librarySubs.subscribe("libraryItems", key); + handle = librarySubs.subscribe("fullLibraryItems", key); } this.autorun(() => { this.readyDict.set(key, handle.ready()); diff --git a/app/server/publications/library.js b/app/server/publications/library.js index 94d9df78..a46d58ed 100644 --- a/app/server/publications/library.js +++ b/app/server/publications/library.js @@ -63,6 +63,12 @@ Meteor.publish("libraryItems", function(libraryId){ }); }); +Meteor.publish("fullLibraryItems", function(libraryId){ + return LibraryItems.find({ + library: libraryId + }); +}); + Meteor.publish("libraryItem", function(itemId){ let cursor = LibraryItems.find(itemId); let item = cursor.fetch()[0]; From 0373feb2ea9cdfd348d6a34962be1c72f17ecdca Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Tue, 7 May 2019 09:18:53 +0200 Subject: [PATCH 052/247] Fixed issue where effects in libraries would appear editable to subscribers --- .../views/library/libraryItemDialog/libraryItemDialog.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/client/views/library/libraryItemDialog/libraryItemDialog.js b/app/client/views/library/libraryItemDialog/libraryItemDialog.js index 3f82c681..14e47b78 100644 --- a/app/client/views/library/libraryItemDialog/libraryItemDialog.js +++ b/app/client/views/library/libraryItemDialog/libraryItemDialog.js @@ -66,7 +66,9 @@ Template.libraryItemDialog.helpers({ return Template.instance().subscriptionsReady(); }, cantEdit(){ - let item = LibraryItems.findOne(this.itemId); + // Get itemId from the top level template data regardless of current context + let itemId = Blaze.getData(Template.instance().view).itemId; + let item = LibraryItems.findOne(itemId); if (!item) return; let library = Libraries.findOne(item.library); if (!library) return; From c84342b21a86b0b04990a220f308316dea997532 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Tue, 7 May 2019 09:19:12 +0200 Subject: [PATCH 053/247] Fixed styling of item library dialog on small screens --- .../views/library/libraryItemDialog/library-item-dialog.css | 3 +++ .../views/library/libraryItemDialog/libraryItemDialog.html | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 app/client/views/library/libraryItemDialog/library-item-dialog.css diff --git a/app/client/views/library/libraryItemDialog/library-item-dialog.css b/app/client/views/library/libraryItemDialog/library-item-dialog.css new file mode 100644 index 00000000..9f92db96 --- /dev/null +++ b/app/client/views/library/libraryItemDialog/library-item-dialog.css @@ -0,0 +1,3 @@ +.library-item-dialog paper-input { + min-width: 160px; +} diff --git a/app/client/views/library/libraryItemDialog/libraryItemDialog.html b/app/client/views/library/libraryItemDialog/libraryItemDialog.html index cdb41347..d9551924 100644 --- a/app/client/views/library/libraryItemDialog/libraryItemDialog.html +++ b/app/client/views/library/libraryItemDialog/libraryItemDialog.html @@ -1,5 +1,5 @@ diff --git a/app/client/views/library/library.html b/app/client/views/library/library.html index d5c52035..88e5e1f7 100644 --- a/app/client/views/library/library.html +++ b/app/client/views/library/library.html @@ -8,49 +8,43 @@
{{name}}
- {{#if isTier5}}{{#if canUserEdit}} + {{#if canUserEdit}} - {{/if}}{{/if}} + {{/if}} +
+
+ + + +
+ {{#if canUserSubscribe}} + + + Subscribe + + {{else if canUserUnsubscribe}} + + + Unsubscribe + + {{/if}}
- {{#if isTier5}} -
- - - -
- {{#if canUserSubscribe}} - - - Subscribe - - {{else if canUserUnsubscribe}} - - - Unsubscribe - - {{/if}} -
- {{/if}} - {{#if isTier5}} -
- - {{#each items}} - - -
{{displayName}}
-
-
- {{/each}} -
-
-
- - {{#simpleTooltip}}Add Library Item{{/simpleTooltip}} -
- {{else}} - {{> patronsOnly }} - {{/if}} +
+ + {{#each items}} + + +
{{displayName}}
+
+
+ {{/each}} +
+
+
+ + {{#simpleTooltip}}Add Library Item{{/simpleTooltip}} +
diff --git a/app/client/views/patreon/patronsOnly.html b/app/client/views/patreon/patronsOnly.html deleted file mode 100644 index 27c55c05..00000000 --- a/app/client/views/patreon/patronsOnly.html +++ /dev/null @@ -1,27 +0,0 @@ - diff --git a/app/client/views/user/profile/profile.html b/app/client/views/user/profile/profile.html index c8b455f4..5a8e6a50 100644 --- a/app/client/views/user/profile/profile.html +++ b/app/client/views/user/profile/profile.html @@ -62,28 +62,6 @@ {{/if}} - - - Patreon - - {{#if patreon.accessToken}} - - {{tier}} tier - - - - - - {{else}} - - - - Connect Patreon account - - - - {{/if}} -
{{> atForm state="signIn"}} diff --git a/app/client/views/user/profile/profile.js b/app/client/views/user/profile/profile.js index c0310773..ca64f6ea 100644 --- a/app/client/views/user/profile/profile.js +++ b/app/client/views/user/profile/profile.js @@ -1,6 +1,5 @@ Template.profile.onCreated(function(){ this.showApiKey = new ReactiveVar(false); - this.loadingPatreon = new ReactiveVar(false); }); Template.profile.helpers({ @@ -13,26 +12,6 @@ Template.profile.helpers({ showApiKey: function(){ return Template.instance().showApiKey.get(); }, - patreon: function(){ - let user = Meteor.user(); - return user && user.patreon || {}; - }, - tier: function(){ - let user = Meteor.user(); - if (!user) return; - patreon = user.patreon; - if (!patreon) return; - let entitledCents = patreon.entitledCents || 0; - if (Template.instance().loadingPatreon.get()){ - return "loading..." - } else if (patreon.entitledCentsOverride > entitledCents){ - return `$ ${(patreon.entitledCentsOverride / 100).toFixed(0)} (overridden)`; - } else if (patreon.entitledCents === undefined){ - return "?"; - } else { - return "$" + (patreon.entitledCents / 100).toFixed(0); - } - }, }); Template.profile.events({ @@ -60,10 +39,4 @@ Template.profile.events({ Meteor.call("generateMyApiKey"); instance.showApiKey.set(true); }, - "click .refreshPatreon": function(event, instance){ - instance.loadingPatreon.set(true); - Meteor.call("updateMyPatreonDetails", (error) => { - instance.loadingPatreon.set(false); - }); - }, }); diff --git a/app/package-lock.json b/app/package-lock.json index 3b66b36c..13229539 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -1,8 +1,2030 @@ { "name": "dicecloud", "version": "0.10.0", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "name": "dicecloud", + "version": "0.10.0", + "hasInstallScript": true, + "dependencies": { + "@babel/runtime": "^7.9.2", + "@polymer/polymer": "^1.2.5-npm-test.2", + "bcrypt": "^5.0.0", + "bower": "^1.8.8", + "core-js": "^2.6.11", + "file-saver": "^2.0.2", + "meteor-node-stubs": "^0.3.3", + "qrcode": "^1.4.4", + "request": "^2.88.2", + "source-map-support": "^0.5.19", + "underscore": "^1.10.2" + }, + "engines": { + "node": "12", + "npm": "6" + } + }, + "node_modules/@babel/runtime": { + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", + "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==", + "dependencies": { + "regenerator-runtime": "^0.13.4" + } + }, + "node_modules/@polymer/polymer": { + "version": "1.2.5-npm-test.2", + "resolved": "https://registry.npmjs.org/@polymer/polymer/-/polymer-1.2.5-npm-test.2.tgz", + "integrity": "sha1-eTD1ZjwvaGkVRR0hHmY6qZl9czY=", + "dependencies": { + "webcomponents.js": "^0.7.20" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/ajv": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", + "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "engines": { + "node": ">=6" + } + }, + "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==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", + "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==" + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "node_modules/bcrypt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.0.tgz", + "integrity": "sha512-jB0yCBl4W/kVHM2whjfyqnxTmOHkCX4kHEa5nYKSoGeYe8YrjTYTc87/6bwt1g8cmV0QrbhKriETg9jWtcREhg==", + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^3.0.0", + "node-pre-gyp": "0.15.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bower": { + "version": "1.8.8", + "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.8.tgz", + "integrity": "sha512-1SrJnXnkP9soITHptSO+ahx3QKp3cVzn8poI6ujqc5SeOkg5iqM1pK9H+DSc2OQ8SnO0jC/NG4Ur/UIwy7574A==", + "bin": { + "bower": "bin/bower" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz", + "integrity": "sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "node_modules/core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", + "hasInstallScript": true + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dijkstrajs": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.1.tgz", + "integrity": "sha1-082BIh4+pAdCz83lVtTpnpjdxxs=" + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/file-saver": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz", + "integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw==" + }, + "node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dependencies": { + "minipass": "^2.6.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/gauge/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dependencies": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "dependencies": { + "minimatch": "^3.0.4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "engines": { + "node": "*" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "node_modules/json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "node_modules/jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/meteor-node-stubs": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/meteor-node-stubs/-/meteor-node-stubs-0.3.3.tgz", + "integrity": "sha512-TI1aQRK0vqs94OCkUMkmf5lXNWfIsjSaEDP1inUuwRGt9w8/S2V+HdRikz9r1k/gew+7NcJieaqHsHX7pSTEgA==", + "dependencies": { + "assert": "^1.4.1", + "browserify-zlib": "^0.1.4", + "buffer": "^4.9.1", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.7", + "events": "^1.1.1", + "https-browserify": "0.0.1", + "os-browserify": "^0.2.1", + "path-browserify": "0.0.0", + "process": "^0.11.9", + "punycode": "^1.4.1", + "querystring-es3": "^0.2.1", + "readable-stream": "git+https://github.com/meteor/readable-stream.git", + "stream-browserify": "^2.0.1", + "stream-http": "^2.8.0", + "string_decoder": "^1.1.0", + "timers-browserify": "^1.4.2", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.10.3", + "vm-browserify": "0.0.4" + } + }, + "node_modules/meteor-node-stubs/node_modules/asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dependencies": { + "util": "0.10.3" + } + }, + "node_modules/meteor-node-stubs/node_modules/base64-js": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.3.tgz", + "integrity": "sha512-MsAhsUW1GxCdgYSO6tAfZrNapmUKk7mWx/k5mFY/A1gBtkaCaNapTg+FExCw1r9yeaZhqx/xPg43xgTFH6KL5w==" + }, + "node_modules/meteor-node-stubs/node_modules/bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + }, + "node_modules/meteor-node-stubs/node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "node_modules/meteor-node-stubs/node_modules/browserify-aes": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", + "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==", + "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.0", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", + "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", + "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.0", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", + "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/meteor-node-stubs/node_modules/browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dependencies": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/meteor-node-stubs/node_modules/browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dependencies": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dependencies": { + "pako": "~0.2.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" + }, + "node_modules/meteor-node-stubs/node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" + }, + "node_modules/meteor-node-stubs/node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/meteor-node-stubs/node_modules/console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dependencies": { + "date-now": "^0.1.4" + } + }, + "node_modules/meteor-node-stubs/node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" + }, + "node_modules/meteor-node-stubs/node_modules/create-ecdh": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", + "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "sha.js": "^2.4.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/create-hmac": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", + "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", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "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/date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" + }, + "node_modules/meteor-node-stubs/node_modules/des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/diffie-hellman": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", + "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "engines": { + "node": ">=0.4", + "npm": ">=1.2" + } + }, + "node_modules/meteor-node-stubs/node_modules/elliptic": { + "version": "6.4.0", + "dependencies": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/meteor-node-stubs/node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/meteor-node-stubs/node_modules/hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", + "dependencies": { + "inherits": "^2.0.1" + } + }, + "node_modules/meteor-node-stubs/node_modules/hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/hash.js/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "node_modules/meteor-node-stubs/node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "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": "0.0.1", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", + "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=" + }, + "node_modules/meteor-node-stubs/node_modules/ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" + }, + "node_modules/meteor-node-stubs/node_modules/indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" + }, + "node_modules/meteor-node-stubs/node_modules/inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "node_modules/meteor-node-stubs/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/meteor-node-stubs/node_modules/md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/meteor-node-stubs/node_modules/md5.js/node_modules/hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/meteor-node-stubs/node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/meteor-node-stubs/node_modules/minimalistic-assert": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=" + }, + "node_modules/meteor-node-stubs/node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "node_modules/meteor-node-stubs/node_modules/os-browserify": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", + "integrity": "sha1-Y/xMzuXS13Y9Jrv4YBB45sLgBE8=" + }, + "node_modules/meteor-node-stubs/node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=" + }, + "node_modules/meteor-node-stubs/node_modules/parse-asn1": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", + "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", + "dependencies": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3" + } + }, + "node_modules/meteor-node-stubs/node_modules/path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=" + }, + "node_modules/meteor-node-stubs/node_modules/pbkdf2": { + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", + "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", + "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", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "node_modules/meteor-node-stubs/node_modules/public-encrypt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", + "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", + "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" + } + }, + "node_modules/meteor-node-stubs/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "node_modules/meteor-node-stubs/node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/meteor-node-stubs/node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/meteor-node-stubs/node_modules/randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/readable-stream": { + "resolved": "git+ssh://git@github.com/meteor/readable-stream.git#c688cdd193549919b840e8d72a86682d91961e12", + "dependencies": { + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.0", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/meteor-node-stubs/node_modules/readable-stream/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "node_modules/meteor-node-stubs/node_modules/ripemd160": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", + "dependencies": { + "hash-base": "^2.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/meteor-node-stubs/node_modules/safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "node_modules/meteor-node-stubs/node_modules/sha.js": { + "version": "2.4.10", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz", + "integrity": "sha512-vnwmrFDlOExK4Nm16J2KMWHLrp14lBrjxMxBJpu++EnsuBmpiYaM/MEs46Vxxm/4FvdP5yTwuCTO9it5FSjrqA==", + "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": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dependencies": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "node_modules/meteor-node-stubs/node_modules/stream-http": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", + "integrity": "sha512-sZOFxI/5xw058XIRHl4dU3dZ+TTOIGJR78Dvo0oEAejIt4ou27k+3ne1zYmCV+v7UucbxIFQuOgnkTVHh8YPnw==", + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.3", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/string_decoder": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.0.tgz", + "integrity": "sha512-8zQpRF6juocE69ae7CSPmYEGJe4VCXwP6S6dxUWI7i53Gwv54/ec41fiUA+X7BPGGv7fRSQJjBQVa0gomGaOgg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "dependencies": { + "process": "~0.11.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" + }, + "node_modules/meteor-node-stubs/node_modules/tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" + }, + "node_modules/meteor-node-stubs/node_modules/url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/meteor-node-stubs/node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "node_modules/meteor-node-stubs/node_modules/util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dependencies": { + "inherits": "2.0.1" + } + }, + "node_modules/meteor-node-stubs/node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/meteor-node-stubs/node_modules/vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dependencies": { + "indexof": "0.0.1" + } + }, + "node_modules/meteor-node-stubs/node_modules/xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/mime-db": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "dependencies": { + "mime-db": "1.43.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dependencies": { + "minipass": "^2.9.0" + } + }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "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==" + }, + "node_modules/needle": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz", + "integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==", + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/node-addon-api": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.0.2.tgz", + "integrity": "sha512-+D4s2HCnxPd5PjjI0STKwncjXTUKKqm74MDMz9OPXavjsGmjkvwgLtA5yoxJUdmpj52+2u+RrXgPipahKczMKg==" + }, + "node_modules/node-pre-gyp": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.15.0.tgz", + "integrity": "sha512-7QcZa8/fpaU/BKenjcaeFF9hLz2+7S9AqyXFhlH/rilsQ/hPZKK32RtR5EQHJElgu+q5RfbJ34KriI79UWaorA==", + "dependencies": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.3", + "needle": "^2.5.0", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "dependencies": { + "abbrev": "1", + "osenv": "^0.1.4" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "dependencies": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + }, + "node_modules/npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "dependencies": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "node_modules/p-limit": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", + "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "node_modules/pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/psl": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", + "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==" + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qrcode": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.4.4.tgz", + "integrity": "sha512-oLzEC5+NKFou9P0bMj5+v6Z40evexeE29Z9cummZXZ9QXyMr3lphkURzxjXgPJC5azpxcshoDWV1xE46z+/c3Q==", + "dependencies": { + "buffer": "^5.4.3", + "buffer-alloc": "^1.2.0", + "buffer-from": "^1.1.1", + "dijkstrajs": "^1.0.1", + "isarray": "^2.0.1", + "pngjs": "^3.3.0", + "yargs": "^13.2.4" + }, + "bin": { + "qrcode": "bin/qrcode" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/regenerator-runtime": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==" + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "dependencies": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + }, + "engines": { + "node": ">=4.5" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "node_modules/underscore": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", + "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==" + }, + "node_modules/uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/webcomponents.js": { + "version": "0.7.24", + "resolved": "https://registry.npmjs.org/webcomponents.js/-/webcomponents.js-0.7.24.tgz", + "integrity": "sha1-IRb7+hRo7EFqe+/aozPh0Rj2nAQ=" + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/wide-align/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + }, + "node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + }, "dependencies": { "@babel/runtime": { "version": "7.9.2", @@ -296,14 +2318,6 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, - "encoding": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", - "requires": { - "iconv-lite": "~0.4.13" - } - }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -352,11 +2366,6 @@ "mime-types": "^2.1.12" } }, - "form-urlencoded": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/form-urlencoded/-/form-urlencoded-2.0.9.tgz", - "integrity": "sha512-fWUzNiOnYa126vFAT6TFXd1mhJrvD8IqmQ9ilZPjkLYQfaRreBr5fIUoOpPlWtqaAG64nzoE7u5zSetifab9IA==" - }, "fs-minipass": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", @@ -518,19 +2527,6 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "requires": { - "isobject": "^3.0.1" - } - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" - }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -541,20 +2537,6 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "isomorphic-fetch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", - "requires": { - "node-fetch": "^1.0.1", - "whatwg-fetch": ">=0.10.0" - } - }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -580,11 +2562,6 @@ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, - "jsonapi-datastore": { - "version": "0.4.0-beta", - "resolved": "https://registry.npmjs.org/jsonapi-datastore/-/jsonapi-datastore-0.4.0-beta.tgz", - "integrity": "sha1-tJn86STUXivDxheGgVIAY+I2HxA=" - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -653,11 +2630,6 @@ "util": "0.10.3" } }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, "base64-js": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.3.tgz", @@ -668,15 +2640,6 @@ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", @@ -775,11 +2738,6 @@ "safe-buffer": "^5.0.1" } }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, "console-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", @@ -875,7 +2833,6 @@ }, "elliptic": { "version": "6.4.0", - "resolved": "", "requires": { "bn.js": "^4.4.0", "brorand": "^1.0.1", @@ -900,24 +2857,6 @@ "safe-buffer": "^5.1.1" } }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, "hash-base": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", @@ -967,15 +2906,6 @@ "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "inherits": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", @@ -1025,22 +2955,6 @@ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, "os-browserify": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", @@ -1068,11 +2982,6 @@ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=" }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, "pbkdf2": { "version": "3.0.14", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", @@ -1140,8 +3049,8 @@ } }, "readable-stream": { - "version": "git+https://github.com/meteor/readable-stream.git#c688cdd193549919b840e8d72a86682d91961e12", - "from": "git+https://github.com/meteor/readable-stream.git", + "version": "git+ssh://git@github.com/meteor/readable-stream.git#c688cdd193549919b840e8d72a86682d91961e12", + "from": "readable-stream@git+https://github.com/meteor/readable-stream.git", "requires": { "inherits": "~2.0.3", "isarray": "~1.0.0", @@ -1158,14 +3067,6 @@ } } }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "requires": { - "glob": "^7.0.5" - } - }, "ripemd160": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", @@ -1273,11 +3174,6 @@ "indexof": "0.0.1" } }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", @@ -1356,15 +3252,6 @@ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.0.2.tgz", "integrity": "sha512-+D4s2HCnxPd5PjjI0STKwncjXTUKKqm74MDMz9OPXavjsGmjkvwgLtA5yoxJUdmpj52+2u+RrXgPipahKczMKg==" }, - "node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "requires": { - "encoding": "^0.1.11", - "is-stream": "^1.0.1" - } - }, "node-pre-gyp": { "version": "0.15.0", "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.15.0.tgz", @@ -1498,17 +3385,6 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, - "patreon": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/patreon/-/patreon-0.4.1.tgz", - "integrity": "sha512-aLhjx4rg2BArTq0Kg61MrM4dkJnTQ9kPN8F6a2IlQoYVEtIH7kUK/dprClTx+QYQKlXMfKksN9NCux1YarQJsQ==", - "requires": { - "form-urlencoded": "^2.0.4", - "is-plain-object": "^2.0.4", - "isomorphic-fetch": "^2.2.1", - "jsonapi-datastore": "^0.4.0-beta" - } - }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -1662,7 +3538,6 @@ }, "set-blocking": { "version": "2.0.0", - "resolved": false, "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "signal-exit": { @@ -1700,16 +3575,6 @@ "tweetnacl": "~0.14.0" } }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -1725,6 +3590,16 @@ } } }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -1812,11 +3687,6 @@ "resolved": "https://registry.npmjs.org/webcomponents.js/-/webcomponents.js-0.7.24.tgz", "integrity": "sha1-IRb7+hRo7EFqe+/aozPh0Rj2nAQ=" }, - "whatwg-fetch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", - "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" - }, "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", diff --git a/app/package.json b/app/package.json index 476ce919..90122f08 100644 --- a/app/package.json +++ b/app/package.json @@ -18,7 +18,6 @@ "core-js": "^2.6.11", "file-saver": "^2.0.2", "meteor-node-stubs": "^0.3.3", - "patreon": "^0.4.1", "qrcode": "^1.4.4", "request": "^2.88.2", "source-map-support": "^0.5.19", diff --git a/app/server/patreon/patreon.js b/app/server/patreon/patreon.js deleted file mode 100644 index 3044873d..00000000 --- a/app/server/patreon/patreon.js +++ /dev/null @@ -1,271 +0,0 @@ -import request from 'request'; - -if ( - Meteor.settings && - Meteor.settings.public && - Meteor.settings.public.patreon -) { - const CLIENT_ID = Meteor.settings.public.patreon.clientId; - const CLIENT_SECRET = Meteor.settings.patreon.clientSecret; - const CREATOR_ACCESS_TOKEN = Meteor.settings.patreon.creatorAccessToken; - const CAMPAIGN_ID = Meteor.settings.public.patreon.campaignId; - - // Handle redirects from patreon - Router.map(function () { - this.route("patreon-redirect", { - path: "/patreon-redirect", - where: "server", - action: function () { - let route = this; - let userId = route.params.query.state; - let singleUseCode = route.params.query.code; - requestToken(singleUseCode, Meteor.bindEnvironment((error, response, body) => { - // Should return an access token, valid for 1 month, which needs to be - // stored and used to make requests on behalf of the user - if (error){ - writePatreonError(userId, error); - return; - } - let token; - try { - token = JSON.parse(body); - writePatreonToken(userId, token); - } catch(error) { - writePatreonError(userId, error); - return; - } - updateIdentity(token.access_token, userId); - })); - route.response.writeHead(302, { - 'Location': Meteor.absoluteUrl() + "account", - }); - route.response.end(); - }, - }); - }); - - const requestToken = function(singleUseCode, callback){ - request({ - method: "POST", - uri: "https://www.patreon.com/api/oauth2/token", - headers: { - "Content-Type": "application/x-www-form-urlencoded", - }, - qs: { - code: singleUseCode, - grant_type: "authorization_code", - client_id: CLIENT_ID, - client_secret: CLIENT_SECRET, - redirect_uri: Meteor.absoluteUrl() + 'patreon-redirect', - }, - }, callback); - } - - const getIdentity = function(accessToken, callback){ - request({ - uri: "https://www.patreon.com/api/oauth2/v2/identity", - headers:{ - Authorization: "Bearer " + accessToken, - }, - qs: { - 'include': 'memberships.currently_entitled_tiers', - 'fields[tier]': 'amount_cents,title', - } - }, callback); - }; - - // Should return a new access token for the user - // callback is called with (error, response, body) - const refreshAccessToken = Meteor.wrapAsync(function(refreshToken, userId, callback){ - request({ - method: "POST", - uri: "https://www.patreon.com/api/oauth2/token", - qs: { - grant_type: "refresh_token", - refresh_token: refreshToken, - client_id: CLIENT_ID, - client_secret: CLIENT_SECRET, - } - }, Meteor.bindEnvironment((error, response, body) => { - // Should return an access token, valid for 1 month, which needs to be - // stored and used to make requests on behalf of the user - if (error){ - callback(error) - return; - } - let token; - try { - token = JSON.parse(body); - writePatreonToken(userId, token); - callback(undefined, token.access_token); - } catch(error) { - callback(error); - } - })); - }); - - const updateIdentity = Meteor.wrapAsync(function(accessToken, userId, callback){ - getIdentity(accessToken, Meteor.bindEnvironment((error, response, body) => { - if (error){ - writePatreonError(userId, error); - return; - } - try { - let identity = JSON.parse(body); - let entitledAmount = 0; - if (identity && identity.included){ - identity.included.forEach(doc => { - if ( - doc.type === 'tier' && - doc.attributes && - doc.attributes.amount_cents > entitledAmount - ){ - entitledAmount = doc.attributes.amount_cents; - } - }); - } - let patreonUserId = identity.data.id; - writeEntitledCentsAndId(userId, entitledAmount, patreonUserId); - if (callback) callback(); - } catch(error) { - writePatreonError(userId, error); - if(callback) callback(error); - } - })); - }); - - Meteor.methods({ - updateMyPatreonDetails(){ - const userId = this.userId; - if (!userId) throw new Meteor.Error("not-logged-in", "You must be logged in to update Patreon details"); - const user = Meteor.users.findOne(userId, {fields: {patreon: 1}}); - Meteor.users.update(userId, {$unset: {"patreon.entitledCents": 1}}); - if (!user.patreon || !user.patreon.accessToken){ - throw new Meteor.Error("no-patreon-access", "Patreon access token not found for this user"); - } - let accessToken = user.patreon.accessToken; - if (user.patreon.tokenExpiryDate < new Date()){ - // Token expired, refresh it before continuing - accessToken = refreshAccessToken(user.patreon.refreshToken, userId); - } - updateIdentity(accessToken, userId); - }, - }); - - const writePatreonToken = function(userId, { - access_token, refresh_token, expires_in - }){ - // The expiry date is now plus `expires_in` seconds - let expiryDate = new Date(); - expiryDate.setSeconds(expiryDate.getSeconds() + expires_in); - // Expire a day early so we don't accidentally miss it - expiryDate.setDate(expiryDate.getDate() - 1); - - // Write - Meteor.users.update(userId, { - $set: { - "patreon.accessToken": access_token, - "patreon.refreshToken": refresh_token, - "patreon.tokenExpiryDate": expiryDate, - }, - $unset: { - "patreon.error": 1, - }, - }); - }; - - const writeEntitledCentsAndId = function(userId, amount, patreonUserId){ - Meteor.users.update(userId, { - $set: { - "patreon.entitledCents": amount, - "patreon.userId": patreonUserId, - }, - $unset: { - "patreon.error": 1, - }, - }); - }; - - const writePatreonError = function(userId, error){ - console.error({patreonError: error}); - Meteor.users.update(userId, { - $set: { - "patreon.error": error.toString(), - }, - }); - } - - - const requestMembers = Meteor.wrapAsync(function(cursor, members, callback){ - request({ - uri: `https://www.patreon.com/api/oauth2/v2/campaigns/${CAMPAIGN_ID}/members`, - headers:{ - Authorization: "Bearer " + CREATOR_ACCESS_TOKEN, - }, - qs: { - "include": "user", - "fields[member]": "currently_entitled_amount_cents", - "page[cursor]": cursor, - } - }, (error, reponse, body) => { - if (error){ - callback(error); - return; - } - let json = JSON.parse(body); - if (json.errors) { - callback(json.errors); - return; - } - let newMembers = json.data.map(member => ({ - id: member.relationships.user.data.id, - entitledCents: member.attributes.currently_entitled_amount_cents, - })); - members.push(...newMembers); - let next = json.meta.pagination.cursors && json.meta.pagination.cursors.next; - if (next){ - callback(undefined, next); - } else { - callback(undefined); - } - }); - }); - - const updatePatreonMembersEntitledCents = function(){ - let next = ""; - let members = []; - do { - next = requestMembers(next, members); - } while (next) - members.forEach(({id, entitledCents}) => { - Meteor.users.update({ - "patreon.userId": id - }, {$set: { - "patreon.entitledCents":entitledCents, - }}); - }); - return members; - } - - // Method to run a manual update - Meteor.methods({ - updatePatreonMembersEntitledCents(){ - const user = Meteor.users.findOne(this.userId); - if (!user || !_.contains(user.roles, "admin")) throw new Meteor.Error( - "permission-error", "You need to be logged in as an admin to run this method" - ); - return updatePatreonMembersEntitledCents(); - }, - }); - - // Cron job to run the update automatically - Meteor.startup(() => { - SyncedCron.add({ - name: "updatePatreonMembersEntitledCents", - schedule: function(parser) { - return parser.text('every 4 hours'); - }, - job: updatePatreonMembersEntitledCents, - }); - }) -} diff --git a/app/server/publications/user.js b/app/server/publications/user.js index fc6c9c6a..ab979722 100644 --- a/app/server/publications/user.js +++ b/app/server/publications/user.js @@ -7,7 +7,6 @@ Meteor.publish("user", function(){ apiKey: 1, librarySubscriptions: 1, lastPatreonPostClicked: 1, - patreon: 1, }}), PatreonPosts.find({},{sort: {dateAdded: -1}, limit: 1}) ]; From c0b031f2b5e5d1b73fc1c627b0179972bc5065a1 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Sat, 17 Jul 2021 14:41:51 +0200 Subject: [PATCH 072/247] Updated packages --- app/.meteor/packages | 14 +- app/.meteor/release | 2 +- app/.meteor/versions | 65 +- app/package-lock.json | 2656 ++++++++++++----------------------------- 4 files changed, 812 insertions(+), 1925 deletions(-) diff --git a/app/.meteor/packages b/app/.meteor/packages index 03cb42df..cfba1fa8 100644 --- a/app/.meteor/packages +++ b/app/.meteor/packages @@ -3,8 +3,8 @@ # 'meteor add' and 'meteor remove' will edit this file for you, # but you can also edit it by hand. -accounts-password@1.6.2 -accounts-ui@1.3.1 +accounts-password@1.7.0 +accounts-ui@1.3.2 random@1.2.0 dburles:collection-helpers reactive-var@1.0.11 @@ -25,13 +25,13 @@ chuangbo:marked reywood:iron-router-ga meteor-base@1.4.0 mobile-experience@1.1.0 -mongo@1.10.0 +mongo@1.11.0 blaze-html-templates session@1.2.0 jquery@1.11.10 tracker@1.2.0 -logging@1.1.20 -reload@1.3.0 +logging@1.2.0 +reload@1.3.1 ejson@1.1.1 spacebars check@1.3.1 @@ -40,14 +40,14 @@ shell-server@0.5.0 seba:minifiers-autoprefixer nikogosovd:multiple-uihooks templates:array -ecmascript@0.14.3 +ecmascript@0.15.1 es5-shim@4.8.0 differential:vulcanize reactive-dict@1.3.0 ongoworks:speakingurl service-configuration@1.0.11 google-config-ui@1.0.1 -dynamic-import@0.5.2 +dynamic-import@0.6.0 ddp-rate-limiter@1.0.9 rate-limit@1.0.9 iron:router diff --git a/app/.meteor/release b/app/.meteor/release index 019e3aef..59245ca5 100644 --- a/app/.meteor/release +++ b/app/.meteor/release @@ -1 +1 @@ -METEOR@1.11.1 +METEOR@2.2.1 diff --git a/app/.meteor/versions b/app/.meteor/versions index 4a62292f..d8bee192 100644 --- a/app/.meteor/versions +++ b/app/.meteor/versions @@ -1,26 +1,26 @@ -accounts-base@1.7.0 +accounts-base@1.9.0 accounts-google@1.3.3 accounts-oauth@1.2.0 -accounts-password@1.6.2 -accounts-ui@1.3.1 -accounts-ui-unstyled@1.4.2 +accounts-password@1.7.0 +accounts-ui@1.3.2 +accounts-ui-unstyled@1.4.3 aldeed:collection2@2.10.0 aldeed:collection2-core@1.2.0 aldeed:schema-deny@1.1.0 aldeed:schema-index@1.1.1 aldeed:simple-schema@1.5.4 allow-deny@1.1.0 -autoupdate@1.6.0 -babel-compiler@7.5.3 +autoupdate@1.7.0 +babel-compiler@7.6.1 babel-runtime@1.5.0 base64@1.0.12 binary-heap@1.0.11 -blaze@2.3.4 +blaze@2.4.0 blaze-html-templates@1.1.2 -blaze-tools@1.0.10 +blaze-tools@1.1.0 boilerplate-generator@1.7.1 caching-compiler@1.2.2 -caching-html-compiler@1.1.3 +caching-html-compiler@1.2.0 callback-hook@1.3.0 check@1.3.1 chuangbo:marked@0.3.5_1 @@ -28,15 +28,15 @@ coffeescript@1.0.17 dburles:collection-helpers@1.1.0 dburles:mongo-collection-instances@0.3.5 ddp@1.4.0 -ddp-client@2.3.3 +ddp-client@2.4.0 ddp-common@1.4.0 ddp-rate-limiter@1.0.9 ddp-server@2.3.2 deps@1.0.12 diff-sequence@1.1.1 differential:vulcanize@3.0.0 -dynamic-import@0.5.2 -ecmascript@0.14.3 +dynamic-import@0.6.0 +ecmascript@0.15.1 ecmascript-runtime@0.7.0 ecmascript-runtime-client@0.11.0 ecmascript-runtime-server@0.10.0 @@ -49,8 +49,8 @@ geojson-utils@1.0.10 google-config-ui@1.0.1 google-oauth@1.3.0 hot-code-push@1.0.4 -html-tools@1.0.11 -htmljs@1.0.11 +html-tools@1.1.0 +htmljs@1.1.0 http@1.4.2 id-map@1.1.0 inter-process-messaging@0.1.1 @@ -65,36 +65,36 @@ iron:url@1.1.0 jquery@1.11.11 lai:collection-extensions@0.2.1_1 lamhieu:meteorx@2.1.1 -launch-screen@1.2.0 -less@2.8.0 +launch-screen@1.2.1 +less@3.0.2 littledata:synced-cron@1.5.1 livedata@1.0.18 localstorage@1.2.0 -logging@1.1.20 +logging@1.2.0 matb33:collection-hooks@0.9.1 mdg:validation-error@0.5.1 meteor@1.9.3 meteor-base@1.4.0 meteorhacks:subs-manager@1.6.4 minifier-css@1.5.3 -minimongo@1.6.0 +minimongo@1.6.2 mixmax:smart-disconnect@0.0.4 mobile-experience@1.1.0 mobile-status-bar@1.1.0 modern-browsers@0.1.5 -modules@0.15.0 +modules@0.16.0 modules-runtime@0.12.0 momentjs:moment@2.29.0 -mongo@1.10.0 -mongo-decimal@0.1.1 +mongo@1.11.0 +mongo-decimal@0.1.2 mongo-dev-server@1.1.0 mongo-id@1.0.7 mongo-livedata@1.0.12 montiapm:agent@2.39.0 nikogosovd:multiple-uihooks@0.1.8 npm-bcrypt@0.9.3 -npm-mongo@3.8.1 -oauth@1.3.0 +npm-mongo@3.9.0 +oauth@1.3.2 oauth2@1.3.0 observe-sequence@1.0.16 ongoworks:speakingurl@9.0.0 @@ -104,9 +104,10 @@ promise@0.11.2 raix:eventemitter@0.1.3 random@1.2.0 rate-limit@1.0.9 +react-fast-refresh@0.1.1 reactive-dict@1.3.0 reactive-var@1.0.11 -reload@1.3.0 +reload@1.3.1 retry@1.1.0 reywood:iron-router-ga@0.7.1 routepolicy@1.1.0 @@ -117,16 +118,16 @@ sha@1.0.9 shell-server@0.5.0 socket-stream-client@0.3.1 softwarerero:accounts-t9n@1.3.11 -spacebars@1.0.15 -spacebars-compiler@1.1.3 +spacebars@1.1.0 +spacebars-compiler@1.2.0 splendido:accounts-emails-field@1.2.0 splendido:accounts-meld@1.3.1 srp@1.1.0 templates:array@1.0.3 -templating@1.3.2 -templating-compiler@1.3.3 -templating-runtime@1.3.2 -templating-tools@1.1.2 +templating@1.4.0 +templating-compiler@1.4.0 +templating-runtime@1.4.0 +templating-tools@1.2.0 tracker@1.2.0 ui@1.0.13 underscore@1.0.10 @@ -134,8 +135,8 @@ url@1.3.1 useraccounts:core@1.14.2 useraccounts:iron-routing@1.14.2 useraccounts:polymer@1.14.2 -webapp@1.9.1 -webapp-hashing@1.0.9 +webapp@1.10.1 +webapp-hashing@1.1.0 zimme:collection-behaviours@1.1.3 zimme:collection-softremovable@1.0.5 zodern:meteor-package-versions@0.2.1 diff --git a/app/package-lock.json b/app/package-lock.json index 13229539..cbdf7fdd 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -27,11 +27,33 @@ } }, "node_modules/@babel/runtime": { - "version": "7.9.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", - "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==", + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz", + "integrity": "sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==", "dependencies": { "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz", + "integrity": "sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA==", + "dependencies": { + "detect-libc": "^1.0.3", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.1", + "nopt": "^5.0.0", + "npmlog": "^4.1.2", + "rimraf": "^3.0.2", + "semver": "^7.3.4", + "tar": "^6.1.0" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" } }, "node_modules/@polymer/polymer": { @@ -47,23 +69,38 @@ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, + "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==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/ajv": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", - "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, "node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, "node_modules/ansi-styles": { @@ -121,28 +158,42 @@ } }, "node_modules/aws4": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", - "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==" + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/base64-js": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/bcrypt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.0.tgz", - "integrity": "sha512-jB0yCBl4W/kVHM2whjfyqnxTmOHkCX4kHEa5nYKSoGeYe8YrjTYTc87/6bwt1g8cmV0QrbhKriETg9jWtcREhg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.1.tgz", + "integrity": "sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw==", "hasInstallScript": true, "dependencies": { - "node-addon-api": "^3.0.0", - "node-pre-gyp": "0.15.0" + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^3.1.0" }, "engines": { "node": ">= 10.0.0" @@ -157,9 +208,9 @@ } }, "node_modules/bower": { - "version": "1.8.8", - "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.8.tgz", - "integrity": "sha512-1SrJnXnkP9soITHptSO+ahx3QKp3cVzn8poI6ujqc5SeOkg5iqM1pK9H+DSc2OQ8SnO0jC/NG4Ur/UIwy7574A==", + "version": "1.8.12", + "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.12.tgz", + "integrity": "sha512-u1xy9SrwwoPlgjuHNjhV+YUPVdqyBj2ALBxuzeIUKXaPI2i2xypGgxqXkuHcITGdi5yBj5JuXgyMvgiWiS1S3Q==", "bin": { "bower": "bin/bower" }, @@ -177,12 +228,26 @@ } }, "node_modules/buffer": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz", - "integrity": "sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, "node_modules/buffer-alloc": { @@ -223,9 +288,12 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } }, "node_modules/cliui": { "version": "5.0.0", @@ -237,6 +305,46 @@ "wrap-ansi": "^5.1.0" } }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "engines": { + "node": ">=4" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -280,9 +388,10 @@ "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "node_modules/core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js.", "hasInstallScript": true }, "node_modules/core-util-is": { @@ -302,11 +411,19 @@ } }, "node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dependencies": { - "ms": "^2.1.1" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/decamelize": { @@ -317,14 +434,6 @@ "node": ">=0.10.0" } }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -350,9 +459,9 @@ } }, "node_modules/dijkstrajs": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.1.tgz", - "integrity": "sha1-082BIh4+pAdCz83lVtTpnpjdxxs=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.2.tgz", + "integrity": "sha512-QV6PMaHTCNmKSeP6QoXhVTw9snc9VD8MulTT0Bd99Pacp4SS1cjcrYPgBPmibqKVtMJJfqC6XvOXgPMEEPH/fg==" }, "node_modules/ecc-jsbn": { "version": "0.1.2", @@ -382,9 +491,9 @@ ] }, "node_modules/fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", @@ -392,9 +501,9 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "node_modules/file-saver": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz", - "integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" }, "node_modules/find-up": { "version": "3.0.0", @@ -429,11 +538,14 @@ } }, "node_modules/fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dependencies": { - "minipass": "^2.6.0" + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" } }, "node_modules/fs.realpath": { @@ -456,49 +568,6 @@ "wide-align": "^1.1.0" } }, - "node_modules/gauge/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gauge/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gauge/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gauge/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -516,9 +585,9 @@ } }, "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -529,6 +598,9 @@ }, "engines": { "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/har-schema": { @@ -540,11 +612,12 @@ } }, "node_modules/har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", "dependencies": { - "ajv": "^6.5.5", + "ajv": "^6.12.3", "har-schema": "^2.0.0" }, "engines": { @@ -570,29 +643,36 @@ "npm": ">=1.3.7" } }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "agent-base": "6", + "debug": "4" }, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, "node_modules/ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" - }, - "node_modules/ignore-walk": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", - "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", - "dependencies": { - "minimatch": "^3.0.4" - } + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/inflight": { "version": "1.0.6", @@ -608,20 +688,15 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "node_modules/ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "engines": { - "node": "*" - } - }, "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dependencies": { + "number-is-nan": "^1.0.0" + }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, "node_modules/is-typedarray": { @@ -685,10 +760,69 @@ "node": ">=6" } }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/meteor-node-stubs": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/meteor-node-stubs/-/meteor-node-stubs-0.3.3.tgz", "integrity": "sha512-TI1aQRK0vqs94OCkUMkmf5lXNWfIsjSaEDP1inUuwRGt9w8/S2V+HdRikz9r1k/gew+7NcJieaqHsHX7pSTEgA==", + "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" + ], + "hasShrinkwrap": true, "dependencies": { "assert": "^1.4.1", "browserify-zlib": "^0.1.4", @@ -715,615 +849,20 @@ "vm-browserify": "0.0.4" } }, - "node_modules/meteor-node-stubs/node_modules/asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/meteor-node-stubs/node_modules/assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", - "dependencies": { - "util": "0.10.3" - } - }, - "node_modules/meteor-node-stubs/node_modules/base64-js": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.3.tgz", - "integrity": "sha512-MsAhsUW1GxCdgYSO6tAfZrNapmUKk7mWx/k5mFY/A1gBtkaCaNapTg+FExCw1r9yeaZhqx/xPg43xgTFH6KL5w==" - }, - "node_modules/meteor-node-stubs/node_modules/bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" - }, - "node_modules/meteor-node-stubs/node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" - }, - "node_modules/meteor-node-stubs/node_modules/browserify-aes": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", - "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==", - "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.0", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", - "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", - "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.0", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", - "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", - "dependencies": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/meteor-node-stubs/node_modules/browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dependencies": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" - } - }, - "node_modules/meteor-node-stubs/node_modules/browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dependencies": { - "bn.js": "^4.1.1", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", - "inherits": "^2.0.1", - "parse-asn1": "^5.0.0" - } - }, - "node_modules/meteor-node-stubs/node_modules/browserify-zlib": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", - "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", - "dependencies": { - "pako": "~0.2.0" - } - }, - "node_modules/meteor-node-stubs/node_modules/buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "node_modules/meteor-node-stubs/node_modules/buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" - }, - "node_modules/meteor-node-stubs/node_modules/builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" - }, - "node_modules/meteor-node-stubs/node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/meteor-node-stubs/node_modules/console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dependencies": { - "date-now": "^0.1.4" - } - }, - "node_modules/meteor-node-stubs/node_modules/constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" - }, - "node_modules/meteor-node-stubs/node_modules/create-ecdh": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", - "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", - "dependencies": { - "bn.js": "^4.1.0", - "elliptic": "^6.0.0" - } - }, - "node_modules/meteor-node-stubs/node_modules/create-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "sha.js": "^2.4.0" - } - }, - "node_modules/meteor-node-stubs/node_modules/create-hmac": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", - "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", - "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", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "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/date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" - }, - "node_modules/meteor-node-stubs/node_modules/des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dependencies": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/meteor-node-stubs/node_modules/diffie-hellman": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", - "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", - "dependencies": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "node_modules/meteor-node-stubs/node_modules/domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "engines": { - "node": ">=0.4", - "npm": ">=1.2" - } - }, - "node_modules/meteor-node-stubs/node_modules/elliptic": { - "version": "6.4.0", - "dependencies": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - } - }, - "node_modules/meteor-node-stubs/node_modules/events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/meteor-node-stubs/node_modules/evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/meteor-node-stubs/node_modules/hash-base": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", - "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", - "dependencies": { - "inherits": "^2.0.1" - } - }, - "node_modules/meteor-node-stubs/node_modules/hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/meteor-node-stubs/node_modules/hash.js/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "node_modules/meteor-node-stubs/node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "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": "0.0.1", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", - "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=" - }, - "node_modules/meteor-node-stubs/node_modules/ieee754": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", - "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" - }, - "node_modules/meteor-node-stubs/node_modules/indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" - }, - "node_modules/meteor-node-stubs/node_modules/inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" - }, - "node_modules/meteor-node-stubs/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "node_modules/meteor-node-stubs/node_modules/md5.js": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", - "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/meteor-node-stubs/node_modules/md5.js/node_modules/hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/meteor-node-stubs/node_modules/miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dependencies": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "bin": { - "miller-rabin": "bin/miller-rabin" - } - }, - "node_modules/meteor-node-stubs/node_modules/minimalistic-assert": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", - "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=" - }, - "node_modules/meteor-node-stubs/node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" - }, - "node_modules/meteor-node-stubs/node_modules/os-browserify": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", - "integrity": "sha1-Y/xMzuXS13Y9Jrv4YBB45sLgBE8=" - }, - "node_modules/meteor-node-stubs/node_modules/pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=" - }, - "node_modules/meteor-node-stubs/node_modules/parse-asn1": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", - "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", - "dependencies": { - "asn1.js": "^4.0.0", - "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3" - } - }, - "node_modules/meteor-node-stubs/node_modules/path-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=" - }, - "node_modules/meteor-node-stubs/node_modules/pbkdf2": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", - "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", - "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", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/meteor-node-stubs/node_modules/process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" - }, - "node_modules/meteor-node-stubs/node_modules/public-encrypt": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", - "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", - "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" - } - }, - "node_modules/meteor-node-stubs/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "node_modules/meteor-node-stubs/node_modules/querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/meteor-node-stubs/node_modules/querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/meteor-node-stubs/node_modules/randombytes": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/meteor-node-stubs/node_modules/randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dependencies": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "node_modules/meteor-node-stubs/node_modules/readable-stream": { - "resolved": "git+ssh://git@github.com/meteor/readable-stream.git#c688cdd193549919b840e8d72a86682d91961e12", - "dependencies": { - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.0", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/meteor-node-stubs/node_modules/readable-stream/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "node_modules/meteor-node-stubs/node_modules/ripemd160": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", - "dependencies": { - "hash-base": "^2.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/meteor-node-stubs/node_modules/safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" - }, - "node_modules/meteor-node-stubs/node_modules/sha.js": { - "version": "2.4.10", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz", - "integrity": "sha512-vnwmrFDlOExK4Nm16J2KMWHLrp14lBrjxMxBJpu++EnsuBmpiYaM/MEs46Vxxm/4FvdP5yTwuCTO9it5FSjrqA==", - "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": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", - "dependencies": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "node_modules/meteor-node-stubs/node_modules/stream-http": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", - "integrity": "sha512-sZOFxI/5xw058XIRHl4dU3dZ+TTOIGJR78Dvo0oEAejIt4ou27k+3ne1zYmCV+v7UucbxIFQuOgnkTVHh8YPnw==", - "dependencies": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.3", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } - }, - "node_modules/meteor-node-stubs/node_modules/string_decoder": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.0.tgz", - "integrity": "sha512-8zQpRF6juocE69ae7CSPmYEGJe4VCXwP6S6dxUWI7i53Gwv54/ec41fiUA+X7BPGGv7fRSQJjBQVa0gomGaOgg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/meteor-node-stubs/node_modules/timers-browserify": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", - "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", - "dependencies": { - "process": "~0.11.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/meteor-node-stubs/node_modules/to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" - }, - "node_modules/meteor-node-stubs/node_modules/tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" - }, - "node_modules/meteor-node-stubs/node_modules/url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" - } - }, - "node_modules/meteor-node-stubs/node_modules/url/node_modules/punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" - }, - "node_modules/meteor-node-stubs/node_modules/util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dependencies": { - "inherits": "2.0.1" - } - }, - "node_modules/meteor-node-stubs/node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "node_modules/meteor-node-stubs/node_modules/vm-browserify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dependencies": { - "indexof": "0.0.1" - } - }, - "node_modules/meteor-node-stubs/node_modules/xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "engines": { - "node": ">=0.4" - } - }, "node_modules/mime-db": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", - "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", + "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.26", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", - "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "version": "2.1.31", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", + "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", "dependencies": { - "mime-db": "1.43.0" + "mime-db": "1.48.0" }, "engines": { "node": ">= 0.6" @@ -1340,37 +879,38 @@ "node": "*" } }, - "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, "node_modules/minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", "dependencies": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dependencies": { - "minipass": "^2.9.0" + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" } }, "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dependencies": { - "minimist": "^1.2.5" - }, + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "bin": { "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/ms": { @@ -1378,80 +918,31 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, - "node_modules/needle": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz", - "integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==", - "dependencies": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - }, - "bin": { - "needle": "bin/needle" - }, - "engines": { - "node": ">= 4.4.x" - } - }, "node_modules/node-addon-api": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.0.2.tgz", - "integrity": "sha512-+D4s2HCnxPd5PjjI0STKwncjXTUKKqm74MDMz9OPXavjsGmjkvwgLtA5yoxJUdmpj52+2u+RrXgPipahKczMKg==" + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" }, - "node_modules/node-pre-gyp": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.15.0.tgz", - "integrity": "sha512-7QcZa8/fpaU/BKenjcaeFF9hLz2+7S9AqyXFhlH/rilsQ/hPZKK32RtR5EQHJElgu+q5RfbJ34KriI79UWaorA==", - "dependencies": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.3", - "needle": "^2.5.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4.4.2" - }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" + "node_modules/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "engines": { + "node": "4.x || >=6.0.0" } }, "node_modules/nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", "dependencies": { - "abbrev": "1", - "osenv": "^0.1.4" + "abbrev": "1" }, "bin": { "nopt": "bin/nopt.js" - } - }, - "node_modules/npm-bundled": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", - "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", - "dependencies": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "node_modules/npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" - }, - "node_modules/npm-packlist": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", - "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", - "dependencies": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" + }, + "engines": { + "node": ">=6" } }, "node_modules/npmlog": { @@ -1497,40 +988,18 @@ "wrappy": "1" } }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dependencies": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, "node_modules/p-limit": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", - "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dependencies": { "p-try": "^2.0.0" }, "engines": { "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { @@ -1587,9 +1056,9 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "node_modules/psl": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", - "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" }, "node_modules/punycode": { "version": "2.1.1", @@ -1627,20 +1096,6 @@ "node": ">=0.6" } }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, "node_modules/readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -1660,20 +1115,16 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, "node_modules/regenerator-runtime": { - "version": "0.13.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", - "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==" + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" }, "node_modules/request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", "dependencies": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -1714,41 +1165,46 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { - "semver": "bin/semver" + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/set-blocking": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "node_modules/signal-exit": { @@ -1800,58 +1256,44 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, "node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, "node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dependencies": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^2.0.0" }, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "engines": { "node": ">=0.10.0" } }, "node_modules/tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", + "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", "dependencies": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" }, "engines": { - "node": ">=4.5" + "node": ">= 10" } }, "node_modules/tough-cookie": { @@ -1883,14 +1325,14 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, "node_modules/underscore": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", - "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==" + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", + "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==" }, "node_modules/uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dependencies": { "punycode": "^2.1.0" } @@ -1904,6 +1346,7 @@ "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", "bin": { "uuid": "bin/uuid" } @@ -1939,37 +1382,6 @@ "string-width": "^1.0.2 || 2" } }, - "node_modules/wide-align/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/wrap-ansi": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", @@ -1983,25 +1395,65 @@ "node": ">=6" } }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "engines": { + "node": ">=4" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "node_modules/y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" }, "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "dependencies": { "cliui": "^5.0.0", "find-up": "^3.0.0", @@ -2012,7 +1464,7 @@ "string-width": "^3.0.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" + "yargs-parser": "^13.1.2" } }, "node_modules/yargs-parser": { @@ -2023,17 +1475,73 @@ "camelcase": "^5.0.0", "decamelize": "^1.2.0" } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "engines": { + "node": ">=4" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } } }, "dependencies": { "@babel/runtime": { - "version": "7.9.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", - "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==", + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz", + "integrity": "sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==", "requires": { "regenerator-runtime": "^0.13.4" } }, + "@mapbox/node-pre-gyp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz", + "integrity": "sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA==", + "requires": { + "detect-libc": "^1.0.3", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.1", + "nopt": "^5.0.0", + "npmlog": "^4.1.2", + "rimraf": "^3.0.2", + "semver": "^7.3.4", + "tar": "^6.1.0" + } + }, "@polymer/polymer": { "version": "1.2.5-npm-test.2", "resolved": "https://registry.npmjs.org/@polymer/polymer/-/polymer-1.2.5-npm-test.2.tgz", @@ -2047,10 +1555,18 @@ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, + "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==", + "requires": { + "debug": "4" + } + }, "ajv": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", - "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2059,9 +1575,9 @@ } }, "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { "version": "3.2.1", @@ -2109,27 +1625,27 @@ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", - "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==" + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "base64-js": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, "bcrypt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.0.tgz", - "integrity": "sha512-jB0yCBl4W/kVHM2whjfyqnxTmOHkCX4kHEa5nYKSoGeYe8YrjTYTc87/6bwt1g8cmV0QrbhKriETg9jWtcREhg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.1.tgz", + "integrity": "sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw==", "requires": { - "node-addon-api": "^3.0.0", - "node-pre-gyp": "0.15.0" + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^3.1.0" } }, "bcrypt-pbkdf": { @@ -2141,9 +1657,9 @@ } }, "bower": { - "version": "1.8.8", - "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.8.tgz", - "integrity": "sha512-1SrJnXnkP9soITHptSO+ahx3QKp3cVzn8poI6ujqc5SeOkg5iqM1pK9H+DSc2OQ8SnO0jC/NG4Ur/UIwy7574A==" + "version": "1.8.12", + "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.12.tgz", + "integrity": "sha512-u1xy9SrwwoPlgjuHNjhV+YUPVdqyBj2ALBxuzeIUKXaPI2i2xypGgxqXkuHcITGdi5yBj5JuXgyMvgiWiS1S3Q==" }, "brace-expansion": { "version": "1.1.11", @@ -2155,12 +1671,12 @@ } }, "buffer": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz", - "integrity": "sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, "buffer-alloc": { @@ -2198,9 +1714,9 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" }, "cliui": { "version": "5.0.0", @@ -2210,6 +1726,36 @@ "string-width": "^3.1.0", "strip-ansi": "^5.2.0", "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } } }, "code-point-at": { @@ -2249,9 +1795,9 @@ "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" }, "core-util-is": { "version": "1.0.2", @@ -2267,11 +1813,11 @@ } }, "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "decamelize": { @@ -2279,11 +1825,6 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -2300,9 +1841,9 @@ "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" }, "dijkstrajs": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.1.tgz", - "integrity": "sha1-082BIh4+pAdCz83lVtTpnpjdxxs=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.2.tgz", + "integrity": "sha512-QV6PMaHTCNmKSeP6QoXhVTw9snc9VD8MulTT0Bd99Pacp4SS1cjcrYPgBPmibqKVtMJJfqC6XvOXgPMEEPH/fg==" }, "ecc-jsbn": { "version": "0.1.2", @@ -2329,9 +1870,9 @@ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-json-stable-stringify": { "version": "2.1.0", @@ -2339,9 +1880,9 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "file-saver": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz", - "integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" }, "find-up": { "version": "3.0.0", @@ -2367,11 +1908,11 @@ } }, "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "requires": { - "minipass": "^2.6.0" + "minipass": "^3.0.0" } }, "fs.realpath": { @@ -2392,39 +1933,6 @@ "string-width": "^1.0.1", "strip-ansi": "^3.0.1", "wide-align": "^1.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - } } }, "get-caller-file": { @@ -2441,9 +1949,9 @@ } }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2459,11 +1967,11 @@ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "requires": { - "ajv": "^6.5.5", + "ajv": "^6.12.3", "har-schema": "^2.0.0" } }, @@ -2482,26 +1990,19 @@ "sshpk": "^1.7.0" } }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "agent-base": "6", + "debug": "4" } }, "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" - }, - "ignore-walk": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", - "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", - "requires": { - "minimatch": "^3.0.4" - } + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "inflight": { "version": "1.0.6", @@ -2517,15 +2018,13 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" - }, "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } }, "is-typedarray": { "version": "1.0.0", @@ -2582,6 +2081,29 @@ "path-exists": "^3.0.0" } }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, "meteor-node-stubs": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/meteor-node-stubs/-/meteor-node-stubs-0.3.3.tgz", @@ -2610,588 +2132,19 @@ "url": "^0.11.0", "util": "^0.10.3", "vm-browserify": "0.0.4" - }, - "dependencies": { - "asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", - "requires": { - "util": "0.10.3" - } - }, - "base64-js": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.3.tgz", - "integrity": "sha512-MsAhsUW1GxCdgYSO6tAfZrNapmUKk7mWx/k5mFY/A1gBtkaCaNapTg+FExCw1r9yeaZhqx/xPg43xgTFH6KL5w==" - }, - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" - }, - "browserify-aes": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", - "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==", - "requires": { - "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" - } - }, - "browserify-cipher": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", - "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "browserify-des": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", - "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1" - } - }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "requires": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" - } - }, - "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "requires": { - "bn.js": "^4.1.1", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", - "inherits": "^2.0.1", - "parse-asn1": "^5.0.0" - } - }, - "browserify-zlib": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", - "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", - "requires": { - "pako": "~0.2.0" - } - }, - "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "requires": { - "date-now": "^0.1.4" - } - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" - }, - "create-ecdh": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", - "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.0.0" - } - }, - "create-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", - "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", - "requires": { - "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" - } - }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "requires": { - "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" - } - }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" - }, - "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "diffie-hellman": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", - "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" - }, - "elliptic": { - "version": "6.4.0", - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - } - }, - "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "hash-base": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", - "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", - "requires": { - "inherits": "^2.0.1" - } - }, - "hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - } - } - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "https-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", - "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=" - }, - "ieee754": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", - "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=" - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" - }, - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "md5.js": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", - "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - }, - "dependencies": { - "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - } - } - }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - } - }, - "minimalistic-assert": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", - "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=" - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" - }, - "os-browserify": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", - "integrity": "sha1-Y/xMzuXS13Y9Jrv4YBB45sLgBE8=" - }, - "pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=" - }, - "parse-asn1": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", - "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", - "requires": { - "asn1.js": "^4.0.0", - "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3" - } - }, - "path-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=" - }, - "pbkdf2": { - "version": "3.0.14", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", - "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" - }, - "public-encrypt": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", - "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1" - } - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" - }, - "randombytes": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "readable-stream": { - "version": "git+ssh://git@github.com/meteor/readable-stream.git#c688cdd193549919b840e8d72a86682d91961e12", - "from": "readable-stream@git+https://github.com/meteor/readable-stream.git", - "requires": { - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.0", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - } - } - }, - "ripemd160": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", - "requires": { - "hash-base": "^2.0.0", - "inherits": "^2.0.1" - } - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" - }, - "sha.js": { - "version": "2.4.10", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz", - "integrity": "sha512-vnwmrFDlOExK4Nm16J2KMWHLrp14lBrjxMxBJpu++EnsuBmpiYaM/MEs46Vxxm/4FvdP5yTwuCTO9it5FSjrqA==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "stream-browserify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "stream-http": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", - "integrity": "sha512-sZOFxI/5xw058XIRHl4dU3dZ+TTOIGJR78Dvo0oEAejIt4ou27k+3ne1zYmCV+v7UucbxIFQuOgnkTVHh8YPnw==", - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.3", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } - }, - "string_decoder": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.0.tgz", - "integrity": "sha512-8zQpRF6juocE69ae7CSPmYEGJe4VCXwP6S6dxUWI7i53Gwv54/ec41fiUA+X7BPGGv7fRSQJjBQVa0gomGaOgg==", - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "timers-browserify": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", - "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", - "requires": { - "process": "~0.11.0" - } - }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" - }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" - } - } - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "requires": { - "inherits": "2.0.1" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "vm-browserify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "requires": { - "indexof": "0.0.1" - } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" - } } }, "mime-db": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", - "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", + "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==" }, "mime-types": { - "version": "2.1.26", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", - "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "version": "2.1.31", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", + "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", "requires": { - "mime-db": "1.43.0" + "mime-db": "1.48.0" } }, "minimatch": { @@ -3202,103 +2155,49 @@ "brace-expansion": "^1.1.7" } }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, "minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" + "yallist": "^4.0.0" } }, "minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "requires": { - "minipass": "^2.9.0" + "minipass": "^3.0.0", + "yallist": "^4.0.0" } }, "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, - "needle": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz", - "integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==", - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, "node-addon-api": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.0.2.tgz", - "integrity": "sha512-+D4s2HCnxPd5PjjI0STKwncjXTUKKqm74MDMz9OPXavjsGmjkvwgLtA5yoxJUdmpj52+2u+RrXgPipahKczMKg==" + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" }, - "node-pre-gyp": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.15.0.tgz", - "integrity": "sha512-7QcZa8/fpaU/BKenjcaeFF9hLz2+7S9AqyXFhlH/rilsQ/hPZKK32RtR5EQHJElgu+q5RfbJ34KriI79UWaorA==", - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.3", - "needle": "^2.5.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4.4.2" - } + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" }, "nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", - "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" - }, - "npm-packlist": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", - "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" + "abbrev": "1" } }, "npmlog": { @@ -3335,29 +2234,10 @@ "wrappy": "1" } }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, "p-limit": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", - "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "requires": { "p-try": "^2.0.0" } @@ -3401,9 +2281,9 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "psl": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", - "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" }, "punycode": { "version": "2.1.1", @@ -3429,17 +2309,6 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } - }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -3458,18 +2327,13 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, "regenerator-runtime": { - "version": "0.13.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", - "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==" + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" }, "request": { "version": "2.88.2", @@ -3509,35 +2373,34 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "requires": { "glob": "^7.1.3" } }, "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } }, "set-blocking": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "signal-exit": { @@ -3581,50 +2444,37 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } } }, "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^2.0.0" } }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - }, "tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", + "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" } }, "tough-cookie": { @@ -3650,14 +2500,14 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, "underscore": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", - "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==" + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", + "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==" }, "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "requires": { "punycode": "^2.1.0" } @@ -3698,30 +2548,6 @@ "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "requires": { "string-width": "^1.0.2 || 2" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" - } - } } }, "wrap-ansi": { @@ -3732,6 +2558,36 @@ "ansi-styles": "^3.2.0", "string-width": "^3.0.0", "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } } }, "wrappy": { @@ -3740,19 +2596,19 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" }, "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "requires": { "cliui": "^5.0.0", "find-up": "^3.0.0", @@ -3763,7 +2619,37 @@ "string-width": "^3.0.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" + "yargs-parser": "^13.1.2" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } } }, "yargs-parser": { From c48cc20fb9b0a5c996b8642089ee47c96f34453e Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Tue, 10 Aug 2021 10:44:24 +0200 Subject: [PATCH 073/247] Added limits to character strings, migration to remove image data urls from character pictures --- app/Model/Character/Characters.js | 24 ++++++++++++------------ app/server/migrations/migrations.js | 25 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/app/Model/Character/Characters.js b/app/Model/Character/Characters.js index f60ef969..b236a4a3 100644 --- a/app/Model/Character/Characters.js +++ b/app/Model/Character/Characters.js @@ -3,18 +3,18 @@ Characters = new Mongo.Collection("characters"); Schemas.Character = new SimpleSchema({ //strings - name: {type: String, defaultValue: "", trim: false, optional: true}, - urlName: {type: String, defaultValue: "-", trim: false, optional: true}, - alignment: {type: String, defaultValue: "", trim: false, optional: true}, - gender: {type: String, defaultValue: "", trim: false, optional: true}, - race: {type: String, defaultValue: "", trim: false, optional: true}, - picture: {type: String, defaultValue: "", trim: true, optional: true}, - description: {type: String, defaultValue: "", trim: false, optional: true}, - personality: {type: String, defaultValue: "", trim: false, optional: true}, - ideals: {type: String, defaultValue: "", trim: false, optional: true}, - bonds: {type: String, defaultValue: "", trim: false, optional: true}, - flaws: {type: String, defaultValue: "", trim: false, optional: true}, - backstory: {type: String, defaultValue: "", trim: false, optional: true}, + name: {type: String, defaultValue: "", trim: false, optional: true, max: 128}, + urlName: {type: String, defaultValue: "-", trim: false, optional: true, max: 128}, + alignment: {type: String, defaultValue: "", trim: false, optional: true, max: 64}, + gender: {type: String, defaultValue: "", trim: false, optional: true, max: 64}, + race: {type: String, defaultValue: "", trim: false, optional: true, max: 64}, + picture: {type: String, defaultValue: "", trim: true, optional: true, max: 256}, + description: {type: String, defaultValue: "", trim: false, optional: true, max: 5000}, + personality: {type: String, defaultValue: "", trim: false, optional: true, max: 5000}, + ideals: {type: String, defaultValue: "", trim: false, optional: true, max: 5000}, + bonds: {type: String, defaultValue: "", trim: false, optional: true, max: 5000}, + flaws: {type: String, defaultValue: "", trim: false, optional: true, max: 5000}, + backstory: {type: String, defaultValue: "", trim: false, optional: true, max: 5000}, //attributes //ability scores diff --git a/app/server/migrations/migrations.js b/app/server/migrations/migrations.js index 383c8ec7..c44bf996 100644 --- a/app/server/migrations/migrations.js +++ b/app/server/migrations/migrations.js @@ -54,3 +54,28 @@ Migrations.add({ return; }, }); + +Migrations.add({ + version: 3, + name: "Removes data images from character pictures", + up: function() { + //update characters + Characters.find({}).forEach(function(char){ + if (char.tempHP) return; + Characters.update(char._id, {$set: { + "tempHP.adjustment": 0, + "tempHP.reset": "longRest", + }}); + }); + Characters.update({ + picture: /^data/ + }, { + $set: {picture: ''} + }, { + multi: true + }); + }, + down: function(){ + return; + }, +}); From a5b4b2032431b478bc5c96b6518615b1fe7e1971 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Tue, 11 Oct 2022 14:08:33 +0200 Subject: [PATCH 074/247] Added link to V2 --- app/client/views/layout/layout.html | 37 +- app/client/views/layout/layout.js | 48 +- app/package-lock.json | 2134 ++++++++------------------- 3 files changed, 660 insertions(+), 1559 deletions(-) diff --git a/app/client/views/layout/layout.html b/app/client/views/layout/layout.html index ea44b732..53ff0a0f 100644 --- a/app/client/views/layout/layout.html +++ b/app/client/views/layout/layout.html @@ -5,8 +5,8 @@ {{> yield}} - {{#if disconnected}} -
- Disconnected, changes won't be saved. {{#if connectionStatus}}({{connectionStatus}}){{/if}} -
- {{/if}} + Disconnected, changes won't be saved. {{#if connectionStatus}}({{connectionStatus}}){{/if}} +
+ {{/if}} {{> Template.dynamic template=globalToastTemplate data=globalToastData }} @@ -31,17 +31,23 @@ {{#if currentUser}} - - {{profileLink}} - + + {{profileLink}} + {{else}} - - Sign in - + + Sign in + {{/if}} - + \ No newline at end of file diff --git a/app/client/views/layout/layout.js b/app/client/views/layout/layout.js index 8e480df6..daa944f1 100644 --- a/app/client/views/layout/layout.js +++ b/app/client/views/layout/layout.js @@ -1,53 +1,53 @@ -Template.layout.onCreated(function() { +Template.layout.onCreated(function () { this.subscribe("user"); }); Template.layout.helpers({ - connectionStatus: function(){ - let status = Meteor.status() - return status.reason || status.status; - }, - disconnected: function(){ - return !Meteor.status().connected; - }, + connectionStatus: function () { + let status = Meteor.status() + return status.reason || status.status; + }, + disconnected: function () { + return !Meteor.status().connected; + }, }); Template.appDrawer.helpers({ - profileLink: function() { + profileLink: function () { var user = Meteor.user(); return user.profile && user.profile.username || user.username || "My Account"; }, - showPatreonBadge: function(){ - let post = PatreonPosts.findOne({}, {sort: {date: -1}}); + showPatreonBadge: function () { + let post = PatreonPosts.findOne({}, { sort: { date: -1 } }); let user = Meteor.user(); if (!post || !user) return false; return post.link !== user.lastPatreonPostClicked; }, - patreonLink: function(){ - let post = PatreonPosts.findOne({}, {sort: {date: -1}}); + patreonLink: function () { + let post = PatreonPosts.findOne({}, { sort: { date: -1 } }); return (post && post.link) || 'https://www.patreon.com/dicecloud'; }, }); let drawerLayout; -const closeDrawer = function(instance){ +const closeDrawer = function (instance) { if (!drawerLayout) drawerLayout = $("app-drawer-layout")[0]; - if (drawerLayout && drawerLayout.narrow){ + if (drawerLayout && drawerLayout.narrow) { drawerLayout.drawer.close(); } } Template.appDrawer.events({ - "click a": function(event, instance){ + "click a": function (event, instance) { closeDrawer(instance); }, - "click .feedback": function(event, instance) { + "click .feedback": function (event, instance) { pushDialogStack({ template: "feedback", element: event.currentTarget, - callback: function(report){ + callback: function (report) { if (!report) return; - Meteor.call("insertReport", report, function(e, result){ + Meteor.call("insertReport", report, function (e, result) { GlobalUI.toast({ text: e && e.details || "Feedback submitted" }); @@ -56,13 +56,17 @@ Template.appDrawer.events({ }); closeDrawer(instance); }, - "click .patreon": function(event, instance){ - let post = PatreonPosts.findOne({}, {sort: {date: -1}}); + "click .patreon": function (event, instance) { + let post = PatreonPosts.findOne({}, { sort: { date: -1 } }); let link = (post && post.link) || 'https://www.patreon.com/dicecloud'; Meteor.call('clickPatreonPost', link); ga("send", "event", "externalLink", "patreon"); }, - "click .github": function(event, instance){ + "click .github": function (event, instance) { ga("send", "event", "externalLink", "github"); }, + "click .version-2": function (event, instance) { + ga("send", "event", "externalLink", "version-2"); + window.location = 'https://beta.dicecloud.com'; + }, }); diff --git a/app/package-lock.json b/app/package-lock.json index cbdf7fdd..8dd36429 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -1,1522 +1,8 @@ { "name": "dicecloud", "version": "0.10.0", - "lockfileVersion": 2, + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "dicecloud", - "version": "0.10.0", - "hasInstallScript": true, - "dependencies": { - "@babel/runtime": "^7.9.2", - "@polymer/polymer": "^1.2.5-npm-test.2", - "bcrypt": "^5.0.0", - "bower": "^1.8.8", - "core-js": "^2.6.11", - "file-saver": "^2.0.2", - "meteor-node-stubs": "^0.3.3", - "qrcode": "^1.4.4", - "request": "^2.88.2", - "source-map-support": "^0.5.19", - "underscore": "^1.10.2" - }, - "engines": { - "node": "12", - "npm": "6" - } - }, - "node_modules/@babel/runtime": { - "version": "7.14.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz", - "integrity": "sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==", - "dependencies": { - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz", - "integrity": "sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA==", - "dependencies": { - "detect-libc": "^1.0.3", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.1", - "nopt": "^5.0.0", - "npmlog": "^4.1.2", - "rimraf": "^3.0.2", - "semver": "^7.3.4", - "tar": "^6.1.0" - }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" - } - }, - "node_modules/@polymer/polymer": { - "version": "1.2.5-npm-test.2", - "resolved": "https://registry.npmjs.org/@polymer/polymer/-/polymer-1.2.5-npm-test.2.tgz", - "integrity": "sha1-eTD1ZjwvaGkVRR0hHmY6qZl9czY=", - "dependencies": { - "webcomponents.js": "^0.7.20" - } - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "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==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" - }, - "node_modules/are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "node_modules/asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bcrypt": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.1.tgz", - "integrity": "sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw==", - "hasInstallScript": true, - "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.0", - "node-addon-api": "^3.1.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/bower": { - "version": "1.8.12", - "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.12.tgz", - "integrity": "sha512-u1xy9SrwwoPlgjuHNjhV+YUPVdqyBj2ALBxuzeIUKXaPI2i2xypGgxqXkuHcITGdi5yBj5JuXgyMvgiWiS1S3Q==", - "bin": { - "bower": "bin/bower" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dependencies": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "node_modules/buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" - }, - "node_modules/buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" - }, - "node_modules/buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "engines": { - "node": ">=10" - } - }, - "node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "engines": { - "node": ">=4" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" - }, - "node_modules/core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "deprecated": "core-js@<3.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js.", - "hasInstallScript": true - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" - }, - "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "bin": { - "detect-libc": "bin/detect-libc.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/dijkstrajs": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.2.tgz", - "integrity": "sha512-QV6PMaHTCNmKSeP6QoXhVTw9snc9VD8MulTT0Bd99Pacp4SS1cjcrYPgBPmibqKVtMJJfqC6XvOXgPMEEPH/fg==" - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/file-saver": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", - "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" - }, - "node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "node_modules/gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dependencies": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "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==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "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==", - "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/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "node_modules/json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "node_modules/jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/meteor-node-stubs": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/meteor-node-stubs/-/meteor-node-stubs-0.3.3.tgz", - "integrity": "sha512-TI1aQRK0vqs94OCkUMkmf5lXNWfIsjSaEDP1inUuwRGt9w8/S2V+HdRikz9r1k/gew+7NcJieaqHsHX7pSTEgA==", - "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" - ], - "hasShrinkwrap": true, - "dependencies": { - "assert": "^1.4.1", - "browserify-zlib": "^0.1.4", - "buffer": "^4.9.1", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.7", - "events": "^1.1.1", - "https-browserify": "0.0.1", - "os-browserify": "^0.2.1", - "path-browserify": "0.0.0", - "process": "^0.11.9", - "punycode": "^1.4.1", - "querystring-es3": "^0.2.1", - "readable-stream": "git+https://github.com/meteor/readable-stream.git", - "stream-browserify": "^2.0.1", - "stream-http": "^2.8.0", - "string_decoder": "^1.1.0", - "timers-browserify": "^1.4.2", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.10.3", - "vm-browserify": "0.0.4" - } - }, - "node_modules/mime-db": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", - "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.31", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", - "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", - "dependencies": { - "mime-db": "1.48.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minipass": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", - "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "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==" - }, - "node_modules/node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" - }, - "node_modules/node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", - "engines": { - "node": "4.x || >=6.0.0" - } - }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dependencies": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "engines": { - "node": "*" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "engines": { - "node": ">=4" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "node_modules/pngjs": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", - "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/qrcode": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.4.4.tgz", - "integrity": "sha512-oLzEC5+NKFou9P0bMj5+v6Z40evexeE29Z9cummZXZ9QXyMr3lphkURzxjXgPJC5azpxcshoDWV1xE46z+/c3Q==", - "dependencies": { - "buffer": "^5.4.3", - "buffer-alloc": "^1.2.0", - "buffer-from": "^1.1.1", - "dijkstrajs": "^1.0.1", - "isarray": "^2.0.1", - "pngjs": "^3.3.0", - "yargs": "^13.2.4" - }, - "bin": { - "qrcode": "bin/qrcode" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readable-stream/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "node_modules/regenerator-runtime": { - "version": "0.13.7", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" - }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "node_modules/signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tar": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", - "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, - "node_modules/underscore": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", - "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==" - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/webcomponents.js": { - "version": "0.7.24", - "resolved": "https://registry.npmjs.org/webcomponents.js/-/webcomponents.js-0.7.24.tgz", - "integrity": "sha1-IRb7+hRo7EFqe+/aozPh0Rj2nAQ=" - }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" - }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dependencies": { - "string-width": "^1.0.2 || 2" - } - }, - "node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "engines": { - "node": ">=4" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - } - }, "dependencies": { "@babel/runtime": { "version": "7.14.6", @@ -1609,6 +95,48 @@ "safer-buffer": "~2.1.0" } }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==" + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ==", + "requires": { + "inherits": "2.0.1" + } + } + } + }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", @@ -1656,6 +184,11 @@ "tweetnacl": "^0.14.3" } }, + "bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" + }, "bower": { "version": "1.8.12", "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.12.tgz", @@ -1670,6 +203,95 @@ "concat-map": "0.0.1" } }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "requires": { + "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" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "requires": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "requires": { + "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" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "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==" + } + } + }, + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==", + "requires": { + "pako": "~0.2.0" + } + }, "buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -1703,6 +325,16 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==" + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -1718,6 +350,15 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "cliui": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", @@ -1789,11 +430,21 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" + }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==" + }, "core-js": { "version": "2.6.12", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", @@ -1804,6 +455,65 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "requires": { + "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" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "requires": { + "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" + } + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -1835,16 +545,47 @@ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, "detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, "dijkstrajs": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.2.tgz", "integrity": "sha512-QV6PMaHTCNmKSeP6QoXhVTw9snc9VD8MulTT0Bd99Pacp4SS1cjcrYPgBPmibqKVtMJJfqC6XvOXgPMEEPH/fg==" }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -1854,11 +595,46 @@ "safer-buffer": "^2.1.0" } }, + "elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "requires": { + "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" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==" + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -1980,6 +756,52 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "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==" + } + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -1990,6 +812,11 @@ "sshpk": "^1.7.0" } }, + "https-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", + "integrity": "sha512-EjDQFbgJr1vDD/175UJeSX3ncQ3+RUnCL5NkthQGHvF4VNHlzTy8ifJfTqz47qiPRqaFH58+CbuG3x51WuB1XQ==" + }, "https-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", @@ -2004,6 +831,11 @@ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha512-i0G7hLJ1z0DE8dsqJa2rycj9dBmNKgXBvotXtZYXakU9oivfB9Uj2ZBC27qqef2U58/ZLwalxa1X/RDCdkHtVg==" + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2104,6 +936,16 @@ } } }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, "meteor-node-stubs": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/meteor-node-stubs/-/meteor-node-stubs-0.3.3.tgz", @@ -2132,6 +974,56 @@ "url": "^0.11.0", "util": "^0.10.3", "vm-browserify": "0.0.4" + }, + "dependencies": { + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" + }, + "readable-stream": { + "version": "git+https://github.com/meteor/readable-stream.git#c688cdd193549919b840e8d72a86682d91961e12", + "from": "git+https://github.com/meteor/readable-stream.git", + "requires": { + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.0", + "util-deprecate": "~1.0.1" + } + } + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } } }, "mime-db": { @@ -2147,6 +1039,16 @@ "mime-db": "1.48.0" } }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -2234,6 +1136,11 @@ "wrappy": "1" } }, + "os-browserify": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", + "integrity": "sha512-vHbnbzdqWJWvGOm7aOMDXHVUykPG0GdhfLkn5ZDmvbRI+wPj/XoB0/CRAkP9v28eZ7REIPPHJa+8ZEYixsWKmQ==" + }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -2255,6 +1162,28 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" + }, + "parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "requires": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha512-WA3pxi1olUQcsl82W576vkqhUSGp0uBtr/381pxx5WXLp3NC+AB99hUG3aGW7H0Kg9PFr1D8wv1iJeICe+9Mhw==" + }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -2265,6 +1194,18 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, + "pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -2275,6 +1216,11 @@ "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==" }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -2285,6 +1231,26 @@ "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "requires": { + "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" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + } + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -2309,6 +1275,33 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==" + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==" + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -2380,6 +1373,15 @@ "glob": "^7.1.3" } }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -2403,6 +1405,15 @@ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", @@ -2438,12 +1449,25 @@ "tweetnacl": "~0.14.0" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", "requires": { - "safe-buffer": "~5.1.0" + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" } }, "string-width": { @@ -2456,6 +1480,14 @@ "strip-ansi": "^3.0.0" } }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -2477,6 +1509,19 @@ "yallist": "^4.0.0" } }, + "timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha512-PIxwAupJZiYU4JmVZYwXp9FKsHMXb5h0ZEFyuXTAn8WLHOlcij+FEcbrvDsom1o5dr1YggEtFbECvGCW2sT53Q==", + "requires": { + "process": "~0.11.0" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==" + }, "tough-cookie": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", @@ -2486,6 +1531,11 @@ "punycode": "^2.1.1" } }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw==" + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -2512,6 +1562,37 @@ "punycode": "^2.1.0" } }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" + } + } + }, + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + } + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -2532,6 +1613,14 @@ "extsprintf": "^1.2.0" } }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha512-NyZNR3WDah+NPkjh/YmhuWSsT4a0mF0BJYgUmvrJ70zxjTXh5Y2Asobxlh0Nfs0PCFB5FVpRJft7NozAWFMwLQ==", + "requires": { + "indexof": "0.0.1" + } + }, "webcomponents.js": { "version": "0.7.24", "resolved": "https://registry.npmjs.org/webcomponents.js/-/webcomponents.js-0.7.24.tgz", @@ -2595,6 +1684,11 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, "y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", From cc915410dac3c61384c3452fb0424ed2fd6b002b Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Tue, 25 Oct 2022 19:00:02 +0200 Subject: [PATCH 075/247] Fixed query hitting mongo with too much regex --- app/lib/functions/shareCharacter.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/lib/functions/shareCharacter.js b/app/lib/functions/shareCharacter.js index d206fc0f..40ab1322 100644 --- a/app/lib/functions/shareCharacter.js +++ b/app/lib/functions/shareCharacter.js @@ -1,9 +1,9 @@ Meteor.methods({ - "getUserId": function(username){ + "getUserId": function (username) { if (!username) return; if (Meteor.isClient) return; - let user = Accounts.findUserByUsername(username) || - Accounts.findUserByEmail(username); + const user = Meteor.users.findOne({ username }) || + Meteor.users.findOne({ 'emails.address': username }); return user && user._id; } }); From 04c9c4cfc2fe05993aa4a10aa07597549e4dd47e Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Sat, 19 Nov 2022 22:39:35 +0200 Subject: [PATCH 076/247] Fixed bug where updates on sliders weren't debounced --- app/Model/Character/Characters.js | 448 +++++++++--------- .../character/stats/healthCard/healthCard.js | 115 +++-- .../lib/configuration/globalRateLimit.js | 16 + 3 files changed, 296 insertions(+), 283 deletions(-) create mode 100644 app/server/lib/configuration/globalRateLimit.js diff --git a/app/Model/Character/Characters.js b/app/Model/Character/Characters.js index b236a4a3..445e1c7b 100644 --- a/app/Model/Character/Characters.js +++ b/app/Model/Character/Characters.js @@ -3,183 +3,183 @@ Characters = new Mongo.Collection("characters"); Schemas.Character = new SimpleSchema({ //strings - name: {type: String, defaultValue: "", trim: false, optional: true, max: 128}, - urlName: {type: String, defaultValue: "-", trim: false, optional: true, max: 128}, - alignment: {type: String, defaultValue: "", trim: false, optional: true, max: 64}, - gender: {type: String, defaultValue: "", trim: false, optional: true, max: 64}, - race: {type: String, defaultValue: "", trim: false, optional: true, max: 64}, - picture: {type: String, defaultValue: "", trim: true, optional: true, max: 256}, - description: {type: String, defaultValue: "", trim: false, optional: true, max: 5000}, - personality: {type: String, defaultValue: "", trim: false, optional: true, max: 5000}, - ideals: {type: String, defaultValue: "", trim: false, optional: true, max: 5000}, - bonds: {type: String, defaultValue: "", trim: false, optional: true, max: 5000}, - flaws: {type: String, defaultValue: "", trim: false, optional: true, max: 5000}, - backstory: {type: String, defaultValue: "", trim: false, optional: true, max: 5000}, + name: { type: String, defaultValue: "", trim: false, optional: true, max: 128 }, + urlName: { type: String, defaultValue: "-", trim: false, optional: true, max: 128 }, + alignment: { type: String, defaultValue: "", trim: false, optional: true, max: 64 }, + gender: { type: String, defaultValue: "", trim: false, optional: true, max: 64 }, + race: { type: String, defaultValue: "", trim: false, optional: true, max: 64 }, + picture: { type: String, defaultValue: "", trim: true, optional: true, max: 256 }, + description: { type: String, defaultValue: "", trim: false, optional: true, max: 5000 }, + personality: { type: String, defaultValue: "", trim: false, optional: true, max: 5000 }, + ideals: { type: String, defaultValue: "", trim: false, optional: true, max: 5000 }, + bonds: { type: String, defaultValue: "", trim: false, optional: true, max: 5000 }, + flaws: { type: String, defaultValue: "", trim: false, optional: true, max: 5000 }, + backstory: { type: String, defaultValue: "", trim: false, optional: true, max: 5000 }, //attributes //ability scores - strength: {type: Schemas.Attribute}, - dexterity: {type: Schemas.Attribute}, - constitution: {type: Schemas.Attribute}, - intelligence: {type: Schemas.Attribute}, - wisdom: {type: Schemas.Attribute}, - charisma: {type: Schemas.Attribute}, + strength: { type: Schemas.Attribute }, + dexterity: { type: Schemas.Attribute }, + constitution: { type: Schemas.Attribute }, + intelligence: { type: Schemas.Attribute }, + wisdom: { type: Schemas.Attribute }, + charisma: { type: Schemas.Attribute }, //stats - hitPoints: {type: Schemas.Attribute}, - tempHP: {type: Schemas.Attribute}, - experience: {type: Schemas.Attribute}, - proficiencyBonus: {type: Schemas.Attribute}, - speed: {type: Schemas.Attribute}, - weight: {type: Schemas.Attribute}, - age: {type: Schemas.Attribute}, - ageRate: {type: Schemas.Attribute}, - armor: {type: Schemas.Attribute}, - carryMultiplier: {type: Schemas.Attribute}, + hitPoints: { type: Schemas.Attribute }, + tempHP: { type: Schemas.Attribute }, + experience: { type: Schemas.Attribute }, + proficiencyBonus: { type: Schemas.Attribute }, + speed: { type: Schemas.Attribute }, + weight: { type: Schemas.Attribute }, + age: { type: Schemas.Attribute }, + ageRate: { type: Schemas.Attribute }, + armor: { type: Schemas.Attribute }, + carryMultiplier: { type: Schemas.Attribute }, //resources - level1SpellSlots: {type: Schemas.Attribute}, - level2SpellSlots: {type: Schemas.Attribute}, - level3SpellSlots: {type: Schemas.Attribute}, - level4SpellSlots: {type: Schemas.Attribute}, - level5SpellSlots: {type: Schemas.Attribute}, - level6SpellSlots: {type: Schemas.Attribute}, - level7SpellSlots: {type: Schemas.Attribute}, - level8SpellSlots: {type: Schemas.Attribute}, - level9SpellSlots: {type: Schemas.Attribute}, - ki: {type: Schemas.Attribute}, - sorceryPoints: {type: Schemas.Attribute}, - rages: {type: Schemas.Attribute}, - superiorityDice: {type: Schemas.Attribute}, - expertiseDice: {type: Schemas.Attribute}, + level1SpellSlots: { type: Schemas.Attribute }, + level2SpellSlots: { type: Schemas.Attribute }, + level3SpellSlots: { type: Schemas.Attribute }, + level4SpellSlots: { type: Schemas.Attribute }, + level5SpellSlots: { type: Schemas.Attribute }, + level6SpellSlots: { type: Schemas.Attribute }, + level7SpellSlots: { type: Schemas.Attribute }, + level8SpellSlots: { type: Schemas.Attribute }, + level9SpellSlots: { type: Schemas.Attribute }, + ki: { type: Schemas.Attribute }, + sorceryPoints: { type: Schemas.Attribute }, + rages: { type: Schemas.Attribute }, + superiorityDice: { type: Schemas.Attribute }, + expertiseDice: { type: Schemas.Attribute }, //specific features - rageDamage: {type: Schemas.Attribute}, + rageDamage: { type: Schemas.Attribute }, //hit dice - d6HitDice: {type: Schemas.Attribute}, - d8HitDice: {type: Schemas.Attribute}, - d10HitDice: {type: Schemas.Attribute}, - d12HitDice: {type: Schemas.Attribute}, + d6HitDice: { type: Schemas.Attribute }, + d8HitDice: { type: Schemas.Attribute }, + d10HitDice: { type: Schemas.Attribute }, + d12HitDice: { type: Schemas.Attribute }, //vulnerabilities - acidMultiplier: {type: Schemas.Attribute}, - bludgeoningMultiplier: {type: Schemas.Attribute}, - coldMultiplier: {type: Schemas.Attribute}, - fireMultiplier: {type: Schemas.Attribute}, - forceMultiplier: {type: Schemas.Attribute}, - lightningMultiplier: {type: Schemas.Attribute}, - necroticMultiplier: {type: Schemas.Attribute}, - piercingMultiplier: {type: Schemas.Attribute}, - poisonMultiplier: {type: Schemas.Attribute}, - psychicMultiplier: {type: Schemas.Attribute}, - radiantMultiplier: {type: Schemas.Attribute}, - slashingMultiplier: {type: Schemas.Attribute}, - thunderMultiplier: {type: Schemas.Attribute}, + acidMultiplier: { type: Schemas.Attribute }, + bludgeoningMultiplier: { type: Schemas.Attribute }, + coldMultiplier: { type: Schemas.Attribute }, + fireMultiplier: { type: Schemas.Attribute }, + forceMultiplier: { type: Schemas.Attribute }, + lightningMultiplier: { type: Schemas.Attribute }, + necroticMultiplier: { type: Schemas.Attribute }, + piercingMultiplier: { type: Schemas.Attribute }, + poisonMultiplier: { type: Schemas.Attribute }, + psychicMultiplier: { type: Schemas.Attribute }, + radiantMultiplier: { type: Schemas.Attribute }, + slashingMultiplier: { type: Schemas.Attribute }, + thunderMultiplier: { type: Schemas.Attribute }, //skills //saves - strengthSave: {type: Schemas.Skill}, - "strengthSave.ability": {type: String, defaultValue: "strength"}, + strengthSave: { type: Schemas.Skill }, + "strengthSave.ability": { type: String, defaultValue: "strength" }, - dexteritySave: {type: Schemas.Skill}, - "dexteritySave.ability": {type: String, defaultValue: "dexterity"}, + dexteritySave: { type: Schemas.Skill }, + "dexteritySave.ability": { type: String, defaultValue: "dexterity" }, - constitutionSave:{type: Schemas.Skill}, - "constitutionSave.ability": {type: String, defaultValue: "constitution"}, + constitutionSave: { type: Schemas.Skill }, + "constitutionSave.ability": { type: String, defaultValue: "constitution" }, - intelligenceSave:{type: Schemas.Skill}, - "intelligenceSave.ability": {type: String, defaultValue: "intelligence"}, + intelligenceSave: { type: Schemas.Skill }, + "intelligenceSave.ability": { type: String, defaultValue: "intelligence" }, - wisdomSave: {type: Schemas.Skill}, - "wisdomSave.ability": {type: String, defaultValue: "wisdom"}, + wisdomSave: { type: Schemas.Skill }, + "wisdomSave.ability": { type: String, defaultValue: "wisdom" }, - charismaSave: {type: Schemas.Skill}, - "charismaSave.ability": {type: String, defaultValue: "charisma"}, + charismaSave: { type: Schemas.Skill }, + "charismaSave.ability": { type: String, defaultValue: "charisma" }, //skill skills - acrobatics: {type: Schemas.Skill}, - "acrobatics.ability": {type: String, defaultValue: "dexterity"}, + acrobatics: { type: Schemas.Skill }, + "acrobatics.ability": { type: String, defaultValue: "dexterity" }, - animalHandling: {type: Schemas.Skill}, - "animalHandling.ability": {type: String, defaultValue: "wisdom"}, + animalHandling: { type: Schemas.Skill }, + "animalHandling.ability": { type: String, defaultValue: "wisdom" }, - arcana: {type: Schemas.Skill}, - "arcana.ability": {type: String, defaultValue: "intelligence"}, + arcana: { type: Schemas.Skill }, + "arcana.ability": { type: String, defaultValue: "intelligence" }, - athletics: {type: Schemas.Skill}, - "athletics.ability": {type: String, defaultValue: "strength"}, + athletics: { type: Schemas.Skill }, + "athletics.ability": { type: String, defaultValue: "strength" }, - deception: {type: Schemas.Skill}, - "deception.ability": {type: String, defaultValue: "charisma"}, + deception: { type: Schemas.Skill }, + "deception.ability": { type: String, defaultValue: "charisma" }, - history: {type: Schemas.Skill}, - "history.ability": {type: String, defaultValue: "intelligence"}, + history: { type: Schemas.Skill }, + "history.ability": { type: String, defaultValue: "intelligence" }, - insight: {type: Schemas.Skill}, - "insight.ability": {type: String, defaultValue: "wisdom"}, + insight: { type: Schemas.Skill }, + "insight.ability": { type: String, defaultValue: "wisdom" }, - intimidation: {type: Schemas.Skill}, - "intimidation.ability": {type: String, defaultValue: "charisma"}, + intimidation: { type: Schemas.Skill }, + "intimidation.ability": { type: String, defaultValue: "charisma" }, - investigation: {type: Schemas.Skill}, - "investigation.ability": {type: String, defaultValue: "intelligence"}, + investigation: { type: Schemas.Skill }, + "investigation.ability": { type: String, defaultValue: "intelligence" }, - medicine: {type: Schemas.Skill}, - "medicine.ability": {type: String, defaultValue: "wisdom"}, + medicine: { type: Schemas.Skill }, + "medicine.ability": { type: String, defaultValue: "wisdom" }, - nature: {type: Schemas.Skill}, - "nature.ability": {type: String, defaultValue: "intelligence"}, + nature: { type: Schemas.Skill }, + "nature.ability": { type: String, defaultValue: "intelligence" }, - perception: {type: Schemas.Skill}, - "perception.ability": {type: String, defaultValue: "wisdom"}, + perception: { type: Schemas.Skill }, + "perception.ability": { type: String, defaultValue: "wisdom" }, - performance: {type: Schemas.Skill}, - "performance.ability": {type: String, defaultValue: "charisma"}, + performance: { type: Schemas.Skill }, + "performance.ability": { type: String, defaultValue: "charisma" }, - persuasion: {type: Schemas.Skill}, - "persuasion.ability": {type: String, defaultValue: "charisma"}, + persuasion: { type: Schemas.Skill }, + "persuasion.ability": { type: String, defaultValue: "charisma" }, - religion: {type: Schemas.Skill}, - "religion.ability": {type: String, defaultValue: "intelligence"}, + religion: { type: Schemas.Skill }, + "religion.ability": { type: String, defaultValue: "intelligence" }, - sleightOfHand: {type: Schemas.Skill}, - "sleightOfHand.ability": {type: String, defaultValue: "dexterity"}, + sleightOfHand: { type: Schemas.Skill }, + "sleightOfHand.ability": { type: String, defaultValue: "dexterity" }, - stealth: {type: Schemas.Skill}, - "stealth.ability": {type: String, defaultValue: "dexterity"}, + stealth: { type: Schemas.Skill }, + "stealth.ability": { type: String, defaultValue: "dexterity" }, - survival: {type: Schemas.Skill}, - "survival.ability": {type: String, defaultValue: "wisdom"}, + survival: { type: Schemas.Skill }, + "survival.ability": { type: String, defaultValue: "wisdom" }, //Mechanical Skills - initiative: {type: Schemas.Skill}, - "initiative.ability": {type: String, defaultValue: "dexterity"}, + initiative: { type: Schemas.Skill }, + "initiative.ability": { type: String, defaultValue: "dexterity" }, - dexterityArmor: {type: Schemas.Skill}, - "dexterityArmor.ability": {type: String, defaultValue: "dexterity"}, + dexterityArmor: { type: Schemas.Skill }, + "dexterityArmor.ability": { type: String, defaultValue: "dexterity" }, //mechanics - deathSave: {type: Schemas.DeathSave}, + deathSave: { type: Schemas.DeathSave }, //permissions - party: {type: String, regEx: SimpleSchema.RegEx.Id, optional: true}, - owner: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1}, - readers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: [], index: 1}, - writers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: [], index: 1}, - color: { + party: { type: String, regEx: SimpleSchema.RegEx.Id, optional: true }, + owner: { type: String, regEx: SimpleSchema.RegEx.Id, index: 1 }, + readers: { type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: [], index: 1 }, + writers: { type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: [], index: 1 }, + color: { type: String, allowedValues: _.pluck(colorOptions, "key"), defaultValue: "q", }, //TODO add per-character settings //how many experiences to load at a time in XP table - "settings.experiencesInc": {type: Number, defaultValue: 20}, + "settings.experiencesInc": { type: Number, defaultValue: 20 }, //slowed down by carrying too much? - "settings.useVariantEncumbrance": {type: Boolean, defaultValue: false}, - "settings.useStandardEncumbrance": {type: Boolean, defaultValue: true}, + "settings.useVariantEncumbrance": { type: Boolean, defaultValue: false }, + "settings.useStandardEncumbrance": { type: Boolean, defaultValue: true }, //hide spellcasting - "settings.hideSpellcasting": {type: Boolean, defaultValue: false}, + "settings.hideSpellcasting": { type: Boolean, defaultValue: false }, //show to anyone with link "settings.viewPermission": { type: String, @@ -187,19 +187,19 @@ Schemas.Character = new SimpleSchema({ allowedValues: ["whitelist", "public"], index: 1, }, - "settings.swapStatAndModifier": {type: Boolean, defaultValue: false}, - "settings.exportFeatures": {type: Boolean, defaultValue: true}, - "settings.exportAttacks": {type: Boolean, defaultValue: true}, - "settings.exportDescription": {type: Boolean, defaultValue: true}, - "settings.newUserExperience": {type: Boolean, optional: true}, + "settings.swapStatAndModifier": { type: Boolean, defaultValue: false }, + "settings.exportFeatures": { type: Boolean, defaultValue: true }, + "settings.exportAttacks": { type: Boolean, defaultValue: true }, + "settings.exportDescription": { type: Boolean, defaultValue: true }, + "settings.newUserExperience": { type: Boolean, optional: true }, }); Characters.attachSchema(Schemas.Character); -var attributeBase = preventLoop(function(charId, statName){ +var attributeBase = preventLoop(function (charId, statName) { check(statName, String); //if it's a damage multiplier, we treat it specially - if (_.contains(DAMAGE_MULTIPLIERS, statName)){ + if (_.contains(DAMAGE_MULTIPLIERS, statName)) { var invulnerabilityCount = Effects.find({ charId: charId, stat: statName, @@ -222,11 +222,11 @@ var attributeBase = preventLoop(function(charId, statName){ operation: "mul", value: 2, }).count(); - if (!resistCount && !vulnCount){ + if (!resistCount && !vulnCount) { return 1; - } else if (resistCount && !vulnCount){ + } else if (resistCount && !vulnCount) { return 0.5; - } else if (!resistCount && vulnCount){ + } else if (!resistCount && vulnCount) { return 2; } else { return 1; @@ -243,18 +243,18 @@ var attributeBase = preventLoop(function(charId, statName){ charId: charId, stat: statName, enabled: true, - operation: {$in: ["base", "add", "mul", "min", "max"]}, - }).forEach(function(effect) { + operation: { $in: ["base", "add", "mul", "min", "max"] }, + }).forEach(function (effect) { value = evaluateEffect(charId, effect); - if (effect.operation === "base"){ + if (effect.operation === "base") { if (value > base) base = value; - } else if (effect.operation === "add"){ + } else if (effect.operation === "add") { add += value; - } else if (effect.operation === "mul"){ + } else if (effect.operation === "mul") { mul *= value; - } else if (effect.operation === "min"){ + } else if (effect.operation === "min") { if (value > min) min = value; - } else if (effect.operation === "max"){ + } else if (effect.operation === "max") { if (value < max) max = value; } }); @@ -263,18 +263,18 @@ var attributeBase = preventLoop(function(charId, statName){ if (result < min) result = min; if (result > max) result = max; // Don't round carry multiplier - if (statName === "carryMultiplier"){ + if (statName === "carryMultiplier") { return result; } return Math.floor(result); }); if (Meteor.isClient) { - Template.registerHelper("characterCalculate", function(func, charId, input) { + Template.registerHelper("characterCalculate", function (func, charId, input) { try { return Characters.calculate[func](charId, input); - } catch (e){ - if (!Characters.calculate[func]){ + } catch (e) { + if (!Characters.calculate[func]) { throw new Error(func + "is not a function name"); } else { throw e; @@ -284,10 +284,10 @@ if (Meteor.isClient) { } //create a local memoize with a argument concatenating hash function -var memoize = function(f) { +var memoize = function (f) { if (Meteor.isServer) return f; - return Tracker.memoize(f, function() { - return _.reduce(arguments, function(memo, arg) { + return Tracker.memoize(f, function () { + return _.reduce(arguments, function (memo, arg) { return memo + arg; }, ""); }); @@ -295,13 +295,13 @@ var memoize = function(f) { //memoize funcitons that have finds and slow loops Characters.calculate = { - getField: function(charId, fieldName) { + getField: function (charId, fieldName) { var fieldSelector = {}; fieldSelector[fieldName] = 1; - var char = Characters.findOne(charId, {fields: fieldSelector}); + var char = Characters.findOne(charId, { fields: fieldSelector }); if (!char) return; var field = char[fieldName]; - if (field === undefined){ + if (field === undefined) { throw new Meteor.Error( "getField failed", "getField could not find field " + @@ -312,8 +312,8 @@ Characters.calculate = { } return field; }, - fieldValue: function(charId, fieldName) { - if (!Schemas.Character.schema(fieldName)){ + fieldValue: function (charId, fieldName) { + if (!Schemas.Character.schema(fieldName)) { throw new Meteor.Error( "Field not found", "Character's schema does not contain a field called: " + fieldName @@ -321,17 +321,17 @@ Characters.calculate = { } //duck typing to get the right value function //.ability implies skill - if (Schemas.Character.schema(fieldName + ".ability")){ + if (Schemas.Character.schema(fieldName + ".ability")) { return Characters.calculate.skillMod(charId, fieldName); } //adjustment implies attribute - if (Schemas.Character.schema(fieldName + ".adjustment")){ + if (Schemas.Character.schema(fieldName + ".adjustment")) { return Characters.calculate.attributeValue(charId, fieldName); } //fall back to just returning the field itself return Characters.calculate.getField(charId, fieldName); }, - attributeValue: memoize(function(charId, attributeName){ + attributeValue: memoize(function (charId, attributeName) { var attribute = Characters.calculate.getField(charId, attributeName); if (!attribute) return; //base value @@ -340,10 +340,10 @@ Characters.calculate = { value += attribute.adjustment; return value; }), - attributeBase: memoize(function(charId, attributeName){ + attributeBase: memoize(function (charId, attributeName) { return attributeBase(charId, attributeName); }), - skillMod: memoize(preventLoop(function(charId, skillName){ + skillMod: memoize(preventLoop(function (charId, skillName) { var skill = Characters.calculate.getField(charId, skillName); if (!skill) return; //get the final value of the ability score @@ -369,16 +369,16 @@ Characters.calculate = { charId: charId, stat: skillName, enabled: true, - operation: {$in: ["base", "add", "mul", "min", "max"]}, - }).forEach(function(effect) { + operation: { $in: ["base", "add", "mul", "min", "max"] }, + }).forEach(function (effect) { value = evaluateEffect(charId, effect); - if (effect.operation === "add"){ + if (effect.operation === "add") { add += value; - } else if (effect.operation === "mul"){ + } else if (effect.operation === "mul") { mul *= value; - } else if (effect.operation === "min"){ + } else if (effect.operation === "min") { if (value > min) min = value; - } else if (effect.operation === "max"){ + } else if (effect.operation === "max") { if (value < max) max = value; } }); @@ -388,83 +388,83 @@ Characters.calculate = { return Math.floor(result); })), - proficiency: memoize(function(charId, skillName){ + proficiency: memoize(function (charId, skillName) { //return largest value in proficiency array var prof = Proficiencies.findOne( - {charId: charId, name: skillName, enabled: true}, - {sort: {value: -1}} + { charId: charId, name: skillName, enabled: true }, + { sort: { value: -1 } } ); return prof && prof.value || 0; }), - passiveSkill: memoize(function(charId, skillName){ + passiveSkill: memoize(function (charId, skillName) { var mod = +Characters.calculate.skillMod(charId, skillName); var value = 10 + mod; Effects.find( - {charId: charId, stat: skillName, enabled: true, operation: "passiveAdd"} - ).forEach(function(effect){ + { charId: charId, stat: skillName, enabled: true, operation: "passiveAdd" } + ).forEach(function (effect) { value += evaluateEffect(charId, effect); }); var advantage = Characters.calculate.advantage(charId, skillName); value += 5 * advantage; return Math.floor(value); }), - advantage: memoize(function(charId, skillName){ + advantage: memoize(function (charId, skillName) { var advantage = Effects.find( - {charId: charId, stat: skillName, enabled: true, operation: "advantage"} + { charId: charId, stat: skillName, enabled: true, operation: "advantage" } ).count(); var disadvantage = Effects.find( - {charId: charId, stat: skillName, enabled: true, operation: "disadvantage"} + { charId: charId, stat: skillName, enabled: true, operation: "disadvantage" } ).count(); if (advantage && !disadvantage) return 1; if (disadvantage && !advantage) return -1; return 0; }), - abilityMod: function(charId, attribute){ + abilityMod: function (charId, attribute) { return getMod( Characters.calculate.attributeValue(charId, attribute) ); }, - passiveAbility: function(charId, attribute){ + passiveAbility: function (charId, attribute) { var mod = +getMod(Characters.calculate.attributeValue(charId, attribute)); return 10 + mod; }, - xpLevel: function(charId){ + xpLevel: function (charId) { var xp = Characters.calculate.experience(charId); - for (var i = 0; i < 19; i++){ - if (xp < XP_TABLE[i]){ + for (var i = 0; i < 19; i++) { + if (xp < XP_TABLE[i]) { return i; } } if (xp > 355000) return 20; return 0; }, - level: memoize(function(charId){ + level: memoize(function (charId) { var level = 0; - Classes.find({charId: charId}).forEach(function(cls){ + Classes.find({ charId: charId }).forEach(function (cls) { level += cls.level; }); return level; }), - experience: memoize(function(charId){ + experience: memoize(function (charId) { var xp = 0; Experiences.find( - {charId: charId}, - {fields: {value: 1}} - ).forEach(function(e){ + { charId: charId }, + { fields: { value: 1 } } + ).forEach(function (e) { xp += e.value; }); return xp; }), }; -var deprecated = function() { +var deprecated = function () { //var err = new Error("this function has been deprecated"); var name = ""; - if (Template.instance()){ + if (Template.instance()) { name = Template.instance().view.name; } var logString = "this function has been deprecated \n"; - if (name){ + if (name) { logString += "View: " + name + "\n\n"; } //logString += err.stack + "\n\n---------------------\n\n"; @@ -477,104 +477,104 @@ var deprecated = function() { Characters.helpers({ //returns the value stored in the field requested //will set up dependencies on just that field - getField : function(fieldName){ + getField: function (fieldName) { deprecated(); return Characters.calculate.getField(this._id, fieldName); }, //returns the value of a field - fieldValue : function(fieldName){ + fieldValue: function (fieldName) { deprecated(); return Characters.calculate.fieldValue(this._id, fieldName); }, - attributeValue: function(attributeName){ + attributeValue: function (attributeName) { deprecated(); return Characters.calculate.attributeValue(this._id, attributeName); }, - attributeBase: function(attributeName){ + attributeBase: function (attributeName) { deprecated(); return Characters.calculate.attributeBase(this._id, attributeName); }, - skillMod: function(skillName){ + skillMod: function (skillName) { deprecated(); return Characters.calculate.skillMod(this._id, skillName); }, - proficiency: function(skillName){ + proficiency: function (skillName) { deprecated(); return Characters.calculate.proficiency(this._id, skillName); }, - passiveSkill: function(skillName){ + passiveSkill: function (skillName) { deprecated(); return Characters.calculate.passiveSkill(this._id, skillName); }, - advantage: function(skillName){ + advantage: function (skillName) { deprecated(); return Characters.calculate.advantage(this._id, skillName); }, - abilityMod: function(attribute){ + abilityMod: function (attribute) { deprecated(); return Characters.calculate.abilityMod(this._id, attribute); }, - passiveAbility: function(attribute){ + passiveAbility: function (attribute) { deprecated(); return Characters.calculate.passiveAbility(this._id, attribute); }, - xpLevel: function(){ + xpLevel: function () { deprecated(); return Characters.calculate.xpLevel(this._id); }, - level: function(){ + level: function () { deprecated(); return Characters.calculate.level(this._id); }, - experience: function(){ + experience: function () { deprecated(); return Characters.calculate.experience(this._id); }, }); //clean up all data related to that character before removing it -if (Meteor.isServer){ - Characters.after.remove(function(userId, character) { - Actions .remove({charId: character._id}); - Attacks .remove({charId: character._id}); - Buffs .remove({charId: character._id}); - Classes .remove({charId: character._id}); - CustomBuffs .remove({charId: character._id}); - Effects .remove({charId: character._id}); - Experiences .remove({charId: character._id}); - Features .remove({charId: character._id}); - Notes .remove({charId: character._id}); - Proficiencies .remove({charId: character._id}); - SpellLists .remove({charId: character._id}); - Items .remove({charId: character._id}); - Containers .remove({charId: character._id}); +if (Meteor.isServer) { + Characters.after.remove(function (userId, character) { + Actions.remove({ charId: character._id }); + Attacks.remove({ charId: character._id }); + Buffs.remove({ charId: character._id }); + Classes.remove({ charId: character._id }); + CustomBuffs.remove({ charId: character._id }); + Effects.remove({ charId: character._id }); + Experiences.remove({ charId: character._id }); + Features.remove({ charId: character._id }); + Notes.remove({ charId: character._id }); + Proficiencies.remove({ charId: character._id }); + SpellLists.remove({ charId: character._id }); + Items.remove({ charId: character._id }); + Containers.remove({ charId: character._id }); }); - Characters.after.update(function(userId, doc, fieldNames, modifier, options) { - if (_.contains(fieldNames, "name")){ - var urlName = getSlug(doc.name, {maintainCase: true}) || "-"; - Characters.update(doc._id, {$set: {urlName}}); + Characters.after.update(function (userId, doc, fieldNames, modifier, options) { + if (_.contains(fieldNames, "name")) { + var urlName = getSlug(doc.name, { maintainCase: true }) || "-"; + Characters.update(doc._id, { $set: { urlName } }); } }); - Characters.before.insert(function(userId, doc) { - doc.urlName = getSlug(doc.name, {maintainCase: true}) || "-"; + Characters.before.insert(function (userId, doc) { + doc.urlName = getSlug(doc.name, { maintainCase: true }) || "-"; // The first character a user creates should have the new user experience - if (!Characters.find({owner: userId}).count()){ + if (!Characters.find({ owner: userId }).count()) { doc.settings.newUserExperience = true; } }); } Characters.allow({ - insert: function(userId, doc) { + insert: function (userId, doc) { // the user must be logged in, and the document must be owned by the user return (userId && doc.owner === userId); }, - update: function(userId, doc, fields, modifier) { + update: function (userId, doc, fields, modifier) { // can only change documents you have write access to return doc.owner === userId || _.contains(doc.writers, userId); }, - remove: function(userId, doc) { + remove: function (userId, doc) { // can only remove your own documents return doc.owner === userId; }, @@ -582,7 +582,7 @@ Characters.allow({ }); Characters.deny({ - update: function(userId, doc, fields, modifier) { + update: function (userId, doc, fields, modifier) { // can't change owners unless you are the current owner return _.contains(fields, "owner") && doc.owner !== userId; } diff --git a/app/client/views/character/stats/healthCard/healthCard.js b/app/client/views/character/stats/healthCard/healthCard.js index 1c1e7751..cd765a3d 100644 --- a/app/client/views/character/stats/healthCard/healthCard.js +++ b/app/client/views/character/stats/healthCard/healthCard.js @@ -3,18 +3,18 @@ const currentId = () => Template.currentData()._id; // Use binding to ensure max is always set before value to prevent value clamping poorly Template.healthCard.binding({ "#hitPointSlider": { - max: () => Characters.calculate.attributeBase(currentId() , "hitPoints"), - value: () => Characters.calculate.attributeValue(currentId() , "hitPoints"), + max: () => Characters.calculate.attributeBase(currentId(), "hitPoints"), + value: () => Characters.calculate.attributeValue(currentId(), "hitPoints"), }, }); // Reset the old value between characters so that we don't get red health lost // bar when changing character -Template.healthCard.onRendered(function(){ +Template.healthCard.onRendered(function () { let oldId = Template.currentData()._id; this.autorun(() => { const id = Template.currentData()._id; - if (oldId !== id){ + if (oldId !== id) { this.find("#hitPointSlider").resetOldValue(); var thpSlider = this.find("#temporaryHitPointSlider"); thpSlider && thpSlider.resetOldValue(); @@ -24,49 +24,49 @@ Template.healthCard.onRendered(function(){ }); Template.healthCard.helpers({ - extraHitPoints: function(){ - return TemporaryHitPoints.find({charId: this._id}); + extraHitPoints: function () { + return TemporaryHitPoints.find({ charId: this._id }); }, - showDeathSave: function(){ + showDeathSave: function () { return Characters.calculate.attributeValue(this._id, "hitPoints") <= 0; }, - deathSaveObject: function(){ - var char = Characters.findOne(this._id, {fields: {deathSave: 1}}); + deathSaveObject: function () { + var char = Characters.findOne(this._id, { fields: { deathSave: 1 } }); return char && char.deathSave; }, - failIcon: function(num){ + failIcon: function (num) { if (num <= this.fail) return "radio-button-checked"; else return "radio-button-unchecked"; }, - passIcon: function(num){ + passIcon: function (num) { if (num <= this.pass) return "radio-button-checked"; else return "radio-button-unchecked"; }, - failDisabled: function(num){ + failDisabled: function (num) { return !(num === this.fail || num - 1 === this.fail); }, - passDisabled: function(num){ + passDisabled: function (num) { return !(num === this.pass || num - 1 === this.pass); }, - dead: function(){ + dead: function () { return this.fail >= 3; }, - multipliers: function(){ + multipliers: function () { // jscs:disable maximumLineLength var multipliers = [ - {name: "Acid", value: Characters.calculate.attributeValue(this._id, "acidMultiplier")}, - {name: "Bludgeoning", value: Characters.calculate.attributeValue(this._id, "bludgeoningMultiplier")}, - {name: "Cold", value: Characters.calculate.attributeValue(this._id, "coldMultiplier")}, - {name: "Fire", value: Characters.calculate.attributeValue(this._id, "fireMultiplier")}, - {name: "Force", value: Characters.calculate.attributeValue(this._id, "forceMultiplier")}, - {name: "Lightning", value: Characters.calculate.attributeValue(this._id, "lightningMultiplier")}, - {name: "Necrotic", value: Characters.calculate.attributeValue(this._id, "necroticMultiplier")}, - {name: "Piercing", value: Characters.calculate.attributeValue(this._id, "piercingMultiplier")}, - {name: "Poison", value: Characters.calculate.attributeValue(this._id, "poisonMultiplier")}, - {name: "Psychic", value: Characters.calculate.attributeValue(this._id, "psychicMultiplier")}, - {name: "Radiant", value: Characters.calculate.attributeValue(this._id, "radiantMultiplier")}, - {name: "Slashing", value: Characters.calculate.attributeValue(this._id, "slashingMultiplier")}, - {name: "Thunder", value: Characters.calculate.attributeValue(this._id, "thunderMultiplier")}, + { name: "Acid", value: Characters.calculate.attributeValue(this._id, "acidMultiplier") }, + { name: "Bludgeoning", value: Characters.calculate.attributeValue(this._id, "bludgeoningMultiplier") }, + { name: "Cold", value: Characters.calculate.attributeValue(this._id, "coldMultiplier") }, + { name: "Fire", value: Characters.calculate.attributeValue(this._id, "fireMultiplier") }, + { name: "Force", value: Characters.calculate.attributeValue(this._id, "forceMultiplier") }, + { name: "Lightning", value: Characters.calculate.attributeValue(this._id, "lightningMultiplier") }, + { name: "Necrotic", value: Characters.calculate.attributeValue(this._id, "necroticMultiplier") }, + { name: "Piercing", value: Characters.calculate.attributeValue(this._id, "piercingMultiplier") }, + { name: "Poison", value: Characters.calculate.attributeValue(this._id, "poisonMultiplier") }, + { name: "Psychic", value: Characters.calculate.attributeValue(this._id, "psychicMultiplier") }, + { name: "Radiant", value: Characters.calculate.attributeValue(this._id, "radiantMultiplier") }, + { name: "Slashing", value: Characters.calculate.attributeValue(this._id, "slashingMultiplier") }, + { name: "Thunder", value: Characters.calculate.attributeValue(this._id, "thunderMultiplier") }, ]; // jscs:enable maximumLineLength multipliers = _.groupBy(multipliers, "value"); @@ -79,64 +79,61 @@ Template.healthCard.helpers({ }); Template.healthCard.events({ - "change #hitPointSlider": function(event){ + "change #hitPointSlider": _.debounce(function (event) { var value = event.currentTarget.value; var base = Characters.calculate.attributeBase(this._id, "hitPoints"); var adjustment = value - base; - Characters.update(this._id, {$set: {"hitPoints.adjustment": adjustment}}); + var modifier = { $set: { "hitPoints.adjustment": adjustment } }; //reset the death saves if we are gaining HP - if (value > 0) - Characters.update( - this._id, - {$set: { - "deathSave.pass": 0, - "deathSave.fail": 0, - "deathSave.stable": false, - }} - ); - }, - "change #temporaryHitPointSlider": function(event){ //this is the actual THP stat + if (value > 0) { + modifier.$set["deathSave.pass"] = 0; + modifier.$set["deathSave.fail"] = 0; + modifier.$set["deathSave.stable"] = false; + } + Characters.update(this._id, modifier); + }, 300), + "change #temporaryHitPointSlider": _.debounce(function (event) { //this is the actual THP stat var value = event.currentTarget.value; var base = Characters.calculate.attributeBase(this._id, "tempHP"); var adjustment = value - base; - Characters.update(this._id, {$set: {"tempHP.adjustment": adjustment}}); - }, - "change .extraHitPointSlider": function(event){ //this is the extra bars + Characters.update(this._id, { $set: { "tempHP.adjustment": adjustment } }); + }, 300), + "change .extraHitPointSlider": _.debounce(function (event) { //this is the extra bars var value = event.currentTarget.value; var used = this.maximum - value; - TemporaryHitPoints.update(this._id, {$set: {"used": used}}); - }, - "click .deleteEHP": function(event){ + TemporaryHitPoints.update(this._id, { $set: { "used": used } }); + }, 300), + "click .deleteEHP": function (event) { TemporaryHitPoints.remove(this._id); }, - "click #addExtraHP": function(event){ + "click #addExtraHP": function (event) { pushDialogStack({ template: "addEHPDialog", - data: {charId: this._id}, + data: { charId: this._id }, element: event.currentTarget.parentElement, }); }, - "click .failBubble": function(event){ + "click .failBubble": function (event) { if (event.currentTarget.disabled) return; var char = Template.parentData(); - if (event.currentTarget.icon === "radio-button-unchecked"){ - Characters.update(char._id, {$set: {"deathSave.fail": this.fail + 1}}); + if (event.currentTarget.icon === "radio-button-unchecked") { + Characters.update(char._id, { $set: { "deathSave.fail": this.fail + 1 } }); } else { - Characters.update(char._id, {$set: {"deathSave.fail": this.fail - 1}}); + Characters.update(char._id, { $set: { "deathSave.fail": this.fail - 1 } }); } }, - "click .passBubble": function(event){ + "click .passBubble": function (event) { if (event.currentTarget.disabled) return; var char = Template.parentData(); - if (event.currentTarget.icon === "radio-button-unchecked"){ - Characters.update(char._id, {$set: {"deathSave.pass": this.pass + 1}}); + if (event.currentTarget.icon === "radio-button-unchecked") { + Characters.update(char._id, { $set: { "deathSave.pass": this.pass + 1 } }); } else { - Characters.update(char._id, {$set: {"deathSave.pass": this.pass - 1}}); + Characters.update(char._id, { $set: { "deathSave.pass": this.pass - 1 } }); } }, - "click #stableButton": function(event){ + "click #stableButton": function (event) { var char = Characters.findOne(Template.parentData()._id, { - fields: {deathSave: 1} + fields: { deathSave: 1 } }); Characters.update(char._id, { $set: { diff --git a/app/server/lib/configuration/globalRateLimit.js b/app/server/lib/configuration/globalRateLimit.js new file mode 100644 index 00000000..ddd84634 --- /dev/null +++ b/app/server/lib/configuration/globalRateLimit.js @@ -0,0 +1,16 @@ +const logRateLimit = _.debounce(function (ruleInput) { + console.log(`Rate limit on ${ruleInput.name} by user ${ruleInput.userId} at IP ${ruleInput.clientAddress}`); +}, 500); + +DDPRateLimiter.addRule({ + type: 'method', + name(name) { + return true; + }, + // Rate limit per connection ID + connectionId() { return true; } +}, 10, 1000, (reply, ruleInput) => { + if (!reply.allowed) { + logRateLimit(ruleInput); + } +}); From c6bfb84bb033ab70d52951e796a42bb9e1a47ac8 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 24 Nov 2022 11:45:13 +0200 Subject: [PATCH 077/247] Updated default docs --- app/private/docs/defaultDocs.json | 238 +++++++++++++++--------------- 1 file changed, 119 insertions(+), 119 deletions(-) diff --git a/app/private/docs/defaultDocs.json b/app/private/docs/defaultDocs.json index 7eaad790..5b19e1e1 100644 --- a/app/private/docs/defaultDocs.json +++ b/app/private/docs/defaultDocs.json @@ -3,10 +3,10 @@ "_id": "ioei4uvDdGTAFqZrB", "name": "Properties", "order": 1, - "urlName": "properties", + "urlName": "property", "tags": [], "ancestors": [], - "href": "/docs/properties", + "href": "/docs/property", "published": true, "description": "Properties are all the things you can add to a character, like ability scores, actions, spells, and items." }, @@ -21,16 +21,16 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 2, - "urlName": "actions", + "urlName": "action", "tags": [], "description": "Actions are things your character can do. When an action is taken, all the properties under it are applied.\n\nAdd actions to your character sheet, then add children under the action to determine what happenes when the action is applied.\n\nWhen an action is applied it will create an entry in the character's log detailing all the properties that were applied and what their results were.\n\nThe following properties can all be applied by an action: \n\n - [Attribute Damage](/docs/property/attribute-damage)\n - [Branches](/docs/property/branch)\n - [Buffs](/docs/property/buff)\n - [Buff Removers](/docs/property/remove-buff)\n - [Damage](/docs/property/damage)\n - [Notes](/docs/property/note)\n - [Rolls](/docs/property/roll)\n - [Saving Throws](/docs/property/saving-throw)\n - Other actions\n\n---\n\n### Name\n\nThe name of the action.\n\n### Action type\n\nHow long the action takes to perform.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Attack roll\n\nA [computed field](/docs/computed-fields) which calculates the attack roll modifier. If this field is empty, no attack roll will be made. Use 0 to make an attack roll without a modifier.\n\nThe following variables may be added to the action scope when attack rolls are made:\n\n - `$attackDiceRoll` The value of the d20 roll before any modifiers were applied.\n - `$attackRoll` The total attack roll after modifiers.\n - `$criticalHit` Set to `true` if the attack roll's d20 is a natural 20. If `criticalHitTarget` is set, the attack roll's d20 must instead be equal to or greater than `criticalHitTarget` for this to be set to `true`.\n - `$criticalMiss` Set to `true` if the attack roll was not a critical hit and rolled a natural 1 on the d20 roll.\n - `$attackHit` If the attack roll is higher than or equal to the target's AC or a critical hit this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical hit.\n - `$attackMiss` If the attack roll is lower than the target's AC or a critical miss, this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical miss.\n\n### Summary\n\nA brief overview of what the action does. This will appear in the action card, and shows in the log when the action is applied.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Description\n\nA more detailed description of the action. The description does not show in the action card or the log when the action is applied.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Resource\n\nA resource can be any attribute that has a variable name. If the resource attribute is less than the amount required, the action can't be applied.\n\nIf you want to reduce an attribute when taking the action, but want the action to be applied regardless of the value of that attribute, consider using an [Attribute Damage](/docs/property/attribute-damage) property as a child of the action instead. Also use Attribute Damage when the amount to reduce the attribute is determined by a dice roll rather than a stable computed number.\n\n#### Resource attribute\n\nThe variable name of the attribute that will be consumed when taking this action.\n\n#### Resource quantity\n\nA [computed field](/docs/computed-fields) which determines how much of the attribute is required to apply this action. This amount will be deducted from the attribute every time the action is taken.\n\n### Ammo\n\nAmmo represents items that are requied to take the action. If an item is not selected, or there is insufficient quantity of the selected item, the action can't be appled.\n\n#### Ammo item\n\nSpecify what tag an item must have to be considered valid ammo for this action. Any item with this tag can be selected as ammo for this action.\n\n#### Ammo quantity\n\nA [computed field](/docs/computed-fields) which determines how many of the selected items are required to take this action. The quantity is deducted from the total quantity of the item when this action is applied.\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Target\n\nWho this action should apply to. The properties under the action will be applied to the Targets.\n\n- **Self** The action will apply its properties to the creature taking the action\n- **Single Target** The action will apply its properties without a target (for now)\n- **Multiple Targets** The action will apply its properties without a target (for now)\n\n### Uses\n\nA [computed field](/docs/computed-fields) which determines how many times this action can be used before it needs to be reset.\n\n### Uses used\n\nHow many of this action's uses have already been used. Should ideally be between 0 and the total uses available. This number is set to 0 when the action has uses and its uses are reset.\n\n### Don't show in log\n\nWhen this is true, the action does not show up in the log. This does not stop the action's children from appearing in the log when they are applied.\n\n### Reset\n\nIf set, the uses used field is set to 0 at the appropriate time.\n\n- **Long rest** Reset when the long rest button is pushed\n- **Short rest** Reset when either the long or short rest button is pushed", "published": true, - "href": "/docs/properties/actions" + "href": "/docs/property/action" }, { "_id": "FwpkjToybWQKCDhSr", @@ -43,15 +43,15 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 3, "urlName": "attribute-damage", "tags": [], "description": "When applied, attribute damage reduces the value of the [Attribute](/docs/properties/attributes) by some amount or set the value of an attribute to some amount. Attribute damage can by applied by actions or triggers.\n\nUsing a negative value to damage an attribute will heal the attribute instead.\n\n---\n\n### Attribute\n\nThe variable name of the attribute to target.\n\n### Amount\n\nA [computed field](/docs/computed-fields) which determined the amount to damage the attribute or set the attribute's value to.\n\n### Operation\n\n- **Damage** Reduce the value of the attribute by the amount, negative values heal the attribute instead\n- **Set** Set the value of the attribute to the amount\n\n### Target\n\n- **Target** Apply the attribute damage to the same target as the action applying this property\n- **Self** Apply the attribute damage to the creature taking the action\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Don't show in log\n\nWhen this is set, the attribute damage is applied, but does not show in the log.", - "href": "/docs/properties/attribute-damage", + "href": "/docs/property/attribute-damage", "published": true }, { @@ -65,16 +65,16 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 4, - "urlName": "attributes", + "urlName": "attribute", "tags": [], "description": "Attributes represent the numerical values of the creature.\n\nAttributes can be targeted by [effects](/docs/property/effect) which can change their total value in a non-destructive way. For example, if a class level gives you an ability score increase of +2 strength when it is taken, instead of directly editing the strength attribute, you add an effect to the class level that adds 2 to strength. The total value of strength will increase by 2 and it will show a record of that ability score increase and where it came from.\n\nAttributes, [skills](/docs/properties/skill), and [effects](/docs/property/effect) are the core properties of DiceCloud's creature engine.\n\nAttributes have the following fields that can be accessed in calculations with `variableName.field`:\n\n- `.total` The total of the attribute before being damaged\n- `.damage` the amount of damage the attribute has taken\n- `.value` The current value of the attribute including damage. `variableName` and `variableName.value` are equivalent.\n- `.modifier` If the attribute is an ability, this is its roll modifier, eg. `strength.modifier` is +2 when `strength.value` is 14\n\n---\n\n### Base value\n\nA [computed field](/docs/computed-fields) that determines the starting value of the attribute before it is modified by effects and other properties. Multiple properties can set the base value for a given variable name, when this happens the highest base value is chosen, and then all other effects are applied.\n\n### Name\n\nThe name of the attribute\n\n### Variable name\n\nThe name used to refer to the attribute in calculations and by effects. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation.\n\nIf multiple attributes share a variable name, only the last attribute on the [character tree](/docs/tree) will count as the defining attribute and appear on the sheet, while other attributes with that variable name will be used as base value [effects](/docs/property/effect).\n\n### Attribute type\n\n- **Ability** Ablity scores like Strength, Dexterity, etc. Ability scores get a modifier which can be accessed in calculations as `variableName.modifier`,\n- **Stat** Any numerical value that appears on the sheet. Speed, armor class.\n- **Modifier** Any numical value that appears on the sheet with a `+` or `-` sign, eg. Proficiency bonus.\n- **Hit Dice** Hit dice let you select the appropriate hit dice size. Creatures regain half their total hit dice on long rest.\n- **Health Bar** Health bars can by made to take or ignore damage in a specified order\n- **Resource** Rages, sourcery points, things that are spent to use actions.\n- **Spell Slot** Spell slots have a specific level and are used to cast spells.\n- **Utility** Utility attributes don't show up anywhere on the sheet, but can still be used for calculations\n\n### Description\n\nA detailed description of the attribute.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Health bar settings\n\nHealth bars can take or ignore damage and healing from applied damage properties targeting a creature. A lower ordered health bar will take damage before a higher ordered one.\n\nHealth bars can also change color depending on their value. At 50%+ full they are their property color, between 50% and 0% they fade from their half-full color to their empty color.\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Allow decimal values\n\nIf this is set, the attribute will not round-down when its value has a decimal.\n\n### Can be damaged into negative values\n\nIf this is set the attribute can be damaged past zero into negative values.\n\n### Can be incremented above total\n\nIf this is set the attribute can have negative damage such that the value exceeds the total. This can be useful if you are using the attribute to count, it can start at zero and be healed upwards to keep count.\n\n### Reset\n\nIf set, the damage on this attribute is reset to 0 at the appropriate time.\n\n- **Long rest** Reset when the long rest button is pushed\n- **Short rest** Reset when either the long or short rest button is pushed", "published": true, - "href": "/docs/properties/attributes" + "href": "/docs/property/attribute" }, { "_id": "X5NKw8m6ruy9Srynd", @@ -87,16 +87,16 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 5, - "urlName": "branches", + "urlName": "branch", "tags": [], "published": true, "description": "Branches are applied by actions, when they are applied they can control which of their immediate children are applied.\n\n---\n\n### Branch type\n\n- **If condition is true** Apply children if the condition (a [computed field](/docs/computed-fields)) resolves to `true` or a non-zero number\n- **Attack hit** Apply children if the attack roll hit the target\n- **Attack hit** Apply children if the attack roll missed the target\n- **Save failed** Apply children if target failed its saving throw\n- **Save suceeded** Apply children if target made its saving throw\n- **Apply to each target** Apply children separately to each target\n- **Random** Apply one of the immediate children at random\n- **Calculated Index** Use the index (a [computed field](/docs/computed-fields)) to choose which child to apply, starting at 1 for the first child.\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Don't show in log\n\nWhen this is set, the branch is applied, but does not show in the log. This does not prevent its children from appearing in the log.", - "href": "/docs/properties/branches" + "href": "/docs/property/branch" }, { "_id": "7KzMFHqo8DJtFtj7Q", @@ -109,13 +109,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 6, "urlName": "new-doc-6", - "href": "/docs/properties/new-doc-6", + "href": "/docs/property/new-doc-6", "tags": [], "removed": true, "removedAt": "2022-11-21T15:45:45.975Z" @@ -131,13 +131,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 7, "urlName": "new-doc-7", - "href": "/docs/properties/new-doc-7", + "href": "/docs/property/new-doc-7", "tags": [], "removed": true, "removedAt": "2022-11-21T15:49:16.862Z" @@ -153,13 +153,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 8, - "urlName": "buffs", - "href": "/docs/properties/buffs", + "urlName": "buff", + "href": "/docs/property/buff", "tags": [], "description": "Buffs are temporary changes to a character sheet that can be applied by actions. When a buff is applied, it is copied to the target character along with all of its children properties. \n\nBuffs can either be manually removed from the stats page, or be removed by an action applying a [buff remover](/docs/property/remove-buff/) property.\n\n### Variable freezing\n\nWhen a buff is applied, all the calculations in the child properties have their variables frozen to their values at the time the buff is applied. You can prevent this behavior for the whole buff by using the `don't freeze variables` option, or on an individual variable reference by prefixing the variable with the keyword `$target.`.\n\nFor example, if a character has 10 strength and 16 dexterity, and applies a buff with some child property containing the calculation `$target.strength + dexterity` the property's calculation will become `strength + 16` when it is copied to the target character.\n\n---\n\n### Name\n\nThe name of the buff.\n\n### Description\n\nDescription of the applied buff.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Target\n\n- **Target** Apply the buff to the target of the action\n- **Self** Apply the buff to the creature taking the action\n\n### Hide remove button\n\nIf this is set, the remove button next to the buff on the stats page will be hidden. Use this when you expect the buff to be removed automatically by another action.\n\n### Don't show in log\n\nIf set, the buff will not show its name and description in the log when applied.\n\n### Don't freeze variables\n\nPrevent the buff from freezing variables in child property calculations to their value at the time the buff was applied.\n\n### Tags\n\nSee [Tags](/docs/tags)", "published": true @@ -196,13 +196,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 11, - "urlName": "class-levels", - "href": "/docs/properties/class-levels", + "urlName": "class-level", + "href": "/docs/property/class-level", "description": "A class level is a property that represents a single level in a class. It is generally used as a child of a [Class property](/docs/property/class).\n\nFeatures and bonuses that are given by a class level get added as children of the class level.\n\n---\n\n### Level\n\nWhich level this property represents.\n\n### Name\n\nThe name of the class or subclass this level is part of\n\n### Variable name\n\nThe same variable name of the class this level belongs to.\n\n### Description\n\nA description of the benefits gained with this level.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/tags)", "published": true }, @@ -217,13 +217,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 12, - "urlName": "classes", - "href": "/docs/properties/classes", + "urlName": "class", + "href": "/docs/property/class", "published": true, "description": "A class is a property that expects [class levels](/docs/property/class-level) as its immediate children.\n\nLeveling up a class means choosing, or manually adding, class level properties to it. Class levels with the same variable name as the class, and that match all the required tags are found in libraries and added to the class.\n\nThe total level of the class can be accessed in calculations using `classVariableName.level`.\n\n## Making your own class\n\nSee [Create a Class](/docs/walkthroughs/create-a-class)\n\n---\n\n### Name\n\nThe name of the class\n\n### Variable name\n\nThe name used to refer to the class in calculations. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation.\n\n### Description\n\nA description of the class.\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Tags required\n\nOnly class levels with the same variable name as the class, and with tags that match the tags required will be returned from libraries when leveling up this class.\n\n### Condition\n\nA [computed field](/docs/computed-fields) to determine if the class is allowed to level up. If this field results in `true` or a number that is not 0, the class can be levelled, otherwise leveling is disabled." }, @@ -238,13 +238,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 13, - "urlName": "constants", - "href": "/docs/properties/constants", + "urlName": "constant", + "href": "/docs/property/constant", "description": "Constants are properties that store some primitive value in a variable name for use in other calculations.\n\nUnlike attributes, constants can store more than just numbers:\n\n- Arrays: `[1,2,3,4]`\n- Text strings: `'I am a cat'`\n- Numbers: `3.14`\n- Boolean values: `true`, `false`\n- Dice rolls: `1d20 + 2`\n\nConstants just can't use other variables in their calculations.\n\n### Overriding constants\n\nIf multiple constants have the same variable name, only the last active constant in the [character tree](/docs/tree) will be used as the definition for that variable name.\n\nThis can be used to re-write the value of some constant by ensuring there is a new active constant later in the sheet.\n\n---\n\n### Name\n\nThe name of the constants\n\n### Variable Name\n\nThe name used to refer to the constant in calculations. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation.\n\n### Value\n\nA [calculation](/docs/computed-fields) of the final value of the constant.", "published": true }, @@ -259,13 +259,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 14, - "urlName": "containers", - "href": "/docs/properties/containers", + "urlName": "container", + "href": "/docs/property/container", "description": "Containers are things that [items](/docs/property/item) can be put inside of.\n\n---\n\n### Name\n\nThe name of the container\n\n### Carried\n\nIf this is set the weight of the container and its contents will be added to the character's weight carried.\n\n### Value\n\nThe value of the container in gold pieces. Silver pieces are worth 0.1 gp and copper pieces are worth 0.01 gp. So a container that is worth 2 gp 4 sp 7 cp will have a value of 2.47 gp.\n\n### Weight\n\nThe weight of the container in lb.\n\n### Description\n\nA description of the container. \n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Contents are weightless\n\nIf this is set and the container is carried, only the container's own weight will be added to the weight carried by the creature.", "published": true }, @@ -280,13 +280,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 15, - "urlName": "damage-multipliers", - "href": "/docs/properties/damage-multipliers", + "urlName": "damage-multiplier", + "href": "/docs/property/damage-multiplier", "description": "Damage multipliers are used to define vulnerability, resistance, and immunity to damage types.\n\nA single multiplier can apply to multiple damage types, and choose whether or not to apply to an incoming source of damage based on the tags present on that damage.\n\n---\n\n### Name\n\nThe name of the feature that gives this damage multiplier\n\n### Value\n\n- **Immunity** The creature takes no damage from matching damage sources\n- **Resistance** Damage from matching sources is halved.\n- **Vulnerability** Damage from matching sources is doubled.\n\n### Damage types\n\nA list of damage types that this property applies to. Custom types can be used.\n\n### Damage tags required\n\nThis damage multiplier will only be applied if the incoming damage has all of these tags present.\n\n### Damage tags excluded\n\nThis damage multiplier will only apply if the incoming damage has none of these tags present.\n\n### Tags\n\nSee [Tags](/docs/tags)", "published": true }, @@ -301,13 +301,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 16, "urlName": "damage", - "href": "/docs/properties/damage", + "href": "/docs/property/damage", "published": true, "description": "Damage can be applied by an action to damage a target creature's [health bars](/docs/property/attribute). The damage will be modified by [damage multipliers](/docs/property/damage-multiplier), which apply vulnerability, resistance, and immunity before the damage is applied.\n\n---\n\n### Damage\n\nA [computed field](/docs/computed-fields) that determines how much damage to do to the target creature.\n\n### Damage type\n\nDamage type determines how the damage is treated by [damage multipliers](/docs/property/damage-multiplier). A custom type can be used, or one of the existing types can be selected.\n\nThere are two special damage types:\n\n**Extra damage** Damage with the `extra` type will take on the damage type of whatever damage was applied before it by an action. So if an action deals 12 `piercing` damage and `3` extra damage, it will instead deal 15 `piercing` damage.\n\n**Healing** Damage with the `healing` type will heal a creature instead of damaging them.\n\n### Target\n\n- **Target** Apply the damage to the target of the action\n- **Self** Apply the damage to the creature taking the action\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Don't show in log\n\nIf set, the damage will be applied but not show in the log." }, @@ -322,13 +322,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 17, - "urlName": "effects", - "href": "/docs/properties/effects", + "urlName": "effect", + "href": "/docs/property/effect", "description": "Effects are the core of the DiceCloud engine. Effect change the values of attributes, skills, and calculations in a way that is transparent and auditable, keeping character sheets organized and understandable, even when using intricate homebrew rules on high level characters.\n\n---\n\n### Name\n\nThe name of the feature that causes this effect.\n\n### Operation\n\nThe operation determines what the effect will do to the affected property or calcualtion.\n\n- **Base Value** Set the base value of the affected property. If a property has multiple base values, the highest is used\n- **Add** Add the value to the affected property or calculation\n- **Muliply** Multiply the affected property by the value\n- **Minimum** Prevent the affected property from having a value less than the effect value\n- **Maximum** Prevent the affected property from having a value greater than the effect value\n- **Maximum** Prevent the affected property from having a value greater than the effect value\n- **Set** Set the value affected property to the effect value\n- **Advantage** Give advantage to checks made using the affected property\n- **Disadvantage** Give disadvantage to checks made using the affected property\n- **Passive bonus** Add the effect value to the passive scores based on the affected property\n- **Fail** Checks made using the affected property automatically fail\n- **Conditional benefit** Add some text to the affected property describing the benefit recieved\n\n### Value\n\nA [computed field](/docs/computed-fields) that determines the value of the effect.\n\n### Text\n\nIf the operation is a conditional benefit, the note text that will show on affected properties.\n\n### Target stats by variable name\n\nIf selected the effect will apply to all properties that have the given variable names.\n\n### Variable names\n\nA list of variable names of properties to target with this effect.\n\n### Target properties by tags\n\nWhen targeting properties by tag, any property can be targeted with an effect. If the property is one that can usually be targeted by variable name, the effect will apply as ususal, however if the effect targets another property, it will apply to a [computed field](/docs/computed-fields) on the property instead.\n\nThese effects can be used for adding a bonus to a specific attack or damage roll, or manipulating any computed field on the creature.\n\n### Tags required\n\nOnly properties that match the required tags will be targeted by the effect.\n\n### Target field\n\nIf a property has multiple computed fields, which field should be targeted by this effect.\n\n### Tags\n\nSee [Tags](/docs/tags)", "published": true }, @@ -343,13 +343,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 18, - "urlName": "features", - "href": "/docs/properties/features", + "urlName": "feature", + "href": "/docs/property/feature", "description": "Features appear on the features tab. Classes, backgrounds, and race can all give a creature features.\n\n---\n\n### Name\n\nThe name of the feature.\n\n### Summary\n\nA summary of the feature. This will appear on the feature card.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Description\n\nA detailed description of the feature.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/tags)", "published": true }, @@ -364,15 +364,15 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 19, - "urlName": "folders", - "href": "/docs/properties/folders", + "urlName": "folder", + "href": "/docs/property/folder", "published": true, - "description": "Folders allow the [character tree](/docs/tree) to be organized.\n\n### Folders in actions\n\nWhen a folder is the child of an action, it and its children will not show on the action card, but will still appear in the detail view of the action and be applied when the action is taken.\n\n---\n\n### Name\n\nThe name of the folder.\n\n### Tags\n\nSee [Tags](/docs/tags)" + "description": "Folders allow the [character tree](/docs/tree) to be organized.\n\n### Folders in actions\n\nWhen a folder is the child of an action, it and its children will not show on the action card, but will still appear in the detail view of the action and be applied when the action is taken.\n\n### Grouping children\n\nWhen the folder is set to group stats on a card, the immediate children of the folder will be shown in a single card in a location on the sheet you can specify. For now, the following properties are supported:\n\n- Actions, including event actions\n- Attributes\n- Buffs\n- Containers\n- Features\n- Items\n- Notes\n- Skills\n- Toggles (with _Show on character sheet_ enabled)\n\n---\n\n### Name\n\nThe name of the folder.\n\n### Group children on a card\n\nImmediate children will be grouped on a card in the sheet.\n\n### Hide children from stats tab\n\nThe children of this card will not appear on the stats tab, but may still appear in other tabs.\n\n### Tab\n\nDetermines which tab the card will show up on.\n\n### Location\n\nWhere on the tab the card will be positioned.\n\n### Tags\n\nSee [Tags](/docs/tags)" }, { "_id": "5MsdJBbpALgMnYBwk", @@ -385,13 +385,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 20, - "urlName": "items", - "href": "/docs/properties/items", + "urlName": "item", + "href": "/docs/property/item", "published": true, "description": "Items are shown on the Inventory tab. Items can be carried, put in containers, or equipped on a creature. The children of an item are not active unless the item is equipped.\n\n---\n\n### Icon\n\nAn icon representing the item.\n\n### Equipped\n\nIf set, the item appears in the equipment list on the inventory tab and its children become active on the creature.\n\n### Name\n\nThe name of the item.\n\n### Plural name\n\nThe name to use if the quantity of the item is higher than 1.\n\n### Value\n\nThe value of a single item in gold pieces. Silver pieces are worth 0.1 gp and copper pieces are worth 0.01 gp. So an item that is worth 2 gp 4 sp 7 cp will have a value of 2.47 gp.\n\n### Weight\n\nThe weight of a single item in lb.\n\n### Quantity\n\nNumber of items. The value and quantity will be multiplied by the quantity to get the total value and weight of this stack of items.\n\n### Description\n\nA description of the item. \n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Show increment button\n\nIf this is set, the item will show an increment button in the detail view and on the inventory tab. This button can be used to quickly adjust the quantity of the item.\n\n### Requires attunemnt\n\nIf set, the item requires attunemnt to use.\n\n### Attuned\n\nIf set, the item is attuned and counts towards the total number of attuned items for the creature.\n\nIf a child property needs to determine if its parent item is attuned it can use `#item.attuned` in calculations, see *Ancestor references* in [computed fields](/docs/computed-fields)." }, @@ -406,13 +406,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 21, - "urlName": "notes", - "href": "/docs/properties/notes", + "urlName": "note", + "href": "/docs/property/note", "published": true, "description": "Notes are used to store text on the creature that does not have a direct mechanical impact. Notes appear on the journal tab when active on the character, or are shown in the log when applied by an [action](/docs/property/action).\n\n---\n\n### Name\n\nName of the note.\n\n### Summary\n\nA summary of the note. This will appear on the note card and in the log when applied by an [action](/docs/property/action).\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Description\n\nA detailed description of the feature.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/tags)" }, @@ -427,13 +427,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 22, "urlName": "point-buy", - "href": "/docs/properties/point-buy", + "href": "/docs/property/point-buy", "published": true, "description": "A point buy is a set of rows that lets the user choose a set of stats based on a cost per stat.\n\n---\n\n### Table name\n\nThe name of the point buy table.\n\n### Min\n\nThe lowest value available for each row\n\n### Max\n\nThe highest value available for each row\n\n### Cost\n\nA function that uses `value` as the value of a row and determines the cost of that value. For standard D&D 5e 27 point buy, this function is `[0, 1, 2, 3, 4, 5, 7, 9][value - 7]`\n\n### Total available points\n\nA [computed field](/docs/computed-fields) that determines how many points are available to spend in total\n\n## Rows\n\nUp to 32 rows can be added to a point buy table\n\n### Row name\n\nThe name of the row that will appear in the table\n\n### Row variable name\n\nThe variable name of the row that can be used in calculations. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation.\n\nIf the variable name matches an attribute with the same variable name, the row's value will be used as a base value for that attribute." }, @@ -448,13 +448,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 23, - "urlName": "proficiencies", - "href": "/docs/properties/proficiencies", + "urlName": "proficiency", + "href": "/docs/property/proficiency", "description": "Proficiencies add proficiency to an existing skill on the creature. If you need to add a tool or language proficiency to a creature, use a [Skill](/docs/property/skill) instead.\n\n---\n\n### Name\n\nName of the feature that is adding this proficiency\n\n### Skills\n\nA list of variable names of the skills to add proficiency to.\n\n### Proficiency\n\nHow much proficiency to add to the skill. If a skill has multiple proficiencies added to it, the highest one will be used.\n\n### Tags\n\nSee [Tags](/docs/tags)", "published": true }, @@ -469,13 +469,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 24, "urlName": "remove-buff", - "href": "/docs/properties/remove-buff", + "href": "/docs/property/remove-buff", "published": true, "description": "This property can remove a specific buff from a targeted creature.\n\n### Name\n\nThe name of the property. This shows in the log when the property is applied.\n\n### Remove parent buff\n\nWhen this is set and the property is applied, the property will remove the nearest parent buff. If this property is not the child of any buffs, it will log an error.\n\n### Remove all\n\nWhen this is set, all buffs that match the target tags will be removed from the targeted creature. If not set, only the first buff found with the matching tags will be removed.\n\n### Target\n\n- **Target** Matching buffs will be removed from the targeted creature\n- **Self** Matching buffs will be removed from the creature that applied the action\n\n### Tags required\n\nAny buff that has all of the required tags will be removed when the property is applied.\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Don't show in log\n\nWhen this is set, the property is applied, but does not show in the log." }, @@ -490,13 +490,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 25, - "urlName": "rolls", - "href": "/docs/properties/rolls", + "urlName": "roll", + "href": "/docs/property/roll", "published": true, "description": "Rolls are properties that store the result of a calculation to a variable name when applied by an [action](/docs/property/action). The variable name only exists for the duration of that particalar action.\n\nRolls can be useful if you need to deal the same damage to multiple targets, or if damage needs to be rolled then halved by succeeding on a saving throw.\n\n---\n\n### Name\n\nName of the roll. This will be shown in the log when the roll is applied.\n\n### Variable name\n\nThe variable name to store the result of the roll for the duration of the action. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation.\n\n### Roll\n\nA [computed field](/docs/computed-fields) that is computed when the roll is applied by an action.\n\n### Don't show in log\n\nIf set, the roll will be applied and store its result in the variable name, but not be shown in the log.\n\n### Tags\n\nSee [Tags](/docs/tags)" }, @@ -511,13 +511,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 26, - "urlName": "saving-throws", - "href": "/docs/properties/saving-throws", + "urlName": "saving-throw", + "href": "/docs/property/saving-throw", "description": "Saving throws are properties that cause the target to make a saving throw when applied. If you want to add a type of saving throw like Strength Save to a creature, use a [skill](/docs/property/skill) instead.\n\nWhen a saving throw is applied, the following variables are added to the scope of that action:\n\n- `$saveFailed` Set to `true` if the target failed its saving throw or there are no targets for the saving throw\n- `$saveSucceeded` Set to `true` if the target made its saving throw or there are no targets for the saving throw\n- `$saveDiceRoll` The unmodified d20 roll the target made to save\n- `$saveRoll` The final value of the saving throw roll after modifiers\n\n### Name\n\nThe name of the saving throw. Usually the ability saving throw targeted: \"Strength Save\".\n\n### DC\n\nThe DC of the saving throw that the target needs to meet\n\n### Save\n\nThe variable name of the skill that will be used to make the saving throw.\n\n### Target\n\n- **Target** Apply the saving throw to the targets of the action. Each target will make the saving throw in turn. Child properties will be applied to each target separately with the results of their individual saving throw. If a value like damage needs to be shared between targets, it should be calculated in a [Roll](/docs/property/roll) before the saving throw.\n- **Self** Apply the saving throw to the creature taking the action. The creature taking the action will become the target for all child properties.\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Don't show in log\n\nIf set, the saving throw will not show in the log when applied, but will still be rolled and apply its children.", "published": true }, @@ -532,14 +532,14 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 27, - "urlName": "skills", - "href": "/docs/properties/skills", - "description": "Skills represent things the creature can be proficient in. Skills can have their values or behavior modified by [effects](/docs/property/effect), and their proficiencies modified by [proficiencies](/docs/property/proficiency).\n\n---\n\n### Name\n\nThe name of the skill.\n\n### Variable name\n\nThe name used to refer to the skill in calculations and by effects. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation.\n\n### Ability\n\nThe ability score that is the basis for checks made with this skill\n\n### Type\n\n- **Skill** Regular skills like *Athletics*, *Sleight* of Hand\n- **Save** Saving throws like *Strength*, *Charisma*\n- **Check** Checks that aren't skill like *Initiative*\n- **Tool** Tool proficiencies\n- **Weapon** Weapon proficiencies\n- **Armor** Armor proficiencies\n- **Language** Language proficiencies\n- **Utility** Skills that don't show on the charcater sheet but can be used in calculations\n\n### Description\n\nA detailed description of the skill.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Base value\n\nA [computed field](/docs/computed-fields) that determines the starting value of the skill before it is modified by effects and other properties. Multiple properties can set the base value for a given variable name, when this happens the highest base value is chosen, and then all other effects are applied.\n\n### Base proficiency\n\nThe starting proficiency of the skill.", + "urlName": "skill", + "href": "/docs/property/skill", + "description": "Skills represent things the creature can be proficient in. Skills can have their values or behavior modifier by [effects](/docs/property/effect), and their proficiencies modified by [proficiencies](/docs/property/proficiency).\n\n---\n\n### Name\n\nThe name of the skill.\n\n### Variable name\n\nThe name used to refer to the skill in calculations and by effects. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation.\n\n### Ability\n\nThe ability score that is the basis for checks made with this skill\n\n### Type\n\n- **Skill** Regular skills like *Athletics*, *Sleight* of Hand\n- **Save** Saving throws like *Strength*, *Charisma*\n- **Check** Checks that aren't skill like *Initiative*\n- **Tool** Tool proficiencies\n- **Weapon** Weapon proficiencies\n- **Armor** Armor proficiencies\n- **Language** Language proficiencies\n- **Utility** Skills that don't show on the charcater sheet but can be used in calculations\n\n### Description\n\nA detailed description of the skill.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Base value\n\nA [computed field](/docs/computed-fields) that determines the starting value of the skill before it is modified by effects and other properties. Multiple properties can set the base value for a given variable name, when this happens the highest base value is chosen, and then all other effects are applied.\n\n### Base proficiency\n\nThe starting proficiency of the skill.", "published": true }, { @@ -553,13 +553,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 28, "urlName": "slot-filler", - "href": "/docs/properties/slot-filler", + "href": "/docs/property/slot-filler", "published": true, "description": "A slot filler is a property that can be used to add more complex behavior to filling a [slot](/docs/property/slot) from a library.\n\n---\n\n### Name\n\nThe name of the slot filler that will show when choosing the filler from the library.\n\n### Icon\n\nIcon of the slot filler\n\n### Description\n\nA detailed description of the slot filler.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Picture URL\n\nA link to an image to use for this slot filler when being chosen from a library.\n\n### Type\n\nSlot fillers can pretend to be any type of property when a slot is being filled.\n\n### Quantity\n\nHow many spaces the slot filler will take up in a slot.\n\n### Condition\n\nA [computed field](/docs/computed-fields) that determines whether this slot filler can be added to a character.\n\n### Tags\n\nSee [Tags](/docs/tags)" }, @@ -574,13 +574,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 29, - "urlName": "slots", - "href": "/docs/properties/slots", + "urlName": "slot", + "href": "/docs/property/slot", "description": "Slots are the main way creatures interact with libraries. A slot can be filled by choosing a property from a library that fits that particular slot.\n\nIn a complete library, a creature can be built entirely by choosing which properties to fill each slot with.\n\nSlots show up on the build tab, and are highlighted when they have space that can be filled.\n\nIf you are building a creature without a library, you should either ignore slots entirely, or fill them with your own custom properties.\n\n---\n\n### Name\n\nThe name of the slot.\n\n### Type \n\nWhat kind of property this slot expects to fill it.\n\n### Tags required\n\nProperties in a library must have the required tags to fill the slot.\n\n### Quantity\n\nHow many properties are expected to fill this slot. Use 0 for allowing an unlimited number of properties.\n\n### Condition\n\nA [computed field](/docs/computed-fields) that determines whether this slot can accept new properties.\n\n### Unique\n\nThe slot can control how it deals with the uniqueness of properties that fill it.\n\n### Description\n\nA detailed description of the attribute.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Hide when full\n\nWhen set the slot will hide itself when it is filled.\n\n### Ignored\n\nWhen set the slot will not show a prompt card on the build tab.\n\n### Tags\n\nSee [Tags](/docs/tags)", "published": true }, @@ -595,13 +595,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 30, - "urlName": "spell-lists", - "href": "/docs/properties/spell-lists", + "urlName": "spell-list", + "href": "/docs/property/spell-list", "published": true, "description": "Spell lists are collections of [spells](/docs/property/spell).\n\n---\n\n### Name\n\nThe name of the spell list.\n\n### Description\n\nA detailed description of the spell list.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Maximum prepared spells\n\nA [computed field](/docs/computed-fields) that determines how many spells can be considered ready to cast in this spell list.\n\n### Spell casting ability\n\nThe spellcasting ablity for this spell list. The variable name of the ability can be accessed using `#spellList.ability` and the ability modifier with `#spellList.abilityMod`. Setting this field will automatically update Spell save DC and Attack roll bonus if they aren't set manually.\n\n### Spell save DC\n\nA [computed field](/docs/computed-fields) that determines the DC of saving throws in this spell list. Spells can access the DC of their spell list using `#spellList.dc`\n\n### Attack roll bonus\n\nA [computed field](/docs/computed-fields) that determines the bonus to add to a d20 when making a spell attack with a spell in this spell list. Spells can access the attack roll bonus of their spell list using `#spellList.attackRollBonus`\n\n### Tags\n\nSee [Tags](/docs/tags)" }, @@ -616,13 +616,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 31, - "urlName": "spells", - "href": "/docs/properties/spells", + "urlName": "spell", + "href": "/docs/property/spell", "description": "Spells work similarly to [actions](/docs/property/action). They appear on the spells tab and can be cast with or without using up spell slots.\n\n---\n\n### Always prepared\n\nA spell that is always prepared does not count towards the spell list's maximum prepared spells and is always active and ready to cast.\n\n### Prepared\n\nA prepared spell is ready to cast and counts against a spell list's maximum prepared spells.\n\n### Cast without spell slots\n\nWhen set, this spell can be cast without consuming spell slots. It will however consume its own uses and resources.\n\n### School\n\nWhat school the spell belongs to.\n\n### Casting time\n\nHow long the spell takes to Cast\n\n### Range\n\nThe range of the spell\n\n### Duration\n\nHow long the spell lasts\n\n### Components\n\nWhether the spell requires verbal, somatic, or material components and whether the spell is a ritual or requires concentration.\n\n### Target\n\nWho this spell should apply to. The properties under the spell will be applied to the targets.\n\n- **Self** The spell will apply its properties to the creature casting the spell\n- **Single Target** The spell will apply its properties without a target (for now)\n- **Multiple Targets** The spell will apply its properties without a target (for now)\n\n### Attack roll\n\nA [computed field](/docs/computed-fields) which calculates the spell attack roll modifier. If this field is empty, no attack roll will be made. Use 0 to make an attack roll without a modifier. To use the spell list's attack roll bonus use `#spellList.attackRollBonus`.\n\nThe following variables may be added to the action scope when attack rolls are made:\n\n - `$attackDiceRoll` The value of the d20 roll before any modifiers were applied.\n - `$attackRoll` The total attack roll after modifiers.\n - `$criticalHit` Set to `true` if the attack roll's d20 is a natural 20. If `criticalHitTarget` is set, the attack roll's d20 must instead be equal to or greater than `criticalHitTarget` for this to be set to `true`.\n - `$criticalMiss` Set to `true` if the attack roll was not a critical hit and rolled a natural 1 on the d20 roll.\n - `$attackHit` If the attack roll is higher than or equal to the target's AC or a critical hit this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical hit.\n - `$attackMiss` If the attack roll is lower than the target's AC or a critical miss, this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical miss.\n\n### Summary\n\nA brief overview of what the spell does. This will show in the log when the spell is cast.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Description\n\nA more detailed description of the spell. The description does not show in the log when the spell is cast.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Resource\n\nA resource can be any attribute that has a variable name. If the resource attribute is less than the amount required, the spell can't be cast.\n\nIf you want to reduce an attribute when casting the spell, but want the spell to be applied regardless of the value of that attribute, consider using an [Attribute Damage](/docs/property/attribute-damage) property as a child of the spell instead. Also use Attribute Damage when the amount to reduce the attribute is determined by a dice roll rather than a stable computed number.\n\n#### Resource attribute\n\nThe variable name of the attribute that will be consumed when casting this spell.\n\n#### Resource quantity\n\nA [computed field](/docs/computed-fields) which determines how much of the attribute is required to apply this spell. This amount will be deducted from the attribute every time the spell is cast\n### Ammo\n\nAmmo represents items that are requied to cast the spell. If an item is not selected, or there is insufficient quantity of the selected item, the spell can't be appled.\n\n#### Ammo item\n\nSpecify what tag an item must have to be considered valid ammo for this spell. Any item with this tag can be selected as ammo for this spell.\n\n#### Ammo quantity\n\nA [computed field](/docs/computed-fields) which determines how many of the selected items are required to cast this spell. The quantity is deducted from the total quantity of the item when this spell is applied.\n\n### Uses\n\nA [computed field](/docs/computed-fields) which determines how many times this spell can be used before it needs to be reset.\n\n### Uses used\n\nHow many of this spell's uses have already been used. Should ideally be between 0 and the total uses available. This number is set to 0 when the spell has uses and its uses are reset.\n\n### Reset\n\nIf set, the uses used field is set to 0 at the appropriate time.\n\n- **Long rest** Reset when the long rest button is pushed\n- **Short rest** Reset when either the long or short rest button is pushed\n\n\n### Tags\n\nSee [Tags](/docs/tags)", "published": true }, @@ -637,13 +637,13 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 32, - "urlName": "toggles", - "href": "/docs/properties/toggles", + "urlName": "toggle", + "href": "/docs/property/toggle", "published": true, "description": "Toggles are a way to turn on and off parts of a creature. When a toggle is off, none of its children will be active.\n\nCalculated toggles should be avoided if possible, because while they offer a lot of power and flexibility to the creature engine, they often create [dependency loops](/docs/dependency-loops) that can be difficult to troubleshoot, causing parts of a creature to calculate incorrectly.\n\nCalculated toggles can be applied by [actions](/docs/property/action) and will apply their children if the condition is true, but they should be avoided in favor of [conditional branches](/docs/property/branch) which can do the same, but are more efficient.\n\n---\n\n### Name\n\nThe name of the toggle.\n\n### Variable name\n\nThe name used to refer to the value of the toggle in calculations. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation.\n\n### Show on character sheet\n\nIf set, the toggle with show a checkbox on the character sheet. A calculated toggle will show a disabled checkbox, filled in if the toggle's calculation returned `true` or a value that isn't 0.\n\n### State\n\n- **Enabled** The toggle and its children are active\n- **Disabled** The toggle and its children are inactive\n- **Calculated** The active status of the toggle depends on the result of the condition. Use with caution.\n\n### Condition\n\nA [computed field](/docs/computed-fields) that determines if the toggle is active. Use with caution.\n\n### Tags\n\nSee [Tags](/docs/tags)" }, @@ -658,14 +658,14 @@ { "id": "ioei4uvDdGTAFqZrB", "collection": "docs", - "name": "Properties", - "urlName": "properties" + "urlName": "property", + "name": "Properties" } ], "order": 33, - "urlName": "triggers", - "href": "/docs/properties/triggers", - "description": "Triggers apply their children whenever their condition is met. They work like [actions](/docs/property/action) that are taken automatically.\n\n---\n\n### Name\n\nThe name of the trigger.\n\n### Timing\n\n- **Before** The trigger is applied before the triggering event takes place\n- **After** The trigger is fired after the triggering event\n\n### Event\n\n- **Do action** While the creature is doing an action, the action property specified in *Event type* is applied\n- **Roll check** The creature makes a check\n- **Attribute damaged or healed** One of the creature's attributes changed value through attribute damage or manual adjustment\n- **Short or long rest**\n- **Short rest**\n- **Long Rest**\n\n### Event type\n\nThe trigger will apply when this property type is applied by the action\n\n### Tags required\n\nIf this trigger is fired by a property, the property must match these tags for the trigger to fire.\n\n### Condition\n\nA [computed field](/docs/computed-fields) to determine if the trigger should fire. The trigger will fire if the condition field is empty or if it returns `true` or a value that isn't 0.\n\n### Description\n\nA detailed description of the trigger.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Don't show in log\n\nWhen this is true, the trigger does not show up in the log. This does not stop the trigger's children from appearing in the log when they are applied.", + "urlName": "trigger", + "href": "/docs/property/trigger", + "description": "Triggers apply their children whenever their condition is met. They work like [actions](/docs/property/action) that are taken automatically.\n\n---\n\n### Name\n\nThe name of the trigger.\n\n### Timing\n\n- **Before** The trigger is applied before the triggering event takes place\n- **After** The trigger is fired after the triggering event\n\n### Event\n\n- **Do action** While the creature is doing an action, the action property specified in *Event type* is applied\n- **Roll check** The creature makes a check\n- **Attribute damaged or healed** One of the creature's attributes changed value through attribute damage or manual adjustment\n- **Short or long rest**\n- **Short rest**\n- **Long Rest**\n\n### Event type\n\nThe trigger will apply when this property type is applied by the action\n\n### Tags required\n\nIf this trigger is fired by a property, the property must match these tags for the trigger to fire.\n\n### Condition\n\nA [computed field](/docs/computed-fields) to determine if the trigger should fire. The trigger will fire if the condition field is empty or if it returns `true` or a value that isn't 0.\n\n### Description\n\nA detailed description of the trigger.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)\n\n### Don't show in log\n\nWhen this is true, the trigger does not show up in the log. This does not stop the trigger's children from appearing in the log when they are applied.", "published": true }, { @@ -708,7 +708,7 @@ "urlName": "dependency-loops", "href": "/docs/concepts/dependency-loops", "published": true, - "description": "When a variable is referenced in a calculation, that calculation can be said to depend on that variable. In order for the calculation to compute, the value of the variable needs to be known.\n\nBut consider the following property values that could be added to a creature\n\n- The creature's Strength base value is set to `dexterity + 1` so that it will always have 1 more strength than dexterity\n- The creature's Dexterity base value is set to `constitution + 1` so that it will always have 1 more dexterity than constitution\n- The creature's Constitution base value is set to `strength` so that its constitution is always equal to its strength\n\nIt is not possible to resolve these calculations, not just because no values exist which satisfy the constraints, but because strength depends on dexterity which depends on constitution which depends on strength. None can be computed before the others have finalized their values. This is a dependency loop.\n\nMost dependency loops that appear in actual DiceCloud creatures are less trivial than this example, but they cause the same result: a sheet that can't be accurately computed. In these cases, DiceCloud does its best, chooses an order to resolve the calculations arbitrarily, and continues calculating. An error will show on the Build tab to let you know that something went wrong.\n\n![dependency loop example](/images/docs/dependency-loop.png)\n\n## Toggles\n\nCalculated [Toggles](/docs/property/toggle) are the main source of dependency loops on creatures, because they create a dependency that isn't as obvious as a calculation might be. When a toggle is in calculated mode, its children do not know whether they are active or not until the calulation is resolved. Because of this, every calculation under the toggle depends on the toggles calaculation, making the chance for a loop to be formed more likely the more children are under a toggle.\n\nConsider this example\n\n- A calculated toggle that is active if `strength < 10`\n- An effect under that toggle that adds 2 to `strength`\n\nThe effect can't compute, because it does not know if it is active yet, so the toggle must compute its calculation first. The toggle needs to know if `strength` is greater than 10. Strength depends on all of the effects targeting it, it must know if the +2 effect is active or not. This creates a dependency loop, because there is no valid order in which everything can be calculated.\n\n## Troubleshooting a dependency loop\n\n- First, identify all the properties that make up the dependency loop. These are linked in the depdency loop error message. The field names in square brackets after the property name indicates which calculations on the property are directly involved.\n- Move any properties in the loop out from being children of calculated Toggles\n- Use static values in place of variables where they are not stricly needed\n- Ask for [help](/feedback)" + "description": "When a variable is referenced in a calculation, that calculation can be said to depend on that variable. In order for the calculation to compute, the value of the variable needs to be known.\n\nBut consider the following property values that could be added to a creature\n\n- The creature's Strength base value is set to `dexterity + 1` so that it will always have 1 more strength than dexterity\n- The creature's Dexterity base value is set to `constitution + 1` so that it will always have 1 more dexterity than constitution\n- The creature's Constitution base value is set to `strength` so that its constitution is always equal to its strength\n\nIt is not possible to resolve these calculations, not just because no values exist which satisfy the constraints, but because strength depends on dexterity which depends on constitution which depends on strength. None can be computed before the others have finalized their values. This is a dependency loop.\n\nMost dependency loops that appear in actual DiceCloud creatures are less trivial than this example, but they cause the same result: a sheet that can't be accurately computed. In these cases, DiceCloud does its best, chooses an order to resolve the calculations arbitrarily, and continues calculating. An error will show on the Build tab to let you know that something went wrong.\n\n![dependency loop example](/images/docs/dependency-loop.png)\n\n## Toggles\n\nCalculated [Toggles](/docs/property/toggle) are the main source of dependency loops on creatures, because they create a dependency that isn't as obvious as a calculation might be. When a toggle is in calculated mode, its children do not know whether they are active or not until the calulation is resolved. Because of this, every calculation under the toggle depends on the toggles calaculation, making the chance for a loop to be formed more likely the more children are under a toggle.\n\nConsider this example\n\n- A calculated toggle that is active if `strength < 10`\n- An effect under that toggle that adds 2 to `strength`\n\nThe effect can't compute, because it does not know if it is active yet, so the toggle must compute its calculation first. The toggle needs to know if `strength` is greater than 10. Strength depends on all of the effects targeting it, it must know if the +2 effect is active or not. This creates a dependency loop, because there is no valid order in which everything can be calculated.\n\n## Troubleshooting a dependency loop\n\n- First, identify all the properties that make up the dependency loop. These are linked in the dependency loop error message. The field names in square brackets after the property name indicates which calculations on the property are directly involved.\n- Move any properties in the loop out from being children of calculated Toggles\n- Use static values in place of variables where they are not strictly needed\n- Ask for [help](/feedback)" }, { "_id": "KFkmXFLQrdPQNpJ7X", From f13774df11539002367f4017f6a27ad3e35fe282 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 24 Nov 2022 11:56:20 +0200 Subject: [PATCH 078/247] Removed old mardown docs --- app/private/docs/computed-fields.md | 81 ------------------------- app/private/docs/dependency-loops.md | 33 ---------- app/private/docs/docs.md | 39 ------------ app/private/docs/inline-calculations.md | 11 ---- app/private/docs/tags.md | 14 ----- 5 files changed, 178 deletions(-) delete mode 100644 app/private/docs/computed-fields.md delete mode 100644 app/private/docs/dependency-loops.md delete mode 100644 app/private/docs/docs.md delete mode 100644 app/private/docs/inline-calculations.md delete mode 100644 app/private/docs/tags.md diff --git a/app/private/docs/computed-fields.md b/app/private/docs/computed-fields.md deleted file mode 100644 index 6ca1bef5..00000000 --- a/app/private/docs/computed-fields.md +++ /dev/null @@ -1,81 +0,0 @@ -# Computed fields - -Some fields in DiceCloud creature properties expect calculations. These fields are then computed by the DiceCloud engine. - -Some fields, like the value of an attirbute, resolve down to a single number, while others, like the damage to deal in an attack, only simplify their calculation as far as they can, and then resolve down to a number when applied. Avoid adding dice rolls to calculations that expect to resolve down to a number, because they will re-roll every time the creature is recalculated, causing instability in the creature's stats. - -## Parser - -The DiceCloud parser can understand the following syntax: - -| | | -| :- | :- | -| **Numbers** | `13`, `3.14` | -| **Dice rolls** | `3d6`, `(1 + 2)d4`| -| **Strings of text** | `'Some text'`, `"some other text"` | -| **Boolean values** | `true` or `false`. When DiceCloud expects a boolean, `0`, an empty string `''` and `false` are all considered false by DiceCloud's engine, every other value is considered true. | -| **Variable names** | `variableName` | -| **Addition and subtraction** | `1 + 2 + 3`, `12 - 6` | -| **Multiplication** | `6 * 4`, `12 * 2` = `24` | -| **Exponents** | `3 ^ 2` Raise 3 to the power of 2 | -| **Modulo** | Returns the remainder of a division operation `15 % 6` = `3` | -| **AND** | `&` or `&&`: Returns the value of the right hand side if the left side is true `true & 'cat'` = `'cat'` | -| **OR** | `|` or `||`: Returns the left hand side if it is true, otherwise returns the right hand side `'dog' || 'cat'` = `'dog'` | -| **NOT** | `!` returns false if the value after it is true, otherwise returns false | -| **Comparisons** | greater than: `>`, less than: `<`, greater than or equal to: `>=`, less than or equal to: `<=`, equal: `=` or `==` or `===`, not equal: `!=` or `!==` | -| **If-else** | `condition ? resultIfTrue : resultIfFalse`, `level > 10 ? 'high tier' : 'low tier'` | -| **Arrays** | lists of values `[3, 6, 9, 12]`. | -| **Array Indexes** | A value can be chosen from an array using another set of square brackets: `[3, 6, 9, 12][2]` = `[6]` because `[2]` fetches the 2nd value in the array. Arrays start at 1 in DiceCloud so that level tables can have 20 entries and be accessed by `array[level]`. | -| **Function calls** | `functionName(argument1, argument1)` See [Functions](/docs/functions) for a full list of available functions. | - -## Special variables - -### Built-in variables - -These variables are added to the creature automatically when relevant. They can be overriden if needed by creating a property with the same variable name. They can also be targetted by effects. - -- `xp` A total of all the experiences with xp added to the character sheet -- `milestoneLevels` A total of all the experiences with milestone levels added to the character sheet -- `itemsAttuned` Number of items the creature is attuned to -- `weightEquipment` Total weight of all equipment on the creature -- `valueEquipment` Total value of all equipment on the creature -- `weightTotal` Total weight of the creature's entire inventory -- `valueTotal` Total value of the creature's entire inventory -- `weightCarried` Total weight of all carried items and containers -- `valueCarried` Total value of all carried items and containers -- `level` The current level of the creature, including all class levels -- `criticalHitTarget` Defaults to 20, the natural roll needed to consider an attack roll as a critical hit - -### Action variables - -These variables are available during an action after the relevant property has been applied. - -For Advanced users, a [Roll](/docs/property/roll) can set these variables, overriding the default behavior. - -#### [Actions](/docs/property/action) - -- `$attackDiceRoll` The value of the d20 roll before any modifiers were applied. -- `$attackRoll` The total attack roll after modifiers. -- `$criticalHit` Set to `true` if the attack roll's d20 is a natural 20. If `criticalHitTarget` is set, the attack roll's d20 must instead be equal to or greater than `criticalHitTarget` for this to be set to `true`. -- `$criticalMiss` Set to `true` if the attack roll was not a critical hit and rolled a natural 1 on the d20 roll. -- `$attackHit` If the attack roll is higher than or equal to the target's AC or a critical hit this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical hit. -- `$attackMiss` If the attack roll is lower than the target's AC or a critical miss, this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical miss. - -#### [Damage](/docs/property/damage) - -- `$lastDamageType` The type of damage dealt last, any damage that has the `extra` type will use this damage type instead - -#### [Saving throws](/docs/property/saving-throw) - -- `$saveFailed` Set to `true` if the target failed its saving throw or there are no targets for the saving throw -- `$saveSucceeded` Set to `true` if the target made its saving throw or there are no targets for the saving throw -- `$saveDiceRoll` The unmodified d20 roll the target made to save -- `$saveRoll` The final value of the saving throw roll after modifiers - -## Ancestor references - -The ancestors of a property can be accessed directly using the `#ancestorType` syntax. - -For example, a spell might need to know the save DC of the spell list that it is inside of, it can use `#spellList.dc`. - -Triggers and their children work differently: They don't have access to their own ancestors, but rather inherit the ancestors of the property that caused them to fire. For example, a trigger at the root of the creature's tree might be fired by a spell being cast, you can still use references to ancestors like `#spellList.attackRollBonus` inside that trigger as if it were under the spell itself. diff --git a/app/private/docs/dependency-loops.md b/app/private/docs/dependency-loops.md deleted file mode 100644 index 20f8d82f..00000000 --- a/app/private/docs/dependency-loops.md +++ /dev/null @@ -1,33 +0,0 @@ -# Dependency loops - -When a variable is referenced in a calculation, that calculation can be said to depend on that variable. In order for the calculation to compute, the value of the variable needs to be known. - -But consider the following property values that could be added to a creature - -- The creature's Strength base value is set to `dexterity + 1` so that it will always have 1 more strength than dexterity -- The creature's Dexterity base value is set to `constitution + 1` so that it will always have 1 more dexterity than constitution -- The creature's Constitution base value is set to `strength` so that its constitution is always equal to its strength - -It is not possible to resolve these calculations, not just because no values exist which satisfy the constraints, but because strength depends on dexterity which depends on constitution which depends on strength. None can be computed before the others have finalized their values. This is a dependency loop. - -Most dependency loops that appear in actual DiceCloud creatures are less trivial than this example, but they cause the same result: a sheet that can't be accurately computed. In these cases, DiceCloud does its best, chooses an order to resolve the calculations arbitrarily, and continues calculating. An error will show on the Build tab to let you know that something went wrong. - -![dependency loop example](/images/docs/dependency-loop.png) - -## Toggles - -Calculated [Toggles](/docs/property/toggle) are the main source of dependency loops on creatures, because they create a dependency that isn't as obvious as a calculation might be. When a toggle is in calculated mode, its children do not know whether they are active or not until the calulation is resolved. Because of this, every calculation under the toggle depends on the toggles calaculation, making the chance for a loop to be formed more likely the more children are under a toggle. - -Consider this example - -- A calculated toggle that is active if `strength < 10` -- An effect under that toggle that adds 2 to `strength` - -The effect can't compute, because it does not know if it is active yet, so the toggle must compute its calculation first. The toggle needs to know if `strength` is greater than 10. Strength depends on all of the effects targeting it, it must know if the +2 effect is active or not. This creates a dependency loop, because there is no valid order in which everything can be calculated. - -## Troubleshooting a dependency loop - -- First, identify all the properties that make up the dependency loop. These are linked in the depdency loop error message. The field names in square brackets after the property name indicates which calculations on the property are directly involved. -- Move any properties in the loop out from being children of calculated Toggles -- Use static values in place of variables where they are not stricly needed -- Ask for [help](/feedback) diff --git a/app/private/docs/docs.md b/app/private/docs/docs.md deleted file mode 100644 index 424a157e..00000000 --- a/app/private/docs/docs.md +++ /dev/null @@ -1,39 +0,0 @@ -# DiceCloud Docs - -## Properties - -- ### [Action](/docs/property/action) -- ### [Attribute](/docs/property/attribute) -- ### [Attribute Damage](/docs/property/attribute-damage) -- ### [Buff](/docs/property/buff) -- ### [Remove Buff](/docs/property/remove-buff) -- ### [Branch](/docs/property/branch) -- ### [Class](/docs/property/class) -- ### [Class Level](/docs/property/class-level) -- ### [Constant](/docs/property/constant) -- ### [Container](/docs/property/container) -- ### [Damage](/docs/property/damage) -- ### [Damage Multiplier](/docs/property/damage-multiplier) -- ### [Effect](/docs/property/effect) -- ### [Feature](/docs/property/feature) -- ### [Item](/docs/property/item) -- ### [Note](/docs/property/note) -- ### [Point Buy](/docs/property/point-buy) -- ### [Proficiency](/docs/property/proficiency) -- ### [Roll](/docs/property/roll) -- ### [Saving Throw](/docs/property/saving-throw) -- ### [Skill](/docs/property/skill) -- ### [Slot](/docs/property/slot) -- ### [Slot Filler](/docs/property/slot-filler) -- ### [Spell List](/docs/property/spell-list) -- ### [Spell](/docs/property/spell) -- ### [Toggle](/docs/property/toggle) -- ### [Trigger](/docs/property/trigger) - -## Topics - -- ### [Computed fields](/docs/computed-fields) -- ### [Inline Calculations](/docs/inline-calculations) -- ### [Dependency Loops](/docs/dependency-loops) -- ### [Functions](/docs/functions) -- ### [Tags](/docs/tags) diff --git a/app/private/docs/inline-calculations.md b/app/private/docs/inline-calculations.md deleted file mode 100644 index 3d7c0f4d..00000000 --- a/app/private/docs/inline-calculations.md +++ /dev/null @@ -1,11 +0,0 @@ -# Inline Calculations - -Most long-format fields allow inline [calculations](/docs/computed-fields) to be included. Calculations inside of curly bracers will be computed down to numbers using the characters stats. - -For example a creature's strength attribute may have the following in its description: `Your carrying capacity is {strength * 15} lbs.` - -When the creature is calculated, if it has 8 strength, the action description will become: "Your carrying capacity is 120 lbs." - -If a description includes a dice roll, only the part that can be calculated to a single number should be included in the calulation bracers: `The attack does an extra {paladin.level}d8 damage`, which becomes `The attack does an extra 4d8 damage`. - -Do not inlclude the dice roll in the calaculation: `The attack does an extra {(paladin.level)d8} damage`, because it will become `The attack does an extra 16 damage` but the number 16 will change every time the creature recalculates. diff --git a/app/private/docs/tags.md b/app/private/docs/tags.md deleted file mode 100644 index bc84771d..00000000 --- a/app/private/docs/tags.md +++ /dev/null @@ -1,14 +0,0 @@ -# Tags - -Tags are used to reference multiple similar properties at once. A slot can require only properties from your library that has matching tags, effects and some other properties can also target properties to apply to by tags. - -## Built in tags - -Properties have specific tags automatically for use with tag-targeting. These aren't relevant for slots and finding properties in a library with specific tags. - -- `#type` Actions will have the `#action` tag, etc. Damage will either have the tag `#damage` or the tag `#healing` if the damage type is healing -- `variableName` if a property has a variable name it will be included as a tag -- The type of damage done by a [damage](/docs/property/damage) property: `bludgeoning`, `slashing`, `...` -- The skill type of a [skill](/docs/property/skill) property: `skill`, `save`, `check`, `tool`, `weapon`, `armor`, `language`, `utility` -- The attribute type of an [attribute](/docs/property/attribute) property: `ability`, `stat`, `modifier`, `hitDice`, `healthBar`, `resource`, `spellSlot`, `utility` -- When the property resets: `longRest`, `shortRest` From d05cd2fa196a523d1bfa667d081ebae6adcd2530 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 24 Nov 2022 12:29:00 +0200 Subject: [PATCH 079/247] Iterated on docs, fixed links --- app/imports/client/ui/docs/DocEditForm.vue | 2 +- app/private/docs/defaultDocs.json | 90 ++++++++++++---------- 2 files changed, 52 insertions(+), 40 deletions(-) diff --git a/app/imports/client/ui/docs/DocEditForm.vue b/app/imports/client/ui/docs/DocEditForm.vue index 42d1ae54..c77132f0 100644 --- a/app/imports/client/ui/docs/DocEditForm.vue +++ b/app/imports/client/ui/docs/DocEditForm.vue @@ -82,8 +82,8 @@ cols="12" > diff --git a/app/private/docs/defaultDocs.json b/app/private/docs/defaultDocs.json index 5b19e1e1..cb92a93c 100644 --- a/app/private/docs/defaultDocs.json +++ b/app/private/docs/defaultDocs.json @@ -4,7 +4,6 @@ "name": "Properties", "order": 1, "urlName": "property", - "tags": [], "ancestors": [], "href": "/docs/property", "published": true, @@ -27,8 +26,7 @@ ], "order": 2, "urlName": "action", - "tags": [], - "description": "Actions are things your character can do. When an action is taken, all the properties under it are applied.\n\nAdd actions to your character sheet, then add children under the action to determine what happenes when the action is applied.\n\nWhen an action is applied it will create an entry in the character's log detailing all the properties that were applied and what their results were.\n\nThe following properties can all be applied by an action: \n\n - [Attribute Damage](/docs/property/attribute-damage)\n - [Branches](/docs/property/branch)\n - [Buffs](/docs/property/buff)\n - [Buff Removers](/docs/property/remove-buff)\n - [Damage](/docs/property/damage)\n - [Notes](/docs/property/note)\n - [Rolls](/docs/property/roll)\n - [Saving Throws](/docs/property/saving-throw)\n - Other actions\n\n---\n\n### Name\n\nThe name of the action.\n\n### Action type\n\nHow long the action takes to perform.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Attack roll\n\nA [computed field](/docs/computed-fields) which calculates the attack roll modifier. If this field is empty, no attack roll will be made. Use 0 to make an attack roll without a modifier.\n\nThe following variables may be added to the action scope when attack rolls are made:\n\n - `$attackDiceRoll` The value of the d20 roll before any modifiers were applied.\n - `$attackRoll` The total attack roll after modifiers.\n - `$criticalHit` Set to `true` if the attack roll's d20 is a natural 20. If `criticalHitTarget` is set, the attack roll's d20 must instead be equal to or greater than `criticalHitTarget` for this to be set to `true`.\n - `$criticalMiss` Set to `true` if the attack roll was not a critical hit and rolled a natural 1 on the d20 roll.\n - `$attackHit` If the attack roll is higher than or equal to the target's AC or a critical hit this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical hit.\n - `$attackMiss` If the attack roll is lower than the target's AC or a critical miss, this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical miss.\n\n### Summary\n\nA brief overview of what the action does. This will appear in the action card, and shows in the log when the action is applied.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Description\n\nA more detailed description of the action. The description does not show in the action card or the log when the action is applied.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Resource\n\nA resource can be any attribute that has a variable name. If the resource attribute is less than the amount required, the action can't be applied.\n\nIf you want to reduce an attribute when taking the action, but want the action to be applied regardless of the value of that attribute, consider using an [Attribute Damage](/docs/property/attribute-damage) property as a child of the action instead. Also use Attribute Damage when the amount to reduce the attribute is determined by a dice roll rather than a stable computed number.\n\n#### Resource attribute\n\nThe variable name of the attribute that will be consumed when taking this action.\n\n#### Resource quantity\n\nA [computed field](/docs/computed-fields) which determines how much of the attribute is required to apply this action. This amount will be deducted from the attribute every time the action is taken.\n\n### Ammo\n\nAmmo represents items that are requied to take the action. If an item is not selected, or there is insufficient quantity of the selected item, the action can't be appled.\n\n#### Ammo item\n\nSpecify what tag an item must have to be considered valid ammo for this action. Any item with this tag can be selected as ammo for this action.\n\n#### Ammo quantity\n\nA [computed field](/docs/computed-fields) which determines how many of the selected items are required to take this action. The quantity is deducted from the total quantity of the item when this action is applied.\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Target\n\nWho this action should apply to. The properties under the action will be applied to the Targets.\n\n- **Self** The action will apply its properties to the creature taking the action\n- **Single Target** The action will apply its properties without a target (for now)\n- **Multiple Targets** The action will apply its properties without a target (for now)\n\n### Uses\n\nA [computed field](/docs/computed-fields) which determines how many times this action can be used before it needs to be reset.\n\n### Uses used\n\nHow many of this action's uses have already been used. Should ideally be between 0 and the total uses available. This number is set to 0 when the action has uses and its uses are reset.\n\n### Don't show in log\n\nWhen this is true, the action does not show up in the log. This does not stop the action's children from appearing in the log when they are applied.\n\n### Reset\n\nIf set, the uses used field is set to 0 at the appropriate time.\n\n- **Long rest** Reset when the long rest button is pushed\n- **Short rest** Reset when either the long or short rest button is pushed", + "description": "Actions are things your character can do. When an action is taken, all the properties under it are applied.\n\nAdd actions to your character sheet, then add children under the action to determine what happenes when the action is applied.\n\nWhen an action is applied it will create an entry in the character's log detailing all the properties that were applied and what their results were.\n\nThe following properties can all be applied by an action: \n\n - [Attribute Damage](/docs/property/attribute-damage)\n - [Branches](/docs/property/branch)\n - [Buffs](/docs/property/buff)\n - [Buff Removers](/docs/property/remove-buff)\n - [Damage](/docs/property/damage)\n - [Notes](/docs/property/note)\n - [Rolls](/docs/property/roll)\n - [Saving Throws](/docs/property/saving-throw)\n - Other actions\n\n---\n\n### Name\n\nThe name of the action.\n\n### Action type\n\nHow long the action takes to perform.\n\nAllows [inline calculations](/docs/concepts/inline-calculations).\n\n### Attack roll\n\nA [computed field](/docs/concepts/computed-fields) which calculates the attack roll modifier. If this field is empty, no attack roll will be made. Use 0 to make an attack roll without a modifier.\n\nThe following variables may be added to the action scope when attack rolls are made:\n\n - `$attackDiceRoll` The value of the d20 roll before any modifiers were applied.\n - `$attackRoll` The total attack roll after modifiers.\n - `$criticalHit` Set to `true` if the attack roll's d20 is a natural 20. If `criticalHitTarget` is set, the attack roll's d20 must instead be equal to or greater than `criticalHitTarget` for this to be set to `true`.\n - `$criticalMiss` Set to `true` if the attack roll was not a critical hit and rolled a natural 1 on the d20 roll.\n - `$attackHit` If the attack roll is higher than or equal to the target's AC or a critical hit this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical hit.\n - `$attackMiss` If the attack roll is lower than the target's AC or a critical miss, this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical miss.\n\n### Summary\n\nA brief overview of what the action does. This will appear in the action card, and shows in the log when the action is applied.\n\nAllows [inline calculations](/docs/concepts/inline-calculations).\n\n### Description\n\nA more detailed description of the action. The description does not show in the action card or the log when the action is applied.\n\nAllows [inline calculations](/docs/concepts/inline-calculations).\n\n### Resource\n\nA resource can be any attribute that has a variable name. If the resource attribute is less than the amount required, the action can't be applied.\n\nIf you want to reduce an attribute when taking the action, but want the action to be applied regardless of the value of that attribute, consider using an [Attribute Damage](/docs/property/attribute-damage) property as a child of the action instead. Also use Attribute Damage when the amount to reduce the attribute is determined by a dice roll rather than a stable computed number.\n\n#### Resource attribute\n\nThe variable name of the attribute that will be consumed when taking this action.\n\n#### Resource quantity\n\nA [computed field](/docs/concepts/computed-fields) which determines how much of the attribute is required to apply this action. This amount will be deducted from the attribute every time the action is taken.\n\n### Ammo\n\nAmmo represents items that are requied to take the action. If an item is not selected, or there is insufficient quantity of the selected item, the action can't be appled.\n\n#### Ammo item\n\nSpecify what tag an item must have to be considered valid ammo for this action. Any item with this tag can be selected as ammo for this action.\n\n#### Ammo quantity\n\nA [computed field](/docs/concepts/computed-fields) which determines how many of the selected items are required to take this action. The quantity is deducted from the total quantity of the item when this action is applied.\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)\n\n### Target\n\nWho this action should apply to. The properties under the action will be applied to the Targets.\n\n- **Self** The action will apply its properties to the creature taking the action\n- **Single Target** The action will apply its properties without a target (for now)\n- **Multiple Targets** The action will apply its properties without a target (for now)\n\n### Uses\n\nA [computed field](/docs/concepts/computed-fields) which determines how many times this action can be used before it needs to be reset.\n\n### Uses used\n\nHow many of this action's uses have already been used. Should ideally be between 0 and the total uses available. This number is set to 0 when the action has uses and its uses are reset.\n\n### Don't show in log\n\nWhen this is true, the action does not show up in the log. This does not stop the action's children from appearing in the log when they are applied.\n\n### Reset\n\nIf set, the uses used field is set to 0 at the appropriate time.\n\n- **Long rest** Reset when the long rest button is pushed\n- **Short rest** Reset when either the long or short rest button is pushed", "published": true, "href": "/docs/property/action" }, @@ -49,8 +47,7 @@ ], "order": 3, "urlName": "attribute-damage", - "tags": [], - "description": "When applied, attribute damage reduces the value of the [Attribute](/docs/properties/attributes) by some amount or set the value of an attribute to some amount. Attribute damage can by applied by actions or triggers.\n\nUsing a negative value to damage an attribute will heal the attribute instead.\n\n---\n\n### Attribute\n\nThe variable name of the attribute to target.\n\n### Amount\n\nA [computed field](/docs/computed-fields) which determined the amount to damage the attribute or set the attribute's value to.\n\n### Operation\n\n- **Damage** Reduce the value of the attribute by the amount, negative values heal the attribute instead\n- **Set** Set the value of the attribute to the amount\n\n### Target\n\n- **Target** Apply the attribute damage to the same target as the action applying this property\n- **Self** Apply the attribute damage to the creature taking the action\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Don't show in log\n\nWhen this is set, the attribute damage is applied, but does not show in the log.", + "description": "When applied, attribute damage reduces the value of the [Attribute](/docs/property/attribute) by some amount or set the value of an attribute to some amount. Attribute damage can by applied by actions or triggers.\n\nUsing a negative value to damage an attribute will heal the attribute instead.\n\n---\n\n### Attribute\n\nThe variable name of the attribute to target.\n\n### Amount\n\nA [computed field](/docs/concepts/computed-fields) which determined the amount to damage the attribute or set the attribute's value to.\n\n### Operation\n\n- **Damage** Reduce the value of the attribute by the amount, negative values heal the attribute instead\n- **Set** Set the value of the attribute to the amount\n\n### Target\n\n- **Target** Apply the attribute damage to the same target as the action applying this property\n- **Self** Apply the attribute damage to the creature taking the action\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)\n\n### Don't show in log\n\nWhen this is set, the attribute damage is applied, but does not show in the log.", "href": "/docs/property/attribute-damage", "published": true }, @@ -71,8 +68,7 @@ ], "order": 4, "urlName": "attribute", - "tags": [], - "description": "Attributes represent the numerical values of the creature.\n\nAttributes can be targeted by [effects](/docs/property/effect) which can change their total value in a non-destructive way. For example, if a class level gives you an ability score increase of +2 strength when it is taken, instead of directly editing the strength attribute, you add an effect to the class level that adds 2 to strength. The total value of strength will increase by 2 and it will show a record of that ability score increase and where it came from.\n\nAttributes, [skills](/docs/properties/skill), and [effects](/docs/property/effect) are the core properties of DiceCloud's creature engine.\n\nAttributes have the following fields that can be accessed in calculations with `variableName.field`:\n\n- `.total` The total of the attribute before being damaged\n- `.damage` the amount of damage the attribute has taken\n- `.value` The current value of the attribute including damage. `variableName` and `variableName.value` are equivalent.\n- `.modifier` If the attribute is an ability, this is its roll modifier, eg. `strength.modifier` is +2 when `strength.value` is 14\n\n---\n\n### Base value\n\nA [computed field](/docs/computed-fields) that determines the starting value of the attribute before it is modified by effects and other properties. Multiple properties can set the base value for a given variable name, when this happens the highest base value is chosen, and then all other effects are applied.\n\n### Name\n\nThe name of the attribute\n\n### Variable name\n\nThe name used to refer to the attribute in calculations and by effects. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation.\n\nIf multiple attributes share a variable name, only the last attribute on the [character tree](/docs/tree) will count as the defining attribute and appear on the sheet, while other attributes with that variable name will be used as base value [effects](/docs/property/effect).\n\n### Attribute type\n\n- **Ability** Ablity scores like Strength, Dexterity, etc. Ability scores get a modifier which can be accessed in calculations as `variableName.modifier`,\n- **Stat** Any numerical value that appears on the sheet. Speed, armor class.\n- **Modifier** Any numical value that appears on the sheet with a `+` or `-` sign, eg. Proficiency bonus.\n- **Hit Dice** Hit dice let you select the appropriate hit dice size. Creatures regain half their total hit dice on long rest.\n- **Health Bar** Health bars can by made to take or ignore damage in a specified order\n- **Resource** Rages, sourcery points, things that are spent to use actions.\n- **Spell Slot** Spell slots have a specific level and are used to cast spells.\n- **Utility** Utility attributes don't show up anywhere on the sheet, but can still be used for calculations\n\n### Description\n\nA detailed description of the attribute.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Health bar settings\n\nHealth bars can take or ignore damage and healing from applied damage properties targeting a creature. A lower ordered health bar will take damage before a higher ordered one.\n\nHealth bars can also change color depending on their value. At 50%+ full they are their property color, between 50% and 0% they fade from their half-full color to their empty color.\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Allow decimal values\n\nIf this is set, the attribute will not round-down when its value has a decimal.\n\n### Can be damaged into negative values\n\nIf this is set the attribute can be damaged past zero into negative values.\n\n### Can be incremented above total\n\nIf this is set the attribute can have negative damage such that the value exceeds the total. This can be useful if you are using the attribute to count, it can start at zero and be healed upwards to keep count.\n\n### Reset\n\nIf set, the damage on this attribute is reset to 0 at the appropriate time.\n\n- **Long rest** Reset when the long rest button is pushed\n- **Short rest** Reset when either the long or short rest button is pushed", + "description": "Attributes represent the numerical values of the creature.\n\nAttributes can be targeted by [effects](/docs/property/effect) which can change their total value in a non-destructive way. For example, if a class level gives you an ability score increase of +2 strength when it is taken, instead of directly editing the strength attribute, you add an effect to the class level that adds 2 to strength. The total value of strength will increase by 2 and it will show a record of that ability score increase and where it came from.\n\nAttributes, [skills](/docs/property/skill), and [effects](/docs/property/effect) are the core properties of DiceCloud's creature engine.\n\nAttributes have the following fields that can be accessed in calculations with `variableName.field`:\n\n- `.total` The total of the attribute before being damaged\n- `.damage` the amount of damage the attribute has taken\n- `.value` The current value of the attribute including damage. `variableName` and `variableName.value` are equivalent.\n- `.modifier` If the attribute is an ability, this is its roll modifier, eg. `strength.modifier` is +2 when `strength.value` is 14\n\n---\n\n### Base value\n\nA [computed field](/docs/concepts/computed-fields) that determines the starting value of the attribute before it is modified by effects and other properties. Multiple properties can set the base value for a given variable name, when this happens the highest base value is chosen, and then all other effects are applied.\n\n### Name\n\nThe name of the attribute\n\n### Variable name\n\nThe name used to refer to the attribute in calculations and by effects. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation.\n\nIf multiple attributes share a variable name, only the last attribute on the [character tree](/docs/concepts/tree) will count as the defining attribute and appear on the sheet, while other attributes with that variable name will be used as base value [effects](/docs/property/effect).\n\n### Attribute type\n\n- **Ability** Ablity scores like Strength, Dexterity, etc. Ability scores get a modifier which can be accessed in calculations as `variableName.modifier`,\n- **Stat** Any numerical value that appears on the sheet. Speed, armor class.\n- **Modifier** Any numical value that appears on the sheet with a `+` or `-` sign, eg. Proficiency bonus.\n- **Hit Dice** Hit dice let you select the appropriate hit dice size. Creatures regain half their total hit dice on long rest.\n- **Health Bar** Health bars can by made to take or ignore damage in a specified order\n- **Resource** Rages, sourcery points, things that are spent to use actions.\n- **Spell Slot** Spell slots have a specific level and are used to cast spells.\n- **Utility** Utility attributes don't show up anywhere on the sheet, but can still be used for calculations\n\n### Description\n\nA detailed description of the attribute.\n\nAllows [inline calculations](/docs/concepts/inline-calculations).\n\n### Health bar settings\n\nHealth bars can take or ignore damage and healing from applied damage properties targeting a creature. A lower ordered health bar will take damage before a higher ordered one.\n\nHealth bars can also change color depending on their value. At 50%+ full they are their property color, between 50% and 0% they fade from their half-full color to their empty color.\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)\n\n### Allow decimal values\n\nIf this is set, the attribute will not round-down when its value has a decimal.\n\n### Can be damaged into negative values\n\nIf this is set the attribute can be damaged past zero into negative values.\n\n### Can be incremented above total\n\nIf this is set the attribute can have negative damage such that the value exceeds the total. This can be useful if you are using the attribute to count, it can start at zero and be healed upwards to keep count.\n\n### Reset\n\nIf set, the damage on this attribute is reset to 0 at the appropriate time.\n\n- **Long rest** Reset when the long rest button is pushed\n- **Short rest** Reset when either the long or short rest button is pushed", "published": true, "href": "/docs/property/attribute" }, @@ -93,9 +89,8 @@ ], "order": 5, "urlName": "branch", - "tags": [], "published": true, - "description": "Branches are applied by actions, when they are applied they can control which of their immediate children are applied.\n\n---\n\n### Branch type\n\n- **If condition is true** Apply children if the condition (a [computed field](/docs/computed-fields)) resolves to `true` or a non-zero number\n- **Attack hit** Apply children if the attack roll hit the target\n- **Attack hit** Apply children if the attack roll missed the target\n- **Save failed** Apply children if target failed its saving throw\n- **Save suceeded** Apply children if target made its saving throw\n- **Apply to each target** Apply children separately to each target\n- **Random** Apply one of the immediate children at random\n- **Calculated Index** Use the index (a [computed field](/docs/computed-fields)) to choose which child to apply, starting at 1 for the first child.\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Don't show in log\n\nWhen this is set, the branch is applied, but does not show in the log. This does not prevent its children from appearing in the log.", + "description": "Branches are applied by actions, when they are applied they can control which of their immediate children are applied.\n\n---\n\n### Branch type\n\n- **If condition is true** Apply children if the condition (a [computed field](/docs/concepts/computed-fields)) resolves to `true` or a non-zero number\n- **Attack hit** Apply children if the attack roll hit the target\n- **Attack hit** Apply children if the attack roll missed the target\n- **Save failed** Apply children if target failed its saving throw\n- **Save suceeded** Apply children if target made its saving throw\n- **Apply to each target** Apply children separately to each target\n- **Random** Apply one of the immediate children at random\n- **Calculated Index** Use the index (a [computed field](/docs/concepts/computed-fields)) to choose which child to apply, starting at 1 for the first child.\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)\n\n### Don't show in log\n\nWhen this is set, the branch is applied, but does not show in the log. This does not prevent its children from appearing in the log.", "href": "/docs/property/branch" }, { @@ -116,7 +111,6 @@ "order": 6, "urlName": "new-doc-6", "href": "/docs/property/new-doc-6", - "tags": [], "removed": true, "removedAt": "2022-11-21T15:45:45.975Z" }, @@ -138,7 +132,6 @@ "order": 7, "urlName": "new-doc-7", "href": "/docs/property/new-doc-7", - "tags": [], "removed": true, "removedAt": "2022-11-21T15:49:16.862Z" }, @@ -160,8 +153,7 @@ "order": 8, "urlName": "buff", "href": "/docs/property/buff", - "tags": [], - "description": "Buffs are temporary changes to a character sheet that can be applied by actions. When a buff is applied, it is copied to the target character along with all of its children properties. \n\nBuffs can either be manually removed from the stats page, or be removed by an action applying a [buff remover](/docs/property/remove-buff/) property.\n\n### Variable freezing\n\nWhen a buff is applied, all the calculations in the child properties have their variables frozen to their values at the time the buff is applied. You can prevent this behavior for the whole buff by using the `don't freeze variables` option, or on an individual variable reference by prefixing the variable with the keyword `$target.`.\n\nFor example, if a character has 10 strength and 16 dexterity, and applies a buff with some child property containing the calculation `$target.strength + dexterity` the property's calculation will become `strength + 16` when it is copied to the target character.\n\n---\n\n### Name\n\nThe name of the buff.\n\n### Description\n\nDescription of the applied buff.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Target\n\n- **Target** Apply the buff to the target of the action\n- **Self** Apply the buff to the creature taking the action\n\n### Hide remove button\n\nIf this is set, the remove button next to the buff on the stats page will be hidden. Use this when you expect the buff to be removed automatically by another action.\n\n### Don't show in log\n\nIf set, the buff will not show its name and description in the log when applied.\n\n### Don't freeze variables\n\nPrevent the buff from freezing variables in child property calculations to their value at the time the buff was applied.\n\n### Tags\n\nSee [Tags](/docs/tags)", + "description": "Buffs are temporary changes to a character sheet that can be applied by actions. When a buff is applied, it is copied to the target character along with all of its children properties. \n\nBuffs can either be manually removed from the stats page, or be removed by an action applying a [buff remover](/docs/property/remove-buff/) property.\n\n### Variable freezing\n\nWhen a buff is applied, all the calculations in the child properties have their variables frozen to their values at the time the buff is applied. You can prevent this behavior for the whole buff by using the `don't freeze variables` option, or on an individual variable reference by prefixing the variable with the keyword `$target.`.\n\nFor example, if a character has 10 strength and 16 dexterity, and applies a buff with some child property containing the calculation `$target.strength + dexterity` the property's calculation will become `strength + 16` when it is copied to the target character.\n\n---\n\n### Name\n\nThe name of the buff.\n\n### Description\n\nDescription of the applied buff.\n\nAllows [inline calculations](/docs/concepts/inline-calculations).\n\n### Target\n\n- **Target** Apply the buff to the target of the action\n- **Self** Apply the buff to the creature taking the action\n\n### Hide remove button\n\nIf this is set, the remove button next to the buff on the stats page will be hidden. Use this when you expect the buff to be removed automatically by another action.\n\n### Don't show in log\n\nIf set, the buff will not show its name and description in the log when applied.\n\n### Don't freeze variables\n\nPrevent the buff from freezing variables in child property calculations to their value at the time the buff was applied.\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)", "published": true }, { @@ -170,7 +162,6 @@ "order": 9, "urlName": "new-doc-9", "href": "/docs/new-doc-9", - "tags": [], "ancestors": [], "removed": true, "removedAt": "2022-11-21T15:49:40.176Z" @@ -203,7 +194,7 @@ "order": 11, "urlName": "class-level", "href": "/docs/property/class-level", - "description": "A class level is a property that represents a single level in a class. It is generally used as a child of a [Class property](/docs/property/class).\n\nFeatures and bonuses that are given by a class level get added as children of the class level.\n\n---\n\n### Level\n\nWhich level this property represents.\n\n### Name\n\nThe name of the class or subclass this level is part of\n\n### Variable name\n\nThe same variable name of the class this level belongs to.\n\n### Description\n\nA description of the benefits gained with this level.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/tags)", + "description": "A class level is a property that represents a single level in a class. It is generally used as a child of a [Class property](/docs/property/class).\n\nFeatures and bonuses that are given by a class level get added as children of the class level.\n\n---\n\n### Level\n\nWhich level this property represents.\n\n### Name\n\nThe name of the class or subclass this level is part of\n\n### Variable name\n\nThe same variable name of the class this level belongs to.\n\n### Description\n\nA description of the benefits gained with this level.\n\nAllows [inline calculations](/docs/concepts/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)", "published": true }, { @@ -225,7 +216,7 @@ "urlName": "class", "href": "/docs/property/class", "published": true, - "description": "A class is a property that expects [class levels](/docs/property/class-level) as its immediate children.\n\nLeveling up a class means choosing, or manually adding, class level properties to it. Class levels with the same variable name as the class, and that match all the required tags are found in libraries and added to the class.\n\nThe total level of the class can be accessed in calculations using `classVariableName.level`.\n\n## Making your own class\n\nSee [Create a Class](/docs/walkthroughs/create-a-class)\n\n---\n\n### Name\n\nThe name of the class\n\n### Variable name\n\nThe name used to refer to the class in calculations. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation.\n\n### Description\n\nA description of the class.\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Tags required\n\nOnly class levels with the same variable name as the class, and with tags that match the tags required will be returned from libraries when leveling up this class.\n\n### Condition\n\nA [computed field](/docs/computed-fields) to determine if the class is allowed to level up. If this field results in `true` or a number that is not 0, the class can be levelled, otherwise leveling is disabled." + "description": "A class is a property that expects [class levels](/docs/property/class-level) as its immediate children.\n\nLeveling up a class means choosing, or manually adding, class level properties to it. Class levels with the same variable name as the class, and that match all the required tags are found in libraries and added to the class.\n\nThe total level of the class can be accessed in calculations using `classVariableName.level`.\n\n---\n\n### Name\n\nThe name of the class\n\n### Variable name\n\nThe name used to refer to the class in calculations. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctuation.\n\n### Description\n\nA description of the class.\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)\n\n### Tags required\n\nOnly class levels with the same variable name as the class, and with tags that match the tags required will be returned from libraries when leveling up this class.\n\n### Condition\n\nA [computed field](/docs/concepts/computed-fields) to determine if the class is allowed to level up. If this field results in `true` or a number that is not 0, the class can be levelled, otherwise leveling is disabled." }, { "_id": "giHu6Ej7qvsZr4zrJ", @@ -245,7 +236,7 @@ "order": 13, "urlName": "constant", "href": "/docs/property/constant", - "description": "Constants are properties that store some primitive value in a variable name for use in other calculations.\n\nUnlike attributes, constants can store more than just numbers:\n\n- Arrays: `[1,2,3,4]`\n- Text strings: `'I am a cat'`\n- Numbers: `3.14`\n- Boolean values: `true`, `false`\n- Dice rolls: `1d20 + 2`\n\nConstants just can't use other variables in their calculations.\n\n### Overriding constants\n\nIf multiple constants have the same variable name, only the last active constant in the [character tree](/docs/tree) will be used as the definition for that variable name.\n\nThis can be used to re-write the value of some constant by ensuring there is a new active constant later in the sheet.\n\n---\n\n### Name\n\nThe name of the constants\n\n### Variable Name\n\nThe name used to refer to the constant in calculations. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation.\n\n### Value\n\nA [calculation](/docs/computed-fields) of the final value of the constant.", + "description": "Constants are properties that store some primitive value in a variable name for use in other calculations.\n\nUnlike attributes, constants can store more than just numbers:\n\n- Arrays: `[1,2,3,4]`\n- Text strings: `'I am a cat'`\n- Numbers: `3.14`\n- Boolean values: `true`, `false`\n- Dice rolls: `1d20 + 2`\n\nConstants just can't use other variables in their calculations.\n\n### Overriding constants\n\nIf multiple constants have the same variable name, only the last active constant in the [character tree](/docs/concepts/tree) will be used as the definition for that variable name.\n\nThis can be used to re-write the value of some constant by ensuring there is a new active constant later in the sheet.\n\n---\n\n### Name\n\nThe name of the constants\n\n### Variable Name\n\nThe name used to refer to the constant in calculations. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctuation.\n\n### Value\n\nA [calculation](/docs/concepts/computed-fields) of the final value of the constant.", "published": true }, { @@ -266,7 +257,7 @@ "order": 14, "urlName": "container", "href": "/docs/property/container", - "description": "Containers are things that [items](/docs/property/item) can be put inside of.\n\n---\n\n### Name\n\nThe name of the container\n\n### Carried\n\nIf this is set the weight of the container and its contents will be added to the character's weight carried.\n\n### Value\n\nThe value of the container in gold pieces. Silver pieces are worth 0.1 gp and copper pieces are worth 0.01 gp. So a container that is worth 2 gp 4 sp 7 cp will have a value of 2.47 gp.\n\n### Weight\n\nThe weight of the container in lb.\n\n### Description\n\nA description of the container. \n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Contents are weightless\n\nIf this is set and the container is carried, only the container's own weight will be added to the weight carried by the creature.", + "description": "Containers are things that [items](/docs/property/item) can be put inside of.\n\n---\n\n### Name\n\nThe name of the container\n\n### Carried\n\nIf this is set the weight of the container and its contents will be added to the character's weight carried.\n\n### Value\n\nThe value of the container in gold pieces. Silver pieces are worth 0.1 gp and copper pieces are worth 0.01 gp. So a container that is worth 2 gp 4 sp 7 cp will have a value of 2.47 gp.\n\n### Weight\n\nThe weight of the container in lb.\n\n### Description\n\nA description of the container. \n\nAllows [inline calculations](/docs/concepts/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)\n\n### Contents are weightless\n\nIf this is set and the container is carried, only the container's own weight will be added to the weight carried by the creature.", "published": true }, { @@ -287,7 +278,7 @@ "order": 15, "urlName": "damage-multiplier", "href": "/docs/property/damage-multiplier", - "description": "Damage multipliers are used to define vulnerability, resistance, and immunity to damage types.\n\nA single multiplier can apply to multiple damage types, and choose whether or not to apply to an incoming source of damage based on the tags present on that damage.\n\n---\n\n### Name\n\nThe name of the feature that gives this damage multiplier\n\n### Value\n\n- **Immunity** The creature takes no damage from matching damage sources\n- **Resistance** Damage from matching sources is halved.\n- **Vulnerability** Damage from matching sources is doubled.\n\n### Damage types\n\nA list of damage types that this property applies to. Custom types can be used.\n\n### Damage tags required\n\nThis damage multiplier will only be applied if the incoming damage has all of these tags present.\n\n### Damage tags excluded\n\nThis damage multiplier will only apply if the incoming damage has none of these tags present.\n\n### Tags\n\nSee [Tags](/docs/tags)", + "description": "Damage multipliers are used to define vulnerability, resistance, and immunity to damage types.\n\nA single multiplier can apply to multiple damage types, and choose whether or not to apply to an incoming source of damage based on the tags present on that damage.\n\n---\n\n### Name\n\nThe name of the feature that gives this damage multiplier\n\n### Value\n\n- **Immunity** The creature takes no damage from matching damage sources\n- **Resistance** Damage from matching sources is halved.\n- **Vulnerability** Damage from matching sources is doubled.\n\n### Damage types\n\nA list of damage types that this property applies to. Custom types can be used.\n\n### Damage tags required\n\nThis damage multiplier will only be applied if the incoming damage has all of these tags present.\n\n### Damage tags excluded\n\nThis damage multiplier will only apply if the incoming damage has none of these tags present.\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)", "published": true }, { @@ -309,7 +300,7 @@ "urlName": "damage", "href": "/docs/property/damage", "published": true, - "description": "Damage can be applied by an action to damage a target creature's [health bars](/docs/property/attribute). The damage will be modified by [damage multipliers](/docs/property/damage-multiplier), which apply vulnerability, resistance, and immunity before the damage is applied.\n\n---\n\n### Damage\n\nA [computed field](/docs/computed-fields) that determines how much damage to do to the target creature.\n\n### Damage type\n\nDamage type determines how the damage is treated by [damage multipliers](/docs/property/damage-multiplier). A custom type can be used, or one of the existing types can be selected.\n\nThere are two special damage types:\n\n**Extra damage** Damage with the `extra` type will take on the damage type of whatever damage was applied before it by an action. So if an action deals 12 `piercing` damage and `3` extra damage, it will instead deal 15 `piercing` damage.\n\n**Healing** Damage with the `healing` type will heal a creature instead of damaging them.\n\n### Target\n\n- **Target** Apply the damage to the target of the action\n- **Self** Apply the damage to the creature taking the action\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Don't show in log\n\nIf set, the damage will be applied but not show in the log." + "description": "Damage can be applied by an action to damage a target creature's [health bars](/docs/property/attribute). The damage will be modified by [damage multipliers](/docs/property/damage-multiplier), which apply vulnerability, resistance, and immunity before the damage is applied.\n\n---\n\n### Damage\n\nA [computed field](/docs/concepts/computed-fields) that determines how much damage to do to the target creature.\n\n### Damage type\n\nDamage type determines how the damage is treated by [damage multipliers](/docs/property/damage-multiplier). A custom type can be used, or one of the existing types can be selected.\n\nThere are two special damage types:\n\n**Extra damage** Damage with the `extra` type will take on the damage type of whatever damage was applied before it by an action. So if an action deals 12 `piercing` damage and `3` extra damage, it will instead deal 15 `piercing` damage.\n\n**Healing** Damage with the `healing` type will heal a creature instead of damaging them.\n\n### Target\n\n- **Target** Apply the damage to the target of the action\n- **Self** Apply the damage to the creature taking the action\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)\n\n### Don't show in log\n\nIf set, the damage will be applied but not show in the log." }, { "_id": "FHdAjYY2er9xfYsJs", @@ -329,7 +320,7 @@ "order": 17, "urlName": "effect", "href": "/docs/property/effect", - "description": "Effects are the core of the DiceCloud engine. Effect change the values of attributes, skills, and calculations in a way that is transparent and auditable, keeping character sheets organized and understandable, even when using intricate homebrew rules on high level characters.\n\n---\n\n### Name\n\nThe name of the feature that causes this effect.\n\n### Operation\n\nThe operation determines what the effect will do to the affected property or calcualtion.\n\n- **Base Value** Set the base value of the affected property. If a property has multiple base values, the highest is used\n- **Add** Add the value to the affected property or calculation\n- **Muliply** Multiply the affected property by the value\n- **Minimum** Prevent the affected property from having a value less than the effect value\n- **Maximum** Prevent the affected property from having a value greater than the effect value\n- **Maximum** Prevent the affected property from having a value greater than the effect value\n- **Set** Set the value affected property to the effect value\n- **Advantage** Give advantage to checks made using the affected property\n- **Disadvantage** Give disadvantage to checks made using the affected property\n- **Passive bonus** Add the effect value to the passive scores based on the affected property\n- **Fail** Checks made using the affected property automatically fail\n- **Conditional benefit** Add some text to the affected property describing the benefit recieved\n\n### Value\n\nA [computed field](/docs/computed-fields) that determines the value of the effect.\n\n### Text\n\nIf the operation is a conditional benefit, the note text that will show on affected properties.\n\n### Target stats by variable name\n\nIf selected the effect will apply to all properties that have the given variable names.\n\n### Variable names\n\nA list of variable names of properties to target with this effect.\n\n### Target properties by tags\n\nWhen targeting properties by tag, any property can be targeted with an effect. If the property is one that can usually be targeted by variable name, the effect will apply as ususal, however if the effect targets another property, it will apply to a [computed field](/docs/computed-fields) on the property instead.\n\nThese effects can be used for adding a bonus to a specific attack or damage roll, or manipulating any computed field on the creature.\n\n### Tags required\n\nOnly properties that match the required tags will be targeted by the effect.\n\n### Target field\n\nIf a property has multiple computed fields, which field should be targeted by this effect.\n\n### Tags\n\nSee [Tags](/docs/tags)", + "description": "Effects are the core of the DiceCloud engine. Effect change the values of attributes, skills, and calculations in a way that is transparent and auditable, keeping character sheets organized and understandable, even when using intricate homebrew rules on high level characters.\n\n---\n\n### Name\n\nThe name of the feature that causes this effect.\n\n### Operation\n\nThe operation determines what the effect will do to the affected property or calcualtion.\n\n- **Base Value** Set the base value of the affected property. If a property has multiple base values, the highest is used\n- **Add** Add the value to the affected property or calculation\n- **Muliply** Multiply the affected property by the value\n- **Minimum** Prevent the affected property from having a value less than the effect value\n- **Maximum** Prevent the affected property from having a value greater than the effect value\n- **Maximum** Prevent the affected property from having a value greater than the effect value\n- **Set** Set the value affected property to the effect value\n- **Advantage** Give advantage to checks made using the affected property\n- **Disadvantage** Give disadvantage to checks made using the affected property\n- **Passive bonus** Add the effect value to the passive scores based on the affected property\n- **Fail** Checks made using the affected property automatically fail\n- **Conditional benefit** Add some text to the affected property describing the benefit recieved\n\n### Value\n\nA [computed field](/docs/concepts/computed-fields) that determines the value of the effect.\n\n### Text\n\nIf the operation is a conditional benefit, the note text that will show on affected properties.\n\n### Target stats by variable name\n\nIf selected the effect will apply to all properties that have the given variable names.\n\n### Variable names\n\nA list of variable names of properties to target with this effect.\n\n### Target properties by tags\n\nWhen targeting properties by tag, any property can be targeted with an effect. If the property is one that can usually be targeted by variable name, the effect will apply as usual, however if the effect targets another property, it will apply to a [computed field](/docs/concepts/computed-fields) on the property instead.\n\nThese effects can be used for adding a bonus to a specific attack or damage roll, or manipulating any computed field on the creature.\n\n### Tags required\n\nOnly properties that match the required tags will be targeted by the effect.\n\n### Target field\n\nIf a property has multiple computed fields, which field should be targeted by this effect.\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)", "published": true }, { @@ -350,7 +341,7 @@ "order": 18, "urlName": "feature", "href": "/docs/property/feature", - "description": "Features appear on the features tab. Classes, backgrounds, and race can all give a creature features.\n\n---\n\n### Name\n\nThe name of the feature.\n\n### Summary\n\nA summary of the feature. This will appear on the feature card.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Description\n\nA detailed description of the feature.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/tags)", + "description": "Features appear on the features tab. Classes, backgrounds, and race can all give a creature features.\n\n---\n\n### Name\n\nThe name of the feature.\n\n### Summary\n\nA summary of the feature. This will appear on the feature card.\n\nAllows [inline calculations](/docs/concepts/inline-calculations).\n\n### Description\n\nA detailed description of the feature.\n\nAllows [inline calculations](/docs/concepts/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)", "published": true }, { @@ -372,7 +363,7 @@ "urlName": "folder", "href": "/docs/property/folder", "published": true, - "description": "Folders allow the [character tree](/docs/tree) to be organized.\n\n### Folders in actions\n\nWhen a folder is the child of an action, it and its children will not show on the action card, but will still appear in the detail view of the action and be applied when the action is taken.\n\n### Grouping children\n\nWhen the folder is set to group stats on a card, the immediate children of the folder will be shown in a single card in a location on the sheet you can specify. For now, the following properties are supported:\n\n- Actions, including event actions\n- Attributes\n- Buffs\n- Containers\n- Features\n- Items\n- Notes\n- Skills\n- Toggles (with _Show on character sheet_ enabled)\n\n---\n\n### Name\n\nThe name of the folder.\n\n### Group children on a card\n\nImmediate children will be grouped on a card in the sheet.\n\n### Hide children from stats tab\n\nThe children of this card will not appear on the stats tab, but may still appear in other tabs.\n\n### Tab\n\nDetermines which tab the card will show up on.\n\n### Location\n\nWhere on the tab the card will be positioned.\n\n### Tags\n\nSee [Tags](/docs/tags)" + "description": "Folders allow the [character tree](/docs/concepts/tree) to be organized.\n\n### Folders in actions\n\nWhen a folder is the child of an action, it and its children will not show on the action card, but will still appear in the detail view of the action and be applied when the action is taken.\n\n### Grouping children\n\nWhen the folder is set to group stats on a card, the immediate children of the folder will be shown in a single card in a location on the sheet you can specify. For now, the following properties are supported:\n\n- Actions, including event actions\n- Attributes\n- Buffs\n- Containers\n- Features\n- Items\n- Notes\n- Skills\n- Toggles (with _Show on character sheet_ enabled)\n\n---\n\n### Name\n\nThe name of the folder.\n\n### Group children on a card\n\nImmediate children will be grouped on a card in the sheet.\n\n### Hide children from stats tab\n\nThe children of this card will not appear on the stats tab, but may still appear in other tabs.\n\n### Tab\n\nDetermines which tab the card will show up on.\n\n### Location\n\nWhere on the tab the card will be positioned.\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)" }, { "_id": "5MsdJBbpALgMnYBwk", @@ -393,7 +384,7 @@ "urlName": "item", "href": "/docs/property/item", "published": true, - "description": "Items are shown on the Inventory tab. Items can be carried, put in containers, or equipped on a creature. The children of an item are not active unless the item is equipped.\n\n---\n\n### Icon\n\nAn icon representing the item.\n\n### Equipped\n\nIf set, the item appears in the equipment list on the inventory tab and its children become active on the creature.\n\n### Name\n\nThe name of the item.\n\n### Plural name\n\nThe name to use if the quantity of the item is higher than 1.\n\n### Value\n\nThe value of a single item in gold pieces. Silver pieces are worth 0.1 gp and copper pieces are worth 0.01 gp. So an item that is worth 2 gp 4 sp 7 cp will have a value of 2.47 gp.\n\n### Weight\n\nThe weight of a single item in lb.\n\n### Quantity\n\nNumber of items. The value and quantity will be multiplied by the quantity to get the total value and weight of this stack of items.\n\n### Description\n\nA description of the item. \n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Show increment button\n\nIf this is set, the item will show an increment button in the detail view and on the inventory tab. This button can be used to quickly adjust the quantity of the item.\n\n### Requires attunemnt\n\nIf set, the item requires attunemnt to use.\n\n### Attuned\n\nIf set, the item is attuned and counts towards the total number of attuned items for the creature.\n\nIf a child property needs to determine if its parent item is attuned it can use `#item.attuned` in calculations, see *Ancestor references* in [computed fields](/docs/computed-fields)." + "description": "Items are shown on the Inventory tab. Items can be carried, put in containers, or equipped on a creature. The children of an item are not active unless the item is equipped.\n\n---\n\n### Icon\n\nAn icon representing the item.\n\n### Equipped\n\nIf set, the item appears in the equipment list on the inventory tab and its children become active on the creature.\n\n### Name\n\nThe name of the item.\n\n### Plural name\n\nThe name to use if the quantity of the item is higher than 1.\n\n### Value\n\nThe value of a single item in gold pieces. Silver pieces are worth 0.1 gp and copper pieces are worth 0.01 gp. So an item that is worth 2 gp 4 sp 7 cp will have a value of 2.47 gp.\n\n### Weight\n\nThe weight of a single item in lb.\n\n### Quantity\n\nNumber of items. The value and quantity will be multiplied by the quantity to get the total value and weight of this stack of items.\n\n### Description\n\nA description of the item. \n\nAllows [inline calculations](/docs/concepts/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)\n\n### Show increment button\n\nIf this is set, the item will show an increment button in the detail view and on the inventory tab. This button can be used to quickly adjust the quantity of the item.\n\n### Requires attunement\n\nIf set, the item requires attunement to use.\n\n### Attuned\n\nIf set, the item is attuned and counts towards the total number of attuned items for the creature.\n\nIf a child property needs to determine if its parent item is attuned it can use `#item.attuned` in calculations, see *Ancestor references* in [computed fields](/docs/concepts/computed-fields)." }, { "_id": "74utQna6D4ayYyrLp", @@ -414,7 +405,7 @@ "urlName": "note", "href": "/docs/property/note", "published": true, - "description": "Notes are used to store text on the creature that does not have a direct mechanical impact. Notes appear on the journal tab when active on the character, or are shown in the log when applied by an [action](/docs/property/action).\n\n---\n\n### Name\n\nName of the note.\n\n### Summary\n\nA summary of the note. This will appear on the note card and in the log when applied by an [action](/docs/property/action).\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Description\n\nA detailed description of the feature.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/tags)" + "description": "Notes are used to store text on the creature that does not have a direct mechanical impact. Notes appear on the journal tab when active on the character, or are shown in the log when applied by an [action](/docs/property/action).\n\n---\n\n### Name\n\nName of the note.\n\n### Summary\n\nA summary of the note. This will appear on the note card and in the log when applied by an [action](/docs/property/action).\n\nAllows [inline calculations](/docs/concepts/inline-calculations).\n\n### Description\n\nA detailed description of the feature.\n\nAllows [inline calculations](/docs/concepts/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)" }, { "_id": "cuhusZb8xYW8dj743", @@ -435,7 +426,7 @@ "urlName": "point-buy", "href": "/docs/property/point-buy", "published": true, - "description": "A point buy is a set of rows that lets the user choose a set of stats based on a cost per stat.\n\n---\n\n### Table name\n\nThe name of the point buy table.\n\n### Min\n\nThe lowest value available for each row\n\n### Max\n\nThe highest value available for each row\n\n### Cost\n\nA function that uses `value` as the value of a row and determines the cost of that value. For standard D&D 5e 27 point buy, this function is `[0, 1, 2, 3, 4, 5, 7, 9][value - 7]`\n\n### Total available points\n\nA [computed field](/docs/computed-fields) that determines how many points are available to spend in total\n\n## Rows\n\nUp to 32 rows can be added to a point buy table\n\n### Row name\n\nThe name of the row that will appear in the table\n\n### Row variable name\n\nThe variable name of the row that can be used in calculations. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation.\n\nIf the variable name matches an attribute with the same variable name, the row's value will be used as a base value for that attribute." + "description": "A point buy is a set of rows that lets the user choose a set of stats based on a cost per stat.\n\n---\n\n### Table name\n\nThe name of the point buy table.\n\n### Min\n\nThe lowest value available for each row\n\n### Max\n\nThe highest value available for each row\n\n### Cost\n\nA function that uses `value` as the value of a row and determines the cost of that value. For standard D&D 5e 27 point buy, this function is `[0, 1, 2, 3, 4, 5, 7, 9][value - 7]`\n\n### Total available points\n\nA [computed field](/docs/concepts/computed-fields) that determines how many points are available to spend in total\n\n## Rows\n\nUp to 32 rows can be added to a point buy table\n\n### Row name\n\nThe name of the row that will appear in the table\n\n### Row variable name\n\nThe variable name of the row that can be used in calculations. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctuation.\n\nIf the variable name matches an attribute with the same variable name, the row's value will be used as a base value for that attribute." }, { "_id": "Jh92aYezHsEbSkriy", @@ -455,7 +446,7 @@ "order": 23, "urlName": "proficiency", "href": "/docs/property/proficiency", - "description": "Proficiencies add proficiency to an existing skill on the creature. If you need to add a tool or language proficiency to a creature, use a [Skill](/docs/property/skill) instead.\n\n---\n\n### Name\n\nName of the feature that is adding this proficiency\n\n### Skills\n\nA list of variable names of the skills to add proficiency to.\n\n### Proficiency\n\nHow much proficiency to add to the skill. If a skill has multiple proficiencies added to it, the highest one will be used.\n\n### Tags\n\nSee [Tags](/docs/tags)", + "description": "Proficiencies add proficiency to an existing skill on the creature. If you need to add a tool or language proficiency to a creature, use a [Skill](/docs/property/skill) instead.\n\n---\n\n### Name\n\nName of the feature that is adding this proficiency\n\n### Skills\n\nA list of variable names of the skills to add proficiency to.\n\n### Proficiency\n\nHow much proficiency to add to the skill. If a skill has multiple proficiencies added to it, the highest one will be used.\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)", "published": true }, { @@ -477,7 +468,7 @@ "urlName": "remove-buff", "href": "/docs/property/remove-buff", "published": true, - "description": "This property can remove a specific buff from a targeted creature.\n\n### Name\n\nThe name of the property. This shows in the log when the property is applied.\n\n### Remove parent buff\n\nWhen this is set and the property is applied, the property will remove the nearest parent buff. If this property is not the child of any buffs, it will log an error.\n\n### Remove all\n\nWhen this is set, all buffs that match the target tags will be removed from the targeted creature. If not set, only the first buff found with the matching tags will be removed.\n\n### Target\n\n- **Target** Matching buffs will be removed from the targeted creature\n- **Self** Matching buffs will be removed from the creature that applied the action\n\n### Tags required\n\nAny buff that has all of the required tags will be removed when the property is applied.\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Don't show in log\n\nWhen this is set, the property is applied, but does not show in the log." + "description": "This property can remove a specific buff from a targeted creature.\n\n### Name\n\nThe name of the property. This shows in the log when the property is applied.\n\n### Remove parent buff\n\nWhen this is set and the property is applied, the property will remove the nearest parent buff. If this property is not the child of any buffs, it will log an error.\n\n### Remove all\n\nWhen this is set, all buffs that match the target tags will be removed from the targeted creature. If not set, only the first buff found with the matching tags will be removed.\n\n### Target\n\n- **Target** Matching buffs will be removed from the targeted creature\n- **Self** Matching buffs will be removed from the creature that applied the action\n\n### Tags required\n\nAny buff that has all of the required tags will be removed when the property is applied.\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)\n\n### Don't show in log\n\nWhen this is set, the property is applied, but does not show in the log." }, { "_id": "8e67Pmq7RvggHp4pX", @@ -498,7 +489,7 @@ "urlName": "roll", "href": "/docs/property/roll", "published": true, - "description": "Rolls are properties that store the result of a calculation to a variable name when applied by an [action](/docs/property/action). The variable name only exists for the duration of that particalar action.\n\nRolls can be useful if you need to deal the same damage to multiple targets, or if damage needs to be rolled then halved by succeeding on a saving throw.\n\n---\n\n### Name\n\nName of the roll. This will be shown in the log when the roll is applied.\n\n### Variable name\n\nThe variable name to store the result of the roll for the duration of the action. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation.\n\n### Roll\n\nA [computed field](/docs/computed-fields) that is computed when the roll is applied by an action.\n\n### Don't show in log\n\nIf set, the roll will be applied and store its result in the variable name, but not be shown in the log.\n\n### Tags\n\nSee [Tags](/docs/tags)" + "description": "Rolls are properties that store the result of a calculation to a variable name when applied by an [action](/docs/property/action). The variable name only exists for the duration of that particalar action.\n\nRolls can be useful if you need to deal the same damage to multiple targets, or if damage needs to be rolled then halved by succeeding on a saving throw.\n\n---\n\n### Name\n\nName of the roll. This will be shown in the log when the roll is applied.\n\n### Variable name\n\nThe variable name to store the result of the roll for the duration of the action. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation.\n\n### Roll\n\nA [computed field](/docs/concepts/computed-fields) that is computed when the roll is applied by an action.\n\n### Don't show in log\n\nIf set, the roll will be applied and store its result in the variable name, but not be shown in the log.\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)" }, { "_id": "Ecc7oWEtoJgXaYLtS", @@ -518,7 +509,7 @@ "order": 26, "urlName": "saving-throw", "href": "/docs/property/saving-throw", - "description": "Saving throws are properties that cause the target to make a saving throw when applied. If you want to add a type of saving throw like Strength Save to a creature, use a [skill](/docs/property/skill) instead.\n\nWhen a saving throw is applied, the following variables are added to the scope of that action:\n\n- `$saveFailed` Set to `true` if the target failed its saving throw or there are no targets for the saving throw\n- `$saveSucceeded` Set to `true` if the target made its saving throw or there are no targets for the saving throw\n- `$saveDiceRoll` The unmodified d20 roll the target made to save\n- `$saveRoll` The final value of the saving throw roll after modifiers\n\n### Name\n\nThe name of the saving throw. Usually the ability saving throw targeted: \"Strength Save\".\n\n### DC\n\nThe DC of the saving throw that the target needs to meet\n\n### Save\n\nThe variable name of the skill that will be used to make the saving throw.\n\n### Target\n\n- **Target** Apply the saving throw to the targets of the action. Each target will make the saving throw in turn. Child properties will be applied to each target separately with the results of their individual saving throw. If a value like damage needs to be shared between targets, it should be calculated in a [Roll](/docs/property/roll) before the saving throw.\n- **Self** Apply the saving throw to the creature taking the action. The creature taking the action will become the target for all child properties.\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Don't show in log\n\nIf set, the saving throw will not show in the log when applied, but will still be rolled and apply its children.", + "description": "Saving throws are properties that cause the target to make a saving throw when applied. If you want to add a type of saving throw like Strength Save to a creature, use a [skill](/docs/property/skill) instead.\n\nWhen a saving throw is applied, the following variables are added to the scope of that action:\n\n- `$saveFailed` Set to `true` if the target failed its saving throw or there are no targets for the saving throw\n- `$saveSucceeded` Set to `true` if the target made its saving throw or there are no targets for the saving throw\n- `$saveDiceRoll` The unmodified d20 roll the target made to save\n- `$saveRoll` The final value of the saving throw roll after modifiers\n\n### Name\n\nThe name of the saving throw. Usually the ability saving throw targeted: \"Strength Save\".\n\n### DC\n\nThe DC of the saving throw that the target needs to meet\n\n### Save\n\nThe variable name of the skill that will be used to make the saving throw.\n\n### Target\n\n- **Target** Apply the saving throw to the targets of the action. Each target will make the saving throw in turn. Child properties will be applied to each target separately with the results of their individual saving throw. If a value like damage needs to be shared between targets, it should be calculated in a [Roll](/docs/property/roll) before the saving throw.\n- **Self** Apply the saving throw to the creature taking the action. The creature taking the action will become the target for all child properties.\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)\n\n### Don't show in log\n\nIf set, the saving throw will not show in the log when applied, but will still be rolled and apply its children.", "published": true }, { @@ -539,7 +530,7 @@ "order": 27, "urlName": "skill", "href": "/docs/property/skill", - "description": "Skills represent things the creature can be proficient in. Skills can have their values or behavior modifier by [effects](/docs/property/effect), and their proficiencies modified by [proficiencies](/docs/property/proficiency).\n\n---\n\n### Name\n\nThe name of the skill.\n\n### Variable name\n\nThe name used to refer to the skill in calculations and by effects. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation.\n\n### Ability\n\nThe ability score that is the basis for checks made with this skill\n\n### Type\n\n- **Skill** Regular skills like *Athletics*, *Sleight* of Hand\n- **Save** Saving throws like *Strength*, *Charisma*\n- **Check** Checks that aren't skill like *Initiative*\n- **Tool** Tool proficiencies\n- **Weapon** Weapon proficiencies\n- **Armor** Armor proficiencies\n- **Language** Language proficiencies\n- **Utility** Skills that don't show on the charcater sheet but can be used in calculations\n\n### Description\n\nA detailed description of the skill.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/tags)\n\n### Base value\n\nA [computed field](/docs/computed-fields) that determines the starting value of the skill before it is modified by effects and other properties. Multiple properties can set the base value for a given variable name, when this happens the highest base value is chosen, and then all other effects are applied.\n\n### Base proficiency\n\nThe starting proficiency of the skill.", + "description": "Skills represent things the creature can be proficient in. Skills can have their values or behavior modifier by [effects](/docs/property/effect), and their proficiencies modified by [proficiencies](/docs/property/proficiency).\n\n---\n\n### Name\n\nThe name of the skill.\n\n### Variable name\n\nThe name used to refer to the skill in calculations and by effects. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation.\n\n### Ability\n\nThe ability score that is the basis for checks made with this skill\n\n### Type\n\n- **Skill** Regular skills like *Athletics*, *Sleight* of Hand\n- **Save** Saving throws like *Strength*, *Charisma*\n- **Check** Checks that aren't skill like *Initiative*\n- **Tool** Tool proficiencies\n- **Weapon** Weapon proficiencies\n- **Armor** Armor proficiencies\n- **Language** Language proficiencies\n- **Utility** Skills that don't show on the charcater sheet but can be used in calculations\n\n### Description\n\nA detailed description of the skill.\n\nAllows [inline calculations](/docs/concepts/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)\n\n### Base value\n\nA [computed field](/docs/concepts/computed-fields) that determines the starting value of the skill before it is modified by effects and other properties. Multiple properties can set the base value for a given variable name, when this happens the highest base value is chosen, and then all other effects are applied.\n\n### Base proficiency\n\nThe starting proficiency of the skill.", "published": true }, { @@ -561,7 +552,7 @@ "urlName": "slot-filler", "href": "/docs/property/slot-filler", "published": true, - "description": "A slot filler is a property that can be used to add more complex behavior to filling a [slot](/docs/property/slot) from a library.\n\n---\n\n### Name\n\nThe name of the slot filler that will show when choosing the filler from the library.\n\n### Icon\n\nIcon of the slot filler\n\n### Description\n\nA detailed description of the slot filler.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Picture URL\n\nA link to an image to use for this slot filler when being chosen from a library.\n\n### Type\n\nSlot fillers can pretend to be any type of property when a slot is being filled.\n\n### Quantity\n\nHow many spaces the slot filler will take up in a slot.\n\n### Condition\n\nA [computed field](/docs/computed-fields) that determines whether this slot filler can be added to a character.\n\n### Tags\n\nSee [Tags](/docs/tags)" + "description": "A slot filler is a property that can be used to add more complex behavior to filling a [slot](/docs/property/slot) from a library.\n\n---\n\n### Name\n\nThe name of the slot filler that will show when choosing the filler from the library.\n\n### Icon\n\nIcon of the slot filler\n\n### Description\n\nA detailed description of the slot filler.\n\nAllows [inline calculations](/docs/concepts/inline-calculations).\n\n### Picture URL\n\nA link to an image to use for this slot filler when being chosen from a library.\n\n### Type\n\nSlot fillers can pretend to be any type of property when a slot is being filled.\n\n### Quantity\n\nHow many spaces the slot filler will take up in a slot.\n\n### Condition\n\nA [computed field](/docs/concepts/computed-fields) that determines whether this slot filler can be added to a character.\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)" }, { "_id": "bj5Bh5gsmjkLpYqA4", @@ -581,7 +572,7 @@ "order": 29, "urlName": "slot", "href": "/docs/property/slot", - "description": "Slots are the main way creatures interact with libraries. A slot can be filled by choosing a property from a library that fits that particular slot.\n\nIn a complete library, a creature can be built entirely by choosing which properties to fill each slot with.\n\nSlots show up on the build tab, and are highlighted when they have space that can be filled.\n\nIf you are building a creature without a library, you should either ignore slots entirely, or fill them with your own custom properties.\n\n---\n\n### Name\n\nThe name of the slot.\n\n### Type \n\nWhat kind of property this slot expects to fill it.\n\n### Tags required\n\nProperties in a library must have the required tags to fill the slot.\n\n### Quantity\n\nHow many properties are expected to fill this slot. Use 0 for allowing an unlimited number of properties.\n\n### Condition\n\nA [computed field](/docs/computed-fields) that determines whether this slot can accept new properties.\n\n### Unique\n\nThe slot can control how it deals with the uniqueness of properties that fill it.\n\n### Description\n\nA detailed description of the attribute.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Hide when full\n\nWhen set the slot will hide itself when it is filled.\n\n### Ignored\n\nWhen set the slot will not show a prompt card on the build tab.\n\n### Tags\n\nSee [Tags](/docs/tags)", + "description": "Slots are the main way creatures interact with libraries. A slot can be filled by choosing a property from a library that fits that particular slot.\n\nIn a complete library, a creature can be built entirely by choosing which properties to fill each slot with.\n\nSlots show up on the build tab, and are highlighted when they have space that can be filled.\n\nIf you are building a creature without a library, you should either ignore slots entirely, or fill them with your own custom properties.\n\n---\n\n### Name\n\nThe name of the slot.\n\n### Type \n\nWhat kind of property this slot expects to fill it.\n\n### Tags required\n\nProperties in a library must have the required tags to fill the slot.\n\n### Quantity\n\nHow many properties are expected to fill this slot. Use 0 for allowing an unlimited number of properties.\n\n### Condition\n\nA [computed field](/docs/concepts/computed-fields) that determines whether this slot can accept new properties.\n\n### Unique\n\nThe slot can control how it deals with the uniqueness of properties that fill it.\n\n### Description\n\nA detailed description of the attribute.\n\nAllows [inline calculations](/docs/concepts/inline-calculations).\n\n### Hide when full\n\nWhen set the slot will hide itself when it is filled.\n\n### Ignored\n\nWhen set the slot will not show a prompt card on the build tab.\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)", "published": true }, { @@ -603,7 +594,7 @@ "urlName": "spell-list", "href": "/docs/property/spell-list", "published": true, - "description": "Spell lists are collections of [spells](/docs/property/spell).\n\n---\n\n### Name\n\nThe name of the spell list.\n\n### Description\n\nA detailed description of the spell list.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Maximum prepared spells\n\nA [computed field](/docs/computed-fields) that determines how many spells can be considered ready to cast in this spell list.\n\n### Spell casting ability\n\nThe spellcasting ablity for this spell list. The variable name of the ability can be accessed using `#spellList.ability` and the ability modifier with `#spellList.abilityMod`. Setting this field will automatically update Spell save DC and Attack roll bonus if they aren't set manually.\n\n### Spell save DC\n\nA [computed field](/docs/computed-fields) that determines the DC of saving throws in this spell list. Spells can access the DC of their spell list using `#spellList.dc`\n\n### Attack roll bonus\n\nA [computed field](/docs/computed-fields) that determines the bonus to add to a d20 when making a spell attack with a spell in this spell list. Spells can access the attack roll bonus of their spell list using `#spellList.attackRollBonus`\n\n### Tags\n\nSee [Tags](/docs/tags)" + "description": "Spell lists are collections of [spells](/docs/property/spell).\n\n---\n\n### Name\n\nThe name of the spell list.\n\n### Description\n\nA detailed description of the spell list.\n\nAllows [inline calculations](/docs/concepts/inline-calculations).\n\n### Maximum prepared spells\n\nA [computed field](/docs/concepts/computed-fields) that determines how many spells can be considered ready to cast in this spell list.\n\n### Spell casting ability\n\nThe spellcasting ability for this spell list. The variable name of the ability can be accessed using `#spellList.ability` and the ability modifier with `#spellList.abilityMod`. Setting this field will automatically update Spell save DC and Attack roll bonus if they aren't set manually.\n\n### Spell save DC\n\nA [computed field](/docs/concepts/computed-fields) that determines the DC of saving throws in this spell list. Spells can access the DC of their spell list using `#spellList.dc`\n\n### Attack roll bonus\n\nA [computed field](/docs/concepts/computed-fields) that determines the bonus to add to a d20 when making a spell attack with a spell in this spell list. Spells can access the attack roll bonus of their spell list using `#spellList.attackRollBonus`\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)" }, { "_id": "Mji9Cnp2TcFHmQebt", @@ -623,7 +614,7 @@ "order": 31, "urlName": "spell", "href": "/docs/property/spell", - "description": "Spells work similarly to [actions](/docs/property/action). They appear on the spells tab and can be cast with or without using up spell slots.\n\n---\n\n### Always prepared\n\nA spell that is always prepared does not count towards the spell list's maximum prepared spells and is always active and ready to cast.\n\n### Prepared\n\nA prepared spell is ready to cast and counts against a spell list's maximum prepared spells.\n\n### Cast without spell slots\n\nWhen set, this spell can be cast without consuming spell slots. It will however consume its own uses and resources.\n\n### School\n\nWhat school the spell belongs to.\n\n### Casting time\n\nHow long the spell takes to Cast\n\n### Range\n\nThe range of the spell\n\n### Duration\n\nHow long the spell lasts\n\n### Components\n\nWhether the spell requires verbal, somatic, or material components and whether the spell is a ritual or requires concentration.\n\n### Target\n\nWho this spell should apply to. The properties under the spell will be applied to the targets.\n\n- **Self** The spell will apply its properties to the creature casting the spell\n- **Single Target** The spell will apply its properties without a target (for now)\n- **Multiple Targets** The spell will apply its properties without a target (for now)\n\n### Attack roll\n\nA [computed field](/docs/computed-fields) which calculates the spell attack roll modifier. If this field is empty, no attack roll will be made. Use 0 to make an attack roll without a modifier. To use the spell list's attack roll bonus use `#spellList.attackRollBonus`.\n\nThe following variables may be added to the action scope when attack rolls are made:\n\n - `$attackDiceRoll` The value of the d20 roll before any modifiers were applied.\n - `$attackRoll` The total attack roll after modifiers.\n - `$criticalHit` Set to `true` if the attack roll's d20 is a natural 20. If `criticalHitTarget` is set, the attack roll's d20 must instead be equal to or greater than `criticalHitTarget` for this to be set to `true`.\n - `$criticalMiss` Set to `true` if the attack roll was not a critical hit and rolled a natural 1 on the d20 roll.\n - `$attackHit` If the attack roll is higher than or equal to the target's AC or a critical hit this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical hit.\n - `$attackMiss` If the attack roll is lower than the target's AC or a critical miss, this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical miss.\n\n### Summary\n\nA brief overview of what the spell does. This will show in the log when the spell is cast.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Description\n\nA more detailed description of the spell. The description does not show in the log when the spell is cast.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Resource\n\nA resource can be any attribute that has a variable name. If the resource attribute is less than the amount required, the spell can't be cast.\n\nIf you want to reduce an attribute when casting the spell, but want the spell to be applied regardless of the value of that attribute, consider using an [Attribute Damage](/docs/property/attribute-damage) property as a child of the spell instead. Also use Attribute Damage when the amount to reduce the attribute is determined by a dice roll rather than a stable computed number.\n\n#### Resource attribute\n\nThe variable name of the attribute that will be consumed when casting this spell.\n\n#### Resource quantity\n\nA [computed field](/docs/computed-fields) which determines how much of the attribute is required to apply this spell. This amount will be deducted from the attribute every time the spell is cast\n### Ammo\n\nAmmo represents items that are requied to cast the spell. If an item is not selected, or there is insufficient quantity of the selected item, the spell can't be appled.\n\n#### Ammo item\n\nSpecify what tag an item must have to be considered valid ammo for this spell. Any item with this tag can be selected as ammo for this spell.\n\n#### Ammo quantity\n\nA [computed field](/docs/computed-fields) which determines how many of the selected items are required to cast this spell. The quantity is deducted from the total quantity of the item when this spell is applied.\n\n### Uses\n\nA [computed field](/docs/computed-fields) which determines how many times this spell can be used before it needs to be reset.\n\n### Uses used\n\nHow many of this spell's uses have already been used. Should ideally be between 0 and the total uses available. This number is set to 0 when the spell has uses and its uses are reset.\n\n### Reset\n\nIf set, the uses used field is set to 0 at the appropriate time.\n\n- **Long rest** Reset when the long rest button is pushed\n- **Short rest** Reset when either the long or short rest button is pushed\n\n\n### Tags\n\nSee [Tags](/docs/tags)", + "description": "Spells work similarly to [actions](/docs/property/action). They appear on the spells tab and can be cast with or without using up spell slots.\n\n---\n\n### Always prepared\n\nA spell that is always prepared does not count towards the spell list's maximum prepared spells and is always active and ready to cast.\n\n### Prepared\n\nA prepared spell is ready to cast and counts against a spell list's maximum prepared spells.\n\n### Cast without spell slots\n\nWhen set, this spell can be cast without consuming spell slots. It will however consume its own uses and resources.\n\n### School\n\nWhat school the spell belongs to.\n\n### Casting time\n\nHow long the spell takes to Cast\n\n### Range\n\nThe range of the spell\n\n### Duration\n\nHow long the spell lasts\n\n### Components\n\nWhether the spell requires verbal, somatic, or material components and whether the spell is a ritual or requires concentration.\n\n### Target\n\nWho this spell should apply to. The properties under the spell will be applied to the targets.\n\n- **Self** The spell will apply its properties to the creature casting the spell\n- **Single Target** The spell will apply its properties without a target (for now)\n- **Multiple Targets** The spell will apply its properties without a target (for now)\n\n### Attack roll\n\nA [computed field](/docs/concepts/computed-fields) which calculates the spell attack roll modifier. If this field is empty, no attack roll will be made. Use 0 to make an attack roll without a modifier. To use the spell list's attack roll bonus use `#spellList.attackRollBonus`.\n\nThe following variables may be added to the action scope when attack rolls are made:\n\n - `$attackDiceRoll` The value of the d20 roll before any modifiers were applied.\n - `$attackRoll` The total attack roll after modifiers.\n - `$criticalHit` Set to `true` if the attack roll's d20 is a natural 20. If `criticalHitTarget` is set, the attack roll's d20 must instead be equal to or greater than `criticalHitTarget` for this to be set to `true`.\n - `$criticalMiss` Set to `true` if the attack roll was not a critical hit and rolled a natural 1 on the d20 roll.\n - `$attackHit` If the attack roll is higher than or equal to the target's AC or a critical hit this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical hit.\n - `$attackMiss` If the attack roll is lower than the target's AC or a critical miss, this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical miss.\n\n### Summary\n\nA brief overview of what the spell does. This will show in the log when the spell is cast.\n\nAllows [inline calculations](/docs/concepts/inline-calculations).\n\n### Description\n\nA more detailed description of the spell. The description does not show in the log when the spell is cast.\n\nAllows [inline calculations](/docs/concepts/inline-calculations).\n\n### Resource\n\nA resource can be any attribute that has a variable name. If the resource attribute is less than the amount required, the spell can't be cast.\n\nIf you want to reduce an attribute when casting the spell, but want the spell to be applied regardless of the value of that attribute, consider using an [Attribute Damage](/docs/property/attribute-damage) property as a child of the spell instead. Also use Attribute Damage when the amount to reduce the attribute is determined by a dice roll rather than a stable computed number.\n\n#### Resource attribute\n\nThe variable name of the attribute that will be consumed when casting this spell.\n\n#### Resource quantity\n\nA [computed field](/docs/concepts/computed-fields) which determines how much of the attribute is required to apply this spell. This amount will be deducted from the attribute every time the spell is cast\n### Ammo\n\nAmmo represents items that are requied to cast the spell. If an item is not selected, or there is insufficient quantity of the selected item, the spell can't be appled.\n\n#### Ammo item\n\nSpecify what tag an item must have to be considered valid ammo for this spell. Any item with this tag can be selected as ammo for this spell.\n\n#### Ammo quantity\n\nA [computed field](/docs/concepts/computed-fields) which determines how many of the selected items are required to cast this spell. The quantity is deducted from the total quantity of the item when this spell is applied.\n\n### Uses\n\nA [computed field](/docs/concepts/computed-fields) which determines how many times this spell can be used before it needs to be reset.\n\n### Uses used\n\nHow many of this spell's uses have already been used. Should ideally be between 0 and the total uses available. This number is set to 0 when the spell has uses and its uses are reset.\n\n### Reset\n\nIf set, the uses used field is set to 0 at the appropriate time.\n\n- **Long rest** Reset when the long rest button is pushed\n- **Short rest** Reset when either the long or short rest button is pushed\n\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)", "published": true }, { @@ -645,7 +636,7 @@ "urlName": "toggle", "href": "/docs/property/toggle", "published": true, - "description": "Toggles are a way to turn on and off parts of a creature. When a toggle is off, none of its children will be active.\n\nCalculated toggles should be avoided if possible, because while they offer a lot of power and flexibility to the creature engine, they often create [dependency loops](/docs/dependency-loops) that can be difficult to troubleshoot, causing parts of a creature to calculate incorrectly.\n\nCalculated toggles can be applied by [actions](/docs/property/action) and will apply their children if the condition is true, but they should be avoided in favor of [conditional branches](/docs/property/branch) which can do the same, but are more efficient.\n\n---\n\n### Name\n\nThe name of the toggle.\n\n### Variable name\n\nThe name used to refer to the value of the toggle in calculations. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation.\n\n### Show on character sheet\n\nIf set, the toggle with show a checkbox on the character sheet. A calculated toggle will show a disabled checkbox, filled in if the toggle's calculation returned `true` or a value that isn't 0.\n\n### State\n\n- **Enabled** The toggle and its children are active\n- **Disabled** The toggle and its children are inactive\n- **Calculated** The active status of the toggle depends on the result of the condition. Use with caution.\n\n### Condition\n\nA [computed field](/docs/computed-fields) that determines if the toggle is active. Use with caution.\n\n### Tags\n\nSee [Tags](/docs/tags)" + "description": "Toggles are a way to turn on and off parts of a creature. When a toggle is off, none of its children will be active.\n\nCalculated toggles should be avoided if possible, because while they offer a lot of power and flexibility to the creature engine, they often create [dependency loops](/docs/concepts/dependency-loops) that can be difficult to troubleshoot, causing parts of a creature to calculate incorrectly.\n\nCalculated toggles can be applied by [actions](/docs/property/action) and will apply their children if the condition is true, but they should be avoided in favor of [conditional branches](/docs/property/branch) which can do the same, but are more efficient.\n\n---\n\n### Name\n\nThe name of the toggle.\n\n### Variable name\n\nThe name used to refer to the value of the toggle in calculations. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation.\n\n### Show on character sheet\n\nIf set, the toggle with show a checkbox on the character sheet. A calculated toggle will show a disabled checkbox, filled in if the toggle's calculation returned `true` or a value that isn't 0.\n\n### State\n\n- **Enabled** The toggle and its children are active\n- **Disabled** The toggle and its children are inactive\n- **Calculated** The active status of the toggle depends on the result of the condition. Use with caution.\n\n### Condition\n\nA [computed field](/docs/concepts/computed-fields) that determines if the toggle is active. Use with caution.\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)" }, { "_id": "v7eRZRdMoDPah7ZtE", @@ -665,7 +656,7 @@ "order": 33, "urlName": "trigger", "href": "/docs/property/trigger", - "description": "Triggers apply their children whenever their condition is met. They work like [actions](/docs/property/action) that are taken automatically.\n\n---\n\n### Name\n\nThe name of the trigger.\n\n### Timing\n\n- **Before** The trigger is applied before the triggering event takes place\n- **After** The trigger is fired after the triggering event\n\n### Event\n\n- **Do action** While the creature is doing an action, the action property specified in *Event type* is applied\n- **Roll check** The creature makes a check\n- **Attribute damaged or healed** One of the creature's attributes changed value through attribute damage or manual adjustment\n- **Short or long rest**\n- **Short rest**\n- **Long Rest**\n\n### Event type\n\nThe trigger will apply when this property type is applied by the action\n\n### Tags required\n\nIf this trigger is fired by a property, the property must match these tags for the trigger to fire.\n\n### Condition\n\nA [computed field](/docs/computed-fields) to determine if the trigger should fire. The trigger will fire if the condition field is empty or if it returns `true` or a value that isn't 0.\n\n### Description\n\nA detailed description of the trigger.\n\nAllows [inline calculations](/docs/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)\n\n### Don't show in log\n\nWhen this is true, the trigger does not show up in the log. This does not stop the trigger's children from appearing in the log when they are applied.", + "description": "Triggers apply their children whenever their condition is met. They work like [actions](/docs/property/action) that are taken automatically.\n\n---\n\n### Name\n\nThe name of the trigger.\n\n### Timing\n\n- **Before** The trigger is applied before the triggering event takes place\n- **After** The trigger is fired after the triggering event\n\n### Event\n\n- **Do action** While the creature is doing an action, the action property specified in *Event type* is applied\n- **Roll check** The creature makes a check\n- **Attribute damaged or healed** One of the creature's attributes changed value through attribute damage or manual adjustment\n- **Short or long rest**\n- **Short rest**\n- **Long Rest**\n\n### Event type\n\nThe trigger will apply when this property type is applied by the action\n\n### Tags required\n\nIf this trigger is fired by a property, the property must match these tags for the trigger to fire.\n\n### Condition\n\nA [computed field](/docs/concepts/computed-fields) to determine if the trigger should fire. The trigger will fire if the condition field is empty or if it returns `true` or a value that isn't 0.\n\n### Description\n\nA detailed description of the trigger.\n\nAllows [inline calculations](/docs/concepts/inline-calculations).\n\n### Tags\n\nSee [Tags](/docs/concepts/tags)\n\n### Don't show in log\n\nWhen this is true, the trigger does not show up in the log. This does not stop the trigger's children from appearing in the log when they are applied.", "published": true }, { @@ -687,7 +678,7 @@ "urlName": "computed-fields", "href": "/docs/concepts/computed-fields", "published": true, - "description": "Some fields in DiceCloud creature properties expect calculations. These fields are then computed by the DiceCloud engine.\n\nSome fields, like the value of an attirbute, resolve down to a single number, while others, like the damage to deal in an attack, only simplify their calculation as far as they can, and then resolve down to a number when applied. Avoid adding dice rolls to calculations that expect to resolve down to a number, because they will re-roll every time the creature is recalculated, causing instability in the creature's stats.\n\n## Parser\n\nThe DiceCloud parser can understand the following syntax:\n\n| | |\n| :- | :- |\n| **Numbers** | `13`, `3.14` |\n| **Dice rolls** | `3d6`, `(1 + 2)d4`|\n| **Strings of text** | `'Some text'`, `\"some other text\"` |\n| **Boolean values** | `true` or `false`. When DiceCloud expects a boolean, `0`, an empty string `''` and `false` are all considered false by DiceCloud's engine, every other value is considered true. |\n| **Variable names** | `variableName` |\n| **Addition and subtraction** | `1 + 2 + 3`, `12 - 6` |\n| **Multiplication** | `6 * 4`, `12 * 2` = `24` |\n| **Exponents** | `3 ^ 2` Raise 3 to the power of 2 |\n| **Modulo** | Returns the remainder of a division operation `15 % 6` = `3` |\n| **AND** | `&` or `&&`: Returns the value of the right hand side if the left side is true `true & 'cat'` = `'cat'` |\n| **OR** | `|` or `||`: Returns the left hand side if it is true, otherwise returns the right hand side `'dog' || 'cat'` = `'dog'` |\n| **NOT** | `!` returns false if the value after it is true, otherwise returns false |\n| **Comparisons** | greater than: `>`, less than: `<`, greater than or equal to: `>=`, less than or equal to: `<=`, equal: `=` or `==` or `===`, not equal: `!=` or `!==` |\n| **If-else** | `condition ? resultIfTrue : resultIfFalse`, `level > 10 ? 'high tier' : 'low tier'` |\n| **Arrays** | lists of values `[3, 6, 9, 12]`. |\n| **Array Indexes** | A value can be chosen from an array using another set of square brackets: `[3, 6, 9, 12][2]` = `[6]` because `[2]` fetches the 2nd value in the array. Arrays start at 1 in DiceCloud so that level tables can have 20 entries and be accessed by `array[level]`. |\n| **Function calls** | `functionName(argument1, argument1)` See [Functions](/docs/functions) for a full list of available functions. |\n\n## Special variables\n\n### Built-in variables\n\nThese variables are added to the creature automatically when relevant. They can be overriden if needed by creating a property with the same variable name. They can also be targetted by effects.\n\n- `xp` A total of all the experiences with xp added to the character sheet\n- `milestoneLevels` A total of all the experiences with milestone levels added to the character sheet\n- `itemsAttuned` Number of items the creature is attuned to\n- `weightEquipment` Total weight of all equipment on the creature\n- `valueEquipment` Total value of all equipment on the creature\n- `weightTotal` Total weight of the creature's entire inventory\n- `valueTotal` Total value of the creature's entire inventory\n- `weightCarried` Total weight of all carried items and containers\n- `valueCarried` Total value of all carried items and containers\n- `level` The current level of the creature, including all class levels\n- `criticalHitTarget` Defaults to 20, the natural roll needed to consider an attack roll as a critical hit\n\n### Action variables\n\nThese variables are available during an action after the relevant property has been applied.\n\nFor Advanced users, a [Roll](/docs/property/roll) can set these variables, overriding the default behavior.\n\n#### [Actions](/docs/property/action)\n\n- `$attackDiceRoll` The value of the d20 roll before any modifiers were applied.\n- `$attackRoll` The total attack roll after modifiers.\n- `$criticalHit` Set to `true` if the attack roll's d20 is a natural 20. If `criticalHitTarget` is set, the attack roll's d20 must instead be equal to or greater than `criticalHitTarget` for this to be set to `true`.\n- `$criticalMiss` Set to `true` if the attack roll was not a critical hit and rolled a natural 1 on the d20 roll.\n- `$attackHit` If the attack roll is higher than or equal to the target's AC or a critical hit this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical hit.\n- `$attackMiss` If the attack roll is lower than the target's AC or a critical miss, this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical miss.\n\n#### [Damage](/docs/property/damage)\n\n- `$lastDamageType` The type of damage dealt last, any damage that has the `extra` type will use this damage type instead\n\n#### [Saving throws](/docs/property/saving-throw)\n\n- `$saveFailed` Set to `true` if the target failed its saving throw or there are no targets for the saving throw\n- `$saveSucceeded` Set to `true` if the target made its saving throw or there are no targets for the saving throw\n- `$saveDiceRoll` The unmodified d20 roll the target made to save\n- `$saveRoll` The final value of the saving throw roll after modifiers\n\n## Ancestor references\n\nThe ancestors of a property can be accessed directly using the `#ancestorType` syntax.\n\nFor example, a spell might need to know the save DC of the spell list that it is inside of, it can use `#spellList.dc`.\n\nTriggers and their children work differently: They don't have access to their own ancestors, but rather inherit the ancestors of the property that caused them to fire. For example, a trigger at the root of the creature's tree might be fired by a spell being cast, you can still use references to ancestors like `#spellList.attackRollBonus` inside that trigger as if it were under the spell itself." + "description": "Some fields in DiceCloud creature properties expect calculations. These fields are then computed by the DiceCloud engine.\n\nSome fields, like the value of an attirbute, resolve down to a single number, while others, like the damage to deal in an attack, only simplify their calculation as far as they can, and then resolve down to a number when applied. Avoid adding dice rolls to calculations that expect to resolve down to a number, because they will re-roll every time the creature is recalculated, causing instability in the creature's stats.\n\n## Parser\n\nThe DiceCloud parser can understand the following syntax:\n\n| | |\n| :- | :- |\n| **Numbers** | `13`, `3.14` |\n| **Dice rolls** | `3d6`, `(1 + 2)d4`|\n| **Strings of text** | `'Some text'`, `\"some other text\"` |\n| **Boolean values** | `true` or `false`. When DiceCloud expects a boolean, `0`, an empty string `''` and `false` are all considered false by DiceCloud's engine, every other value is considered true. |\n| **Variable names** | `variableName` |\n| **Addition and subtraction** | `1 + 2 + 3`, `12 - 6` |\n| **Multiplication** | `6 * 4`, `12 * 2` = `24` |\n| **Exponents** | `3 ^ 2` Raise 3 to the power of 2 |\n| **Modulo** | Returns the remainder of a division operation `15 % 6` = `3` |\n| **AND** | `&` or `&&`: Returns the value of the right hand side if the left side is true `true & 'cat'` = `'cat'` |\n| **OR** | `|` or `||`: Returns the left hand side if it is true, otherwise returns the right hand side `'dog' || 'cat'` = `'dog'` |\n| **NOT** | `!` returns false if the value after it is true, otherwise returns false |\n| **Comparisons** | greater than: `>`, less than: `<`, greater than or equal to: `>=`, less than or equal to: `<=`, equal: `=` or `==` or `===`, not equal: `!=` or `!==` |\n| **If-else** | `condition ? resultIfTrue : resultIfFalse`, `level > 10 ? 'high tier' : 'low tier'` |\n| **Arrays** | lists of values `[3, 6, 9, 12]`. |\n| **Array Indexes** | A value can be chosen from an array using another set of square brackets: `[3, 6, 9, 12][2]` = `[6]` because `[2]` fetches the 2nd value in the array. Arrays start at 1 in DiceCloud so that level tables can have 20 entries and be accessed by `array[level]`. |\n| **Function calls** | `functionName(argument1, argument1)` See [Functions](/docs/concepts/functions) for a full list of available functions. |\n\n## Special variables\n\n### Built-in variables\n\nThese variables are added to the creature automatically when relevant. They can be overriden if needed by creating a property with the same variable name. They can also be targetted by effects.\n\n- `xp` A total of all the experiences with xp added to the character sheet\n- `milestoneLevels` A total of all the experiences with milestone levels added to the character sheet\n- `itemsAttuned` Number of items the creature is attuned to\n- `weightEquipment` Total weight of all equipment on the creature\n- `valueEquipment` Total value of all equipment on the creature\n- `weightTotal` Total weight of the creature's entire inventory\n- `valueTotal` Total value of the creature's entire inventory\n- `weightCarried` Total weight of all carried items and containers\n- `valueCarried` Total value of all carried items and containers\n- `level` The current level of the creature, including all class levels\n- `criticalHitTarget` Defaults to 20, the natural roll needed to consider an attack roll as a critical hit\n\n### Action variables\n\nThese variables are available during an action after the relevant property has been applied.\n\nFor Advanced users, a [Roll](/docs/property/roll) can set these variables, overriding the default behavior.\n\n#### [Actions](/docs/property/action)\n\n- `$attackDiceRoll` The value of the d20 roll before any modifiers were applied.\n- `$attackRoll` The total attack roll after modifiers.\n- `$criticalHit` Set to `true` if the attack roll's d20 is a natural 20. If `criticalHitTarget` is set, the attack roll's d20 must instead be equal to or greater than `criticalHitTarget` for this to be set to `true`.\n- `$criticalMiss` Set to `true` if the attack roll was not a critical hit and rolled a natural 1 on the d20 roll.\n- `$attackHit` If the attack roll is higher than or equal to the target's AC or a critical hit this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical hit.\n- `$attackMiss` If the attack roll is lower than the target's AC or a critical miss, this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical miss.\n\n#### [Damage](/docs/property/damage)\n\n- `$lastDamageType` The type of damage dealt last, any damage that has the `extra` type will use this damage type instead\n\n#### [Saving throws](/docs/property/saving-throw)\n\n- `$saveFailed` Set to `true` if the target failed its saving throw or there are no targets for the saving throw\n- `$saveSucceeded` Set to `true` if the target made its saving throw or there are no targets for the saving throw\n- `$saveDiceRoll` The unmodified d20 roll the target made to save\n- `$saveRoll` The final value of the saving throw roll after modifiers\n\n## Ancestor references\n\nThe ancestors of a property can be accessed directly using the `#ancestorType` syntax.\n\nFor example, a spell might need to know the save DC of the spell list that it is inside of, it can use `#spellList.dc`.\n\nTriggers and their children work differently: They don't have access to their own ancestors, but rather inherit the ancestors of the property that caused them to fire. For example, a trigger at the root of the creature's tree might be fired by a spell being cast, you can still use references to ancestors like `#spellList.attackRollBonus` inside that trigger as if it were under the spell itself." }, { "_id": "o8u2Z5gZW54ZXNeZB", @@ -728,7 +719,7 @@ "order": 36, "urlName": "inline-calculations", "href": "/docs/concepts/inline-calculations", - "description": "Most long-format fields allow inline [calculations](/docs/computed-fields) to be included. Calculations inside of curly bracers will be computed down to numbers using the characters stats.\n\nFor example a creature's strength attribute may have the following in its description: `Your carrying capacity is {strength * 15} lbs.`\n\nWhen the creature is calculated, if it has 8 strength, the action description will become: \"Your carrying capacity is 120 lbs.\"\n\nIf a description includes a dice roll, only the part that can be calculated to a single number should be included in the calulation bracers: `The attack does an extra {paladin.level}d8 damage`, which becomes `The attack does an extra 4d8 damage`.\n\nDo not inlclude the dice roll in the calaculation: `The attack does an extra {(paladin.level)d8} damage`, because it will become `The attack does an extra 16 damage` but the number 16 will change every time the creature recalculates.", + "description": "Most long-format fields allow inline [calculations](/docs/concepts/computed-fields) to be included. Calculations inside of curly bracers will be computed down to numbers using the characters stats.\n\nFor example a creature's strength attribute may have the following in its description: `Your carrying capacity is {strength * 15} lbs.`\n\nWhen the creature is calculated, if it has 8 strength, the action description will become: \"Your carrying capacity is 120 lbs.\"\n\nIf a description includes a dice roll, only the part that can be calculated to a single number should be included in the calulation bracers: `The attack does an extra {paladin.level}d8 damage`, which becomes `The attack does an extra 4d8 damage`.\n\nDo not inlclude the dice roll in the calaculation: `The attack does an extra {(paladin.level)d8} damage`, because it will become `The attack does an extra 16 damage` but the number 16 will change every time the creature recalculates.", "published": true }, { @@ -771,5 +762,26 @@ "href": "/docs/concepts/functions", "description": "## min\nReturns the smallest of the given numbers\n`min(12, 6, 3, 168)` = `3`\n\n## round\nReturns the value of a number rounded to the nearest integer\n`round(5.95)` = `6`\n`round(5.5)` = `6`\n`round(5.05)` = `5`\n\n## floor\nRounds a number down to the next smallest integer\n`floor(5.95)` = `5`\n`floor(5.05)` = `5`\n`floor(5)` = `5`\n`floor(-5.5)` = `-6`\n\n## ceil\nRounds a number up to the next largest integer\n`ceil(5.95)` = `6`\n`ceil(5.05)` = `6`\n`ceil(5)` = `5`\n`ceil(-5.5)` = `-5`\n\n## trunc\nReturns the integer part of a number by removing any fractional digits\n`trunc(5.95)` = `5`\n`trunc(5.05)` = `5`\n`trunc(5)` = `5`\n`trunc(-5.5)` = `-5`\n\n## sign\nReturns either a positive or negative 1, indicating the sign of a number, or zero\n`sign(-3)` = `-1`\n`sign(3)` = `1`\n`sign(0)` = `0`\n\n## tableLookup\nReturns the index of the last value in the array that is less than the specified amount\n`tableLookup([100, 300, 900], 457)` = `2`\n`tableLookup([100, 300, 900], 23)` = `0`\n`tableLookup([100, 300, 900, 1200], 900)` = `3`\n`tableLookup([100, 300], 594)` = `2`\n\n## resolve\nForces the given calcultion to resolve into a number, even in calculations where it would usually keep the unknown values as is\n`resolve(someUndefinedVariable + 3 + 4)` = `7`\n`resolve(1d6)` = `4`", "published": true + }, + { + "_id": "AQGjqq6grmKXZN6dB", + "name": "Character Tree", + "parent": { + "id": "E2DFwsCoiKy2Rc9Mz", + "collection": "docs" + }, + "ancestors": [ + { + "id": "E2DFwsCoiKy2Rc9Mz", + "collection": "docs", + "name": "Concepts", + "urlName": "concepts" + } + ], + "order": 39, + "urlName": "tree", + "href": "/docs/concepts/tree", + "published": false, + "description": "TODO" } ] \ No newline at end of file From 002c767d1a2716914ae1e093fcf6b62f6be84603 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 24 Nov 2022 12:57:53 +0200 Subject: [PATCH 080/247] Bumped version --- app/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/package.json b/app/package.json index 5ce84b96..82d80adf 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "dicecloud", - "version": "2.0.44", + "version": "2.0.45", "description": "Unofficial Online Realtime D&D 5e App", "license": "GPL-3.0", "repository": { @@ -118,4 +118,4 @@ ] } } -} +} \ No newline at end of file From 881496e9c131aac0f79ade6d16c3b37d54ed840e Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 24 Nov 2022 13:09:03 +0200 Subject: [PATCH 081/247] Removed all md docs --- app/private/docs/property/action.md | 113 ----------------- app/private/docs/property/attribute-damage.md | 33 ----- app/private/docs/property/attribute.md | 76 ------------ app/private/docs/property/branch.md | 24 ---- app/private/docs/property/buff.md | 44 ------- app/private/docs/property/class-level.md | 29 ----- app/private/docs/property/class.md | 37 ------ app/private/docs/property/constant.md | 33 ----- app/private/docs/property/container.md | 35 ------ .../docs/property/damage-multiplier.md | 33 ----- app/private/docs/property/damage.md | 32 ----- app/private/docs/property/effect.md | 60 --------- app/private/docs/property/feature.md | 25 ---- app/private/docs/property/folder.md | 17 --- app/private/docs/property/item.md | 57 --------- app/private/docs/property/note.md | 25 ---- app/private/docs/property/point-buy.md | 39 ------ app/private/docs/property/proficiency.md | 21 ---- app/private/docs/property/remove-buff.md | 32 ----- app/private/docs/property/roll.md | 27 ---- app/private/docs/property/saving-throw.md | 35 ------ app/private/docs/property/slot-filler.md | 39 ------ app/private/docs/property/slot.md | 53 -------- app/private/docs/property/spell.md | 115 ------------------ app/private/docs/property/toggle.md | 36 ------ app/private/docs/property/trigger.md | 49 -------- .../docs/walkthroughs/create-a-class.md | 47 ------- 27 files changed, 1166 deletions(-) delete mode 100644 app/private/docs/property/action.md delete mode 100644 app/private/docs/property/attribute-damage.md delete mode 100644 app/private/docs/property/attribute.md delete mode 100644 app/private/docs/property/branch.md delete mode 100644 app/private/docs/property/buff.md delete mode 100644 app/private/docs/property/class-level.md delete mode 100644 app/private/docs/property/class.md delete mode 100644 app/private/docs/property/constant.md delete mode 100644 app/private/docs/property/container.md delete mode 100644 app/private/docs/property/damage-multiplier.md delete mode 100644 app/private/docs/property/damage.md delete mode 100644 app/private/docs/property/effect.md delete mode 100644 app/private/docs/property/feature.md delete mode 100644 app/private/docs/property/folder.md delete mode 100644 app/private/docs/property/item.md delete mode 100644 app/private/docs/property/note.md delete mode 100644 app/private/docs/property/point-buy.md delete mode 100644 app/private/docs/property/proficiency.md delete mode 100644 app/private/docs/property/remove-buff.md delete mode 100644 app/private/docs/property/roll.md delete mode 100644 app/private/docs/property/saving-throw.md delete mode 100644 app/private/docs/property/slot-filler.md delete mode 100644 app/private/docs/property/slot.md delete mode 100644 app/private/docs/property/spell.md delete mode 100644 app/private/docs/property/toggle.md delete mode 100644 app/private/docs/property/trigger.md delete mode 100644 app/private/docs/walkthroughs/create-a-class.md diff --git a/app/private/docs/property/action.md b/app/private/docs/property/action.md deleted file mode 100644 index ca1ae0ab..00000000 --- a/app/private/docs/property/action.md +++ /dev/null @@ -1,113 +0,0 @@ -# Actions - -Actions are things your character can do. When an action is taken, all the properties under it are applied. - -Add actions to your character sheet, then add children under the action to determine what happenes when the action is applied. - -When an action is applied it will create an entry in the character's log detailing all the properties that were applied and what their results were. - -The following properties can all be applied by an action: - - - [Attribute Damage](/docs/property/attribute-damage) - - [Branches](/docs/property/branch) - - [Buffs](/docs/property/buff) - - [Buff Removers](/docs/property/remove-buff) - - [Damage](/docs/property/damage) - - [Notes](/docs/property/note) - - [Rolls](/docs/property/roll) - - [Saving Throws](/docs/property/saving-throw) - - Other actions - ---- - -### Name - -The name of the action. - -### Action type - -How long the action takes to perform. - -Allows [inline calculations](/docs/inline-calculations). - -### Attack roll - -A [computed field](/docs/computed-fields) which calculates the attack roll modifier. If this field is empty, no attack roll will be made. Use 0 to make an attack roll without a modifier. - -The following variables may be added to the action scope when attack rolls are made: - - - `$attackDiceRoll` The value of the d20 roll before any modifiers were applied. - - `$attackRoll` The total attack roll after modifiers. - - `$criticalHit` Set to `true` if the attack roll's d20 is a natural 20. If `criticalHitTarget` is set, the attack roll's d20 must instead be equal to or greater than `criticalHitTarget` for this to be set to `true`. - - `$criticalMiss` Set to `true` if the attack roll was not a critical hit and rolled a natural 1 on the d20 roll. - - `$attackHit` If the attack roll is higher than or equal to the target's AC or a critical hit this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical hit. - - `$attackMiss` If the attack roll is lower than the target's AC or a critical miss, this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical miss. - -### Summary - -A brief overview of what the action does. This will appear in the action card, and shows in the log when the action is applied. - -Allows [inline calculations](/docs/inline-calculations). - -### Description - -A more detailed description of the action. The description does not show in the action card or the log when the action is applied. - -Allows [inline calculations](/docs/inline-calculations). - -### Resource - -A resource can be any attribute that has a variable name. If the resource attribute is less than the amount required, the action can't be applied. - -If you want to reduce an attribute when taking the action, but want the action to be applied regardless of the value of that attribute, consider using an [Attribute Damage](/docs/property/attribute-damage) property as a child of the action instead. Also use Attribute Damage when the amount to reduce the attribute is determined by a dice roll rather than a stable computed number. - -#### Resource attribute - -The variable name of the attribute that will be consumed when taking this action. - -#### Resource quantity - -A [computed field](/docs/computed-fields) which determines how much of the attribute is required to apply this action. This amount will be deducted from the attribute every time the action is taken. - -### Ammo - -Ammo represents items that are requied to take the action. If an item is not selected, or there is insufficient quantity of the selected item, the action can't be appled. - -#### Ammo item - -Specify what tag an item must have to be considered valid ammo for this action. Any item with this tag can be selected as ammo for this action. - -#### Ammo quantity - -A [computed field](/docs/computed-fields) which determines how many of the selected items are required to take this action. The quantity is deducted from the total quantity of the item when this action is applied. - -### Tags - -See [Tags](/docs/tags) - -### Target - -Who this action should apply to. The properties under the action will be applied to the Targets. - -- **Self** The action will apply its properties to the creature taking the action -- **Single Target** The action will apply its properties without a target (for now) -- **Multiple Targets** The action will apply its properties without a target (for now) - -### Uses - -A [computed field](/docs/computed-fields) which determines how many times this action can be used before it needs to be reset. - -### Uses used - -How many of this action's uses have already been used. Should ideally be between 0 and the total uses available. This number is set to 0 when the action has uses and its uses are reset. - -### Don't show in log - -When this is true, the action does not show up in the log. This does not stop the action's children from appearing in the log when they are applied. - -### Reset - -If set, the uses used field is set to 0 at the appropriate time. - -- **Long rest** Reset when the long rest button is pushed -- **Short rest** Reset when either the long or short rest button is pushed diff --git a/app/private/docs/property/attribute-damage.md b/app/private/docs/property/attribute-damage.md deleted file mode 100644 index 166f864c..00000000 --- a/app/private/docs/property/attribute-damage.md +++ /dev/null @@ -1,33 +0,0 @@ -# Attribute Damage - -When applied, attribute damage reduces the value of the attribute by some amount or set the value of an attribute to some amount. Attribute damage can by applied by actions or triggers. - -Using a negative value to damage an attribute will heal the attribute instead. - ---- - -### Attribute - -The variable name of the attribute to target. - -### Amount - -A [computed field](/docs/computed-fields) which determined the amount to damage the attribute or set the attribute's value to. - -### Operation - -- **Damage** Reduce the value of the attribute by the amount, negative values heal the attribute instead -- **Set** Set the value of the attribute to the amount - -### Target - -- **Target** Apply the attribute damage to the same target as the action applying this property -- **Self** Apply the attribute damage to the creature taking the action - -### Tags - -See [Tags](/docs/tags) - -### Don't show in log - -When this is set, the attribute damage is applied, but does not show in the log. diff --git a/app/private/docs/property/attribute.md b/app/private/docs/property/attribute.md deleted file mode 100644 index 156289f5..00000000 --- a/app/private/docs/property/attribute.md +++ /dev/null @@ -1,76 +0,0 @@ -# Attribute - -Attributes represent the numerical values of the creature. - -Attributes can be targeted by [effects](/docs/property/effect) which can change their total value in a non-destructive way. For example, if a class level gives you an ability score increase of +2 strength when it is taken, instead of directly editing the strength attribute, you add an effect to the class level that adds 2 to strength. The total value of strength will increase by 2 and it will show a record of that ability score increase and where it came from. - -Attributes, [skills](/docs/properties/skill), and [effects](/docs/property/effect) are the core properties of DiceCloud's creature engine. - -Attributes have the following fields that can be accessed in calculations with `variableName.field`: - -- `.total` The total of the attribute before being damaged -- `.damage` the amount of damage the attribute has taken -- `.value` The current value of the attribute including damage. `variableName` and `variableName.value` are equivalent. -- `.modifier` If the attribute is an ability, this is its roll modifier, eg. `strength.modifier` is +2 when `strength.value` is 14 - ---- - -### Base value - -A [computed field](/docs/computed-fields) that determines the starting value of the attribute before it is modified by effects and other properties. Multiple properties can set the base value for a given variable name, when this happens the highest base value is chosen, and then all other effects are applied. - -### Name - -The name of the attribute - -### Variable name - -The name used to refer to the attribute in calculations and by effects. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation. - -If multiple attributes share a variable name, only the last attribute on the [character tree](/docs/tree) will count as the defining attribute and appear on the sheet, while other attributes with that variable name will be used as base value [effects](/docs/property/effect). - -### Attribute type - -- **Ability** Ablity scores like Strength, Dexterity, etc. Ability scores get a modifier which can be accessed in calculations as `variableName.modifier`, -- **Stat** Any numerical value that appears on the sheet. Speed, armor class. -- **Modifier** Any numical value that appears on the sheet with a `+` or `-` sign, eg. Proficiency bonus. -- **Hit Dice** Hit dice let you select the appropriate hit dice size. Creatures regain half their total hit dice on long rest. -- **Health Bar** Health bars can by made to take or ignore damage in a specified order -- **Resource** Rages, sourcery points, things that are spent to use actions. -- **Spell Slot** Spell slots have a specific level and are used to cast spells. -- **Utility** Utility attributes don't show up anywhere on the sheet, but can still be used for calculations - -### Description - -A detailed description of the attribute. - -Allows [inline calculations](/docs/inline-calculations). - -### Health bar settings - -Health bars can take or ignore damage and healing from applied damage properties targeting a creature. A lower ordered health bar will take damage before a higher ordered one. - -Health bars can also change color depending on their value. At 50%+ full they are their property color, between 50% and 0% they fade from their half-full color to their empty color. - -### Tags - -See [Tags](/docs/tags) - -### Allow decimal values - -If this is set, the attribute will not round-down when its value has a decimal. - -### Can be damaged into negative values - -If this is set the attribute can be damaged past zero into negative values. - -### Can be incremented above total - -If this is set the attribute can have negative damage such that the value exceeds the total. This can be useful if you are using the attribute to count, it can start at zero and be healed upwards to keep count. - -### Reset - -If set, the damage on this attribute is reset to 0 at the appropriate time. - -- **Long rest** Reset when the long rest button is pushed -- **Short rest** Reset when either the long or short rest button is pushed diff --git a/app/private/docs/property/branch.md b/app/private/docs/property/branch.md deleted file mode 100644 index cdd579d9..00000000 --- a/app/private/docs/property/branch.md +++ /dev/null @@ -1,24 +0,0 @@ -# Branches - -Branches are applied by actions, when they are applied they can control which of their immediate children are applied. - ---- - -### Branch type - -- **If condition is true** Apply children if the condition (a [computed field](/docs/computed-fields)) resolves to `true` or a non-zero number -- **Attack hit** Apply children if the attack roll hit the target -- **Attack hit** Apply children if the attack roll missed the target -- **Save failed** Apply children if target failed its saving throw -- **Save suceeded** Apply children if target made its saving throw -- **Apply to each target** Apply children separately to each target -- **Random** Apply one of the immediate children at random -- **Calculated Index** Use the index (a [computed field](/docs/computed-fields)) to choose which child to apply, starting at 1 for the first child. - -### Tags - -See [Tags](/docs/tags) - -### Don't show in log - -When this is set, the branch is applied, but does not show in the log. This does not prevent its children from appearing in the log. diff --git a/app/private/docs/property/buff.md b/app/private/docs/property/buff.md deleted file mode 100644 index 3196f0ab..00000000 --- a/app/private/docs/property/buff.md +++ /dev/null @@ -1,44 +0,0 @@ -# Buffs - -Buffs are temporary changes to a character sheet that can be applied by actions. When a buff is applied, it is copied to the target character along with all of its children properties. - -Buffs can either be manually removed from the stats page, or be removed by an action applying a [buff remover](/docs/property/remove-buff/) property. - -### Variable freezing - -When a buff is applied, all the calculations in the child properties have their variables frozen to their values at the time the buff is applied. You can prevent this behavior for the whole buff by using the `don't freeze variables` option, or on an individual variable reference by prefixing the variable with the keyword `$target.`. - -For example, if a character has 10 strength and 16 dexterity, and applies a buff with some child property containing the calculation `$target.strength + dexterity` the property's calculation will become `strength + 16` when it is copied to the target character. - ---- - -### Name - -The name of the buff. - -### Description - -Description of the applied buff. - -Allows [inline calculations](/docs/inline-calculations). - -### Target - -- **Target** Apply the buff to the target of the action -- **Self** Apply the buff to the creature taking the action - -### Hide remove button - -If this is set, the remove button next to the buff on the stats page will be hidden. Use this when you expect the buff to be removed automatically by another action. - -### Don't show in log - -If set, the buff will not show its name and description in the log when applied. - -### Don't freeze variables - -Prevent the buff from freezing variables in child property calculations to their value at the time the buff was applied. - -### Tags - -See [Tags](/docs/tags) diff --git a/app/private/docs/property/class-level.md b/app/private/docs/property/class-level.md deleted file mode 100644 index c4b1a3f3..00000000 --- a/app/private/docs/property/class-level.md +++ /dev/null @@ -1,29 +0,0 @@ -# Class level - -A class level is a property that represents a single level in a class. It is generally used as a child of a [Class property](/docs/property/class). - -Features and bonuses that are given by a class level get added as children of the class level. - ---- - -### Level - -Which level this property represents. - -### Name - -The name of the class or subclass this level is part of - -### Variable name - -The same variable name of the class this level belongs to. - -### Description - -A description of the benefits gained with this level. - -Allows [inline calculations](/docs/inline-calculations). - -### Tags - -See [Tags](/docs/tags) diff --git a/app/private/docs/property/class.md b/app/private/docs/property/class.md deleted file mode 100644 index b8630da3..00000000 --- a/app/private/docs/property/class.md +++ /dev/null @@ -1,37 +0,0 @@ -# Classes - -A class is a property that expects [class levels](/docs/property/class-level) as its immediate children. - -Leveling up a class means choosing, or manually adding, class level properties to it. Class levels with the same variable name as the class, and that match all the required tags are found in libraries and added to the class. - -The total level of the class can be accessed in calculations using `classVariableName.level`. - -## Making your own class - -See [Create a Class](/docs/walkthroughs/create-a-class) - ---- - -### Name - -The name of the class - -### Variable name - -The name used to refer to the class in calculations. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation. - -### Description - -A description of the class. - -### Tags - -See [Tags](/docs/tags) - -### Tags required - -Only class levels with the same variable name as the class, and with tags that match the tags required will be returned from libraries when leveling up this class. - -### Condition - -A [computed field](/docs/computed-fields) to determine if the class is allowed to level up. If this field results in `true` or a number that is not 0, the class can be levelled, otherwise leveling is disabled. diff --git a/app/private/docs/property/constant.md b/app/private/docs/property/constant.md deleted file mode 100644 index a37af5a5..00000000 --- a/app/private/docs/property/constant.md +++ /dev/null @@ -1,33 +0,0 @@ -# Constants - -Constants are properties that store some primitive value in a variable name for use in other calculations. - -Unlike attributes, constants can store more than just numbers: - -- Arrays: `[1,2,3,4]` -- Text strings: `'I am a cat'` -- Numbers: `3.14` -- Boolean values: `true`, `false` -- Dice rolls: `1d20 + 2` - -Constants just can't use other variables in their calculations. - -### Overriding constants - -If multiple constants have the same variable name, only the last active constant in the [character tree](/docs/tree) will be used as the definition for that variable name. - -This can be used to re-write the value of some constant by ensuring there is a new active constant later in the sheet. - ---- - -### Name - -The name of the constants - -### Variable Name - -The name used to refer to the constant in calculations. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation. - -### Value - -A [calculation](/docs/computed-fields) of the final value of the constant. diff --git a/app/private/docs/property/container.md b/app/private/docs/property/container.md deleted file mode 100644 index 30e302ce..00000000 --- a/app/private/docs/property/container.md +++ /dev/null @@ -1,35 +0,0 @@ -# Containers - -Containers are things that [items](/docs/property/item) can be put inside of. - ---- - -### Name - -The name of the container - -### Carried - -If this is set the weight of the container and its contents will be added to the character's weight carried. - -### Value - -The value of the container in gold pieces. Silver pieces are worth 0.1 gp and copper pieces are worth 0.01 gp. So a container that is worth 2 gp 4 sp 7 cp will have a value of 2.47 gp. - -### Weight - -The weight of the container in lb. - -### Description - -A description of the container. - -Allows [inline calculations](/docs/inline-calculations). - -### Tags - -See [Tags](/docs/tags) - -### Contents are weightless - -If this is set and the container is carried, only the container's own weight will be added to the weight carried by the creature. diff --git a/app/private/docs/property/damage-multiplier.md b/app/private/docs/property/damage-multiplier.md deleted file mode 100644 index c9e97869..00000000 --- a/app/private/docs/property/damage-multiplier.md +++ /dev/null @@ -1,33 +0,0 @@ -# Damage multipliers - -Damage multipliers are used to define vulnerability, resistance, and immunity to damage types. - -A single multiplier can apply to multiple damage types, and choose whether or not to apply to an incoming source of damage based on the tags present on that damage. - ---- - -### Name - -The name of the feature that gives this damage multiplier - -### Value - -- **Immunity** The creature takes no damage from matching damage sources -- **Resistance** Damage from matching sources is halved. -- **Vulnerability** Damage from matching sources is doubled. - -### Damage types - -A list of damage types that this property applies to. Custom types can be used. - -### Damage tags required - -This damage multiplier will only be applied if the incoming damage has all of these tags present. - -### Damage tags excluded - -This damage multiplier will only apply if the incoming damage has none of these tags present. - -### Tags - -See [Tags](/docs/tags) diff --git a/app/private/docs/property/damage.md b/app/private/docs/property/damage.md deleted file mode 100644 index 4c004ffd..00000000 --- a/app/private/docs/property/damage.md +++ /dev/null @@ -1,32 +0,0 @@ -# Damage - -Damage can be applied by an action to damage a target creature's [health bars](/docs/property/attribute). The damage will be modified by [damage multipliers](/docs/property/damage-multiplier), which apply vulnerability, resistance, and immunity before the damage is applied. - ---- - -### Damage - -A [computed field](/docs/computed-fields) that determines how much damage to do to the target creature. - -### Damage type - -Damage type determines how the damage is treated by [damage multipliers](/docs/property/damage-multiplier). A custom type can be used, or one of the existing types can be selected. - -There are two special damage types: - -**Extra damage** Damage with the `extra` type will take on the damage type of whatever damage was applied before it by an action. So if an action deals 12 `piercing` damage and `3` extra damage, it will instead deal 15 `piercing` damage. - -**Healing** Damage with the `healing` type will heal a creature instead of damaging them. - -### Target - -- **Target** Apply the damage to the target of the action -- **Self** Apply the damage to the creature taking the action - -### Tags - -See [Tags](/docs/tags) - -### Don't show in log - -If set, the damage will be applied but not show in the log. diff --git a/app/private/docs/property/effect.md b/app/private/docs/property/effect.md deleted file mode 100644 index b453e94f..00000000 --- a/app/private/docs/property/effect.md +++ /dev/null @@ -1,60 +0,0 @@ -# Effects - -Effects are the core of the DiceCloud engine. Effect change the values of attributes, skills, and calculations in a way that is transparent and auditable, keeping character sheets organized and understandable, even when using intricate homebrew rules on high level characters. - ---- - -### Name - -The name of the feature that causes this effect. - -### Operation - -The operation determines what the effect will do to the affected property or calcualtion. - -- **Base Value** Set the base value of the affected property. If a property has multiple base values, the highest is used -- **Add** Add the value to the affected property or calculation -- **Muliply** Multiply the affected property by the value -- **Minimum** Prevent the affected property from having a value less than the effect value -- **Maximum** Prevent the affected property from having a value greater than the effect value -- **Maximum** Prevent the affected property from having a value greater than the effect value -- **Set** Set the value affected property to the effect value -- **Advantage** Give advantage to checks made using the affected property -- **Disadvantage** Give disadvantage to checks made using the affected property -- **Passive bonus** Add the effect value to the passive scores based on the affected property -- **Fail** Checks made using the affected property automatically fail -- **Conditional benefit** Add some text to the affected property describing the benefit recieved - -### Value - -A [computed field](/docs/computed-fields) that determines the value of the effect. - -### Text - -If the operation is a conditional benefit, the note text that will show on affected properties. - -### Target stats by variable name - -If selected the effect will apply to all properties that have the given variable names. - -### Variable names - -A list of variable names of properties to target with this effect. - -### Target properties by tags - -When targeting properties by tag, any property can be targeted with an effect. If the property is one that can usually be targeted by variable name, the effect will apply as ususal, however if the effect targets another property, it will apply to a [computed field](/docs/computed-fields) on the property instead. - -These effects can be used for adding a bonus to a specific attack or damage roll, or manipulating any computed field on the creature. - -### Tags required - -Only properties that match the required tags will be targeted by the effect. - -### Target field - -If a property has multiple computed fields, which field should be targeted by this effect. - -### Tags - -See [Tags](/docs/tags) diff --git a/app/private/docs/property/feature.md b/app/private/docs/property/feature.md deleted file mode 100644 index 98bc0c28..00000000 --- a/app/private/docs/property/feature.md +++ /dev/null @@ -1,25 +0,0 @@ -# Features - -Features appear on the features tab. Classes, backgrounds, and race can all give a creature features. - ---- - -### Name - -The name of the feature. - -### Summary - -A summary of the feature. This will appear on the feature card. - -Allows [inline calculations](/docs/inline-calculations). - -### Description - -A detailed description of the feature. - -Allows [inline calculations](/docs/inline-calculations). - -### Tags - -See [Tags](/docs/tags) diff --git a/app/private/docs/property/folder.md b/app/private/docs/property/folder.md deleted file mode 100644 index 61d04523..00000000 --- a/app/private/docs/property/folder.md +++ /dev/null @@ -1,17 +0,0 @@ -# Folders - -Folders allow the [character tree](/docs/tree) to be organized. - -### Folders in actions - -When a folder is the child of an action, it and its children will not show on the action card, but will still appear in the detail view of the action and be applied when the action is taken. - ---- - -### Name - -The name of the folder. - -### Tags - -See [Tags](/docs/tags) diff --git a/app/private/docs/property/item.md b/app/private/docs/property/item.md deleted file mode 100644 index 1855f36c..00000000 --- a/app/private/docs/property/item.md +++ /dev/null @@ -1,57 +0,0 @@ -# Items - -Items are shown on the Inventory tab. Items can be carried, put in containers, or equipped on a creature. The children of an item are not active unless the item is equipped. - ---- - -### Icon - -An icon representing the item. - -### Equipped - -If set, the item appears in the equipment list on the inventory tab and its children become active on the creature. - -### Name - -The name of the item. - -### Plural name - -The name to use if the quantity of the item is higher than 1. - -### Value - -The value of a single item in gold pieces. Silver pieces are worth 0.1 gp and copper pieces are worth 0.01 gp. So an item that is worth 2 gp 4 sp 7 cp will have a value of 2.47 gp. - -### Weight - -The weight of a single item in lb. - -### Quantity - -Number of items. The value and quantity will be multiplied by the quantity to get the total value and weight of this stack of items. - -### Description - -A description of the item. - -Allows [inline calculations](/docs/inline-calculations). - -### Tags - -See [Tags](/docs/tags) - -### Show increment button - -If this is set, the item will show an increment button in the detail view and on the inventory tab. This button can be used to quickly adjust the quantity of the item. - -### Requires attunemnt - -If set, the item requires attunemnt to use. - -### Attuned - -If set, the item is attuned and counts towards the total number of attuned items for the creature. - -If a child property needs to determine if its parent item is attuned it can use `#item.attuned` in calculations, see *Ancestor references* in [computed fields](/docs/computed-fields). diff --git a/app/private/docs/property/note.md b/app/private/docs/property/note.md deleted file mode 100644 index 928a0f2c..00000000 --- a/app/private/docs/property/note.md +++ /dev/null @@ -1,25 +0,0 @@ -# Notes - -Notes are used to store text on the creature that does not have a direct mechanical impact. Notes appear on the journal tab when active on the character, or are shown in the log when applied by an [action](/docs/property/action). - ---- - -### Name - -Name of the note. - -### Summary - -A summary of the note. This will appear on the note card and in the log when applied by an [action](/docs/property/action). - -Allows [inline calculations](/docs/inline-calculations). - -### Description - -A detailed description of the feature. - -Allows [inline calculations](/docs/inline-calculations). - -### Tags - -See [Tags](/docs/tags) diff --git a/app/private/docs/property/point-buy.md b/app/private/docs/property/point-buy.md deleted file mode 100644 index 419a8cb3..00000000 --- a/app/private/docs/property/point-buy.md +++ /dev/null @@ -1,39 +0,0 @@ -# Point buy - -A point buy is a set of rows that lets the user choose a set of stats based on a cost per stat. - ---- - -### Table name - -The name of the point buy table. - -### Min - -The lowest value available for each row - -### Max - -The highest value available for each row - -### Cost - -A function that uses `value` as the value of a row and determines the cost of that value. For standard D&D 5e 27 point buy, this function is `[0, 1, 2, 3, 4, 5, 7, 9][value - 7]` - -### Total available points - -A [computed field](/docs/computed-fields) that determines how many points are available to spend in total - -## Rows - -Up to 32 rows can be added to a point buy table - -### Row name - -The name of the row that will appear in the table - -### Row variable name - -The variable name of the row that can be used in calculations. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation. - -If the variable name matches an attribute with the same variable name, the row's value will be used as a base value for that attribute. diff --git a/app/private/docs/property/proficiency.md b/app/private/docs/property/proficiency.md deleted file mode 100644 index 2a1c7c41..00000000 --- a/app/private/docs/property/proficiency.md +++ /dev/null @@ -1,21 +0,0 @@ -# Proficiencies - -Proficiencies add proficiency to an existing skill on the creature. If you need to add a tool or language proficiency to a creature, use a [Skill](/docs/property/skill) instead. - ---- - -### Name - -Name of the feature that is adding this proficiency - -### Skills - -A list of variable names of the skills to add proficiency to. - -### Proficiency - -How much proficiency to add to the skill. If a skill has multiple proficiencies added to it, the highest one will be used. - -### Tags - -See [Tags](/docs/tags) diff --git a/app/private/docs/property/remove-buff.md b/app/private/docs/property/remove-buff.md deleted file mode 100644 index 77888a98..00000000 --- a/app/private/docs/property/remove-buff.md +++ /dev/null @@ -1,32 +0,0 @@ -# Remove Buff - -This property can remove a specific buff from a targeted creature. - -### Name - -The name of the property. This shows in the log when the property is applied. - -### Remove parent buff - -When this is set and the property is applied, the property will remove the nearest parent buff. If this property is not the child of any buffs, it will log an error. - -### Remove all - -When this is set, all buffs that match the target tags will be removed from the targeted creature. If not set, only the first buff found with the matching tags will be removed. - -### Target - -- **Target** Matching buffs will be removed from the targeted creature -- **Self** Matching buffs will be removed from the creature that applied the action - -### Tags required - -Any buff that has all of the required tags will be removed when the property is applied. - -### Tags - -See [Tags](/docs/tags) - -### Don't show in log - -When this is set, the property is applied, but does not show in the log. \ No newline at end of file diff --git a/app/private/docs/property/roll.md b/app/private/docs/property/roll.md deleted file mode 100644 index 35898bdf..00000000 --- a/app/private/docs/property/roll.md +++ /dev/null @@ -1,27 +0,0 @@ -# Rolls - -Rolls are properties that store the result of a calculation to a variable name when applied by an [action](/docs/property/action). The variable name only exists for the duration of that particalar action. - -Rolls can be useful if you need to deal the same damage to multiple targets, or if damage needs to be rolled then halved by succeeding on a saving throw. - ---- - -### Name - -Name of the roll. This will be shown in the log when the roll is applied. - -### Variable name - -The variable name to store the result of the roll for the duration of the action. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation. - -### Roll - -A [computed field](/docs/computed-fields) that is computed when the roll is applied by an action. - -### Don't show in log - -If set, the roll will be applied and store its result in the variable name, but not be shown in the log. - -### Tags - -See [Tags](/docs/tags) diff --git a/app/private/docs/property/saving-throw.md b/app/private/docs/property/saving-throw.md deleted file mode 100644 index 907b8fe4..00000000 --- a/app/private/docs/property/saving-throw.md +++ /dev/null @@ -1,35 +0,0 @@ -# Saving throws - -Saving throws are properties that cause the target to make a saving throw when applied. If you want to add a type of saving throw like Strength Save to a creature, use a [skill](/docs/property/skill) instead. - -When a saving throw is applied, the following variables are added to the scope of that action: - -- `$saveFailed` Set to `true` if the target failed its saving throw or there are no targets for the saving throw -- `$saveSucceeded` Set to `true` if the target made its saving throw or there are no targets for the saving throw -- `$saveDiceRoll` The unmodified d20 roll the target made to save -- `$saveRoll` The final value of the saving throw roll after modifiers - -### Name - -The name of the saving throw. Usually the ability saving throw targeted: "Strength Save". - -### DC - -The DC of the saving throw that the target needs to meet - -### Save - -The variable name of the skill that will be used to make the saving throw. - -### Target - -- **Target** Apply the saving throw to the targets of the action. Each target will make the saving throw in turn. Child properties will be applied to each target separately with the results of their individual saving throw. If a value like damage needs to be shared between targets, it should be calculated in a [Roll](/docs/property/roll) before the saving throw. -- **Self** Apply the saving throw to the creature taking the action. The creature taking the action will become the target for all child properties. - -### Tags - -See [Tags](/docs/tags) - -### Don't show in log - -If set, the saving throw will not show in the log when applied, but will still be rolled and apply its children. diff --git a/app/private/docs/property/slot-filler.md b/app/private/docs/property/slot-filler.md deleted file mode 100644 index 9e465a18..00000000 --- a/app/private/docs/property/slot-filler.md +++ /dev/null @@ -1,39 +0,0 @@ -# Slot filler - -A slot filler is a property that can be used to add more complex behavior to filling a [slot](/docs/property/slot) from a library. - ---- - -### Name - -The name of the slot filler that will show when choosing the filler from the library. - -### Icon - -Icon of the slot filler - -### Description - -A detailed description of the slot filler. - -Allows [inline calculations](/docs/inline-calculations). - -### Picture URL - -A link to an image to use for this slot filler when being chosen from a library. - -### Type - -Slot fillers can pretend to be any type of property when a slot is being filled. - -### Quantity - -How many spaces the slot filler will take up in a slot. - -### Condition - -A [computed field](/docs/computed-fields) that determines whether this slot filler can be added to a character. - -### Tags - -See [Tags](/docs/tags) diff --git a/app/private/docs/property/slot.md b/app/private/docs/property/slot.md deleted file mode 100644 index 61793f81..00000000 --- a/app/private/docs/property/slot.md +++ /dev/null @@ -1,53 +0,0 @@ -# Slots - -Slots are the main way creatures interact with libraries. A slot can be filled by choosing a property from a library that fits that particular slot. - -In a complete library, a creature can be built entirely by choosing which properties to fill each slot with. - -Slots show up on the build tab, and are highlighted when they have space that can be filled. - -If you are building a creature without a library, you should either ignore slots entirely, or fill them with your own custom properties. - ---- - -### Name - -The name of the slot. - -### Type - -What kind of property this slot expects to fill it. - -### Tags required - -Properties in a library must have the required tags to fill the slot. - -### Quantity - -How many properties are expected to fill this slot. Use 0 for allowing an unlimited number of properties. - -### Condition - -A [computed field](/docs/computed-fields) that determines whether this slot can accept new properties. - -### Unique - -The slot can control how it deals with the uniqueness of properties that fill it. - -### Description - -A detailed description of the attribute. - -Allows [inline calculations](/docs/inline-calculations). - -### Hide when full - -When set the slot will hide itself when it is filled. - -### Ignored - -When set the slot will not show a prompt card on the build tab. - -### Tags - -See [Tags](/docs/tags) \ No newline at end of file diff --git a/app/private/docs/property/spell.md b/app/private/docs/property/spell.md deleted file mode 100644 index ca878747..00000000 --- a/app/private/docs/property/spell.md +++ /dev/null @@ -1,115 +0,0 @@ -# Spells - -Spells work similarly to [actions](/docs/property/action). They appear on the spells tab and can be cast with or without using up spell slots. - ---- - -### Always prepared - -A spell that is always prepared does not count towards the spell list's maximum prepared spells and is always active and ready to cast. - -### Prepared - -A prepared spell is ready to cast and counts against a spell list's maximum prepared spells. - -### Cast without spell slots - -When set, this spell can be cast without consuming spell slots. It will however consume its own uses and resources. - -### School - -What school the spell belongs to. - -### Casting time - -How long the spell takes to Cast - -### Range - -The range of the spell - -### Duration - -How long the spell lasts - -### Components - -Whether the spell requires verbal, somatic, or material components and whether the spell is a ritual or requires concentration. - -### Target - -Who this spell should apply to. The properties under the spell will be applied to the targets. - -- **Self** The spell will apply its properties to the creature casting the spell -- **Single Target** The spell will apply its properties without a target (for now) -- **Multiple Targets** The spell will apply its properties without a target (for now) - -### Attack roll - -A [computed field](/docs/computed-fields) which calculates the spell attack roll modifier. If this field is empty, no attack roll will be made. Use 0 to make an attack roll without a modifier. To use the spell list's attack roll bonus use `#spellList.attackRollBonus`. - -The following variables may be added to the action scope when attack rolls are made: - - - `$attackDiceRoll` The value of the d20 roll before any modifiers were applied. - - `$attackRoll` The total attack roll after modifiers. - - `$criticalHit` Set to `true` if the attack roll's d20 is a natural 20. If `criticalHitTarget` is set, the attack roll's d20 must instead be equal to or greater than `criticalHitTarget` for this to be set to `true`. - - `$criticalMiss` Set to `true` if the attack roll was not a critical hit and rolled a natural 1 on the d20 roll. - - `$attackHit` If the attack roll is higher than or equal to the target's AC or a critical hit this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical hit. - - `$attackMiss` If the attack roll is lower than the target's AC or a critical miss, this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical miss. - -### Summary - -A brief overview of what the spell does. This will show in the log when the spell is cast. - -Allows [inline calculations](/docs/inline-calculations). - -### Description - -A more detailed description of the spell. The description does not show in the log when the spell is cast. - -Allows [inline calculations](/docs/inline-calculations). - -### Resource - -A resource can be any attribute that has a variable name. If the resource attribute is less than the amount required, the spell can't be cast. - -If you want to reduce an attribute when casting the spell, but want the spell to be applied regardless of the value of that attribute, consider using an [Attribute Damage](/docs/property/attribute-damage) property as a child of the spell instead. Also use Attribute Damage when the amount to reduce the attribute is determined by a dice roll rather than a stable computed number. - -#### Resource attribute - -The variable name of the attribute that will be consumed when casting this spell. - -#### Resource quantity - -A [computed field](/docs/computed-fields) which determines how much of the attribute is required to apply this spell. This amount will be deducted from the attribute every time the spell is cast -### Ammo - -Ammo represents items that are requied to cast the spell. If an item is not selected, or there is insufficient quantity of the selected item, the spell can't be appled. - -#### Ammo item - -Specify what tag an item must have to be considered valid ammo for this spell. Any item with this tag can be selected as ammo for this spell. - -#### Ammo quantity - -A [computed field](/docs/computed-fields) which determines how many of the selected items are required to cast this spell. The quantity is deducted from the total quantity of the item when this spell is applied. - -### Uses - -A [computed field](/docs/computed-fields) which determines how many times this spell can be used before it needs to be reset. - -### Uses used - -How many of this spell's uses have already been used. Should ideally be between 0 and the total uses available. This number is set to 0 when the spell has uses and its uses are reset. - -### Reset - -If set, the uses used field is set to 0 at the appropriate time. - -- **Long rest** Reset when the long rest button is pushed -- **Short rest** Reset when either the long or short rest button is pushed - - -### Tags - -See [Tags](/docs/tags) \ No newline at end of file diff --git a/app/private/docs/property/toggle.md b/app/private/docs/property/toggle.md deleted file mode 100644 index 1dcaf102..00000000 --- a/app/private/docs/property/toggle.md +++ /dev/null @@ -1,36 +0,0 @@ -# Toggles - -Toggles are a way to turn on and off parts of a creature. When a toggle is off, none of its children will be active. - -Calculated toggles should be avoided if possible, because while they offer a lot of power and flexibility to the creature engine, they often create [dependency loops](/docs/dependency-loops) that can be difficult to troubleshoot, causing parts of a creature to calculate incorrectly. - -Calculated toggles can be applied by [actions](/docs/property/action) and will apply their children if the condition is true, but they should be avoided in favor of [conditional branches](/docs/property/branch) which can do the same, but are more efficient. - ---- - -### Name - -The name of the toggle. - -### Variable name - -The name used to refer to the value of the toggle in calculations. Must start with a letter and be made up of only letters and numbers without spaces, symbols, or punctiation. - -### Show on character sheet - -If set, the toggle with show a checkbox on the character sheet. A calculated toggle will show a disabled checkbox, filled in if the toggle's calculation returned `true` or a value that isn't 0. - -### State - -- **Enabled** The toggle and its children are active -- **Disabled** The toggle and its children are inactive -- **Calculated** The active status of the toggle depends on the result of the condition. Use with caution. - -### Condition - -A [computed field](/docs/computed-fields) that determines if the toggle is active. Use with caution. - -### Tags - -See [Tags](/docs/tags) - diff --git a/app/private/docs/property/trigger.md b/app/private/docs/property/trigger.md deleted file mode 100644 index 9e996838..00000000 --- a/app/private/docs/property/trigger.md +++ /dev/null @@ -1,49 +0,0 @@ -# Triggers - -Triggers apply their children whenever their condition is met. They work like [actions](/docs/property/action) that are taken automatically. - ---- - -### Name - -The name of the trigger. - -### Timing - -- **Before** The trigger is applied before the triggering event takes place -- **After** The trigger is fired after the triggering event - -### Event - -- **Do action** While the creature is doing an action, the action property specified in *Event type* is applied -- **Roll check** The creature makes a check -- **Attribute damaged or healed** One of the creature's attributes changed value through attribute damage or manual adjustment -- **Short or long rest** -- **Short rest** -- **Long Rest** - -### Event type - -The trigger will apply when this property type is applied by the action - -### Tags required - -If this trigger is fired by a property, the property must match these tags for the trigger to fire. - -### Condition - -A [computed field](/docs/computed-fields) to determine if the trigger should fire. The trigger will fire if the condition field is empty or if it returns `true` or a value that isn't 0. - -### Description - -A detailed description of the trigger. - -Allows [inline calculations](/docs/inline-calculations). - -### Tags - -See [Tags](/docs/tags) - -### Don't show in log - -When this is true, the trigger does not show up in the log. This does not stop the trigger's children from appearing in the log when they are applied. diff --git a/app/private/docs/walkthroughs/create-a-class.md b/app/private/docs/walkthroughs/create-a-class.md deleted file mode 100644 index 6987b391..00000000 --- a/app/private/docs/walkthroughs/create-a-class.md +++ /dev/null @@ -1,47 +0,0 @@ -# Create a Class - -This is a guide on creating a custom class in a character sheet. If possible, it is always faster to use an existing library that contains the class you want to use. Before continuing, check the #libraries channel of the [official discord](https://discord.gg/qEvdfeB) to see if a library exists with the class you are creating. - -This guide assumes you are using the ruleset provided in the [5e System Reference Document library](/library/qkv8aptJH2fCXARcJ). If you are using a different ruleset for your character, there may be some discrepancies. - -## Adding the class property - -On the build tab of your character, in the card labeled **Slots**, expand the rulset, then click the slot where you would like to place the custom class, if it is your starting class in an SRD character, this would be the Class slot. Be sure to click the name of the slot, not the **+** button. - -![Screenshot of Build Tab > Slots > Ruleset > Class](/images/docs/walkthroughs/create-a-class-1.png) - -This opens the slot in detail view, showing you how the slot expected to be filled from a library, instead of filling the slot, we will be manually adding a class to the slot that we create ourselves. - -Click the **Edit** button in the top right of the slot detail dialog. - -![Screenshot of slot detail dialog](/images/docs/walkthroughs/create-a-class-2.png) - -Expand the children of the class slot, and click the plus button to add a child property. - -![Screenshot of adding a child property](/images/docs/walkthroughs/create-a-class-3.png) - -This brings up the create a property dialog, we are creating a class, so select the class property type. - -![Screenshot of choosing a class property](/images/docs/walkthroughs/create-a-class-4.png) - -Now that we have selected the class property type, the create tab is selected where we can enter the details of our class, fill in the form and click **Create**. - -![Screenshot of the class form](/images/docs/walkthroughs/create-a-class-5.png) - -Now that our custom class is created, we can close the class slot dialog. - -On the Build tab, in the card with the title **Level**, you will see your new class, with a button to **Level Up**, clicking the level up button would usually search your libraries for class levels that match the variable name of the class, however, since it's a custom class, it will probably not find any levels. - -Instead, as we did with the class slot, click on the class name to bring up the class detail dialog, click **Edit**, expand children and click the **+** button to add a child to the class. Here we will add all of the things our class gives the character. - -Add an [Effect](/docs/property/effect) which targets `hitPoints` to add the starting hitpoints of the class. Add a [proficiencies](/docs/property/proficiency) for all the skill and saving throw proficiencies the class gives. Add [skills](/docs/property/skill) for all the tool and weapon proficiencies of the class, making sure to set the base proficiency of those skills to proficient. Add any text [features](/docs/property/feature) the class gives you, along with [actions](/docs/property/action) which may be children of those features, or direct children of the class. - -Once you have added Everything the class gives you, it's time to add class levels. As a child of the class, add a [class level](/docs/property/class-level) property. Set the level to 1 and the name and variable name to match the variable name of the class. - -Once the class level is created, open the class level and edit it. Use the **+** button in the children of the class level to add all the properties the class level gives your character. - -Repeat this for every level of the class until your character is at the correct level. - -You can use a separate character with levels in a class that is available in your libraries as an example of what properties you may want to add to your class and class levels. - -![Example wizard class](/images/docs/walkthroughs/create-a-class-6.png) From 23d44e54e3d6ac50f98a7ffb4b260a1e0d8cb97c Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 24 Nov 2022 13:39:28 +0200 Subject: [PATCH 082/247] Hotfixed S3 not loading --- app/imports/api/files/s3FileStorage.js | 2 +- app/imports/api/files/server/s3.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/imports/api/files/s3FileStorage.js b/app/imports/api/files/s3FileStorage.js index 1ef22730..c26d13bc 100644 --- a/app/imports/api/files/s3FileStorage.js +++ b/app/imports/api/files/s3FileStorage.js @@ -33,7 +33,7 @@ let createS3FilesCollection; /* This is the best practice for app security */ if (Meteor.isServer && Meteor.settings.useS3) { // Create a new S3 object - const s3 = new S3({ + const s3 = S3({ accessKeyId: s3Conf.key, secretAccessKey: s3Conf.secret, endpoint: s3Conf.endpoint, diff --git a/app/imports/api/files/server/s3.js b/app/imports/api/files/server/s3.js index 83719fa6..46a8e8a9 100644 --- a/app/imports/api/files/server/s3.js +++ b/app/imports/api/files/server/s3.js @@ -1,2 +1,5 @@ import S3 from 'aws-sdk/clients/s3'; -export default S3; + +export default function () { + return new S3(...arguments); +} From 420663c149865ee7d7e2adc0b1fdd64382e3b041 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 24 Nov 2022 14:10:22 +0200 Subject: [PATCH 083/247] Hotfix 2 crashy boogaloo --- .../creature/archive/ArchiveCreatureFiles.js | 8 ++++++- app/imports/api/files/UserImages.js | 7 +++++- app/imports/api/files/client/s3FileStorage.js | 24 +++++++++++++++++++ app/imports/api/files/server/s3.js | 5 ---- .../api/files/{ => server}/s3FileStorage.js | 20 +++++++--------- 5 files changed, 45 insertions(+), 19 deletions(-) create mode 100644 app/imports/api/files/client/s3FileStorage.js delete mode 100644 app/imports/api/files/server/s3.js rename app/imports/api/files/{ => server}/s3FileStorage.js (95%) diff --git a/app/imports/api/creature/archive/ArchiveCreatureFiles.js b/app/imports/api/creature/archive/ArchiveCreatureFiles.js index c0d1094e..044e6158 100644 --- a/app/imports/api/creature/archive/ArchiveCreatureFiles.js +++ b/app/imports/api/creature/archive/ArchiveCreatureFiles.js @@ -1,8 +1,14 @@ -import { createS3FilesCollection } from '/imports/api/files/s3FileStorage.js'; + import SimpleSchema from 'simpl-schema'; import { incrementFileStorageUsed } from '/imports/api/users/methods/updateFileStorageUsed.js'; import { CreaturePropertySchema } from '/imports/api/creature/creatureProperties/CreatureProperties.js'; import { CreatureSchema } from '/imports/api/creature/creatures/Creatures.js'; +let createS3FilesCollection; +if (Meteor.isServer) { + createS3FilesCollection = require('/imports/api/files/server/s3FileStorage.js').createS3FilesCollection +} else { + createS3FilesCollection = require('/imports/api/files/client/s3FileStorage.js').createS3FilesCollection +} const ArchiveCreatureFiles = createS3FilesCollection({ collectionName: 'archiveCreatureFiles', diff --git a/app/imports/api/files/UserImages.js b/app/imports/api/files/UserImages.js index 9638d2f0..057c48a0 100644 --- a/app/imports/api/files/UserImages.js +++ b/app/imports/api/files/UserImages.js @@ -1,4 +1,9 @@ -import { createS3FilesCollection } from '/imports/api/files/s3FileStorage.js'; +let createS3FilesCollection; +if (Meteor.isServer) { + createS3FilesCollection = require('/imports/api/files/server/s3FileStorage.js').createS3FilesCollection +} else { + createS3FilesCollection = require('/imports/api/files/client/s3FileStorage.js').createS3FilesCollection +} const UserImages = createS3FilesCollection({ collectionName: 'userImages', diff --git a/app/imports/api/files/client/s3FileStorage.js b/app/imports/api/files/client/s3FileStorage.js new file mode 100644 index 00000000..ce2777cc --- /dev/null +++ b/app/imports/api/files/client/s3FileStorage.js @@ -0,0 +1,24 @@ +// https://github.com/VeliovGroup/Meteor-Files/blob/master/docs/aws-s3-integration.md +import { FilesCollection } from 'meteor/ostrio:files'; + +const createS3FilesCollection = function ({ + collectionName, + storagePath, + onBeforeUpload, + onAfterUpload, + debug,// = !Meteor.isProduction, + allowClientCode = false, +}) { + const collection = new FilesCollection({ + collectionName, + storagePath, + onBeforeUpload, + onAfterUpload, + debug, + allowClientCode, + }); + + return collection; +} + +export { createS3FilesCollection }; diff --git a/app/imports/api/files/server/s3.js b/app/imports/api/files/server/s3.js deleted file mode 100644 index 46a8e8a9..00000000 --- a/app/imports/api/files/server/s3.js +++ /dev/null @@ -1,5 +0,0 @@ -import S3 from 'aws-sdk/clients/s3'; - -export default function () { - return new S3(...arguments); -} diff --git a/app/imports/api/files/s3FileStorage.js b/app/imports/api/files/server/s3FileStorage.js similarity index 95% rename from app/imports/api/files/s3FileStorage.js rename to app/imports/api/files/server/s3FileStorage.js index c26d13bc..27fbed67 100644 --- a/app/imports/api/files/s3FileStorage.js +++ b/app/imports/api/files/server/s3FileStorage.js @@ -4,9 +4,7 @@ import { each, clone } from 'lodash'; import { Random } from 'meteor/random'; import { FilesCollection } from 'meteor/ostrio:files'; import stream from 'stream'; -if (Meteor.isServer) { - import S3 from '/imports/api/files/server/s3.js'; -} +import S3 from 'aws-sdk/clients/s3'; /* See fs-extra and graceful-fs NPM packages */ /* For better i/o performance */ @@ -31,9 +29,9 @@ let createS3FilesCollection; /* Check settings existence in `Meteor.settings` */ /* This is the best practice for app security */ -if (Meteor.isServer && Meteor.settings.useS3) { +if (Meteor.settings.useS3) { // Create a new S3 object - const s3 = S3({ + const s3 = new S3({ accessKeyId: s3Conf.key, secretAccessKey: s3Conf.secret, endpoint: s3Conf.endpoint, @@ -236,13 +234,11 @@ if (Meteor.isServer && Meteor.settings.useS3) { allowClientCode, }); - if (Meteor.isServer) { - // Use the normal file system to read files - collection.readJSONFile = async function (file) { - const fileString = await fsp.readFile(file.path, 'utf8'); - return JSON.parse(fileString); - }; - } + // Use the normal file system to read files + collection.readJSONFile = async function (file) { + const fileString = await fsp.readFile(file.path, 'utf8'); + return JSON.parse(fileString); + }; return collection; } From bac9fc98dd77e85d3f098c3285bda568d417a692 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 24 Nov 2022 14:48:58 +0200 Subject: [PATCH 084/247] Fixed order of stats tab, unhid sneaky folders --- .../ui/creature/character/characterSheetTabs/StatsTab.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/imports/client/ui/creature/character/characterSheetTabs/StatsTab.vue b/app/imports/client/ui/creature/character/characterSheetTabs/StatsTab.vue index b5254836..751b4326 100644 --- a/app/imports/client/ui/creature/character/characterSheetTabs/StatsTab.vue +++ b/app/imports/client/ui/creature/character/characterSheetTabs/StatsTab.vue @@ -428,7 +428,7 @@ const propertyHandlers = { let skipChildren; let propPath = null; if (prop.hideStatsGroup) { - return { skipChildren: true} + skipChildren = true; } if (prop.tab === 'stats') { propPath = ['folder', prop.location] @@ -546,7 +546,7 @@ export default { if (creature.settings.hideUnusedStats) { filter.hide = { $ne: true }; } - const allProps = CreatureProperties.find(filter, { sort: { order: 1 } }); + const allProps = CreatureProperties.find(filter, { sort: { order: -1 } }); const forest = nodeArrayToTree(allProps); const properties = { folder: {}, attribute: {}, skill: {} }; walkDown(forest, node => { From e19e91f7e0789abd399b2bd466a59c26b377f8ed Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 24 Nov 2022 14:51:05 +0200 Subject: [PATCH 085/247] Fixed broken $attackRoll always returning 0 --- .../api/engine/actions/applyPropertyByType/applyAction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/imports/api/engine/actions/applyPropertyByType/applyAction.js b/app/imports/api/engine/actions/applyPropertyByType/applyAction.js index d749990d..021370d4 100644 --- a/app/imports/api/engine/actions/applyPropertyByType/applyAction.js +++ b/app/imports/api/engine/actions/applyPropertyByType/applyAction.js @@ -165,7 +165,7 @@ function rollAttack(attack, scope) { } scope['$attackDiceRoll'] = { value }; const result = value + attack.value; - scope['$attackRoll'] = { result }; + scope['$attackRoll'] = { value: result }; const { criticalHit, criticalMiss } = applyCrits(value, scope); return { resultPrefix, result, value, criticalHit, criticalMiss }; } From bda446858ea17a68a022ec6f9749e29fa4348223 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Thu, 24 Nov 2022 15:04:35 +0200 Subject: [PATCH 086/247] Fixed spell tab btn not hiding correctly on mobile --- app/imports/client/ui/creature/character/CharacterSheet.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/imports/client/ui/creature/character/CharacterSheet.vue b/app/imports/client/ui/creature/character/CharacterSheet.vue index 0f6099be..7596c629 100644 --- a/app/imports/client/ui/creature/character/CharacterSheet.vue +++ b/app/imports/client/ui/creature/character/CharacterSheet.vue @@ -104,8 +104,8 @@ Actions mdi-lightning-bolt - - Spells + + Spells mdi-fire From bb1e9624ad33a4aff45006bf0d8163fd79d4f118 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Fri, 25 Nov 2022 12:14:47 +0200 Subject: [PATCH 087/247] Fixed hit dice missing on stats tab --- .../ui/creature/character/characterSheetTabs/StatsTab.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/imports/client/ui/creature/character/characterSheetTabs/StatsTab.vue b/app/imports/client/ui/creature/character/characterSheetTabs/StatsTab.vue index 751b4326..e751f8e8 100644 --- a/app/imports/client/ui/creature/character/characterSheetTabs/StatsTab.vue +++ b/app/imports/client/ui/creature/character/characterSheetTabs/StatsTab.vue @@ -161,13 +161,13 @@
Hit Dice - diff --git a/app/imports/client/ui/creature/creatureProperties/Breadcrumbs.vue b/app/imports/client/ui/creature/creatureProperties/Breadcrumbs.vue index 228e47f2..54703e43 100644 --- a/app/imports/client/ui/creature/creatureProperties/Breadcrumbs.vue +++ b/app/imports/client/ui/creature/creatureProperties/Breadcrumbs.vue @@ -4,11 +4,14 @@ :class="{'no-icons': noIcons}" > - + mdi-account + + mdi-book-open-blank-variant + fetchDocByRef(ref)) - .filter(prop => prop.type !== 'propertySlot'); + .filter(prop => (this.collection !== 'creatureProperties' || prop.type !== 'propertySlot')); }, }, methods: { - click(id){ + click(id) { + if (this.embedded) { + this.$emit('select-sub-property', id); + return; + } const store = this.$store; // Check if there is a dialog open for this doc already let dialogFound; @@ -92,9 +104,12 @@ // Pop dialogs until we get to it store.dispatch('popDialogStacks', dialogsToPop); } else { + const component = this.collection === 'creatureProperties' ? 'creature-property-dialog' + : this.collection === 'libraryNodes' ? 'library-node-dialog' + : undefined; // Otherwise open it as a new dialog store.commit('pushDialogStack', { - component: 'creature-property-dialog', + component, elementId: `breadcrumb-${id}`, data: { _id: id, @@ -139,9 +154,6 @@ .breadcrumbs { margin-bottom: 16px; opacity: 0.8; -} -.no-icons { - } diff --git a/app/imports/client/ui/creature/creatureProperties/CreaturePropertyDialog.vue b/app/imports/client/ui/creature/creatureProperties/CreaturePropertyDialog.vue index 606e270b..ce6e3c83 100644 --- a/app/imports/client/ui/creature/creatureProperties/CreaturePropertyDialog.vue +++ b/app/imports/client/ui/creature/creatureProperties/CreaturePropertyDialog.vue @@ -16,12 +16,12 @@
- + {{ typeName }} @@ -43,31 +43,12 @@ @select-sub-property="selectSubProperty" />
-
- - - - - - -
+
+ +
+ + + + {{ typeName }} + +
+
@@ -41,16 +59,13 @@ @add-child="addLibraryNode" @select-sub-property="selectSubProperty" /> - -

- This property can't be viewed yet. -

- + > + + + + +
+ + {{ tag }} + +
+
+ + + +
+
This property can't be viewed yet.
@@ -13,15 +106,40 @@ diff --git a/app/imports/client/ui/properties/viewers/SlotFillerViewer.vue b/app/imports/client/ui/properties/viewers/SlotFillerViewer.vue index fc53aec7..2e24617e 100644 --- a/app/imports/client/ui/properties/viewers/SlotFillerViewer.vue +++ b/app/imports/client/ui/properties/viewers/SlotFillerViewer.vue @@ -1,32 +1,6 @@ From 442aea2bbe562fc6cde62155c73f4a04b46d843d Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Tue, 13 Jun 2023 14:27:32 +0200 Subject: [PATCH 214/247] Forms try to hold your place better Expanding form sections keeps them expanded when changing property viewed or opening a new prop Disabled auto-focus, because it forces scroll --- .../client/ui/properties/PropertyForm.vue | 2 ++ .../client/ui/properties/forms/ActionForm.vue | 2 +- .../ui/properties/forms/AdjustmentForm.vue | 8 +------ .../ui/properties/forms/AttributeForm.vue | 2 +- .../client/ui/properties/forms/BranchForm.vue | 2 +- .../client/ui/properties/forms/BuffForm.vue | 2 +- .../ui/properties/forms/BuffRemoverForm.vue | 2 +- .../client/ui/properties/forms/ClassForm.vue | 2 +- .../ui/properties/forms/ClassLevelForm.vue | 1 + .../ui/properties/forms/ConstantForm.vue | 1 + .../ui/properties/forms/ContainerForm.vue | 5 ++++- .../client/ui/properties/forms/DamageForm.vue | 2 +- .../properties/forms/DamageMultiplierForm.vue | 2 +- .../client/ui/properties/forms/EffectForm.vue | 1 + .../ui/properties/forms/FeatureForm.vue | 1 + .../client/ui/properties/forms/FolderForm.vue | 2 +- .../client/ui/properties/forms/ItemForm.vue | 2 +- .../client/ui/properties/forms/NoteForm.vue | 1 + .../ui/properties/forms/PointBuyForm.vue | 2 +- .../ui/properties/forms/ProficiencyForm.vue | 1 + .../ui/properties/forms/ReferenceForm.vue | 1 + .../client/ui/properties/forms/RollForm.vue | 2 +- .../ui/properties/forms/SavingThrowForm.vue | 2 +- .../client/ui/properties/forms/SkillForm.vue | 2 +- .../ui/properties/forms/SlotFillerForm.vue | 1 + .../client/ui/properties/forms/SlotForm.vue | 9 +------- .../client/ui/properties/forms/SpellForm.vue | 2 +- .../ui/properties/forms/SpellListForm.vue | 1 + .../client/ui/properties/forms/ToggleForm.vue | 2 +- .../ui/properties/forms/TriggerForm.vue | 2 +- .../properties/forms/shared/FormSections.vue | 21 ++++++++++++++++++- app/imports/client/ui/vuexStore.js | 9 +++++++- 32 files changed, 62 insertions(+), 35 deletions(-) diff --git a/app/imports/client/ui/properties/PropertyForm.vue b/app/imports/client/ui/properties/PropertyForm.vue index 003a1fbc..473e49ab 100644 --- a/app/imports/client/ui/properties/PropertyForm.vue +++ b/app/imports/client/ui/properties/PropertyForm.vue @@ -283,6 +283,7 @@ export default { } }, mounted() { + /** Disable auto-focus, it gets in the way more than it helps // Don't autofocus on mobile, it brings up the on-screen keyboard if (this.$vuetify.breakpoint.smAndDown) return; @@ -291,6 +292,7 @@ export default { this.$refs.focusFirst.focus() } }, 300); + */ }, methods: { selectSubProperty(_id){ diff --git a/app/imports/client/ui/properties/forms/ActionForm.vue b/app/imports/client/ui/properties/forms/ActionForm.vue index 1b89930e..218f0c03 100644 --- a/app/imports/client/ui/properties/forms/ActionForm.vue +++ b/app/imports/client/ui/properties/forms/ActionForm.vue @@ -93,7 +93,7 @@ $emit('change', {path: ['description', ...path], value, ack})" /> - + - + - - -
diff --git a/app/imports/client/ui/properties/forms/AttributeForm.vue b/app/imports/client/ui/properties/forms/AttributeForm.vue index 02f53aaa..32072b95 100644 --- a/app/imports/client/ui/properties/forms/AttributeForm.vue +++ b/app/imports/client/ui/properties/forms/AttributeForm.vue @@ -74,7 +74,7 @@ @change="({path, value, ack}) => $emit('change', {path: ['description', ...path], value, ack})" /> - + - + - +
- + - + diff --git a/app/imports/client/ui/properties/forms/ConstantForm.vue b/app/imports/client/ui/properties/forms/ConstantForm.vue index 297ff737..316688bd 100644 --- a/app/imports/client/ui/properties/forms/ConstantForm.vue +++ b/app/imports/client/ui/properties/forms/ConstantForm.vue @@ -24,6 +24,7 @@ diff --git a/app/imports/client/ui/properties/forms/ContainerForm.vue b/app/imports/client/ui/properties/forms/ContainerForm.vue index 71e4ccec..9d8556f3 100644 --- a/app/imports/client/ui/properties/forms/ContainerForm.vue +++ b/app/imports/client/ui/properties/forms/ContainerForm.vue @@ -71,7 +71,10 @@ $emit('change', {path: ['description', ...path], value, ack})" /> - + diff --git a/app/imports/client/ui/properties/forms/DamageForm.vue b/app/imports/client/ui/properties/forms/DamageForm.vue index bf7682af..b7ed8881 100644 --- a/app/imports/client/ui/properties/forms/DamageForm.vue +++ b/app/imports/client/ui/properties/forms/DamageForm.vue @@ -42,7 +42,7 @@ :error-messages="errors.target" @change="change('target', ...arguments)" /> - + - + diff --git a/app/imports/client/ui/properties/forms/FeatureForm.vue b/app/imports/client/ui/properties/forms/FeatureForm.vue index fbde4df8..acf86e2c 100644 --- a/app/imports/client/ui/properties/forms/FeatureForm.vue +++ b/app/imports/client/ui/properties/forms/FeatureForm.vue @@ -21,6 +21,7 @@ diff --git a/app/imports/client/ui/properties/forms/FolderForm.vue b/app/imports/client/ui/properties/forms/FolderForm.vue index 0d4e0825..3baab232 100644 --- a/app/imports/client/ui/properties/forms/FolderForm.vue +++ b/app/imports/client/ui/properties/forms/FolderForm.vue @@ -1,7 +1,7 @@