diff --git a/app/.meteor/packages b/app/.meteor/packages index d2c043aa..102191c1 100644 --- a/app/.meteor/packages +++ b/app/.meteor/packages @@ -50,3 +50,4 @@ littledata:synced-cron typescript@4.9.4 seba:minifiers-autoprefixer mixmax:smart-disconnect +zodern:types diff --git a/app/.meteor/versions b/app/.meteor/versions index e5431969..4f1ea628 100644 --- a/app/.meteor/versions +++ b/app/.meteor/versions @@ -125,3 +125,4 @@ url@1.3.2 webapp@1.13.5 webapp-hashing@1.1.1 zer0th:meteor-vuetify-loader@0.1.41 +zodern:types@1.0.9 diff --git a/app/imports/api/parenting/ChildSchema.js b/app/imports/api/parenting/ChildSchema.js deleted file mode 100644 index c09a1fa7..00000000 --- a/app/imports/api/parenting/ChildSchema.js +++ /dev/null @@ -1,41 +0,0 @@ -import SimpleSchema from 'simpl-schema'; -import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js'; - -const RefSchema = new SimpleSchema({ - id: { - type: String, - regEx: SimpleSchema.RegEx.Id, - // TODO: Rather than indexing this field, index `ancestors.0.id` to only - // index the root of the ancestor heirarchy to significantly reduce - // index size and improve performance - // All queries on an ancestor document need to target `ancestors.0.id` first - // before targeting a younger ancestor - index: 1 - }, - collection: { - type: String, - max: STORAGE_LIMITS.collectionName, - }, -}); - -let ChildSchema = new SimpleSchema({ - order: { - type: Number, - }, - parent: { - type: RefSchema, - optional: true, - }, - // Change this from ancestor list to left and right indices - ancestors: { - type: Array, - defaultValue: [], - maxCount: STORAGE_LIMITS.ancestorCount, - }, - 'ancestors.$': { - type: RefSchema, - }, -}); - -export default ChildSchema; -export { RefSchema }; diff --git a/app/imports/api/parenting/ChildSchema.ts b/app/imports/api/parenting/ChildSchema.ts new file mode 100644 index 00000000..251128fa --- /dev/null +++ b/app/imports/api/parenting/ChildSchema.ts @@ -0,0 +1,78 @@ +import SimpleSchema from 'simpl-schema'; +import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js'; + +const RefSchema = new SimpleSchema({ + id: { + type: String, + regEx: SimpleSchema.RegEx.Id, + }, + collection: { + type: String, + max: STORAGE_LIMITS.collectionName, + }, +}); + +const ChildSchema = new SimpleSchema({ + root: { + type: RefSchema, + }, + 'root.id': { + type: String, + regEx: SimpleSchema.RegEx.Id, + index: 1, + }, + // Parent id of a document in the same collection + // Undefined parent id implies the root is the parent + parentId: { + type: String, + regEx: SimpleSchema.RegEx.Id, + optional: true, + }, + /** + * The tree structure goes as follows where the numbering follows a counterclockwise depth first + * path around the tree. The canonical structure comes from the root and parentId references, + * while the left and right numbering is used to optimize ancestor queries. + * + * Left can be used as the canonical ordering of properties in an expanded tree folder view. + * + * 1 Books 12 + * ┃ + * 2 Programming 11 + * ┏━━━━━━━━┻━━━━━━━━━┓ + * 3 Languages 4 5 Databases 10 + * ┏━━━━━━━┻━━━━━━━┓ + * 6 MongoDB 7 8 dbm 9 + */ + left: { + type: Number, + index: 1, + }, + right: { + type: Number, + index: 1, + } +}); + +export interface Reference { + collection: string, + id: string, +} + +export interface TreeDoc { + _id: string, + root: Reference, + parentId?: string, + left: number, + right: number, +} + +export const treeDocFields = { + _id: 1, + root: 1, + parentId: 1, + left: 1, + right: 1, +} + +export default ChildSchema; +export { RefSchema }; diff --git a/app/imports/api/parenting/fetchDocByRef.js b/app/imports/api/parenting/fetchDocByRef.js deleted file mode 100644 index dfa485dc..00000000 --- a/app/imports/api/parenting/fetchDocByRef.js +++ /dev/null @@ -1,12 +0,0 @@ -import getCollectionByName from '/imports/api/parenting/getCollectionByName.js'; - -const docNotFoundError = function({id, collection}){ - throw new Meteor.Error('document-not-found', - `No document could be found with id: ${id} in ${collection}` - ); -}; - -export default function fetchDocByRef({id, collection}, options){ - return getCollectionByName(collection).findOne(id, options) || - docNotFoundError({id, collection}); -} diff --git a/app/imports/api/parenting/getCollectionByName.js b/app/imports/api/parenting/getCollectionByName.js deleted file mode 100644 index bc9fe4e0..00000000 --- a/app/imports/api/parenting/getCollectionByName.js +++ /dev/null @@ -1,11 +0,0 @@ -const collectionDoesntExistError = function(collectionName){ - throw new Meteor.Error('bad-collection-reference', - `Parent references collection ${collectionName}, which does not exist` - ); -}; - -const getCollectionByName = function(name){ - return Mongo.Collection.get(name) || collectionDoesntExistError(name); -}; - -export default getCollectionByName; diff --git a/app/imports/api/parenting/getDescendantsInDepthFirstOrder.js b/app/imports/api/parenting/getDescendantsInDepthFirstOrder.js deleted file mode 100644 index 9010d51b..00000000 --- a/app/imports/api/parenting/getDescendantsInDepthFirstOrder.js +++ /dev/null @@ -1,27 +0,0 @@ -import nodesToTree from '/imports/api/parenting/nodesToTree.js'; - -export default function getDescendantsInDepthFirstOrder({ - collection, - ancestorId, - filter, - options = {fields: {order: 1, ancestors: 1}}, -}){ - let forest = nodesToTree({collection, ancestorId, filter, options}); - let orderMemo = getDocsInDepthFirstOrder(forest); - return orderMemo; -} - -export function getDocsInDepthFirstOrder(forest){ - let docs = []; - forest.forEach(node => { - addNodeAndTraverse(node, docs) - }); - return docs; -} - -function addNodeAndTraverse(node, docs){ - docs.push(node.node); - node.children.forEach(child => { - addNodeAndTraverse(child, docs) - }); -} diff --git a/app/imports/api/parenting/nodesToTree.js b/app/imports/api/parenting/nodesToTree.js deleted file mode 100644 index 86fbe1c1..00000000 --- a/app/imports/api/parenting/nodesToTree.js +++ /dev/null @@ -1,122 +0,0 @@ -import { union, difference, sortBy, findLast, intersection } from 'lodash'; - -export function nodeArrayToTree(nodes) { - // Store a dict and list of all the nodes - let nodeIndex = {}; - let nodeList = []; - nodes.forEach(node => { - let treeNode = { - node: node, - children: [], - }; - nodeIndex[node._id] = treeNode; - nodeList.push(treeNode); - }); - // Create a forest of trees - let forest = []; - // Either the node is a child of its nearest found ancestor, or in the forest as a root - nodeList.forEach(treeNode => { - let ancestorInForest = findLast( - treeNode.node.ancestors, - ancestor => !!nodeIndex[ancestor.id] - ); - if (ancestorInForest) { - nodeIndex[ancestorInForest.id].children.push(treeNode); - } else { - forest.push(treeNode); - } - }); - forest.nodeIndex = nodeIndex; - return forest; -} - -// Fetch the documents from a collection, and return the tree of those documents -export default function nodesToTree({ - collection, ancestorId, filter, options = {}, - includeFilteredDocAncestors = false, includeFilteredDocDescendants = false -}) { - // Setup the filter - let collectionFilter = { - 'ancestors.id': ancestorId, - 'removed': { $ne: true }, - }; - if (filter) { - collectionFilter = { - ...collectionFilter, - ...filter, - } - } - // Set up the options - let collectionSort = { - order: 1 - }; - if (options && options.sort) { - collectionSort = { - ...collectionSort, - ...options.sort, - } - } - let collectionOptions = { - sort: collectionSort, - } - if (options) { - collectionOptions = { - ...collectionOptions, - ...options, - } - } - // Find all the nodes that match the filter - let docs = collection.find(collectionFilter, collectionOptions).map(doc => { - if (!filter) return doc; - // Mark the nodes that were found by the custom filter - doc._matchedDocumentFilter = true; - return doc; - }); - let ancestors = []; - let ancestorIds = []; - let docIds = []; - if (filter && (includeFilteredDocAncestors || includeFilteredDocDescendants)) { - docIds = docs.map(doc => doc._id) - } - if (filter && includeFilteredDocAncestors) { - // Add all ancestor ids to an array - docs.forEach(doc => { - ancestorIds = union(ancestorIds, doc.ancestors.map(ref => ref.id)); - }); - // Get all the docs that are also ancestors and mark them - docs.forEach(doc => { - if (ancestorIds.includes(doc._id)) { - doc._ancestorOfMatchedDocument = true; - } - }); - // Remove the ancestor IDs of docs we have already found - ancestorIds = difference(ancestorIds, docIds); - // Get the ancestor docs from the collection, don't worry about `removed` docs, - // if their descendant was not removed, neither are they - ancestors = collection.find({ _id: { $in: ancestorIds } }).map(doc => { - // Mark that the nodes are ancestors of the found nodes - doc._ancestorOfMatchedDocument = true; - return doc; - }); - } - let descendants = []; - if (filter && includeFilteredDocDescendants) { - let exludeIds = union(ancestorIds, docIds); - descendants = collection.find({ - '_id': { $nin: exludeIds }, - 'ancestors.id': { $in: docIds }, - 'removed': { $ne: true }, - }).map(doc => { - // Mark that the nodes are descendants of the found nodes - doc._descendantOfMatchedDocument = true; - return doc; - }); - } - let nodes = sortBy([ - ...ancestors, - ...docs, - ...descendants - ], 'order'); - // Find all the nodes - return nodeArrayToTree(nodes); -} diff --git a/app/imports/api/parenting/order.js b/app/imports/api/parenting/order.js deleted file mode 100644 index c94e814b..00000000 --- a/app/imports/api/parenting/order.js +++ /dev/null @@ -1,156 +0,0 @@ -import fetchDocByRef from '/imports/api/parenting/fetchDocByRef.js'; -import getCollectionByName from '/imports/api/parenting/getCollectionByName.js'; -import getDescendantsInDepthFirstOrder from '/imports/api/parenting/getDescendantsInDepthFirstOrder.js' - -// Docs keep track of their depth-first order amongst their entire ancestor tree -export function compareOrder(docA, docB){ - // < 0 if A comes before B - // = 0 if A and B are the same order - // > 0 if B comes before A - - // They must share a root ancestor to be meaningfully sorted - if (docA.ancestors[0].id !== docB.ancestors[0].id){ - return 0; - } else { - return docA.order - docB.order; - } -} - -export function getHighestOrder({collection, ancestorId}){ - const highestOrderedDoc = collection.findOne({ - 'ancestors.id': ancestorId, - }, { - fields: {order: 1}, - sort: {order: -1}, - }); - return highestOrderedDoc ? highestOrderedDoc.order : -1; -} - -export function setDocToLastOrder({collection, doc}){ - doc.order = getHighestOrder({ - collection, - ancestorId: doc.ancestors[0].id, - }) + 1; -} - -// update the order of a doc, and shift the related docs around to suit the new -// order -function cheapUpdateDocOrder({docRef, order}){ - let doc = fetchDocByRef(docRef, {fields: { - order: 1, - parent: 1, - }}); - let collection = getCollectionByName(docRef.collection); - const currentOrder = doc.order; - if (currentOrder === order){ - return; - } else { - // First move the documents that are in the way - let inBetweenSelector, increment; - if (order > currentOrder){ - // Move in-between docs backward - inBetweenSelector = { - $gt: currentOrder, - $lte: order - }; - increment = -1; - } else if (order < currentOrder){ - // Move in-between docs forward - inBetweenSelector = { - $lt: currentOrder, - $gte: order - }; - increment = 1; - } - collection.update({ - 'ancestors.id': doc.ancestors[0].id, - order: inBetweenSelector, - }, { - $inc: {order: increment}, - }, { - multi: true, - selector: {type: 'any'}, - }); - // Then move the document itself - collection.update(doc._id, {$set: {order}}, {selector: {type: 'any'}}); - } -} - -export function cheapRemovedDocAtOrder({collection, doc}){ - // Decrement the order of all docs after the removed doc - collection.update({ - 'ancestors.id': doc.ancestors[0].id, - order: {$gt: doc.order}, - }, { - $inc: {order: -1}, - }, { - multi: true, - selector: {type: 'any'}, - }); -} - -export function cheapInsertedDocAtOrder({collection, ancestorId, order}){ - // Increment the order of all docs after the inserted doc - collection.update({ - 'ancestors.id': ancestorId, - order: {$gte: order}, - }, { - $inc: {order: 1}, - }, { - multi: true, - selector: {type: 'any'}, - }); -} - -// Update the order a single doc and re-order the entire related doc list -// with the change -export function safeUpdateDocOrder({docRef, order}){ - let collection = getCollectionByName(docRef.collection); - // Put the new doc half a step in front of its new order - // to ensure it's in front of whichever doc was there before - collection.update(docRef.id, { - $set: {order} - }, { - selector: {type: 'any'} - }); - // reorder all related docs so that order is back to being a continous - // set of whole numbers - let movedDoc = fetchDocByRef(docRef, {fields: {ancestors: 1}}); - let ancestorId = movedDoc.ancestors[0].id; - reorderDocs({collection, ancestorId}); -} - -export function reorderDocs({collection, ancestorId}){ - let orderedDocs = getDescendantsInDepthFirstOrder({collection, ancestorId}); - let bulkWrite = []; - orderedDocs.forEach((doc, index) => { - if (doc.order !== index){ - bulkWrite.push({ - updateOne : { - filter: {_id: doc._id}, - update: {$set: {order: index}}, - }, - }); - } - }); - if (Meteor.isServer && bulkWrite.length){ - collection.rawCollection().bulkWrite( - bulkWrite, - {ordered : false}, - function(e){ - if (e) { - console.error('Bulk write failed: '); - console.error(e); - } - } - ); - } else { - bulkWrite.forEach(op => { - collection.update( - op.updateOne.filter, - op.updateOne.update, - {selector: {type: 'any'}} - ); - }); - } -} diff --git a/app/imports/api/parenting/organizeMethods.js b/app/imports/api/parenting/organizeMethods.ts similarity index 52% rename from app/imports/api/parenting/organizeMethods.js rename to app/imports/api/parenting/organizeMethods.ts index 54d5f1ba..e51bb108 100644 --- a/app/imports/api/parenting/organizeMethods.js +++ b/app/imports/api/parenting/organizeMethods.ts @@ -2,12 +2,9 @@ import SimpleSchema from 'simpl-schema'; import { union } from 'lodash'; import { ValidatedMethod } from 'meteor/mdg:validated-method'; import { RateLimiterMixin } from 'ddp-rate-limiter-mixin'; -import { updateParent } from '/imports/api/parenting/parenting.js'; -import { reorderDocs, safeUpdateDocOrder } from '/imports/api/parenting/order.js'; -import { RefSchema } from '/imports/api/parenting/ChildSchema.js'; +import { changeParent, fetchDocByRef, getCollectionByName } from '/imports/api/parenting/parentingFunctions'; +import { RefSchema } from '/imports/api/parenting/ChildSchema'; import { assertDocEditPermission } from '/imports/api/sharing/sharingPermissions.js'; -import fetchDocByRef from '/imports/api/parenting/fetchDocByRef.js'; -import getCollectionByName from '/imports/api/parenting/getCollectionByName.js'; import Creatures from '/imports/api/creature/creatures/Creatures.js'; const organizeDoc = new ValidatedMethod({ @@ -33,47 +30,45 @@ const organizeDoc = new ValidatedMethod({ numRequests: 5, timeInterval: 5000, }, - run({ docRef, parentRef, order, skipRecompute, skipClient }) { + async run({ docRef, parentId, order, skipRecompute, skipClient }) { if (skipClient && this.isSimulation) { return; } - let doc = fetchDocByRef(docRef); - let collection = getCollectionByName(docRef.collection); + const collection = getCollectionByName(docRef.collection); + const [doc, parent] = await Promise.all([ + collection.findOneAsync(docRef.id), + collection.findOneAsync(parentId), + ]); + + if (!doc) throw new Meteor.Error('Document not found', 'The property to move could not be found'); + if (!parent) throw new Meteor.Error('Document not found', 'The new parent could not be found'); // The user must be able to edit both the doc and its parent to move it // successfully - assertDocEditPermission(doc, this.userId); - let parent = fetchDocByRef(parentRef); - assertDocEditPermission(parent, this.userId); + await Promise.all([ + assertDocEditPermission(doc, this.userId), + // Only check parent if it has a different root + doc.root.id !== parent.root.id && assertDocEditPermission(parent, this.userId), + ]); // Change the doc's parent - updateParent({ docRef, parentRef }); - // Change the doc's order to be a half step ahead of its target location - collection.update(doc._id, { $set: { order } }, { selector: { type: 'any' } }); - - // Reorder both ancestors' documents - let oldAncestorId = doc.ancestors[0].id; - reorderDocs({ collection, ancestorId: oldAncestorId }); - - let newAncestorId = getRootId(parent); - if (newAncestorId !== oldAncestorId) { - reorderDocs({ collection, ancestorId: newAncestorId }); - } + await changeParent(doc, parent, collection, order); // Figure out which creatures need to be recalculated after this move - let docCreatures = getCreatureAncestors(doc); - let parentCreatures = getCreatureAncestors(parent); - if (!skipRecompute) { - let creaturesToRecompute = union(docCreatures, parentCreatures); + if (!skipRecompute && docRef.collection === 'creatures') { + const creaturesToRecompute = union[doc.root.id, parent.root.id]; // Mark the creatures for recompute - Creatures.update({ + await Creatures.updateAsync({ _id: { $in: creaturesToRecompute } }, { $set: { dirty: true }, + }, { + multi: true }); } }, }); +// TODO, rewrite const reorderDoc = new ValidatedMethod({ name: 'organize.reorderDoc', validate: new SimpleSchema({ @@ -104,27 +99,4 @@ const reorderDoc = new ValidatedMethod({ }, }); -function getRootId(doc) { - if (doc.ancestors && doc.ancestors.length && doc.ancestors[0]) { - return doc.ancestors[0].id; - } else { - return doc._id; - } -} - -function getCreatureAncestors(doc) { - let ids = []; - if (doc.type === 'pc' || doc.type === 'npc' || doc.type === 'monster') { - ids.push(doc._id); - } - if (doc.ancestors) { - doc.ancestors.forEach(ancestorRef => { - if (ancestorRef.collection === 'creatures') { - ids.push(ancestorRef.id); - } - }); - } - return ids; -} - export { organizeDoc, reorderDoc }; diff --git a/app/imports/api/parenting/parenting.js b/app/imports/api/parenting/parenting.js deleted file mode 100644 index e5a8cc62..00000000 --- a/app/imports/api/parenting/parenting.js +++ /dev/null @@ -1,217 +0,0 @@ -import fetchDocByRef from '/imports/api/parenting/fetchDocByRef.js'; -import getCollectionByName from '/imports/api/parenting/getCollectionByName.js'; -import { flatten } from 'lodash'; - -const generalParents = [ - 'attribute', - 'buff', - 'classLevel', - 'feature', - 'folder', - 'root', - 'item', - 'spell', -]; - -// Which types are allowed as parents for other types -const allowedParenting = { - folder: [...generalParents, 'container'], - rollResult: ['roll', 'rollResult'], - container: ['root', 'folder'], - item: ['root', 'container', 'folder'], -}; - -const allParentTypes = new Set(flatten(Object.values(allowedParenting))); - -export function canBeParent(type){ - return true; - //TODO until there is a good reason to disallow certain parenting options, - // this should just let the user do whatever - return type && allParentTypes.has(type); -} - -export function getAllowedParents({childType}){ - return allowedParenting[childType] || generalParents; -} - -export function isParentAllowed({parentType = 'root', childType}){ - return true; - //TODO until there is a good reason to disallow certain parenting options, - // this should just let the user do whatever - if (!childType) throw 'childType is required'; - let allowedParents = getAllowedParents({childType}); - return allowedParents.includes(parentType); -} - -export function fetchParent({id, collection}){ - return fetchDocByRef({id, collection}); -} - -export function fetchChildren({ collection, parentId, filter = {}, options = {sort: {order: 1}} }){ - filter['parent.id'] = parentId; - let children = []; - children.push( - ...collection.find({ - 'parent.id': parentId - }, options).fetch() - ); - return children; -} - -export function updateChildren({collection, parentId, filter = {}, modifier, options={}}){ - filter['parent.id'] = parentId; - options.multi = true; - collection.update(filter, modifier, options); -} - -export function fetchDescendants({ collection, ancestorId, filter = {}, options}){ - filter['ancestors.id'] = ancestorId; - let descendants = []; - descendants.push(...collection.find(filter, options).fetch()); - return descendants; -} - -export function updateDescendants({collection, ancestorId, filter = {}, modifier, options={}}){ - filter['ancestors.id'] = ancestorId; - options.multi = true; - options.selector = {type: 'any'}; - collection.update(filter, modifier, options); -} - -export function forEachDescendant({collection, ancestorId, filter = {}, options}, callback){ - filter['ancestors.id'] = ancestorId; - collection.find(filter, options).forEach(callback); -} - -// 1 database read -export function getAncestry({parentRef, inheritedFields = {}}){ - let parentDoc = fetchDocByRef(parentRef, {fields: inheritedFields}); - let parent = { ...parentRef}; - for (let field in inheritedFields){ - if (inheritedFields[field]){ - parent[field] = parentDoc[field]; - } - } - - // Ancestors is [...parent's ancestors, parent ref] - let ancestors = parentDoc.ancestors || []; - ancestors.push(parent); - - return {parentDoc, parent, ancestors}; -} - -export function setLineageOfDocs({docArray, oldParent, newAncestry}){ - const newParent = newAncestry[newAncestry.length - 1]; - docArray.forEach(doc => { - if(doc.parent.id === oldParent.id){ - doc.parent = newParent; - } - let oldAncestors = doc.ancestors; - let oldParentIndex = oldAncestors.findIndex(a => a.id === oldParent.id); - if (oldParentIndex === -1) return; - doc.ancestors = [...newAncestry, ...oldAncestors.slice(oldParentIndex + 1)]; - }); -} - -/** - * Give documents new random ids and transform their references. - * Transform collections of re-IDed docs according to the collection map - */ -export function renewDocIds({docArray, collectionMap, idMap = {}}){ - // idMap is a map of {oldId: newId} - // Get a random generator that's consistent on client and server - let randomSrc = DDP.randomStream('renewDocIds'); - - // Give new ids and map the changes as {oldId: newId} - docArray.forEach(doc => { - let oldId = doc._id; - let newId = idMap[oldId] || randomSrc.id(); - doc._id = newId; - idMap[oldId] = newId; - }); - - // Remap all references using the new IDs - const remapReference = ref => { - if (idMap[ref.id]){ - ref.id = idMap[ref.id]; - ref.collection = collectionMap && collectionMap[ref.collection] || ref.collection; - } - } - docArray.forEach(doc => { - remapReference(doc.parent); - doc.ancestors.forEach(remapReference); - }); -} - -export function updateParent({docRef, parentRef}){ - let collection = getCollectionByName(docRef.collection); - let oldDoc = fetchDocByRef(docRef, {fields: { - parent: 1, - ancestors: 1, - type: 1, - }}); - let updateOptions = { selector: {type: 'any'} }; - - // Skip if we aren't changing the parent id - if (oldDoc.parent.id === parentRef.id) return; - - // Get the parent and its ancestry - let {parentDoc, parent, ancestors} = getAncestry({parentRef}); - - // Check that the doc isn't its own ancestor - ancestors.forEach(ancestor => { - if (docRef.id === ancestor.id){ - throw new Meteor.Error('invalid parenting', - 'A doc can\'t be its own ancestor') - } - }); - - // If the doc and its parent are in the same collection, apply the allowed - // parent rules based on type - if (docRef.collection === parentRef.collection){ - let parentAllowed = isParentAllowed({ - parentType: parentDoc.type, - childType: oldDoc.type - }); - if (!parentAllowed){ - throw new Meteor.Error('invalid parenting', - `Can't make ${oldDoc.type} a child of ${parentDoc.type}`) - } - } - - // update the document's parenting - collection.update(docRef.id, { - $set: {parent, ancestors} - }, updateOptions); - - // Remove the old ancestors from the descendants - updateDescendants({ - collection, - ancestorId: docRef.id, - modifier: {$pullAll: { - ancestors: oldDoc.ancestors, - }}, - options: updateOptions, - }); - - // Add the new ancestors to the descendants - updateDescendants({ - collection, - ancestorId: docRef.id, - modifier: {$push: { - ancestors: { - $each: ancestors, - $position: 0, - }, - }}, - options: updateOptions, - }); -} - -export function getName(doc){ - if (doc.name) return name; - var i = doc.ancestors.length; - while(i--) { - if (doc.ancestors[i].name) return doc.ancestors[i].name; - } -} diff --git a/app/imports/api/parenting/parentingFunctions.test.ts b/app/imports/api/parenting/parentingFunctions.test.ts new file mode 100644 index 00000000..8c4f9104 --- /dev/null +++ b/app/imports/api/parenting/parentingFunctions.test.ts @@ -0,0 +1,77 @@ +import { docsToForest, calculateNestedSetOperations } from '/imports/api/parenting/parentingFunctions' +import { TreeDoc } from '/imports/api/parenting/ChildSchema'; +import { assert } from 'chai'; + +function doc(_id, left, right, parentId?): TreeDoc { + return { _id, root: { id: 'root', collection: 'col' }, left, right, parentId }; +} + +function op(_id, left, right) { + return { + updateOne: { + filter: { _id }, + update: { $set: { left, right } }, + }, + }; +} + +describe('Parenting with nested sets', function () { + /** + * Test the following structure + * + * 1 Books 12 + * ┃ + * 2 Programming 11 + * ┏━━━━━━━━┻━━━━━━━━━┓ + * 3 Languages 4 5 Databases 10 + * ┏━━━━━━━┻━━━━━━━┓ + * 6 MongoDB 7 8 dbm 9 + */ + it('Takes a set of documents and builds the forest', function () { + const docArray: Array = [ + doc('Books', 1, 12), + doc('Programming', 2, 11), + doc('Languages', 3, 4), + doc('Databases', 5, 10), + doc('MongoDB', 6, 7), + doc('dbm', 8, 9), + ]; + const forest = docsToForest(docArray); + assert.deepEqual(forest, [ + { + doc: doc('Books', 1, 12), children: [ + { + doc: doc('Programming', 2, 11), children: [ + { doc: doc('Languages', 3, 4), children: [] }, + { + doc: doc('Databases', 5, 10), children: [ + { doc: doc('MongoDB', 6, 7), children: [] }, + { doc: doc('dbm', 8, 9), children: [] }, + ] + } + ] + } + ] + } + ]); + }); + it('Can recalculate left and right for docs with set parents', function () { + const docArray = [ + doc('Books', 71, 33, undefined), + doc('Programming', 72, 33, 'Books'), + doc('Languages', 73, 33, 'Programming'), + doc('Databases', 74, 33, 'Programming'), + doc('MongoDB', 75, 33, 'Databases'), + doc('dbm', 76, 33, 'Databases'), + ]; + const ops = calculateNestedSetOperations(docArray); + assert.deepEqual(ops, [ + op('Books', 1, 12), + op('Programming', 2, 11), + op('Languages', 3, 4), + op('Databases', 5, 10), + op('MongoDB', 6, 7), + op('dbm', 8, 9), + ]); + }); +}); diff --git a/app/imports/api/parenting/parentingFunctions.ts b/app/imports/api/parenting/parentingFunctions.ts new file mode 100644 index 00000000..34d8eb91 --- /dev/null +++ b/app/imports/api/parenting/parentingFunctions.ts @@ -0,0 +1,494 @@ +import { chain, reverse } from 'lodash'; +import { TreeDoc, treeDocFields, Reference } from '/imports/api/parenting/ChildSchema'; + +export function getCollectionByName(name: string): Mongo.Collection { + const collection = Mongo.Collection.get(name) + if (!collection) { + throw new Meteor.Error('bad-collection-reference', + `Parent references collection ${name}, which does not exist` + ); + } + return collection; +} + +export async function fetchDocByRef(ref: Reference, options?: Mongo.Options) { + const doc = await getCollectionByName(ref.collection).findOneAsync(ref.id, options); + if (!doc) { + throw new Meteor.Error('document-not-found', + `No document could be found with id: ${ref.id} in ${ref.collection}` + ); + } + return doc; +} + +interface TreeNode { + doc: T, + children: TreeNode[] +} + +/** + * + * @param nodes An array of documents that share a common root. Must already be sorted by `.left` in ascending order + * @returns An array of tree nodes that each contain a document and its children. Children are + * assigned based on the nearest ancestor included in the input, which may or may not be their + * actual direct parents + */ +export function docsToForest(docs: Array): TreeNode[] { + if (!docs.length) return []; + const forest: TreeNode[] = []; + const ancestorStack: TreeNode[] = []; + let currentAncestor: TreeNode | undefined; + docs.forEach(doc => { + const node: TreeNode = { + doc, + children: [], + }; + // Remove ancestors from the stack until we find one that contains the current document + // Ancestor contains document if ancestor.left < doc.left and ancestor.right > doc.right + // ancestor.left < doc.left is ensured already, because we sorted by doc.left + while (currentAncestor && currentAncestor.doc.right < doc.left) { + currentAncestor = ancestorStack.pop(); + } + // Add this child to its place in the forest, either as a child of the ancestor or as the root + // of a new tree + if (currentAncestor) { + currentAncestor.children.push(node); + } else { + forest.push(node); + } + // Move the last ancestor onto the stack and make this node the new one + if (currentAncestor) ancestorStack.push(currentAncestor); + currentAncestor = node; + }); + return forest; +} + +/** + * Fetch the documents from a collection, and return the tree of those documents, potentially + * including their ancestors or descendants as required + * @param param options + * @returns An array of tree nodes that each contain a document and its children. Children are + * assigned based on the nearest ancestor included in the input, which may or may not be their + * actual direct parents + */ +type FilteredDoc = { + _descendantOfMatchedDocument?: boolean, + _matchedDocumentFilter?: boolean, + _ancestorOfMatchedDocument?: boolean, +} & TreeDoc; + +export default async function filterToForest( + collection: Mongo.Collection, + rootId: string, + filter: Mongo.Query, + options: Mongo.Options = {}, + includeFilteredDocAncestors = false, + includeFilteredDocDescendants = false +): Promise[]> { + // Setup the filter + let collectionFilter = { + 'root.id': rootId, + 'removed': { $ne: true }, + }; + if (filter) { + collectionFilter = { + ...collectionFilter, + ...filter, + } + } + // Set up the options + let collectionSort = { + left: 1 + }; + if (options && options.sort) { + collectionSort = { + ...collectionSort, + ...options.sort, + } + } + let collectionOptions: Mongo.Options = { + sort: collectionSort, + } + if (options) { + collectionOptions = { + ...collectionOptions, + ...options, + } + } + // Find all the docs that match the filter + const docs: TreeDoc[] = await collection.find(collectionFilter, collectionOptions) + .mapAsync(doc => { + if (!filter) return doc; + // Mark the docs that were found by the custom filter + doc._matchedDocumentFilter = true; + return doc; + }); + + // Get the doc ancestors + let ancestors: object[] = []; + if (filter && includeFilteredDocAncestors) { + ancestors = await collection.find(getFilter.ancestorsOfAll(docs), collectionOptions).mapAsync(doc => { + // Mark that the nodes are ancestors of the found nodes + doc._ancestorOfMatchedDocument = true; + return doc; + }); + } + + // Get the doc descendants + let descendants: FilteredDoc[] = []; + if (filter && includeFilteredDocDescendants) { + descendants = await collection.find({ + 'removed': { $ne: true }, + ...getFilter.descendantsOfAll(docs), + }).mapAsync((doc: FilteredDoc) => { + // Mark that the nodes are descendants of the found nodes + doc._descendantOfMatchedDocument = true; + return doc; + }); + } + const nodes = chain([ + ancestors, + docs, + descendants + ]).uniqBy('_id') + .sortBy('left') + .value(); + // Find all the nodes + return docsToForest(nodes); +} + +type ForestAndOrphans = { forest: TreeNode[], orphanIds: string[] } +/** + * Takes a complete set of documents and builds a forest using just their `.parentIds` + * Uses `.left` for sibling order within a parent only. + * Orphans whose direct parents can't be found are collected separately + * @param docs An array of all document that share a common root already sorted by `.left` in + * ascending order + * @returns forest: An array of tree nodes that each contain a document and its children. + * orphans: an array of the same, but their parents weren't in the input array + */ +export function docsToForestByParentId(docs: TreeDoc[]): ForestAndOrphans { + // Collect all the docs in a dict by id + const nodesById = <{ [_id: string]: TreeNode }>{}; + docs.forEach(doc => { + nodesById[doc._id] = { doc, children: [] }; + }); + // Assign the docs to their parent or the forest or orphanage + const forest: TreeNode[] = []; + const orphanIds: string[] = []; + docs.forEach(doc => { + const node = nodesById[doc._id]; + if (!doc.parentId) { + // Root is parent + forest.push(node); + } else if (nodesById[doc.parentId]) { + // Parent is found + nodesById[doc.parentId].children.push(node); + } else { + // Parent is missing, unset it, and store orphan + node.doc.parentId = undefined; + orphanIds.push(node.doc._id); + forest.push(node); + } + }); + return { forest, orphanIds }; +} + +export const getFilter = { + /** + * + * @param doc A document or array of documents that share a root + * @returns A query filter that finds all the ancestors of the doc(s) + */ + ancestors(doc: TreeDoc): Mongo.Query { + return { + 'root.id': doc.root.id, + left: { $lt: doc.left }, + right: { $gt: doc.right }, + }; + }, + ancestorsOfAll(docs: Array): Mongo.Query { + // The ancestors of no documents is a query that returns nothing + if (docs.length === 0) { + return { _id: '' }; + } + // Fallback to the simpler filter for a single document + if (docs.length === 1) { + return getFilter.ancestors(docs[0]); + } + // Build a filter that selects all ancestors + const filter = { + 'root.id': docs[0].root.id, + $or: [], + }; + docs.forEach(doc => { + filter.$or.push({ + left: { $lt: doc.left }, + right: { $gt: doc.right }, + }); + }); + return filter; + }, + descendants(doc: TreeDoc): Mongo.Query { + return { + 'root.id': doc.root.id, + left: { $gt: doc.left }, + right: { $lt: doc.right }, + }; + }, + descendantsOfAll(docs: Array): Mongo.Query { + // The descendants of no documents is a query that returns nothing + if (docs.length === 0) { + return { _id: '' }; + } + // Fallback to the simpler filter for a single document + if (docs.length === 1) { + return getFilter.descendants(docs[0]); + } + // Build a filter that selects all descendants + const filter = { + 'root.id': docs[0].root.id, + $or: [], + }; + docs.forEach(doc => { + filter.$or.push({ + left: { $gt: doc.left }, + right: { $lt: doc.right }, + }); + }); + return filter; + }, + children(doc: TreeDoc): Mongo.Query { + return { + 'root.id': doc.root.id, + parentId: doc._id, + }; + }, + parent(doc: TreeDoc): Mongo.Query { + return { + _id: doc.parentId, + }; + }, +} + +export async function fetchParent({ id, collection }) { + return await fetchDocByRef({ id, collection }); +} + +/** + * Give documents new random ids and transform their references. + * Transform collections of re-IDed docs according to the collection map + */ +export function renewDocIds({ docArray, collectionMap, idMap = {} }) { + // idMap is a map of {oldId: newId} + // Get a random generator that's consistent on client and server + const randomSrc = DDP.randomStream('renewDocIds'); + + // Give new ids and map the changes as {oldId: newId} + docArray.forEach(doc => { + const oldId = doc._id; + const newId = idMap[oldId] || randomSrc.id(); + doc._id = newId; + idMap[oldId] = newId; + }); + + // Remap all references using the new IDs + const remapReference = ref => { + if (idMap[ref.id]) { + ref.id = idMap[ref.id]; + ref.collection = collectionMap && collectionMap[ref.collection] || ref.collection; + } + } + docArray.forEach(doc => { + remapReference(doc.parent); + remapReference(doc.root); + }); +} + +/** + * Changes the doc to be a child of the parent, and then rebuilds the nested sets of the roots + * of both doc and parent + * @param doc The doc to move + * @param parent The new parent of the doc + * @param collection + * @returns + */ +export async function changeParent(doc: TreeDoc, parent: TreeDoc, collection: Mongo.Collection, order?: number) { + // Skip if we aren't changing the parent id + if (doc.parentId === parent._id) return; + + // Store the original roots + const rootChange = doc.root.id !== parent.root.id; + + // Check that the doc isn't becoming its own ancestor + if (parent.left > doc.left && parent.right < doc.right) { + throw new Meteor.Error('invalid parenting', 'A doc can\'t be its own ancestor'); + } + + // update the document's parenting and root if necessary + const update: Mongo.Modifier = { + $set: { parentId: parent._id } + }; + if (rootChange && update.$set) { + update.$set.root = parent.root; + } + if (order && update.$set) { + update.$set.left = order; + } + await collection.updateAsync(doc._id, update); + + // Rebuild the nested sets of everything on the root document(s) + rebuildNestedSets(collection, doc.root.id); + if (rootChange) { + rebuildNestedSets(collection, parent.root.id); + } +} + +export function compareOrder(docA, docB) { + // < 0 if A comes before B + // = 0 if A and B are the same order + // > 0 if B comes before A + + // They must share a root ancestor to be meaningfully sorted + if (docA.root.id !== docB.root.id) { + return 0; + } else { + return docA.left - docB.left; + } +} + +/** + * @deprecated Just set left to Number.MAX_SAFE_INTEGER instead + */ +export function setDocToLastOrder(collection: Mongo.Collection, doc: TreeDoc) { + doc.left = Number.MAX_SAFE_INTEGER; +} + +export async function rebuildNestedSets(collection: Mongo.Collection, rootId: string) { + const docs = collection.find({ + 'root.id': rootId, + removed: { $ne: true } + }, { + fields: { + root: 1, + parentId: 1, + left: 1, + right: 1, + }, + sort: { + //Reverse sorting so that arrays can be used as stacks with the first item on top + left: 1, + }, + }).fetch(); + + const operations = calculateNestedSetOperations(docs); + + await writeBulkOperations(collection, operations); +} + +export function calculateNestedSetOperations(docs: TreeDoc[]) { + // Walk around the tree numbering left on the way down and right on the way up like so: + /* + * 1 Books 12 + * ┃ + * 2 Programming 11 + * ┏━━━━━━━━┻━━━━━━━━━┓ + * 3 Languages 4 5 Databases 10 + * ┏━━━━━━━┻━━━━━━━┓ + * 6 MongoDB 7 8 dbm 9 + */ + // Get the forest, but in reverse order so that the stack always has the first documents on top + const { forest: stack, orphanIds } = docsToForestByParentId(reverse(docs)); + const removeMissingParentsOp = orphanIds.length ? { + updateMany: { + filter: { _id: { $in: orphanIds } }, + update: { $unset: { parentId: 1 } }, + } + } : undefined; + const visitedNodes = new Set(); + const visitedChildren = new Set(); + const opsById: { [_id: string]: any } = {} + let count = 1; + + while (stack.length) { + const top = stack[stack.length - 1]; + if (visitedNodes.has(top)) { + // We've arrived at this node again for some reason, this shouldn't happen + console.log('visited already, parent loop maybe?') + stack.pop(); + } else if (visitedChildren.has(top)) { + // We've arrived at this node after visiting the children, + // we must be on the way up, mark the right number + visitedNodes.add(top); + stack.pop(); + if (top.doc.right !== count) { + opsById[top.doc._id].updateOne.update.$set.right = count; + } + count += 1; + } else { + // We're arriving at this node for the first time + // We must be on the way down, mark the left number and go visit the children + visitedChildren.add(top); + stack.push(...top.children); + if (top.doc.left !== count) { + opsById[top.doc._id] = { + updateOne: { + filter: { _id: top.doc._id }, + update: { $set: { left: count } }, + } + }; + } + count += 1; + } + } + + const operations = [...Object.values(opsById)]; + if (removeMissingParentsOp) operations.push(removeMissingParentsOp); + return operations; +} + +/** + * Write some number of bulk operations to the collection, uses a bulk write on the server + * and iterates through regular updates on the client + * Resolves once all writes have completed + * @param collection The collection to write to + * @param operations An array of bulk operations to write + * @returns Promise + */ +async function writeBulkOperations(collection: Mongo.Collection, operations) { + if (Meteor.isServer && operations.length) { + return new Promise((resolve, reject) => { + collection.rawCollection().bulkWrite( + operations, + { ordered: false }, + function (e) { + if (e) { + reject(e); + } else { + resolve(undefined); + } + } + ); + }); + } else { + const promises = operations.map(op => { + if (op.updateOne) { + return collection.updateAsync( + op.updateOne.filter, + op.updateOne.update, + { selector: { type: 'any' } } + ); + } else if (op.updateMany) { + return collection.updateAsync( + op.updateMany.filter, + op.updateMany.update, + { + selector: { type: 'any' }, + multi: true, + }, + ) + } + }); + return Promise.all(promises); + } +} diff --git a/app/imports/api/parenting/softRemove.js b/app/imports/api/parenting/softRemove.js deleted file mode 100644 index 099abfc2..00000000 --- a/app/imports/api/parenting/softRemove.js +++ /dev/null @@ -1,74 +0,0 @@ -import getCollectionByName from '/imports/api/parenting/getCollectionByName.js'; -import { updateDescendants } from '/imports/api/parenting/parenting.js'; - -export function softRemove({_id, collection}){ - let removalDate = new Date(); - if (typeof collection === 'string') { - collection = getCollectionByName(collection); - } - // Remove this document - collection.update( - _id, { - $set: { - removed: true, - removedAt: removalDate, - }, - $unset: { - removedWith: 1, - } - }, { - selector: {type: 'any'}, - }, - ); - // Remove all the descendants that have not yet been removed, and set them to be - // removed with this document - updateDescendants({ - collection, - ancestorId: _id, - filter: {removed: {$ne: true}}, - modifier: {$set: { - removed: true, - removedAt: removalDate, - removedWith: _id, - }}, - }); -} - -const restoreError = function(){ - throw new Meteor.Error('restore-failed', - 'Could not restore this document, maybe it was removed by a parent?' - ); -}; - -export function restore({ _id, collection, extraUpdates}){ - if (typeof collection === 'string') { - collection = getCollectionByName(collection); - } - const update = { - $unset: { - removed: 1, - removedAt: 1, - }, - ...extraUpdates - } - - let numUpdated = collection.update({ - _id, - removedWith: {$exists: false} - }, update , { - selector: {type: 'any'}, - },); - if (numUpdated === 0) restoreError(); - updateDescendants({ - collection, - ancestorId: _id, - filter: { - removedWith: _id, - }, - modifier: { $unset: { - removed: 1, - removedAt: 1, - removedWith: 1, - }}, - }); -} diff --git a/app/imports/api/parenting/softRemove.ts b/app/imports/api/parenting/softRemove.ts new file mode 100644 index 00000000..e08cf7ba --- /dev/null +++ b/app/imports/api/parenting/softRemove.ts @@ -0,0 +1,90 @@ +import { getCollectionByName, getFilter } from '/imports/api/parenting/parentingFunctions'; +import { TreeDoc } from '/imports/api/parenting/ChildSchema'; + +export async function softRemove(collection: Mongo.Collection | string, doc?: TreeDoc | string) { + const removalDate = new Date(); + if (typeof collection === 'string') { + collection = getCollectionByName(collection); + } + if (typeof doc === 'string') { + doc = await collection.findOneAsync(doc); + } + if (!doc) { + throw new Meteor.Error('not found', 'The document to remove was not found'); + } + // Remove this document + const removeDocPromise = collection.updateAsync( + doc._id, + { + $set: { + removed: true, + removedAt: removalDate, + }, + $unset: { + removedWith: 1, + } + }, { + selector: { type: 'any' }, + }, + ); + // Remove all the descendants that have not yet been removed, and set them to be + // removed with this document + const removeDescendantsPromise = collection.updateAsync({ + ...getFilter.descendants(doc), + removed: { $ne: true }, + }, { + $set: { + removed: true, + removedAt: removalDate, + removedWith: doc._id, + } + }, { + selector: { type: 'any' }, + multi: true, + }); + return Promise.all([removeDocPromise, removeDescendantsPromise]); +} + +const restoreError = function () { + throw new Meteor.Error('restore-failed', + 'Could not restore this document, maybe it was removed by a parent?' + ); +}; + +export async function restore(collection: Mongo.Collection | string, doc: TreeDoc | string, extraUpdates) { + if (typeof collection === 'string') { + collection = getCollectionByName(collection); + } + if (typeof doc === 'string') { + const foundDoc = await collection.findOneAsync(doc) + if (!foundDoc) { + throw new Meteor.Error('not found', 'The document to remove was not found'); + } + doc = foundDoc; + } + const numUpdated: number = await collection.updateAsync({ + _id: doc._id, + removedWith: { $exists: false } + }, { + $unset: { + removed: 1, + removedAt: 1, + }, + ...extraUpdates + }, { + selector: { type: 'any' }, + }); + if (numUpdated === 0) restoreError(); + return collection.updateAsync({ + removedWith: doc._id, + }, { + $unset: { + removed: 1, + removedAt: 1, + removedWith: 1, + } + }, { + selector: { type: 'any' }, + multi: true, + }); +} diff --git a/app/package-lock.json b/app/package-lock.json index a772ebfa..23d1c5c1 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -4,6 +4,700 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@aws-crypto/crc32": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", + "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "optional": true, + "requires": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "@aws-crypto/ie11-detection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", + "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", + "optional": true, + "requires": { + "tslib": "^1.11.1" + } + }, + "@aws-crypto/sha256-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", + "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", + "optional": true, + "requires": { + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/sha256-js": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "@aws-crypto/sha256-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", + "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", + "optional": true, + "requires": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "@aws-crypto/supports-web-crypto": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", + "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", + "optional": true, + "requires": { + "tslib": "^1.11.1" + } + }, + "@aws-crypto/util": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", + "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", + "optional": true, + "requires": { + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "@aws-sdk/client-cognito-identity": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.410.0.tgz", + "integrity": "sha512-J4iPhXswm66Fsk1x0Kly+PWzBizmms4kkkoAU1sk9n08XfWqNBTyf01mx6/t/X+Yh43p2zaeB/XvUwa0jSsWaQ==", + "optional": true, + "requires": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.410.0", + "@aws-sdk/credential-provider-node": "3.410.0", + "@aws-sdk/middleware-host-header": "3.410.0", + "@aws-sdk/middleware-logger": "3.410.0", + "@aws-sdk/middleware-recursion-detection": "3.410.0", + "@aws-sdk/middleware-signing": "3.410.0", + "@aws-sdk/middleware-user-agent": "3.410.0", + "@aws-sdk/types": "3.410.0", + "@aws-sdk/util-endpoints": "3.410.0", + "@aws-sdk/util-user-agent-browser": "3.410.0", + "@aws-sdk/util-user-agent-node": "3.410.0", + "@smithy/config-resolver": "^2.0.7", + "@smithy/fetch-http-handler": "^2.1.2", + "@smithy/hash-node": "^2.0.6", + "@smithy/invalid-dependency": "^2.0.6", + "@smithy/middleware-content-length": "^2.0.8", + "@smithy/middleware-endpoint": "^2.0.6", + "@smithy/middleware-retry": "^2.0.9", + "@smithy/middleware-serde": "^2.0.6", + "@smithy/middleware-stack": "^2.0.0", + "@smithy/node-config-provider": "^2.0.9", + "@smithy/node-http-handler": "^2.1.2", + "@smithy/protocol-http": "^3.0.2", + "@smithy/smithy-client": "^2.1.3", + "@smithy/types": "^2.3.0", + "@smithy/url-parser": "^2.0.6", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.7", + "@smithy/util-defaults-mode-node": "^2.0.9", + "@smithy/util-retry": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/client-sso": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.410.0.tgz", + "integrity": "sha512-MC9GrgwtlOuSL2WS3DRM3dQ/5y+49KSMMJRH6JiEcU5vE0dX/OtEcX+VfEwpi73x5pSfIjm7xnzjzOFx+sQBIg==", + "optional": true, + "requires": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.410.0", + "@aws-sdk/middleware-logger": "3.410.0", + "@aws-sdk/middleware-recursion-detection": "3.410.0", + "@aws-sdk/middleware-user-agent": "3.410.0", + "@aws-sdk/types": "3.410.0", + "@aws-sdk/util-endpoints": "3.410.0", + "@aws-sdk/util-user-agent-browser": "3.410.0", + "@aws-sdk/util-user-agent-node": "3.410.0", + "@smithy/config-resolver": "^2.0.7", + "@smithy/fetch-http-handler": "^2.1.2", + "@smithy/hash-node": "^2.0.6", + "@smithy/invalid-dependency": "^2.0.6", + "@smithy/middleware-content-length": "^2.0.8", + "@smithy/middleware-endpoint": "^2.0.6", + "@smithy/middleware-retry": "^2.0.9", + "@smithy/middleware-serde": "^2.0.6", + "@smithy/middleware-stack": "^2.0.0", + "@smithy/node-config-provider": "^2.0.9", + "@smithy/node-http-handler": "^2.1.2", + "@smithy/protocol-http": "^3.0.2", + "@smithy/smithy-client": "^2.1.3", + "@smithy/types": "^2.3.0", + "@smithy/url-parser": "^2.0.6", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.7", + "@smithy/util-defaults-mode-node": "^2.0.9", + "@smithy/util-retry": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/client-sts": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.410.0.tgz", + "integrity": "sha512-e6VMrBJtnTxxUXwDmkADGIvyppmDMFf4+cGGA68tVCUm1cFNlCI6M/67bVSIPN/WVKAAfhEL5O2vVXCM7aatYg==", + "optional": true, + "requires": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/credential-provider-node": "3.410.0", + "@aws-sdk/middleware-host-header": "3.410.0", + "@aws-sdk/middleware-logger": "3.410.0", + "@aws-sdk/middleware-recursion-detection": "3.410.0", + "@aws-sdk/middleware-sdk-sts": "3.410.0", + "@aws-sdk/middleware-signing": "3.410.0", + "@aws-sdk/middleware-user-agent": "3.410.0", + "@aws-sdk/types": "3.410.0", + "@aws-sdk/util-endpoints": "3.410.0", + "@aws-sdk/util-user-agent-browser": "3.410.0", + "@aws-sdk/util-user-agent-node": "3.410.0", + "@smithy/config-resolver": "^2.0.7", + "@smithy/fetch-http-handler": "^2.1.2", + "@smithy/hash-node": "^2.0.6", + "@smithy/invalid-dependency": "^2.0.6", + "@smithy/middleware-content-length": "^2.0.8", + "@smithy/middleware-endpoint": "^2.0.6", + "@smithy/middleware-retry": "^2.0.9", + "@smithy/middleware-serde": "^2.0.6", + "@smithy/middleware-stack": "^2.0.0", + "@smithy/node-config-provider": "^2.0.9", + "@smithy/node-http-handler": "^2.1.2", + "@smithy/protocol-http": "^3.0.2", + "@smithy/smithy-client": "^2.1.3", + "@smithy/types": "^2.3.0", + "@smithy/url-parser": "^2.0.6", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.7", + "@smithy/util-defaults-mode-node": "^2.0.9", + "@smithy/util-retry": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/credential-provider-cognito-identity": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.410.0.tgz", + "integrity": "sha512-2QMvdnwnYsKnwy8O+o9ozKL80VFWI0skXVvKB3DFW4cr9IX5cBCx7xuhI7TXbCqiBxuz5SSiA1s19fVtq0sUmw==", + "optional": true, + "requires": { + "@aws-sdk/client-cognito-identity": "3.410.0", + "@aws-sdk/types": "3.410.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.3.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/credential-provider-env": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.410.0.tgz", + "integrity": "sha512-c7TB9LbN0PkFOsXI0lcRJnqPNOmc4VBvrHf8jP/BkTDg4YUoKQKOFd4d0SqzODmlZiAyoMQVZTR4ISZo95Zj4Q==", + "optional": true, + "requires": { + "@aws-sdk/types": "3.410.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.3.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/credential-provider-ini": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.410.0.tgz", + "integrity": "sha512-D8rcr5bRCFD0f42MPQ7K6TWZq5d3pfqrKINL1/bpfkK5BJbvq1BGYmR88UC6CLpTRtZ1LHY2HgYG0fp/2zjjww==", + "optional": true, + "requires": { + "@aws-sdk/credential-provider-env": "3.410.0", + "@aws-sdk/credential-provider-process": "3.410.0", + "@aws-sdk/credential-provider-sso": "3.410.0", + "@aws-sdk/credential-provider-web-identity": "3.410.0", + "@aws-sdk/types": "3.410.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.3.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/credential-provider-node": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.410.0.tgz", + "integrity": "sha512-0wmVm33T/j1FS7MZ/j+WsPlgSc0YnCXnpbWSov1Mn6R86SHI2b2JhdIPRRE4XbGfyW2QGNUl2CwoZVaqhXeF5g==", + "optional": true, + "requires": { + "@aws-sdk/credential-provider-env": "3.410.0", + "@aws-sdk/credential-provider-ini": "3.410.0", + "@aws-sdk/credential-provider-process": "3.410.0", + "@aws-sdk/credential-provider-sso": "3.410.0", + "@aws-sdk/credential-provider-web-identity": "3.410.0", + "@aws-sdk/types": "3.410.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.3.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/credential-provider-process": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.410.0.tgz", + "integrity": "sha512-BMju1hlDCDNkkSZpKF5SQ8G0WCLRj6/Jvw9QmudLHJuVwYJXEW1r2AsVMg98OZ3hB9G+MAvHruHZIbMiNmUMXQ==", + "optional": true, + "requires": { + "@aws-sdk/types": "3.410.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.3.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/credential-provider-sso": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.410.0.tgz", + "integrity": "sha512-zEaoY/sY+KYTlQUkp9dvveAHf175b8RIt0DsQkDrRPtrg/RBHR00r5rFvz9+nrwsR8546RaBU7h/zzTaQGhmcA==", + "optional": true, + "requires": { + "@aws-sdk/client-sso": "3.410.0", + "@aws-sdk/token-providers": "3.410.0", + "@aws-sdk/types": "3.410.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.3.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/credential-provider-web-identity": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.410.0.tgz", + "integrity": "sha512-cE0l8LmEHdWbDkdPNgrfdYSgp4/cIVXrjUKI1QCATA729CrHZ/OQjB/maOBOrMHO9YTiggko887NkslVvwVB7w==", + "optional": true, + "requires": { + "@aws-sdk/types": "3.410.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.3.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/credential-providers": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.410.0.tgz", + "integrity": "sha512-QcunzQRNi9dJdAGdduST7itRW+QhDrb9zZHn+HhLKUoVwLrqk1iuH2R9SoEdZg8eV5jR04yoOPdjj1jzdIkFXQ==", + "optional": true, + "requires": { + "@aws-sdk/client-cognito-identity": "3.410.0", + "@aws-sdk/client-sso": "3.410.0", + "@aws-sdk/client-sts": "3.410.0", + "@aws-sdk/credential-provider-cognito-identity": "3.410.0", + "@aws-sdk/credential-provider-env": "3.410.0", + "@aws-sdk/credential-provider-ini": "3.410.0", + "@aws-sdk/credential-provider-node": "3.410.0", + "@aws-sdk/credential-provider-process": "3.410.0", + "@aws-sdk/credential-provider-sso": "3.410.0", + "@aws-sdk/credential-provider-web-identity": "3.410.0", + "@aws-sdk/types": "3.410.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.3.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/middleware-host-header": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.410.0.tgz", + "integrity": "sha512-ED/OVcyITln5rrxnajZP+V0PN1nug+gSDHJDqdDo/oLy7eiDr/ZWn3nlWW7WcMplQ1/Jnb+hK0UetBp/25XooA==", + "optional": true, + "requires": { + "@aws-sdk/types": "3.410.0", + "@smithy/protocol-http": "^3.0.2", + "@smithy/types": "^2.3.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/middleware-logger": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.410.0.tgz", + "integrity": "sha512-YtmKYCVtBfScq3/UFJk+aSZOktKJBNZL9DaSc2aPcy/goCVsYDOkGwtHk0jIkC1JRSNCkVTqL7ya60sSr8zaQQ==", + "optional": true, + "requires": { + "@aws-sdk/types": "3.410.0", + "@smithy/types": "^2.3.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/middleware-recursion-detection": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.410.0.tgz", + "integrity": "sha512-KWaes5FLzRqj28vaIEE4Bimpga2E596WdPF2HaH6zsVMJddoRDsc3ZX9ZhLOGrXzIO1RqBd0QxbLrM0S/B2aOQ==", + "optional": true, + "requires": { + "@aws-sdk/types": "3.410.0", + "@smithy/protocol-http": "^3.0.2", + "@smithy/types": "^2.3.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/middleware-sdk-sts": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.410.0.tgz", + "integrity": "sha512-YfBpctDocRR4CcROoDueJA7D+aMLBV8nTFfmVNdLLLgyuLZ/AUR11VQSu1lf9gQZKl8IpKE/BLf2fRE/qV1ZuA==", + "optional": true, + "requires": { + "@aws-sdk/middleware-signing": "3.410.0", + "@aws-sdk/types": "3.410.0", + "@smithy/types": "^2.3.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/middleware-signing": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.410.0.tgz", + "integrity": "sha512-KBAZ/eoAJUSJv5us2HsKwK2OszG2s9FEyKpEhgnHLcbbKzW873zHBH5GcOGEQu4AWArTy2ndzJu3FF+9/J9hJQ==", + "optional": true, + "requires": { + "@aws-sdk/types": "3.410.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.2", + "@smithy/signature-v4": "^2.0.0", + "@smithy/types": "^2.3.0", + "@smithy/util-middleware": "^2.0.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/middleware-user-agent": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.410.0.tgz", + "integrity": "sha512-ZayDtLfvCZUohSxQc/49BfoU/y6bDHLfLdyyUJbJ54Sv8zQcrmdyKvCBFUZwE6tHQgAmv9/ZT18xECMl+xiONA==", + "optional": true, + "requires": { + "@aws-sdk/types": "3.410.0", + "@aws-sdk/util-endpoints": "3.410.0", + "@smithy/protocol-http": "^3.0.2", + "@smithy/types": "^2.3.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/token-providers": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.410.0.tgz", + "integrity": "sha512-d5Nc0xydkH/X0LA1HDyhGY5sEv4LuADFk+QpDtT8ogLilcre+b1jpdY8Sih/gd1KoGS1H+d1tz2hSGwUHAbUbw==", + "optional": true, + "requires": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.410.0", + "@aws-sdk/middleware-logger": "3.410.0", + "@aws-sdk/middleware-recursion-detection": "3.410.0", + "@aws-sdk/middleware-user-agent": "3.410.0", + "@aws-sdk/types": "3.410.0", + "@aws-sdk/util-endpoints": "3.410.0", + "@aws-sdk/util-user-agent-browser": "3.410.0", + "@aws-sdk/util-user-agent-node": "3.410.0", + "@smithy/config-resolver": "^2.0.7", + "@smithy/fetch-http-handler": "^2.1.2", + "@smithy/hash-node": "^2.0.6", + "@smithy/invalid-dependency": "^2.0.6", + "@smithy/middleware-content-length": "^2.0.8", + "@smithy/middleware-endpoint": "^2.0.6", + "@smithy/middleware-retry": "^2.0.9", + "@smithy/middleware-serde": "^2.0.6", + "@smithy/middleware-stack": "^2.0.0", + "@smithy/node-config-provider": "^2.0.9", + "@smithy/node-http-handler": "^2.1.2", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.2", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/smithy-client": "^2.1.3", + "@smithy/types": "^2.3.0", + "@smithy/url-parser": "^2.0.6", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.7", + "@smithy/util-defaults-mode-node": "^2.0.9", + "@smithy/util-retry": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/types": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.410.0.tgz", + "integrity": "sha512-D7iaUCszv/v04NDaZUmCmekamy6VD/lKozm/3gS9+dkfU6cC2CsNoUfPV8BlV6dPdw0oWgF91am3I1stdvfVrQ==", + "optional": true, + "requires": { + "@smithy/types": "^2.3.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/util-endpoints": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.410.0.tgz", + "integrity": "sha512-iNiqJyC7N3+8zFwnXUqcWSxrZecVZLToo1iTQQdeYL2af1IcOtRgb7n8jpAI/hmXhBSx2+3RI+Y7pxyFo1vu+w==", + "optional": true, + "requires": { + "@aws-sdk/types": "3.410.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/util-locate-window": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", + "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", + "optional": true, + "requires": { + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/util-user-agent-browser": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.410.0.tgz", + "integrity": "sha512-i1G/XGpXGMRT2zEiAhi1xucJsfCWk8nNYjk/LbC0sA+7B9Huri96YAzVib12wkHPsJQvZxZC6CpQDIHWm4lXMA==", + "optional": true, + "requires": { + "@aws-sdk/types": "3.410.0", + "@smithy/types": "^2.3.0", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/util-user-agent-node": { + "version": "3.410.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.410.0.tgz", + "integrity": "sha512-bK70t1jHRl8HrJXd4hEIwc5PBZ7U0w+81AKFnanIVKZwZedd6nLibUXDTK14z/Jp2GFcBqd4zkt2YLGkRt/U4A==", + "optional": true, + "requires": { + "@aws-sdk/types": "3.410.0", + "@smithy/node-config-provider": "^2.0.9", + "@smithy/types": "^2.3.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", + "optional": true, + "requires": { + "tslib": "^2.3.1" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, "@babel/code-frame": { "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", @@ -164,6 +858,15 @@ "tar": "^6.1.11" } }, + "@mongodb-js/saslprep": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz", + "integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==", + "optional": true, + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -190,29 +893,834 @@ "fastq": "^1.6.0" } }, + "@smithy/abort-controller": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.7.tgz", + "integrity": "sha512-rITz65zk8QA3GQ1OeoJ3/Q4+8j/HqubWU8TBqk57BMYTOX+P+LNMoVHPqzLHhE6qKot5muhThNCYvOKNt7ojJA==", + "optional": true, + "requires": { + "@smithy/types": "^2.3.1", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/config-resolver": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.8.tgz", + "integrity": "sha512-e7mwQteHjo9S1GK+TfzP3o7ujE2ZK30d6wkv5brKtabrZF7MBflj9CwUP2XYuOYebdWirHOtv8ZfkMrpcbJfYw==", + "optional": true, + "requires": { + "@smithy/node-config-provider": "^2.0.10", + "@smithy/types": "^2.3.1", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/credential-provider-imds": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.10.tgz", + "integrity": "sha512-may2/gYlDip2rjlU1Z5fcCEWY0Fu3tSu/HykgZrLfb2/171P6OYuz7dGNKBOCS1W57vP4W5wmUhm0WGehrixig==", + "optional": true, + "requires": { + "@smithy/node-config-provider": "^2.0.10", + "@smithy/property-provider": "^2.0.8", + "@smithy/types": "^2.3.1", + "@smithy/url-parser": "^2.0.7", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/eventstream-codec": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.7.tgz", + "integrity": "sha512-sW3AhXZhmmhh0f11EOotmNNa0rjrKwnMYNKfbp3B/qigdw6foKcmFGX+HF3XGN7w7fFeEFuXr97Ok24gRj92Xg==", + "optional": true, + "requires": { + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^2.3.1", + "@smithy/util-hex-encoding": "^2.0.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/fetch-http-handler": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.1.3.tgz", + "integrity": "sha512-kUg+Ey4mJeR/3+Ponuhb1rsmsfZRwjCLvC+WcPgeI+ittretEzuWAPN+9anD0HJEoApVjHpndzxPtlncbCUJDQ==", + "optional": true, + "requires": { + "@smithy/protocol-http": "^3.0.3", + "@smithy/querystring-builder": "^2.0.7", + "@smithy/types": "^2.3.1", + "@smithy/util-base64": "^2.0.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/hash-node": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.7.tgz", + "integrity": "sha512-aB5lvIDP1v+ZUUS8ek3XW5xnZ6jUQ86JXqG7a5jMP6AbjAc3439mIbs6+f1EQ5MtYmrQCEtRRyvv5QofvotH0w==", + "optional": true, + "requires": { + "@smithy/types": "^2.3.1", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/invalid-dependency": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.7.tgz", + "integrity": "sha512-qVOZnHFPzQo4BS47/PANHX32Y69c0tJxKBkqTL795D/DKInqBwmBO/m1gS7v0ZQqmtCuoy2l87RflQfRY2xEIw==", + "optional": true, + "requires": { + "@smithy/types": "^2.3.1", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/is-array-buffer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz", + "integrity": "sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==", + "optional": true, + "requires": { + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/middleware-content-length": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.9.tgz", + "integrity": "sha512-2XVFsGqswxrIBi0w4Njwzb1zsbte26U513K+WPFm9z6SB/3WR5/VBVjTaTcamrXznTAqBjTwTL0Ysisv1dW0Rw==", + "optional": true, + "requires": { + "@smithy/protocol-http": "^3.0.3", + "@smithy/types": "^2.3.1", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/middleware-endpoint": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.0.7.tgz", + "integrity": "sha512-4/L0wV7PzHEprJB0gazSTIwlW/2cCfwC9EHavUMhoCyl1tLer6CJwDbAMit1IMvwbHkwuKopueb8dFPHfpS2Pw==", + "optional": true, + "requires": { + "@smithy/middleware-serde": "^2.0.7", + "@smithy/types": "^2.3.1", + "@smithy/url-parser": "^2.0.7", + "@smithy/util-middleware": "^2.0.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/middleware-retry": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.10.tgz", + "integrity": "sha512-VwAQOR5Rh/y9BzUgb5DzUk7qYBiMZu3pEQa5EwwAf/F7lpMuNildGrAxtDmsXk90490FJwa6LyFknXP3kO5BnA==", + "optional": true, + "requires": { + "@smithy/node-config-provider": "^2.0.10", + "@smithy/protocol-http": "^3.0.3", + "@smithy/service-error-classification": "^2.0.0", + "@smithy/types": "^2.3.1", + "@smithy/util-middleware": "^2.0.0", + "@smithy/util-retry": "^2.0.0", + "tslib": "^2.5.0", + "uuid": "^8.3.2" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "optional": true + } + } + }, + "@smithy/middleware-serde": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.7.tgz", + "integrity": "sha512-tOldis4PUNafdGErLZ+33p9Pf3MmTlLa176X321Z6ZaCf1XNEow9m3T5vXrcHErVAvjPG0mp3l54J94HnPc+rQ==", + "optional": true, + "requires": { + "@smithy/types": "^2.3.1", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/middleware-stack": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.0.tgz", + "integrity": "sha512-31XC1xNF65nlbc16yuh3wwTudmqs6qy4EseQUGF8A/p2m/5wdd/cnXJqpniy/XvXVwkHPz/GwV36HqzHtIKATQ==", + "optional": true, + "requires": { + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/node-config-provider": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.0.10.tgz", + "integrity": "sha512-e5MiLH5Eu+BbYsmhZIkvUKCzite6JCBPL75PNjlRK2TWvSpfp19hNf2SiJIQbPalcFj5zlyBvtcEkF1sfYIdhg==", + "optional": true, + "requires": { + "@smithy/property-provider": "^2.0.8", + "@smithy/shared-ini-file-loader": "^2.0.9", + "@smithy/types": "^2.3.1", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/node-http-handler": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.1.3.tgz", + "integrity": "sha512-TGkgpx68SqvbspVHaG3iwqP2mKYOT4whiq7Kv2X9v+InngL4MkpH3LQ0Dk7kbloahZr+hAOyb6s8D7T8TXRrzA==", + "optional": true, + "requires": { + "@smithy/abort-controller": "^2.0.7", + "@smithy/protocol-http": "^3.0.3", + "@smithy/querystring-builder": "^2.0.7", + "@smithy/types": "^2.3.1", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/property-provider": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.8.tgz", + "integrity": "sha512-oaaP/i7bGG8XbxG9Kx4PZh83iJ2jo/vt8RmJdi9hmc8APBaW1HGDperVXDCyPQdVYXmiqrtxc/rPImyBma1G3A==", + "optional": true, + "requires": { + "@smithy/types": "^2.3.1", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/protocol-http": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.3.tgz", + "integrity": "sha512-UGfmQNdijlFV+UzgdRyfe05S5vLDdcdkvNcxhGvQ+Er7TjUkZSxjukQB9VXtT8oTHztgOMX74DDlPBsVzZR5Pg==", + "optional": true, + "requires": { + "@smithy/types": "^2.3.1", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/querystring-builder": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.7.tgz", + "integrity": "sha512-RPHnqt4iH1Kwp1Zbf4gJI88hZiynEZjE5hEWJNBmKqCe1Q6v7HBLtaovTaiuYaMEmPyb2KxOi3lISAdT6uuPqw==", + "optional": true, + "requires": { + "@smithy/types": "^2.3.1", + "@smithy/util-uri-escape": "^2.0.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/querystring-parser": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.7.tgz", + "integrity": "sha512-Cwi/Hgs73nbLKfgH7dXAxzvDxyTrK+BLrlAd0KXU7xcBR94V132nvxoq39BMWckYAPmnMwxCwq8uusNH4Dnagw==", + "optional": true, + "requires": { + "@smithy/types": "^2.3.1", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/service-error-classification": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.0.tgz", + "integrity": "sha512-2z5Nafy1O0cTf69wKyNjGW/sNVMiqDnb4jgwfMG8ye8KnFJ5qmJpDccwIbJNhXIfbsxTg9SEec2oe1cexhMJvw==", + "optional": true + }, + "@smithy/shared-ini-file-loader": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.0.9.tgz", + "integrity": "sha512-vBLgJI+Qpz1TZ0W2kUBOmG2Q+geVEhiXE99UX02+UFag2WzOQ6frvV6rpadwJu0uwF02GG620NbiKGboqZ19YA==", + "optional": true, + "requires": { + "@smithy/types": "^2.3.1", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/signature-v4": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.7.tgz", + "integrity": "sha512-qNCJpyhRWxT5RWmeSo/Zv+miQ60Y/D2JmPdFw7v2WpPVxVK7JDpqUbvq0QYE+dBGPX/uagAkE3NvJUcn0fTE3A==", + "optional": true, + "requires": { + "@smithy/eventstream-codec": "^2.0.7", + "@smithy/is-array-buffer": "^2.0.0", + "@smithy/types": "^2.3.1", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-middleware": "^2.0.0", + "@smithy/util-uri-escape": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/smithy-client": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.4.tgz", + "integrity": "sha512-KRQvYYjEGqvmwnKSAZ8EL0hZvPxGQMYbAKS/AMGq2fuRmwAlinSVJ/fkIs65bZp2oYjcskd1ZgKcP+2UDjNPTQ==", + "optional": true, + "requires": { + "@smithy/middleware-stack": "^2.0.0", + "@smithy/types": "^2.3.1", + "@smithy/util-stream": "^2.0.10", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/types": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.3.1.tgz", + "integrity": "sha512-cS48e4Yawb6pGakj7DBJUIPFIkqnUWyXTe2ndPRNagD73b6kEJqTc8bhTyfUve0A+sijK256UKE0J1juAfCeDA==", + "optional": true, + "requires": { + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/url-parser": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.7.tgz", + "integrity": "sha512-SwMl1Lq3yFR2hzhwWYKg04uJHpfcXWMBPycm4Z8GkLI6Dw7rJNDApEbMtujlYw6pVP2WKbrpaGHjQ9MdP92kMQ==", + "optional": true, + "requires": { + "@smithy/querystring-parser": "^2.0.7", + "@smithy/types": "^2.3.1", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/util-base64": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.0.tgz", + "integrity": "sha512-Zb1E4xx+m5Lud8bbeYi5FkcMJMnn+1WUnJF3qD7rAdXpaL7UjkFQLdmW5fHadoKbdHpwH9vSR8EyTJFHJs++tA==", + "optional": true, + "requires": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/util-body-length-browser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.0.tgz", + "integrity": "sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg==", + "optional": true, + "requires": { + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/util-body-length-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.1.0.tgz", + "integrity": "sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==", + "optional": true, + "requires": { + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/util-buffer-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz", + "integrity": "sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==", + "optional": true, + "requires": { + "@smithy/is-array-buffer": "^2.0.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/util-config-provider": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.0.0.tgz", + "integrity": "sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==", + "optional": true, + "requires": { + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/util-defaults-mode-browser": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.8.tgz", + "integrity": "sha512-8znx01mkmfKxhiSB2bOF5eMutuCLMd8m2Kh0ulRp8vgzhwRLDJoU6aHSEUoNptbuTAtiFf4u0gpkYC2XfbWwuA==", + "optional": true, + "requires": { + "@smithy/property-provider": "^2.0.8", + "@smithy/types": "^2.3.1", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/util-defaults-mode-node": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.10.tgz", + "integrity": "sha512-QUcUckL4ZqDFVwLnh7zStRUnXtTC6hcJZ4FmMqnxlPcL33Rko0sMQwrMDnMdzF3rS3wvqugAaq3zzop1HCluvw==", + "optional": true, + "requires": { + "@smithy/config-resolver": "^2.0.8", + "@smithy/credential-provider-imds": "^2.0.10", + "@smithy/node-config-provider": "^2.0.10", + "@smithy/property-provider": "^2.0.8", + "@smithy/types": "^2.3.1", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/util-hex-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.0.0.tgz", + "integrity": "sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==", + "optional": true, + "requires": { + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/util-middleware": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.0.tgz", + "integrity": "sha512-eCWX4ECuDHn1wuyyDdGdUWnT4OGyIzV0LN1xRttBFMPI9Ff/4heSHVxneyiMtOB//zpXWCha1/SWHJOZstG7kA==", + "optional": true, + "requires": { + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/util-retry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.0.tgz", + "integrity": "sha512-/dvJ8afrElasuiiIttRJeoS2sy8YXpksQwiM/TcepqdRVp7u4ejd9C4IQURHNjlfPUT7Y6lCDSa2zQJbdHhVTg==", + "optional": true, + "requires": { + "@smithy/service-error-classification": "^2.0.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/util-stream": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.10.tgz", + "integrity": "sha512-2EgK5cBiv9OaDmhSXmsZY8ZByBl1dg/Tbc51iBJ5GkLGVYhaA6/1l6vHHV41m4Im3D0XfZV1tmeLlQgmRnYsTQ==", + "optional": true, + "requires": { + "@smithy/fetch-http-handler": "^2.1.3", + "@smithy/node-http-handler": "^2.1.3", + "@smithy/types": "^2.3.1", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/util-uri-escape": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.0.0.tgz", + "integrity": "sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==", + "optional": true, + "requires": { + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, + "@smithy/util-utf8": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.0.tgz", + "integrity": "sha512-rctU1VkziY84n5OXe3bPNpKR001ZCME2JCaBBFgtiM2hfKbHFudc/BkMuPab8hRbLd0j3vbnBTTZ1igBf0wgiQ==", + "optional": true, + "requires": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + }, + "dependencies": { + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "optional": true + } + } + }, "@tozd/vue-observer-utils": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/@tozd/vue-observer-utils/-/vue-observer-utils-0.5.0.tgz", "integrity": "sha512-HeRxWFJB7FXcQigH2LvauiR0l7hA4qqBC6hK9rBeKf076Ew08C4lx3eo7/YmvADt3b8ZP1j+TN0pGCEhKYOhEA==" }, + "@types/connect": { + "version": "3.4.36", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", + "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", + "requires": { + "@types/node": "*" + } + }, + "@types/jquery": { + "version": "3.5.18", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.18.tgz", + "integrity": "sha512-sNm7O6LECFhHmF+3KYo6QIl2fIbjlPYa0PDgDQwfOaEJzwpK20Eub9Ke7VKkGsSJ2K0HUR50S266qYzRX4GlSw==", + "requires": { + "@types/sizzle": "*" + } + }, "@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", "dev": true }, + "@types/meteor": { + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/@types/meteor/-/meteor-2.9.4.tgz", + "integrity": "sha512-hJd3hHs9OxK4LdJM483zHIw1ORE7V8iLLs4tmvSERRR2L4yUJaLu+xeBq/rZDEzRdpdxvc1f3ywYzcLsP1KFkg==", + "requires": { + "@types/connect": "*", + "@types/jquery": "*", + "@types/nodemailer": "*", + "@types/react": "*", + "@types/underscore": "*", + "mongodb": "^4.3.1" + } + }, "@types/mocha": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz", "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==", "dev": true }, + "@types/node": { + "version": "20.6.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.0.tgz", + "integrity": "sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg==" + }, + "@types/nodemailer": { + "version": "6.4.10", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.10.tgz", + "integrity": "sha512-oPW/IdhkU3FyZc1dzeqmS+MBjrjZNiiINnrEOrWALzccJlP5xTlbkNr2YnTnnyj9Eqm5ofjRoASEbrCYpA7BrA==", + "requires": { + "@types/node": "*" + } + }, + "@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + }, + "@types/react": { + "version": "18.2.21", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.21.tgz", + "integrity": "sha512-neFKG/sBAwGxHgXiIxnbm3/AAVQ/cMRS93hvBpg8xYRbeQSPVABp9U2bRnPf0iI4+Ucdv3plSxKK+3CW2ENJxA==", + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "@types/scheduler": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" + }, "@types/semver": { "version": "7.3.13", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", "dev": true }, + "@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==" + }, + "@types/underscore": { + "version": "1.11.9", + "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.9.tgz", + "integrity": "sha512-M63wKUdsjDFUfyFt1TCUZHGFk9KDAa5JP0adNUErbm0U45Lr06HtANdYRP+GyleEopEoZ4UyBcdAC5TnW4Uz2w==" + }, + "@types/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" + }, + "@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "requires": { + "@types/node": "*", + "@types/webidl-conversions": "*" + } + }, "@typescript-eslint/eslint-plugin": { "version": "5.59.2", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.2.tgz", @@ -241,9 +1749,9 @@ } }, "semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -338,9 +1846,9 @@ } }, "semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -365,9 +1873,9 @@ }, "dependencies": { "semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -690,6 +2198,12 @@ } } }, + "bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", + "optional": true + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -708,6 +2222,25 @@ "fill-range": "^7.0.1" } }, + "bson": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz", + "integrity": "sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ==", + "requires": { + "buffer": "^5.6.0" + }, + "dependencies": { + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + } + } + }, "buffer": { "version": "4.9.2", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", @@ -934,8 +2467,7 @@ "csstype": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", - "dev": true + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" }, "cytoscape": { "version": "3.25.0", @@ -1213,9 +2745,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -1394,6 +2926,15 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "fast-xml-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", + "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", + "optional": true, + "requires": { + "strnum": "^1.0.5" + } + }, "fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -1739,6 +3280,11 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, + "ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, "is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -1968,9 +3514,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, @@ -1979,6 +3525,12 @@ "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==" }, + "memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "optional": true + }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -2848,6 +4400,51 @@ "resolved": "https://registry.npmjs.org/mongo-object/-/mongo-object-0.1.4.tgz", "integrity": "sha512-QtYk0gupWEn2+iB+DDRt1L+WbcNYvJRaHdih/dcqthOa1DbnREUGSs2WGcW478GNYpElflo/yybZXu0sTiRXHg==" }, + "mongodb": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.17.1.tgz", + "integrity": "sha512-MBuyYiPUPRTqfH2dV0ya4dcr2E5N52ocBuZ8Sgg/M030nGF78v855B3Z27mZJnp8PxjnUquEnAtjOsphgMZOlQ==", + "requires": { + "@aws-sdk/credential-providers": "^3.186.0", + "@mongodb-js/saslprep": "^1.1.0", + "bson": "^4.7.2", + "mongodb-connection-string-url": "^2.6.0", + "socks": "^2.7.1" + } + }, + "mongodb-connection-string-url": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", + "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", + "requires": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + }, + "dependencies": { + "tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "requires": { + "punycode": "^2.1.1" + } + }, + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" + }, + "whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "requires": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + } + } + } + }, "moo": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", @@ -3368,9 +4965,9 @@ "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -3401,9 +4998,9 @@ }, "dependencies": { "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -3520,6 +5117,20 @@ } } }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" + }, + "socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "requires": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + } + }, "sortablejs": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.10.2.tgz", @@ -3545,6 +5156,15 @@ "source-map": "^0.6.0" } }, + "sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "optional": true, + "requires": { + "memory-pager": "^1.0.2" + } + }, "speakingurl": { "version": "14.0.1", "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", @@ -3618,6 +5238,12 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "optional": true + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -3767,8 +5393,7 @@ "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "tsutils": { "version": "3.21.0", @@ -3952,9 +5577,9 @@ } }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -4045,9 +5670,9 @@ } }, "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true }, "wrappy": { diff --git a/app/package.json b/app/package.json index db8214ba..4a97e9e8 100644 --- a/app/package.json +++ b/app/package.json @@ -23,6 +23,7 @@ "@babel/runtime": "^7.21.5", "@chenfengyuan/vue-countdown": "^1.1.5", "@tozd/vue-observer-utils": "^0.5.0", + "@types/meteor": "^2.9.4", "aws-sdk": "^2.1373.0", "bcrypt": "^5.1.0", "chroma-js": "^2.4.2", diff --git a/app/jsconfig.json b/app/tsconfig.json similarity index 75% rename from app/jsconfig.json rename to app/tsconfig.json index 82b81ff2..f2595a71 100644 --- a/app/jsconfig.json +++ b/app/tsconfig.json @@ -7,12 +7,17 @@ "strictNullChecks": true, "strictFunctionTypes": true, "baseUrl": ".", + "preserveSymlinks": true, "paths": { "/*": [ "./*" ], + "meteor/*": [ + "node_modules/@types/meteor/*", + ".meteor/local/types/packages.d.ts" + ], "meteor/aldeed:collection2": [ - "packages\\collection2\\collection2.js" + "packages/collection2/collection2.js" ] }, "checkJs": false,