From 17f8256eff196e5479b13334e79273cef4c6aaa3 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Thu, 31 Oct 2024 15:54:21 -0400 Subject: [PATCH 01/48] add setImmediate for inbound messages --- packages/ddp-server/livedata_server.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/ddp-server/livedata_server.js b/packages/ddp-server/livedata_server.js index cd7a24094c..0f21be2d18 100644 --- a/packages/ddp-server/livedata_server.js +++ b/packages/ddp-server/livedata_server.js @@ -80,6 +80,8 @@ Object.assign(DummyDocumentView.prototype, { var SessionDocumentView = function () { var self = this; self.existsIn = new Set(); // set of subscriptionHandle + + // Memory Growth self.dataByKey = new Map(); // key-> [ {subscriptionHandle, value} by precedence] }; @@ -185,6 +187,7 @@ Object.assign(SessionDocumentView.prototype, { var SessionCollectionView = function (collectionName, sessionCallbacks) { var self = this; self.collectionName = collectionName; + // Memory Growth self.documents = new Map(); self.callbacks = sessionCallbacks; }; @@ -636,7 +639,7 @@ Object.assign(Session.prototype, { if (!blocked) return; // idempotent blocked = false; - processNext(); + setImmediate(processNext); }; self.server.onMessageHook.each(function (callback) { From 91f9ed434641553192705ca51aac71f787dcb83d Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Thu, 31 Oct 2024 15:54:39 -0400 Subject: [PATCH 02/48] annotate memory growth point --- packages/mongo/oplog_observe_driver.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/mongo/oplog_observe_driver.js b/packages/mongo/oplog_observe_driver.js index c857a14f48..cb67ac7fc5 100644 --- a/packages/mongo/oplog_observe_driver.js +++ b/packages/mongo/oplog_observe_driver.js @@ -87,6 +87,7 @@ export const OplogObserveDriver = function (options) { self._comparator = null; self._sorter = null; self._unpublishedBuffer = null; + // Memory Growth self._published = new LocalCollection._IdMap; } From 8a71fd06b52e283e21edc1316be40069f06d82b0 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Mon, 4 Nov 2024 08:37:33 -0400 Subject: [PATCH 03/48] refactor to oplog_v2_converter to typescript --- packages/mongo/oplog_v2_converter.js | 127 ------------------ packages/mongo/oplog_v2_converter.ts | 184 +++++++++++++++++++++++++++ packages/mongo/package.js | 2 +- 3 files changed, 185 insertions(+), 128 deletions(-) delete mode 100644 packages/mongo/oplog_v2_converter.js create mode 100644 packages/mongo/oplog_v2_converter.ts diff --git a/packages/mongo/oplog_v2_converter.js b/packages/mongo/oplog_v2_converter.js deleted file mode 100644 index 6cb6b4c726..0000000000 --- a/packages/mongo/oplog_v2_converter.js +++ /dev/null @@ -1,127 +0,0 @@ -// Converter of the new MongoDB Oplog format (>=5.0) to the one that Meteor -// handles well, i.e., `$set` and `$unset`. The new format is completely new, -// and looks as follows: -// -// { $v: 2, diff: Diff } -// -// where `Diff` is a recursive structure: -// -// { -// // Nested updates (sometimes also represented with an s-field). -// // Example: `{ $set: { 'foo.bar': 1 } }`. -// i: { : , ... }, -// -// // Top-level updates. -// // Example: `{ $set: { foo: { bar: 1 } } }`. -// u: { : , ... }, -// -// // Unsets. -// // Example: `{ $unset: { foo: '' } }`. -// d: { : false, ... }, -// -// // Array operations. -// // Example: `{ $push: { foo: 'bar' } }`. -// s: { a: true, u: , ... }, -// ... -// -// // Nested operations (sometimes also represented in the `i` field). -// // Example: `{ $set: { 'foo.bar': 1 } }`. -// s: Diff, -// ... -// } -// -// (all fields are optional). - -function join(prefix, key) { - return prefix ? `${prefix}.${key}` : key; -} - -const arrayOperatorKeyRegex = /^(a|[su]\d+)$/; - -function isArrayOperatorKey(field) { - return arrayOperatorKeyRegex.test(field); -} - -function isArrayOperator(operator) { - return operator.a === true && Object.keys(operator).every(isArrayOperatorKey); -} - -function flattenObjectInto(target, source, prefix) { - if (Array.isArray(source) || typeof source !== 'object' || source === null || - source instanceof Mongo.ObjectID) { - target[prefix] = source; - } else { - const entries = Object.entries(source); - if (entries.length) { - entries.forEach(([key, value]) => { - flattenObjectInto(target, value, join(prefix, key)); - }); - } else { - target[prefix] = source; - } - } -} - -const logDebugMessages = !!process.env.OPLOG_CONVERTER_DEBUG; - -function convertOplogDiff(oplogEntry, diff, prefix) { - if (logDebugMessages) { - console.log(`convertOplogDiff(${JSON.stringify(oplogEntry)}, ${JSON.stringify(diff)}, ${JSON.stringify(prefix)})`); - } - - Object.entries(diff).forEach(([diffKey, value]) => { - if (diffKey === 'd') { - // Handle `$unset`s. - oplogEntry.$unset ??= {}; - Object.keys(value).forEach(key => { - oplogEntry.$unset[join(prefix, key)] = true; - }); - } else if (diffKey === 'i') { - // Handle (potentially) nested `$set`s. - oplogEntry.$set ??= {}; - flattenObjectInto(oplogEntry.$set, value, prefix); - } else if (diffKey === 'u') { - // Handle flat `$set`s. - oplogEntry.$set ??= {}; - Object.entries(value).forEach(([key, value]) => { - oplogEntry.$set[join(prefix, key)] = value; - }); - } else { - // Handle s-fields. - const key = diffKey.slice(1); - if (isArrayOperator(value)) { - // Array operator. - Object.entries(value).forEach(([position, value]) => { - if (position === 'a') { - return; - } - - const positionKey = join(join(prefix, key), position.slice(1)); - if (position[0] === 's') { - convertOplogDiff(oplogEntry, value, positionKey); - } else if (value === null) { - oplogEntry.$unset ??= {}; - oplogEntry.$unset[positionKey] = true; - } else { - oplogEntry.$set ??= {}; - oplogEntry.$set[positionKey] = value; - } - }); - } else if (key) { - // Nested object. - convertOplogDiff(oplogEntry, value, join(prefix, key)); - } - } - }); -} - -export function oplogV2V1Converter(oplogEntry) { - // Pass-through v1 and (probably) invalid entries. - if (oplogEntry.$v !== 2 || !oplogEntry.diff) { - return oplogEntry; - } - - const convertedOplogEntry = { $v: 2 }; - convertOplogDiff(convertedOplogEntry, oplogEntry.diff, ''); - return convertedOplogEntry; -} diff --git a/packages/mongo/oplog_v2_converter.ts b/packages/mongo/oplog_v2_converter.ts new file mode 100644 index 0000000000..a892633b79 --- /dev/null +++ b/packages/mongo/oplog_v2_converter.ts @@ -0,0 +1,184 @@ +/** + * Converter module for the new MongoDB Oplog format (>=5.0) to the one that Meteor + * handles well, i.e., `$set` and `$unset`. The new format is completely new, + * and looks as follows: + * + * ```js + * { $v: 2, diff: Diff } + * ``` + * + * where `Diff` is a recursive structure: + * ```js + * { + * // Nested updates (sometimes also represented with an s-field). + * // Example: `{ $set: { 'foo.bar': 1 } }`. + * i: { : , ... }, + * + * // Top-level updates. + * // Example: `{ $set: { foo: { bar: 1 } } }`. + * u: { : , ... }, + * + * // Unsets. + * // Example: `{ $unset: { foo: '' } }`. + * d: { : false, ... }, + * + * // Array operations. + * // Example: `{ $push: { foo: 'bar' } }`. + * s: { a: true, u: , ... }, + * ... + * + * // Nested operations (sometimes also represented in the `i` field). + * // Example: `{ $set: { 'foo.bar': 1 } }`. + * s: Diff, + * ... + * } + * ``` + * + * (all fields are optional) + */ + +interface OplogEntry { + $v: number; + diff?: OplogDiff; + $set?: Record; + $unset?: Record; +} + +interface OplogDiff { + i?: Record; + u?: Record; + d?: Record; + [key: `s${string}`]: ArrayOperator | Record; +} + +interface ArrayOperator { + a: true; + [key: `u${number}`]: any; +} + +const arrayOperatorKeyRegex = /^(a|[su]\d+)$/; + +/** + * Checks if a field is an array operator key of form 'a' or 's1' or 'u1' etc + */ +function isArrayOperatorKey(field: string): boolean { + return arrayOperatorKeyRegex.test(field); +} + +/** + * Type guard to check if an operator is a valid array operator. + * Array operators have 'a: true' and keys that match the arrayOperatorKeyRegex + */ +function isArrayOperator(operator: unknown): operator is ArrayOperator { + return ( + operator !== null && + typeof operator === 'object' && + 'a' in operator && + (operator as ArrayOperator).a === true && + Object.keys(operator).every(isArrayOperatorKey) + ); +} + +/** + * Recursively flattens an object into a target object with dot notation paths. + * Handles arrays, plain objects, nulls and Mongo.ObjectIDs differently: + * - Arrays, nulls, and ObjectIDs are assigned directly + * - Objects are recursively flattened with dot notation + * - Empty objects are assigned directly + */ +function flattenObjectInto( + target: Record, + source: any, + prefix: string +): void { + if ( + Array.isArray(source) || + typeof source !== 'object' || + source === null || + source instanceof Mongo.ObjectID + ) { + target[prefix] = source; + return; + } + + const entries = Object.entries(source); + if (entries.length) { + entries.forEach(([key, value]) => { + flattenObjectInto(target, value, prefix ? `${prefix}.${key}` : key); + }); + } else { + target[prefix] = source; + } +} + +/** + * Converts an oplog diff to a series of $set and $unset operations. + * Handles: + * - Direct unsets via 'd' field + * - Nested sets via 'i' field + * - Top-level sets via 'u' field + * - Array operations and nested objects via 's' prefixed fields + */ +function convertOplogDiff( + oplogEntry: OplogEntry, + diff: OplogDiff, + prefix = '' +): void { + Object.entries(diff).forEach(([diffKey, value]) => { + if (diffKey === 'd') { + // Handle `$unset`s + oplogEntry.$unset ??= {}; + Object.keys(value).forEach(key => { + oplogEntry.$unset![`${prefix}${key}`] = true; + }); + } else if (diffKey === 'i') { + // Handle (potentially) nested `$set`s + oplogEntry.$set ??= {}; + flattenObjectInto(oplogEntry.$set, value, prefix); + } else if (diffKey === 'u') { + // Handle flat `$set`s + oplogEntry.$set ??= {}; + Object.entries(value).forEach(([key, fieldValue]) => { + oplogEntry.$set![`${prefix}${key}`] = fieldValue; + }); + } else if (diffKey.startsWith('s')) { + // Handle s-fields (array operations and nested objects) + const key = diffKey.slice(1); + if (isArrayOperator(value)) { + // Array operator + Object.entries(value).forEach(([position, fieldValue]) => { + if (position === 'a') return; + + const positionKey = `${prefix}${key}.${position.slice(1)}`; + if (position[0] === 's') { + convertOplogDiff(oplogEntry, fieldValue, positionKey); + } else if (fieldValue === null) { + oplogEntry.$unset ??= {}; + oplogEntry.$unset[positionKey] = true; + } else { + oplogEntry.$set ??= {}; + oplogEntry.$set[positionKey] = fieldValue; + } + }); + } else if (key) { + // Nested object + convertOplogDiff(oplogEntry, value, prefix ? `${prefix}.${key}` : key); + } + } + }); +} + +/** + * Converts a MongoDB v2 oplog entry to v1 format. + * Returns the original entry unchanged if it's not a v2 oplog entry + * or doesn't contain a diff field. + */ +export function oplogV2V1Converter(oplogEntry: OplogEntry): OplogEntry { + if (oplogEntry.$v !== 2 || !oplogEntry.diff) { + return oplogEntry; + } + + const convertedOplogEntry: OplogEntry = { $v: 2 }; + convertOplogDiff(convertedOplogEntry, oplogEntry.diff); + return convertedOplogEntry; +} \ No newline at end of file diff --git a/packages/mongo/package.js b/packages/mongo/package.js index 1356ad0756..8f3bb65cb9 100644 --- a/packages/mongo/package.js +++ b/packages/mongo/package.js @@ -90,7 +90,7 @@ Package.onUse(function (api) { "doc_fetcher.js", "polling_observe_driver.ts", "oplog_observe_driver.js", - "oplog_v2_converter.js", + "oplog_v2_converter.ts", "cursor_description.ts", "mongo_connection.js", "mongo_common.js", From b84afd9a528d92960056ff915fa395f65431e3d5 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Mon, 4 Nov 2024 10:58:57 -0400 Subject: [PATCH 04/48] fix tests --- packages/mongo/oplog_v2_converter.ts | 91 ++++------------------------ 1 file changed, 13 insertions(+), 78 deletions(-) diff --git a/packages/mongo/oplog_v2_converter.ts b/packages/mongo/oplog_v2_converter.ts index a892633b79..df320873f9 100644 --- a/packages/mongo/oplog_v2_converter.ts +++ b/packages/mongo/oplog_v2_converter.ts @@ -1,47 +1,10 @@ -/** - * Converter module for the new MongoDB Oplog format (>=5.0) to the one that Meteor - * handles well, i.e., `$set` and `$unset`. The new format is completely new, - * and looks as follows: - * - * ```js - * { $v: 2, diff: Diff } - * ``` - * - * where `Diff` is a recursive structure: - * ```js - * { - * // Nested updates (sometimes also represented with an s-field). - * // Example: `{ $set: { 'foo.bar': 1 } }`. - * i: { : , ... }, - * - * // Top-level updates. - * // Example: `{ $set: { foo: { bar: 1 } } }`. - * u: { : , ... }, - * - * // Unsets. - * // Example: `{ $unset: { foo: '' } }`. - * d: { : false, ... }, - * - * // Array operations. - * // Example: `{ $push: { foo: 'bar' } }`. - * s: { a: true, u: , ... }, - * ... - * - * // Nested operations (sometimes also represented in the `i` field). - * // Example: `{ $set: { 'foo.bar': 1 } }`. - * s: Diff, - * ... - * } - * ``` - * - * (all fields are optional) - */ +import { EJSON } from 'meteor/ejson'; interface OplogEntry { $v: number; diff?: OplogDiff; $set?: Record; - $unset?: Record; + $unset?: Record; } interface OplogDiff { @@ -58,17 +21,10 @@ interface ArrayOperator { const arrayOperatorKeyRegex = /^(a|[su]\d+)$/; -/** - * Checks if a field is an array operator key of form 'a' or 's1' or 'u1' etc - */ function isArrayOperatorKey(field: string): boolean { return arrayOperatorKeyRegex.test(field); } -/** - * Type guard to check if an operator is a valid array operator. - * Array operators have 'a: true' and keys that match the arrayOperatorKeyRegex - */ function isArrayOperator(operator: unknown): operator is ArrayOperator { return ( operator !== null && @@ -79,13 +35,10 @@ function isArrayOperator(operator: unknown): operator is ArrayOperator { ); } -/** - * Recursively flattens an object into a target object with dot notation paths. - * Handles arrays, plain objects, nulls and Mongo.ObjectIDs differently: - * - Arrays, nulls, and ObjectIDs are assigned directly - * - Objects are recursively flattened with dot notation - * - Empty objects are assigned directly - */ +function join(prefix: string, key: string): string { + return prefix ? `${prefix}.${key}` : key; +} + function flattenObjectInto( target: Record, source: any, @@ -95,7 +48,8 @@ function flattenObjectInto( Array.isArray(source) || typeof source !== 'object' || source === null || - source instanceof Mongo.ObjectID + source instanceof Mongo.ObjectID || + EJSON._isCustomType(source) ) { target[prefix] = source; return; @@ -104,21 +58,13 @@ function flattenObjectInto( const entries = Object.entries(source); if (entries.length) { entries.forEach(([key, value]) => { - flattenObjectInto(target, value, prefix ? `${prefix}.${key}` : key); + flattenObjectInto(target, value, join(prefix, key)); }); } else { target[prefix] = source; } } -/** - * Converts an oplog diff to a series of $set and $unset operations. - * Handles: - * - Direct unsets via 'd' field - * - Nested sets via 'i' field - * - Top-level sets via 'u' field - * - Array operations and nested objects via 's' prefixed fields - */ function convertOplogDiff( oplogEntry: OplogEntry, diff: OplogDiff, @@ -126,30 +72,25 @@ function convertOplogDiff( ): void { Object.entries(diff).forEach(([diffKey, value]) => { if (diffKey === 'd') { - // Handle `$unset`s oplogEntry.$unset ??= {}; Object.keys(value).forEach(key => { - oplogEntry.$unset![`${prefix}${key}`] = true; + oplogEntry.$unset![join(prefix, key)] = true; }); } else if (diffKey === 'i') { - // Handle (potentially) nested `$set`s oplogEntry.$set ??= {}; flattenObjectInto(oplogEntry.$set, value, prefix); } else if (diffKey === 'u') { - // Handle flat `$set`s oplogEntry.$set ??= {}; Object.entries(value).forEach(([key, fieldValue]) => { - oplogEntry.$set![`${prefix}${key}`] = fieldValue; + oplogEntry.$set![join(prefix, key)] = fieldValue; }); } else if (diffKey.startsWith('s')) { - // Handle s-fields (array operations and nested objects) const key = diffKey.slice(1); if (isArrayOperator(value)) { - // Array operator Object.entries(value).forEach(([position, fieldValue]) => { if (position === 'a') return; - const positionKey = `${prefix}${key}.${position.slice(1)}`; + const positionKey = join(prefix, `${key}.${position.slice(1)}`); if (position[0] === 's') { convertOplogDiff(oplogEntry, fieldValue, positionKey); } else if (fieldValue === null) { @@ -161,18 +102,12 @@ function convertOplogDiff( } }); } else if (key) { - // Nested object - convertOplogDiff(oplogEntry, value, prefix ? `${prefix}.${key}` : key); + convertOplogDiff(oplogEntry, value, join(prefix, key)); } } }); } -/** - * Converts a MongoDB v2 oplog entry to v1 format. - * Returns the original entry unchanged if it's not a v2 oplog entry - * or doesn't contain a diff field. - */ export function oplogV2V1Converter(oplogEntry: OplogEntry): OplogEntry { if (oplogEntry.$v !== 2 || !oplogEntry.diff) { return oplogEntry; From 2acc66f1a382e247193664f25c5f15a159a1a616 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Mon, 4 Nov 2024 14:01:44 -0400 Subject: [PATCH 05/48] add docs back --- packages/mongo/oplog_v2_converter.ts | 85 ++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/packages/mongo/oplog_v2_converter.ts b/packages/mongo/oplog_v2_converter.ts index df320873f9..708f2d00c8 100644 --- a/packages/mongo/oplog_v2_converter.ts +++ b/packages/mongo/oplog_v2_converter.ts @@ -1,3 +1,42 @@ +/** + * Converter module for the new MongoDB Oplog format (>=5.0) to the one that Meteor + * handles well, i.e., `$set` and `$unset`. The new format is completely new, + * and looks as follows: + * + * ```js + * { $v: 2, diff: Diff } + * ``` + * + * where `Diff` is a recursive structure: + * ```js + * { + * // Nested updates (sometimes also represented with an s-field). + * // Example: `{ $set: { 'foo.bar': 1 } }`. + * i: { : , ... }, + * + * // Top-level updates. + * // Example: `{ $set: { foo: { bar: 1 } } }`. + * u: { : , ... }, + * + * // Unsets. + * // Example: `{ $unset: { foo: '' } }`. + * d: { : false, ... }, + * + * // Array operations. + * // Example: `{ $push: { foo: 'bar' } }`. + * s: { a: true, u: , ... }, + * ... + * + * // Nested operations (sometimes also represented in the `i` field). + * // Example: `{ $set: { 'foo.bar': 1 } }`. + * s: Diff, + * ... + * } + * ``` + * + * (all fields are optional) + */ + import { EJSON } from 'meteor/ejson'; interface OplogEntry { @@ -21,10 +60,17 @@ interface ArrayOperator { const arrayOperatorKeyRegex = /^(a|[su]\d+)$/; +/** + * Checks if a field is an array operator key of form 'a' or 's1' or 'u1' etc + */ function isArrayOperatorKey(field: string): boolean { return arrayOperatorKeyRegex.test(field); } +/** + * Type guard to check if an operator is a valid array operator. + * Array operators have 'a: true' and keys that match the arrayOperatorKeyRegex + */ function isArrayOperator(operator: unknown): operator is ArrayOperator { return ( operator !== null && @@ -35,10 +81,23 @@ function isArrayOperator(operator: unknown): operator is ArrayOperator { ); } +/** + * Joins two parts of a field path with a dot. + * Returns the key itself if prefix is empty. + */ function join(prefix: string, key: string): string { return prefix ? `${prefix}.${key}` : key; } +/** + * Recursively flattens an object into a target object with dot notation paths. + * Handles special cases: + * - Arrays are assigned directly + * - Custom EJSON types are preserved + * - Mongo.ObjectIDs are preserved + * - Plain objects are recursively flattened + * - Empty objects are assigned directly + */ function flattenObjectInto( target: Record, source: any, @@ -65,6 +124,17 @@ function flattenObjectInto( } } +/** + * Converts an oplog diff to a series of $set and $unset operations. + * Handles several types of operations: + * - Direct unsets via 'd' field + * - Nested sets via 'i' field + * - Top-level sets via 'u' field + * - Array operations and nested objects via 's' prefixed fields + * + * Preserves the structure of EJSON custom types and ObjectIDs while + * flattening paths into dot notation for MongoDB updates. + */ function convertOplogDiff( oplogEntry: OplogEntry, diff: OplogDiff, @@ -72,21 +142,26 @@ function convertOplogDiff( ): void { Object.entries(diff).forEach(([diffKey, value]) => { if (diffKey === 'd') { + // Handle `$unset`s oplogEntry.$unset ??= {}; Object.keys(value).forEach(key => { oplogEntry.$unset![join(prefix, key)] = true; }); } else if (diffKey === 'i') { + // Handle (potentially) nested `$set`s oplogEntry.$set ??= {}; flattenObjectInto(oplogEntry.$set, value, prefix); } else if (diffKey === 'u') { + // Handle flat `$set`s oplogEntry.$set ??= {}; Object.entries(value).forEach(([key, fieldValue]) => { oplogEntry.$set![join(prefix, key)] = fieldValue; }); } else if (diffKey.startsWith('s')) { + // Handle s-fields (array operations and nested objects) const key = diffKey.slice(1); if (isArrayOperator(value)) { + // Array operator Object.entries(value).forEach(([position, fieldValue]) => { if (position === 'a') return; @@ -102,12 +177,22 @@ function convertOplogDiff( } }); } else if (key) { + // Nested object convertOplogDiff(oplogEntry, value, join(prefix, key)); } } }); } +/** + * Converts a MongoDB v2 oplog entry to v1 format. + * Returns the original entry unchanged if it's not a v2 oplog entry + * or doesn't contain a diff field. + * + * The converted entry will contain $set and $unset operations that are + * equivalent to the v2 diff format, with paths flattened to dot notation + * and special handling for EJSON custom types and ObjectIDs. + */ export function oplogV2V1Converter(oplogEntry: OplogEntry): OplogEntry { if (oplogEntry.$v !== 2 || !oplogEntry.diff) { return oplogEntry; From 75966aed5d5d4aceb40b958383adf54929f61fbd Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Mon, 4 Nov 2024 14:01:52 -0400 Subject: [PATCH 06/48] shrinkwrap --- packages/modules/.npm/package/npm-shrinkwrap.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/modules/.npm/package/npm-shrinkwrap.json b/packages/modules/.npm/package/npm-shrinkwrap.json index 7c1a6396d6..bd86daae17 100644 --- a/packages/modules/.npm/package/npm-shrinkwrap.json +++ b/packages/modules/.npm/package/npm-shrinkwrap.json @@ -12,9 +12,9 @@ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" }, "acorn": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", - "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==" + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==" }, "estree-walker": { "version": "2.0.2", From c56361f112585a1700d2016398a2fb74958a9b90 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Mon, 4 Nov 2024 16:43:37 -0400 Subject: [PATCH 07/48] refactor session and document views --- .../.npm/package/npm-shrinkwrap.json | 5 + packages/ddp-server/livedata_server.js | 213 +----------------- packages/ddp-server/package.js | 4 +- .../ddp-server/session_collection_view.ts | 200 ++++++++++++++++ packages/ddp-server/session_document_view.ts | 103 +++++++++ 5 files changed, 313 insertions(+), 212 deletions(-) create mode 100644 packages/ddp-server/session_collection_view.ts create mode 100644 packages/ddp-server/session_document_view.ts diff --git a/packages/ddp-server/.npm/package/npm-shrinkwrap.json b/packages/ddp-server/.npm/package/npm-shrinkwrap.json index f7fd53b35e..542ff6f6fe 100644 --- a/packages/ddp-server/.npm/package/npm-shrinkwrap.json +++ b/packages/ddp-server/.npm/package/npm-shrinkwrap.json @@ -31,6 +31,11 @@ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" }, + "lru_map": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.4.1.tgz", + "integrity": "sha512-I+lBvqMMFfqaV8CJCISjI3wbjmwVu/VyOoU7+qtu9d7ioW5klMgsTTiUOUp+DJvfTTzKXoPbyC6YfgkNcyPSOg==" + }, "permessage-deflate": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/permessage-deflate/-/permessage-deflate-0.1.7.tgz", diff --git a/packages/ddp-server/livedata_server.js b/packages/ddp-server/livedata_server.js index 0f21be2d18..75406778b8 100644 --- a/packages/ddp-server/livedata_server.js +++ b/packages/ddp-server/livedata_server.js @@ -1,6 +1,8 @@ import isEmpty from 'lodash.isempty'; import isString from 'lodash.isstring'; import isObject from 'lodash.isobject'; +import { SessionCollectionView } from './session_collection_view'; +import { SessionDocumentView } from './session_document_view'; DDPServer = {}; @@ -76,15 +78,6 @@ Object.assign(DummyDocumentView.prototype, { } }); -// Represents a single document in a SessionCollectionView -var SessionDocumentView = function () { - var self = this; - self.existsIn = new Set(); // set of subscriptionHandle - - // Memory Growth - self.dataByKey = new Map(); // key-> [ {subscriptionHandle, value} by precedence] -}; - DDPServer._SessionDocumentView = SessionDocumentView; DDPServer._getCurrentFence = function () { @@ -96,211 +89,9 @@ DDPServer._getCurrentFence = function () { return currentInvocation ? currentInvocation.fence : undefined; }; -Object.assign(SessionDocumentView.prototype, { - - getFields: function () { - var self = this; - var ret = {}; - self.dataByKey.forEach(function (precedenceList, key) { - ret[key] = precedenceList[0].value; - }); - return ret; - }, - - clearField: function (subscriptionHandle, key, changeCollector) { - var self = this; - // Publish API ignores _id if present in fields - if (key === "_id") - return; - var precedenceList = self.dataByKey.get(key); - - // It's okay to clear fields that didn't exist. No need to throw - // an error. - if (!precedenceList) - return; - - var removedValue = undefined; - for (var i = 0; i < precedenceList.length; i++) { - var precedence = precedenceList[i]; - if (precedence.subscriptionHandle === subscriptionHandle) { - // The view's value can only change if this subscription is the one that - // used to have precedence. - if (i === 0) - removedValue = precedence.value; - precedenceList.splice(i, 1); - break; - } - } - if (precedenceList.length === 0) { - self.dataByKey.delete(key); - changeCollector[key] = undefined; - } else if (removedValue !== undefined && - !EJSON.equals(removedValue, precedenceList[0].value)) { - changeCollector[key] = precedenceList[0].value; - } - }, - - changeField: function (subscriptionHandle, key, value, - changeCollector, isAdd) { - var self = this; - // Publish API ignores _id if present in fields - if (key === "_id") - return; - - // Don't share state with the data passed in by the user. - value = EJSON.clone(value); - - if (!self.dataByKey.has(key)) { - self.dataByKey.set(key, [{subscriptionHandle: subscriptionHandle, - value: value}]); - changeCollector[key] = value; - return; - } - var precedenceList = self.dataByKey.get(key); - var elt; - if (!isAdd) { - elt = precedenceList.find(function (precedence) { - return precedence.subscriptionHandle === subscriptionHandle; - }); - } - - if (elt) { - if (elt === precedenceList[0] && !EJSON.equals(value, elt.value)) { - // this subscription is changing the value of this field. - changeCollector[key] = value; - } - elt.value = value; - } else { - // this subscription is newly caring about this field - precedenceList.push({subscriptionHandle: subscriptionHandle, value: value}); - } - - } -}); - -/** - * Represents a client's view of a single collection - * @param {String} collectionName Name of the collection it represents - * @param {Object.} sessionCallbacks The callbacks for added, changed, removed - * @class SessionCollectionView - */ -var SessionCollectionView = function (collectionName, sessionCallbacks) { - var self = this; - self.collectionName = collectionName; - // Memory Growth - self.documents = new Map(); - self.callbacks = sessionCallbacks; -}; DDPServer._SessionCollectionView = SessionCollectionView; - -Object.assign(SessionCollectionView.prototype, { - - isEmpty: function () { - var self = this; - return self.documents.size === 0; - }, - - diff: function (previous) { - var self = this; - DiffSequence.diffMaps(previous.documents, self.documents, { - both: self.diffDocument.bind(self), - - rightOnly: function (id, nowDV) { - self.callbacks.added(self.collectionName, id, nowDV.getFields()); - }, - - leftOnly: function (id, prevDV) { - self.callbacks.removed(self.collectionName, id); - } - }); - }, - - diffDocument: function (id, prevDV, nowDV) { - var self = this; - var fields = {}; - DiffSequence.diffObjects(prevDV.getFields(), nowDV.getFields(), { - both: function (key, prev, now) { - if (!EJSON.equals(prev, now)) - fields[key] = now; - }, - rightOnly: function (key, now) { - fields[key] = now; - }, - leftOnly: function(key, prev) { - fields[key] = undefined; - } - }); - self.callbacks.changed(self.collectionName, id, fields); - }, - - added: function (subscriptionHandle, id, fields) { - var self = this; - var docView = self.documents.get(id); - var added = false; - if (!docView) { - added = true; - if (Meteor.server.getPublicationStrategy(this.collectionName).useDummyDocumentView) { - docView = new DummyDocumentView(); - } else { - docView = new SessionDocumentView(); - } - - self.documents.set(id, docView); - } - docView.existsIn.add(subscriptionHandle); - var changeCollector = {}; - Object.entries(fields).forEach(function ([key, value]) { - docView.changeField( - subscriptionHandle, key, value, changeCollector, true); - }); - if (added) - self.callbacks.added(self.collectionName, id, changeCollector); - else - self.callbacks.changed(self.collectionName, id, changeCollector); - }, - - changed: function (subscriptionHandle, id, changed) { - var self = this; - var changedResult = {}; - var docView = self.documents.get(id); - if (!docView) - throw new Error("Could not find element with id " + id + " to change"); - Object.entries(changed).forEach(function ([key, value]) { - if (value === undefined) - docView.clearField(subscriptionHandle, key, changedResult); - else - docView.changeField(subscriptionHandle, key, value, changedResult); - }); - self.callbacks.changed(self.collectionName, id, changedResult); - }, - - removed: function (subscriptionHandle, id) { - var self = this; - var docView = self.documents.get(id); - if (!docView) { - var err = new Error("Removed nonexistent document " + id); - throw err; - } - docView.existsIn.delete(subscriptionHandle); - if (docView.existsIn.size === 0) { - // it is gone from everyone - self.callbacks.removed(self.collectionName, id); - self.documents.delete(id); - } else { - var changed = {}; - // remove this subscription from every precedence list - // and record the changes - docView.dataByKey.forEach(function (precedenceList, key) { - docView.clearField(subscriptionHandle, key, changed); - }); - - self.callbacks.changed(self.collectionName, id, changed); - } - } -}); - /******************************************************************************/ /* Session */ /******************************************************************************/ diff --git a/packages/ddp-server/package.js b/packages/ddp-server/package.js index c8e42343a8..8ca3864c42 100644 --- a/packages/ddp-server/package.js +++ b/packages/ddp-server/package.js @@ -10,7 +10,8 @@ Npm.depends({ "lodash.once": "4.1.1", "lodash.isempty": "4.4.0", "lodash.isstring": "4.0.1", - "lodash.isobject": "3.0.2" + "lodash.isobject": "3.0.2", + "lru_map": '0.4.1' }); Package.onUse(function (api) { @@ -23,6 +24,7 @@ Package.onUse(function (api) { "mongo-id", "diff-sequence", "ecmascript", + "typescript", ], "server" ); diff --git a/packages/ddp-server/session_collection_view.ts b/packages/ddp-server/session_collection_view.ts new file mode 100644 index 0000000000..add76cda85 --- /dev/null +++ b/packages/ddp-server/session_collection_view.ts @@ -0,0 +1,200 @@ +import { SessionDocumentView } from './session_document_view'; +import { LRUMap } from 'lru_map' +import isEmpty from 'lodash.isempty'; + +/** + * Represents a client's view of documents within a single collection + * @class SessionCollectionView + */ +export class SessionCollectionView { + private readonly collectionName: string; + private readonly callbacks: SessionCallbacks; + private readonly documents: LRUMap; + private readonly options: ViewOptions; + + /** + * @param collectionName - Name of the collection this view represents + * @param callbacks - Callbacks for document changes (added/changed/removed) + * @param options - Configuration options for the view + */ + constructor( + collectionName: string, + callbacks: SessionCallbacks, + options: ViewOptions = {} + ) { + this.collectionName = collectionName; + this.callbacks = callbacks; + this.options = { + maxDocuments: options.maxDocuments || 10000, + documentTTL: options.documentTTL || 3600000, // 1 hour in ms + cleanupInterval: options.cleanupInterval || 300000 // 5 minutes in ms + }; + + // Use LRU cache with max size limit + this.documents = new LRUMap(this.options.maxDocuments); + + // Start periodic cleanup + this.startCleanup(); + } + + /** + * Periodically removes stale documents and frees memory + * @private + */ + private startCleanup(): void { + const cleanup = (): void => { + const now = Date.now(); + this.documents.forEach((doc, id) => { + if (now - doc.lastAccessed > this.options.documentTTL) { + this.documents.delete(id); + } + }); + }; + + if (typeof setInterval !== 'undefined') { + setInterval(cleanup, this.options.cleanupInterval); + } + } + + /** + * Checks if the view is empty + */ + public isEmpty(): boolean { + return this.documents.size === 0; + } + + /** + * Adds or updates a document in the view + */ + public added(subscriptionHandle: string, id: string, fields: Record): void { + let docView = this.documents.get(id); + const added = !docView; + + if (!docView) { + docView = new SessionDocumentView(); + this.documents.set(id, docView); + } + + docView.existsIn.add(subscriptionHandle); + const changeCollector: Record = {}; + + Object.entries(fields).forEach(([key, value]) => { + docView.changeField(subscriptionHandle, key, value, changeCollector, true); + }); + + if (added) { + this.callbacks.added(this.collectionName, id, changeCollector); + } else { + this.callbacks.changed(this.collectionName, id, changeCollector); + } + } + + /** + * Updates an existing document in the view + */ + public changed(subscriptionHandle: string, id: string, changed: Record): void { + const docView = this.documents.get(id); + if (!docView) { + throw new Error(`Changed called on document ${id} that does not exist`); + } + + const changedResult: Record = {}; + Object.entries(changed).forEach(([key, value]) => { + if (value === undefined) { + docView.clearField(subscriptionHandle, key, changedResult); + } else { + docView.changeField(subscriptionHandle, key, value, changedResult); + } + }); + + if (!isEmpty(changedResult)) { + this.callbacks.changed(this.collectionName, id, changedResult); + } + } + + /** + * Removes a document from the view + */ + public removed(subscriptionHandle: string, id: string): void { + const docView = this.documents.get(id); + if (!docView) { + throw new Error(`Removed called on document ${id} that does not exist`); + } + + docView.existsIn.delete(subscriptionHandle); + + if (docView.existsIn.size === 0) { + this.documents.delete(id); + this.callbacks.removed(this.collectionName, id); + } else { + const changed: Record = {}; + docView.dataByKey.forEach((precedenceList, key) => { + docView.clearField(subscriptionHandle, key, changed); + }); + + if (!isEmpty(changed)) { + this.callbacks.changed(this.collectionName, id, changed); + } + } + } + + /** + * Compares this view with another and sends appropriate callbacks + */ + public diff(previous: SessionCollectionView): void { + DiffSequence.diffMaps(previous.documents, this.documents, { + both: (id, prevDocView, newDocView) => { + this.diffDocument(id, prevDocView, newDocView); + }, + rightOnly: (id, newDocView) => { + this.callbacks.added(this.collectionName, id, newDocView.getFields()); + }, + leftOnly: (id) => { + this.callbacks.removed(this.collectionName, id); + } + }); + } + + /** + * Cleans up resources used by this view + */ + public destroy(): void { + this.documents.clear(); + } + + /** + * @private + */ + private diffDocument(id: string, prevDocView: SessionDocumentView, newDocView: SessionDocumentView): void { + const fields: Record = {}; + DiffSequence.diffObjects(prevDocView.getFields(), newDocView.getFields(), { + both: (key, prev, now) => { + if (!EJSON.equals(prev, now)) { + fields[key] = now; + } + }, + rightOnly: (key, now) => { + fields[key] = now; + }, + leftOnly: (key) => { + fields[key] = undefined; + } + }); + + if (!isEmpty(fields)) { + this.callbacks.changed(this.collectionName, id, fields); + } + } +} + +interface ViewOptions { + maxDocuments?: number; + documentTTL?: number; + cleanupInterval?: number; +} + +interface SessionCallbacks { + added: (collection: string, id: string, fields: Record) => void; + changed: (collection: string, id: string, fields: Record) => void; + removed: (collection: string, id: string) => void; +} \ No newline at end of file diff --git a/packages/ddp-server/session_document_view.ts b/packages/ddp-server/session_document_view.ts new file mode 100644 index 0000000000..b4cd3801b7 --- /dev/null +++ b/packages/ddp-server/session_document_view.ts @@ -0,0 +1,103 @@ +/** + * Represents a single document in a SessionCollectionView + * @class SessionDocumentView + */ +export class SessionDocumentView { + public existsIn: Set; + public dataByKey: Map>; + public lastAccessed: number; + + constructor() { + this.existsIn = new Set(); + this.dataByKey = new Map(); + this.lastAccessed = Date.now(); + } + + /** + * Gets the current fields of the document + */ + public getFields(): Record { + this.lastAccessed = Date.now(); + const fields: Record = {}; + + this.dataByKey.forEach((precedenceList, key) => { + if (precedenceList.length > 0) { + fields[key] = precedenceList[0].value; + } + }); + + return fields; + } + + /** + * Clears a field from the document + */ + public clearField(subscriptionHandle: string, key: string, changeCollector: Record): void { + if (key === '_id') return; + + const precedenceList = this.dataByKey.get(key); + if (!precedenceList) return; + + let removedValue: any; + for (let i = 0; i < precedenceList.length; i++) { + if (precedenceList[i].subscriptionHandle === subscriptionHandle) { + if (i === 0) { + removedValue = precedenceList[i].value; + } + precedenceList.splice(i, 1); + break; + } + } + + if (precedenceList.length === 0) { + this.dataByKey.delete(key); + changeCollector[key] = undefined; + } else if (removedValue !== undefined && + !EJSON.equals(removedValue, precedenceList[0].value)) { + changeCollector[key] = precedenceList[0].value; + } + } + + /** + * Changes a field value in the document + */ + public changeField( + subscriptionHandle: string, + key: string, + value: any, + changeCollector: Record, + isAdd: boolean = false + ): void { + if (key === '_id') return; + + value = EJSON.clone(value); + + if (!this.dataByKey.has(key)) { + this.dataByKey.set(key, [{ + subscriptionHandle, + value + }]); + changeCollector[key] = value; + return; + } + + const precedenceList = this.dataByKey.get(key)!; + let item = !isAdd && precedenceList.find( + p => p.subscriptionHandle === subscriptionHandle + ); + + if (item) { + if (item === precedenceList[0] && !EJSON.equals(value, item.value)) { + changeCollector[key] = value; + } + item.value = value; + } else { + precedenceList.push({ subscriptionHandle, value }); + } + } +} + +interface PrecedenceItem { + subscriptionHandle: string; + value: any; +} \ No newline at end of file From a9f2656e22ca36f293c6d0b74867ddffb3faa306 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Mon, 4 Nov 2024 18:14:29 -0400 Subject: [PATCH 08/48] fix race condition in oplog tailing --- packages/mongo/oplog_tailing.ts | 156 ++++++++++++++++---------------- 1 file changed, 79 insertions(+), 77 deletions(-) diff --git a/packages/mongo/oplog_tailing.ts b/packages/mongo/oplog_tailing.ts index 440339fa6f..d56bf8e8eb 100644 --- a/packages/mongo/oplog_tailing.ts +++ b/packages/mongo/oplog_tailing.ts @@ -11,7 +11,7 @@ export const OPLOG_COLLECTION = 'oplog.rs'; let TOO_FAR_BEHIND = +(process.env.METEOR_OPLOG_TOO_FAR_BEHIND || 2000); const TAIL_TIMEOUT = +(process.env.METEOR_OPLOG_TAIL_TIMEOUT || 30000); -interface OplogEntry { +export interface OplogEntry { op: string; o: any; o2?: any; @@ -19,12 +19,12 @@ interface OplogEntry { ns: string; } -interface CatchingUpResolver { +export interface CatchingUpResolver { ts: any; resolver: () => void; } -interface OplogTrigger { +export interface OplogTrigger { dropCollection: boolean; dropDatabase: boolean; op: OplogEntry; @@ -34,7 +34,7 @@ interface OplogTrigger { export class OplogHandle { private _oplogUrl: string; - private _dbName: string; + public _dbName: string; private _oplogLastEntryConnection: MongoConnection | null; private _oplogTailConnection: MongoConnection | null; private _oplogOptions: { excludeCollections?: string[]; includeCollections?: string[] } | null; @@ -42,16 +42,18 @@ export class OplogHandle { private _tailHandle: any; private _readyPromiseResolver: (() => void) | null; private _readyPromise: Promise; - private _crossbar: any; + public _crossbar: any; private _baseOplogSelector: any; private _catchingUpResolvers: CatchingUpResolver[]; private _lastProcessedTS: any; private _onSkippedEntriesHook: any; - private _entryQueue: any; - private _workerActive: boolean; private _startTrailingPromise: Promise; private _resolveTimeout: any; + private _entryQueue = new Meteor._DoubleEndedQueue(); + private _workerActive = false; + private _workerPromise: Promise | null = null; + constructor(oplogUrl: string, dbName: string) { this._oplogUrl = oplogUrl; this._dbName = dbName; @@ -90,10 +92,6 @@ export class OplogHandle { debugPrintExceptions: "onSkippedEntries callback" }); - // @ts-ignore - this._entryQueue = new Meteor._DoubleEndedQueue(); - this._workerActive = false; - this._startTrailingPromise = this._startTailing(); } @@ -298,64 +296,11 @@ export class OplogHandle { } private _maybeStartWorker(): void { - if (this._workerActive) return; + if (this._workerPromise) return; this._workerActive = true; - Meteor.defer(async () => { - // May be called recursively in case of transactions. - const handleDoc = async (doc: OplogEntry): Promise => { - if (doc.ns === "admin.$cmd") { - if (doc.o.applyOps) { - // This was a successful transaction, so we need to apply the - // operations that were involved. - let nextTimestamp = doc.ts; - for (const op of doc.o.applyOps) { - // See https://github.com/meteor/meteor/issues/10420. - if (!op.ts) { - op.ts = nextTimestamp; - nextTimestamp = nextTimestamp.add(Long.ONE); - } - await handleDoc(op); - } - return; - } - throw new Error("Unknown command " + JSON.stringify(doc)); - } - - const trigger: OplogTrigger = { - dropCollection: false, - dropDatabase: false, - op: doc, - }; - - if (typeof doc.ns === "string" && doc.ns.startsWith(this._dbName + ".")) { - trigger.collection = doc.ns.slice(this._dbName.length + 1); - } - - // Is it a special command and the collection name is hidden - // somewhere in operator? - if (trigger.collection === "$cmd") { - if (doc.o.dropDatabase) { - delete trigger.collection; - trigger.dropDatabase = true; - } else if ("drop" in doc.o) { - trigger.collection = doc.o.drop; - trigger.dropCollection = true; - trigger.id = null; - } else if ("create" in doc.o && "idIndex" in doc.o) { - // A collection got implicitly created within a transaction. There's - // no need to do anything about it. - } else { - throw Error("Unknown command " + JSON.stringify(doc)); - } - } else { - // All other ops have an id. - trigger.id = idForOp(doc); - } - - await this._crossbar.fire(trigger); - }; - + // Convert to a proper promise-based queue processor + this._workerPromise = (async () => { try { while (!this._stopped && !this._entryQueue.isEmpty()) { // Are we too far behind? Just tell our observers that they need to @@ -375,23 +320,25 @@ export class OplogHandle { continue; } + // Process next batch from the queue const doc = this._entryQueue.shift(); - // Fire trigger(s) for this doc. - await handleDoc(doc); - - // Now that we've processed this operation, process pending - // sequencers. - if (doc.ts) { - this._setLastProcessedTS(doc.ts); - } else { - throw Error("oplog entry without ts: " + JSON.stringify(doc)); + try { + await handleDoc(this, doc); + // Process any waiting fence callbacks + if (doc.ts) { + this._setLastProcessedTS(doc.ts); + } + } catch (e) { + // Keep processing queue even if one entry fails + console.error('Error processing oplog entry:', e); } } } finally { + this._workerPromise = null; this._workerActive = false; } - }); + })(); } _setLastProcessedTS(ts: any): void { @@ -422,3 +369,58 @@ export function idForOp(op: OplogEntry): string { throw Error("Unknown op: " + JSON.stringify(op)); } } + +async function handleDoc(handle: OplogHandle, doc: OplogEntry): Promise { + if (doc.ns === "admin.$cmd") { + if (doc.o.applyOps) { + // This was a successful transaction, so we need to apply the + // operations that were involved. + let nextTimestamp = doc.ts; + for (const op of doc.o.applyOps) { + // See https://github.com/meteor/meteor/issues/10420. + if (!op.ts) { + op.ts = nextTimestamp; + nextTimestamp = nextTimestamp.add(Long.ONE); + } + await handleDoc(handle, op); + } + return; + } + throw new Error("Unknown command " + JSON.stringify(doc)); + } + + const trigger: OplogTrigger = { + dropCollection: false, + dropDatabase: false, + op: doc, + }; + + if (typeof doc.ns === "string" && doc.ns.startsWith(handle._dbName + ".")) { + trigger.collection = doc.ns.slice(handle._dbName.length + 1); + } + + // Is it a special command and the collection name is hidden + // somewhere in operator? + if (trigger.collection === "$cmd") { + if (doc.o.dropDatabase) { + delete trigger.collection; + trigger.dropDatabase = true; + } else if ("drop" in doc.o) { + trigger.collection = doc.o.drop; + trigger.dropCollection = true; + trigger.id = null; + } else if ("create" in doc.o && "idIndex" in doc.o) { + // A collection got implicitly created within a transaction. There's + // no need to do anything about it. + } else { + throw Error("Unknown command " + JSON.stringify(doc)); + } + } else { + // All other ops have an id. + trigger.id = idForOp(doc); + } + + await handle._crossbar.fire(trigger); + + await new Promise(resolve => setImmediate(resolve)); +} \ No newline at end of file From 748f7c4f29d87907af8eaeaa9e87d3c09fdef8c0 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Mon, 4 Nov 2024 18:21:39 -0400 Subject: [PATCH 09/48] prevent blocking event loop in write fence --- packages/ddp-server/writefence.js | 121 +++++++++++++----------------- 1 file changed, 53 insertions(+), 68 deletions(-) diff --git a/packages/ddp-server/writefence.js b/packages/ddp-server/writefence.js index a07ab575fc..aee0f1fde7 100644 --- a/packages/ddp-server/writefence.js +++ b/packages/ddp-server/writefence.js @@ -1,7 +1,3 @@ -// A write fence collects a group of writes, and provides a callback -// when all of the writes are fully committed and propagated (all -// observers have been notified of the write and acknowledged it.) -// DDPServer._WriteFence = class { constructor() { this.armed = false; @@ -12,58 +8,49 @@ DDPServer._WriteFence = class { this.completion_callbacks = []; } - // Start tracking a write, and return an object to represent it. The - // object has a single method, committed(). This method should be - // called when the write is fully committed and propagated. You can - // continue to add writes to the WriteFence up until it is triggered - // (calls its callbacks because all writes have committed.) beginWrite() { - if (this.retired) - return { committed: function () {} }; + if (this.retired) { + return { committed: () => {} }; + } - if (this.fired) + if (this.fired) { throw new Error("fence has already activated -- too late to add writes"); + } this.outstanding_writes++; let committed = false; - const _committedFn = async () => { - if (committed) - throw new Error("committed called twice on the same write"); - committed = true; - this.outstanding_writes--; - await this._maybeFire(); - }; return { - committed: _committedFn, + committed: async () => { + if (committed) { + throw new Error("committed called twice on the same write"); + } + committed = true; + this.outstanding_writes--; + await this._maybeFire(); + } }; } - // Arm the fence. Once the fence is armed, and there are no more - // uncommitted writes, it will activate. arm() { - - if (this === DDPServer._getCurrentFence()) + if (this === DDPServer._getCurrentFence()) { throw Error("Can't arm the current fence"); + } this.armed = true; return this._maybeFire(); } - // Register a function to be called once before firing the fence. - // Callback function can add new writes to the fence, in which case - // it won't fire until those writes are done as well. onBeforeFire(func) { - if (this.fired) - throw new Error("fence has already activated -- too late to " + - "add a callback"); + if (this.fired) { + throw new Error("fence has already activated -- too late to add a callback"); + } this.before_fire_callbacks.push(func); } - // Register a function to be called when the fence fires. onAllCommitted(func) { - if (this.fired) - throw new Error("fence has already activated -- too late to " + - "add a callback"); + if (this.fired) { + throw new Error("fence has already activated -- too late to add a callback"); + } this.completion_callbacks.push(func); } @@ -72,56 +59,54 @@ DDPServer._WriteFence = class { const returnValue = new Promise(r => resolver = r); this.onAllCommitted(resolver); await this.arm(); - return returnValue; } - // Convenience function. Arms the fence, then blocks until it fires. - async armAndWait() { + + armAndWait() { return this._armAndWait(); } async _maybeFire() { - if (this.fired) + if (this.fired) { throw new Error("write fence already activated?"); - if (this.armed && !this.outstanding_writes) { - const invokeCallback = async (func) => { - try { - await func(this); - } catch (err) { - Meteor._debug("exception in write fence callback:", err); - } - }; + } - this.outstanding_writes++; - while (this.before_fire_callbacks.length > 0) { - const cb = this.before_fire_callbacks.shift(); - await invokeCallback(cb); - } - this.outstanding_writes--; + if (!this.armed || this.outstanding_writes > 0) { + return; + } - if (!this.outstanding_writes) { - this.fired = true; - const callbacks = this.completion_callbacks || []; - this.completion_callbacks = []; - while (callbacks.length > 0) { - const cb = callbacks.shift(); - await invokeCallback(cb); - } + const invokeCallback = async (func) => { + try { + await func(this); + } catch (err) { + Meteor._debug("exception in write fence callback:", err); } + }; + + this.outstanding_writes++; + + // Process all before_fire callbacks in parallel + const beforeCallbacks = [...this.before_fire_callbacks]; + this.before_fire_callbacks = []; + await Promise.all(beforeCallbacks.map(cb => invokeCallback(cb))); + + this.outstanding_writes--; + + if (this.outstanding_writes === 0) { + this.fired = true; + // Process all completion callbacks in parallel + const callbacks = [...this.completion_callbacks]; + this.completion_callbacks = []; + await Promise.all(callbacks.map(cb => invokeCallback(cb))); } } - // Deactivate this fence so that adding more writes has no effect. - // The fence must have already fired. retire() { - if (!this.fired) + if (!this.fired) { throw new Error("Can't retire a fence that hasn't fired."); + } this.retired = true; } }; -// The current write fence. When there is a current write fence, code -// that writes to databases should register their writes with it using -// beginWrite(). -// -DDPServer._CurrentWriteFence = new Meteor.EnvironmentVariable; +DDPServer._CurrentWriteFence = new Meteor.EnvironmentVariable; \ No newline at end of file From 104cede0e1be1f48dec40b7eb36c42b7a4e3ea84 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Tue, 5 Nov 2024 18:32:15 -0400 Subject: [PATCH 10/48] rename files --- packages/ddp-client/client/client_convenience.js | 2 +- .../client/{queueStubsHelpers.js => queue_stub_helpers.js} | 0 packages/ddp-client/common/livedata_connection.js | 4 ++-- .../ddp-client/common/{MethodInvoker.js => method_invoker.js} | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename packages/ddp-client/client/{queueStubsHelpers.js => queue_stub_helpers.js} (100%) rename packages/ddp-client/common/{MethodInvoker.js => method_invoker.js} (98%) diff --git a/packages/ddp-client/client/client_convenience.js b/packages/ddp-client/client/client_convenience.js index 78a1ff7473..052a3087bb 100644 --- a/packages/ddp-client/client/client_convenience.js +++ b/packages/ddp-client/client/client_convenience.js @@ -1,6 +1,6 @@ import { DDP } from '../common/namespace.js'; import { Meteor } from 'meteor/meteor'; -import { loadAsyncStubHelpers } from "./queueStubsHelpers"; +import { loadAsyncStubHelpers } from "./queue_stub_helpers"; // Meteor.refresh can be called on the client (if you're in common code) but it // only has an effect on the server. diff --git a/packages/ddp-client/client/queueStubsHelpers.js b/packages/ddp-client/client/queue_stub_helpers.js similarity index 100% rename from packages/ddp-client/client/queueStubsHelpers.js rename to packages/ddp-client/client/queue_stub_helpers.js diff --git a/packages/ddp-client/common/livedata_connection.js b/packages/ddp-client/common/livedata_connection.js index e8967e3651..31081f7bcb 100644 --- a/packages/ddp-client/common/livedata_connection.js +++ b/packages/ddp-client/common/livedata_connection.js @@ -5,14 +5,14 @@ import { EJSON } from 'meteor/ejson'; import { Random } from 'meteor/random'; import { MongoID } from 'meteor/mongo-id'; import { DDP } from './namespace.js'; -import MethodInvoker from './MethodInvoker.js'; +import { MethodInvoker } from './method_invoker'; import { hasOwn, slice, keys, isEmpty, last, -} from "meteor/ddp-common/utils.js"; +} from "meteor/ddp-common/utils"; class MongoIDMap extends IdMap { constructor() { diff --git a/packages/ddp-client/common/MethodInvoker.js b/packages/ddp-client/common/method_invoker.js similarity index 98% rename from packages/ddp-client/common/MethodInvoker.js rename to packages/ddp-client/common/method_invoker.js index f2490b92f8..e0ef59e478 100644 --- a/packages/ddp-client/common/MethodInvoker.js +++ b/packages/ddp-client/common/method_invoker.js @@ -3,7 +3,7 @@ // _methodInvokers map; it removes itself once the method is fully finished and // the callback is invoked. This occurs when it has both received a result, // and the data written by it is fully visible. -export default class MethodInvoker { +export class MethodInvoker { constructor(options) { // Public (within this file) fields. this.methodId = options.methodId; From 4e8c7cf1815298da77f206c2b94d9b52f12e5e60 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Tue, 5 Nov 2024 18:40:50 -0400 Subject: [PATCH 11/48] fix potential race condition dropping messages --- .../ddp-client/common/livedata_connection.js | 119 ++++++++---------- 1 file changed, 50 insertions(+), 69 deletions(-) diff --git a/packages/ddp-client/common/livedata_connection.js b/packages/ddp-client/common/livedata_connection.js index 31081f7bcb..75fe2ae7cf 100644 --- a/packages/ddp-client/common/livedata_connection.js +++ b/packages/ddp-client/common/livedata_connection.js @@ -941,7 +941,7 @@ export class Connection { // documents. _saveOriginals() { if (! this._waitingForQuiescence()) { - this._flushBufferedWritesClient(); + this._flushBufferedWrites(); } Object.values(this._stores).forEach((store) => { @@ -1332,61 +1332,40 @@ export class Connection { return writes; } - async _flushBufferedWritesServer() { - const self = this; - const writes = self._prepareBuffersToFlush(); - await self._performWritesServer(writes); - } - _flushBufferedWritesClient() { - const self = this; - const writes = self._prepareBuffersToFlush(); - self._performWritesClient(writes); - } - _flushBufferedWrites() { - const self = this; - return Meteor.isClient - ? self._flushBufferedWritesClient() - : self._flushBufferedWritesServer(); - } + /** + * Server-side store updates handled asynchronously + * @private + */ async _performWritesServer(updates) { const self = this; - if (self._resetStores || ! isEmpty(updates)) { - // Begin a transactional update of each store. - - for (const [storeName, store] of Object.entries(self._stores)) { + if (self._resetStores || !isEmpty(updates)) { + // Start all store updates + for (const store of Object.values(self._stores)) { await store.beginUpdate( - hasOwn.call(updates, storeName) - ? updates[storeName].length - : 0, + updates[store._name]?.length || 0, self._resetStores ); } self._resetStores = false; - for (const [storeName, updateMessages] of Object.entries(updates)) { + // Process each store's updates + for (const [storeName, messages] of Object.entries(updates)) { const store = self._stores[storeName]; if (store) { - for (const updateMessage of updateMessages) { - await store.update(updateMessage); + for (const msg of messages) { + await store.update(msg); } } else { - // Nobody's listening for this data. Queue it up until - // someone wants it. - // XXX memory use will grow without bound if you forget to - // create a collection or just don't care about it... going - // to have to do something about that. - const updates = self._updatesForUnknownStores; - - if (! hasOwn.call(updates, storeName)) { - updates[storeName] = []; - } - - updates[storeName].push(...updateMessages); + // Queue updates for uninitialized stores + self._updatesForUnknownStores[storeName] = + self._updatesForUnknownStores[storeName] || []; + self._updatesForUnknownStores[storeName].push(...messages); } } - // End update transaction. + + // Complete all updates for (const store of Object.values(self._stores)) { await store.endUpdate(); } @@ -1394,53 +1373,55 @@ export class Connection { self._runAfterUpdateCallbacks(); } + + /** + * Client-side store updates handled synchronously for optimistic UI + * @private + */ _performWritesClient(updates) { const self = this; - if (self._resetStores || ! isEmpty(updates)) { - // Begin a transactional update of each store. - - for (const [storeName, store] of Object.entries(self._stores)) { + if (self._resetStores || !isEmpty(updates)) { + // Synchronous store updates for client + Object.values(self._stores).forEach(store => { store.beginUpdate( - hasOwn.call(updates, storeName) - ? updates[storeName].length - : 0, + updates[store._name]?.length || 0, self._resetStores ); - } + }); self._resetStores = false; - for (const [storeName, updateMessages] of Object.entries(updates)) { + Object.entries(updates).forEach(([storeName, messages]) => { const store = self._stores[storeName]; if (store) { - for (const updateMessage of updateMessages) { - store.update(updateMessage); - } + messages.forEach(msg => store.update(msg)); } else { - // Nobody's listening for this data. Queue it up until - // someone wants it. - // XXX memory use will grow without bound if you forget to - // create a collection or just don't care about it... going - // to have to do something about that. - const updates = self._updatesForUnknownStores; - - if (! hasOwn.call(updates, storeName)) { - updates[storeName] = []; - } - - updates[storeName].push(...updateMessages); + self._updatesForUnknownStores[storeName] = + self._updatesForUnknownStores[storeName] || []; + self._updatesForUnknownStores[storeName].push(...messages); } - } - // End update transaction. - for (const store of Object.values(self._stores)) { - store.endUpdate(); - } + }); + + Object.values(self._stores).forEach(store => store.endUpdate()); } self._runAfterUpdateCallbacks(); } + /** + * Executes buffered writes either synchronously (client) or async (server) + * @private + */ + _flushBufferedWrites() { + const self = this; + const writes = self._prepareBuffersToFlush(); + + return Meteor.isClient + ? self._performWritesClient(writes) + : self._performWritesServer(writes); + } + // Call any callbacks deferred with _runWhenAllServerDocsAreFlushed whose // relevant docs have been flushed, as well as dataVisible callbacks at // reconnect-quiescence time. From 2779e6563049e2cdda202e2d0a5c9a56a055e514 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Wed, 6 Nov 2024 13:08:40 -0400 Subject: [PATCH 12/48] improve buffered writes flushing logic in order to not block the event loop --- .../ddp-client/common/livedata_connection.js | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/packages/ddp-client/common/livedata_connection.js b/packages/ddp-client/common/livedata_connection.js index 75fe2ae7cf..08e080b7e4 100644 --- a/packages/ddp-client/common/livedata_connection.js +++ b/packages/ddp-client/common/livedata_connection.js @@ -202,12 +202,6 @@ export class Connection { self._updatesForUnknownStores = {}; // if we're blocking a migration, the retry func self._retryMigrate = null; - - self.__flushBufferedWrites = Meteor.bindEnvironment( - self._flushBufferedWrites, - 'flushing DDP buffered writes', - self - ); // Collection name -> array of messages. self._bufferedWrites = {}; // When current buffer of updates must be flushed at, in ms timestamp. @@ -1306,7 +1300,7 @@ export class Connection { self._bufferedWritesFlushHandle = setTimeout(() => { // __flushBufferedWrites is a promise, so with this we can wait the promise to finish // before doing something - self._liveDataWritesPromise = self.__flushBufferedWrites(); + self._liveDataWritesPromise = self._flushBufferedWrites(); if (Meteor._isPromise(self._liveDataWritesPromise)) { self._liveDataWritesPromise.finally( @@ -1340,7 +1334,7 @@ export class Connection { const self = this; if (self._resetStores || !isEmpty(updates)) { - // Start all store updates + // Start all store updates - keeping original loop structure for (const store of Object.values(self._stores)) { await store.beginUpdate( updates[store._name]?.length || 0, @@ -1350,12 +1344,21 @@ export class Connection { self._resetStores = false; - // Process each store's updates + // Process each store's updates sequentially as before for (const [storeName, messages] of Object.entries(updates)) { const store = self._stores[storeName]; if (store) { - for (const msg of messages) { - await store.update(msg); + // Batch each store's messages in modest chunks to prevent event loop blocking + // while maintaining operation order + const CHUNK_SIZE = 100; + for (let i = 0; i < messages.length; i += CHUNK_SIZE) { + const chunk = messages.slice(i, Math.min(i + CHUNK_SIZE, messages.length)); + + for (const msg of chunk) { + await store.update(msg); + } + + await new Promise(resolve => process.nextTick(resolve)); } } else { // Queue updates for uninitialized stores @@ -1413,7 +1416,7 @@ export class Connection { * Executes buffered writes either synchronously (client) or async (server) * @private */ - _flushBufferedWrites() { + async _flushBufferedWrites() { const self = this; const writes = self._prepareBuffersToFlush(); From 6c1fd9c3138ec3fbc6959cd4e335897cb025f5b5 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Wed, 6 Nov 2024 14:07:36 -0400 Subject: [PATCH 13/48] extract stream handlers --- .../common/connection_stream_handlers.js | 202 ++++++++++++++++++ .../ddp-client/common/livedata_connection.js | 179 ++-------------- packages/ddp-client/common/mongo_id_map.js | 7 + 3 files changed, 227 insertions(+), 161 deletions(-) create mode 100644 packages/ddp-client/common/connection_stream_handlers.js create mode 100644 packages/ddp-client/common/mongo_id_map.js diff --git a/packages/ddp-client/common/connection_stream_handlers.js b/packages/ddp-client/common/connection_stream_handlers.js new file mode 100644 index 0000000000..bfef109ff0 --- /dev/null +++ b/packages/ddp-client/common/connection_stream_handlers.js @@ -0,0 +1,202 @@ +import { DDPCommon } from 'meteor/ddp-common'; +import { Meteor } from 'meteor/meteor'; + +export class ConnectionStreamHandlers { + constructor(connection) { + this._connection = connection; + } + + /** + * Handles incoming raw messages from the DDP stream + * @param {String} raw_msg The raw message received from the stream + */ + async onMessage(raw_msg) { + let msg; + try { + msg = DDPCommon.parseDDP(raw_msg); + } catch (e) { + Meteor._debug('Exception while parsing DDP', e); + return; + } + + // Any message counts as receiving a pong, as it demonstrates that + // the server is still alive. + if (this._connection._heartbeat) { + this._connection._heartbeat.messageReceived(); + } + + if (msg === null || !msg.msg) { + if(!msg || !msg.testMessageOnConnect) { + if (Object.keys(msg).length === 1 && msg.server_id) return; + Meteor._debug('discarding invalid livedata message', msg); + } + return; + } + + // Important: This was missing from previous version + // We need to set the current version before routing the message + if (msg.msg === 'connected') { + this._connection._version = this._connection._versionSuggestion; + } + + await this._routeMessage(msg); + } + + /** + * Routes messages to their appropriate handlers based on message type + * @private + * @param {Object} msg The parsed DDP message + */ + async _routeMessage(msg) { + switch (msg.msg) { + case 'connected': + await this._connection._livedata_connected(msg); + this._connection.options.onConnected(); + break; + + case 'failed': + await this._handleFailedMessage(msg); + break; + + case 'ping': + if (this._connection.options.respondToPings) { + this._connection._send({ msg: 'pong', id: msg.id }); + } + break; + + case 'pong': + // noop, as we assume everything's a pong + break; + + case 'added': + case 'changed': + case 'removed': + case 'ready': + case 'updated': + await this._connection._livedata_data(msg); + break; + + case 'nosub': + await this._connection._livedata_nosub(msg); + break; + + case 'result': + await this._connection._livedata_result(msg); + break; + + case 'error': + this._connection._livedata_error(msg); + break; + + default: + Meteor._debug('discarding unknown livedata message type', msg); + } + } + + /** + * Handles failed connection messages + * @private + * @param {Object} msg The failed message object + */ + _handleFailedMessage(msg) { + if (this._connection._supportedDDPVersions.indexOf(msg.version) >= 0) { + this._connection._versionSuggestion = msg.version; + this._connection._stream.reconnect({ _force: true }); + } else { + const description = + 'DDP version negotiation failed; server requested version ' + + msg.version; + this._connection._stream.disconnect({ _permanent: true, _error: description }); + this._connection.options.onDDPVersionNegotiationFailure(description); + } + } + + /** + * Handles connection reset events + */ + onReset() { + // Reset is called even on the first connection, so this is + // the only place we send this message. + const msg = this._buildConnectMessage(); + this._connection._send(msg); + + // Mark non-retry calls as failed and handle outstanding methods + this._handleOutstandingMethodsOnReset(); + + // Now, to minimize setup latency, go ahead and blast out all of + // our pending methods ands subscriptions before we've even taken + // the necessary RTT to know if we successfully reconnected. + this._connection._callOnReconnectAndSendAppropriateOutstandingMethods(); + this._resendSubscriptions(); + } + + /** + * Builds the initial connect message + * @private + * @returns {Object} The connect message object + */ + _buildConnectMessage() { + const msg = { msg: 'connect' }; + if (this._connection._lastSessionId) { + msg.session = this._connection._lastSessionId; + } + msg.version = this._connection._versionSuggestion || this._connection._supportedDDPVersions[0]; + this._connection._versionSuggestion = msg.version; + msg.support = this._connection._supportedDDPVersions; + return msg; + } + + /** + * Handles outstanding methods during a reset + * @private + */ + _handleOutstandingMethodsOnReset() { + const blocks = this._connection._outstandingMethodBlocks; + if (blocks.length === 0) return; + + const currentMethodBlock = blocks[0].methods; + blocks[0].methods = currentMethodBlock.filter( + methodInvoker => { + // Methods with 'noRetry' option set are not allowed to re-send after + // recovering dropped connection. + if (methodInvoker.sentMessage && methodInvoker.noRetry) { + methodInvoker.receiveResult( + new Meteor.Error( + 'invocation-failed', + 'Method invocation might have failed due to dropped connection. ' + + 'Failing because `noRetry` option was passed to Meteor.apply.' + ) + ); + } + + // Only keep a method if it wasn't sent or it's allowed to retry. + return !(methodInvoker.sentMessage && methodInvoker.noRetry); + } + ); + + // Clear empty blocks + if (blocks.length > 0 && blocks[0].methods.length === 0) { + blocks.shift(); + } + + // Reset all method invokers as unsent + Object.values(this._connection._methodInvokers).forEach(invoker => { + invoker.sentMessage = false; + }); + } + + /** + * Resends all active subscriptions + * @private + */ + _resendSubscriptions() { + Object.entries(this._connection._subscriptions).forEach(([id, sub]) => { + this._connection._sendQueued({ + msg: 'sub', + id: id, + name: sub.name, + params: sub.params + }); + }); + } +} \ No newline at end of file diff --git a/packages/ddp-client/common/livedata_connection.js b/packages/ddp-client/common/livedata_connection.js index 08e080b7e4..d7c67c2038 100644 --- a/packages/ddp-client/common/livedata_connection.js +++ b/packages/ddp-client/common/livedata_connection.js @@ -13,12 +13,8 @@ import { isEmpty, last, } from "meteor/ddp-common/utils"; - -class MongoIDMap extends IdMap { - constructor() { - super(MongoID.idStringify, MongoID.idParse); - } -} +import { ConnectionStreamHandlers } from './connection_stream_handlers'; +import { MongoIDMap } from './mongo_id_map'; // @param url {String|Object} URL to Meteor app, // or an object as a test hook (see code) @@ -243,33 +239,38 @@ export class Connection { }); } + this._streamHandlers = new ConnectionStreamHandlers(this); + const onDisconnect = () => { - if (self._heartbeat) { - self._heartbeat.stop(); - self._heartbeat = null; + if (this._heartbeat) { + this._heartbeat.stop(); + this._heartbeat = null; } }; if (Meteor.isServer) { - self._stream.on( + this._stream.on( 'message', Meteor.bindEnvironment( - this.onMessage.bind(this), + msg => this._streamHandlers.onMessage(msg), 'handling DDP message' ) ); - self._stream.on( + this._stream.on( 'reset', - Meteor.bindEnvironment(this.onReset.bind(this), 'handling DDP reset') + Meteor.bindEnvironment( + () => this._streamHandlers.onReset(), + 'handling DDP reset' + ) ); - self._stream.on( + this._stream.on( 'disconnect', Meteor.bindEnvironment(onDisconnect, 'handling DDP disconnect') ); } else { - self._stream.on('message', this.onMessage.bind(this)); - self._stream.on('reset', this.onReset.bind(this)); - self._stream.on('disconnect', onDisconnect); + this._stream.on('message', msg => this._streamHandlers.onMessage(msg)); + this._stream.on('reset', () => this._streamHandlers.onReset()); + this._stream.on('disconnect', onDisconnect); } } @@ -1854,148 +1855,4 @@ export class Connection { self._retryMigrate = null; } } - - async onMessage(raw_msg) { - let msg; - try { - msg = DDPCommon.parseDDP(raw_msg); - } catch (e) { - Meteor._debug('Exception while parsing DDP', e); - return; - } - - // Any message counts as receiving a pong, as it demonstrates that - // the server is still alive. - if (this._heartbeat) { - this._heartbeat.messageReceived(); - } - - if (msg === null || !msg.msg) { - if(!msg || !msg.testMessageOnConnect) { - if (Object.keys(msg).length === 1 && msg.server_id) return; - Meteor._debug('discarding invalid livedata message', msg); - } - return; - } - - if (msg.msg === 'connected') { - this._version = this._versionSuggestion; - await this._livedata_connected(msg); - this.options.onConnected(); - } else if (msg.msg === 'failed') { - if (this._supportedDDPVersions.indexOf(msg.version) >= 0) { - this._versionSuggestion = msg.version; - this._stream.reconnect({ _force: true }); - } else { - const description = - 'DDP version negotiation failed; server requested version ' + - msg.version; - this._stream.disconnect({ _permanent: true, _error: description }); - this.options.onDDPVersionNegotiationFailure(description); - } - } else if (msg.msg === 'ping' && this.options.respondToPings) { - this._send({ msg: 'pong', id: msg.id }); - } else if (msg.msg === 'pong') { - // noop, as we assume everything's a pong - } else if ( - ['added', 'changed', 'removed', 'ready', 'updated'].includes(msg.msg) - ) { - await this._livedata_data(msg); - } else if (msg.msg === 'nosub') { - await this._livedata_nosub(msg); - } else if (msg.msg === 'result') { - await this._livedata_result(msg); - } else if (msg.msg === 'error') { - this._livedata_error(msg); - } else { - Meteor._debug('discarding unknown livedata message type', msg); - } - } - - onReset() { - // Send a connect message at the beginning of the stream. - // NOTE: reset is called even on the first connection, so this is - // the only place we send this message. - const msg = { msg: 'connect' }; - if (this._lastSessionId) msg.session = this._lastSessionId; - msg.version = this._versionSuggestion || this._supportedDDPVersions[0]; - this._versionSuggestion = msg.version; - msg.support = this._supportedDDPVersions; - this._send(msg); - - // Mark non-retry calls as failed. This has to be done early as getting these methods out of the - // current block is pretty important to making sure that quiescence is properly calculated, as - // well as possibly moving on to another useful block. - - // Only bother testing if there is an outstandingMethodBlock (there might not be, especially if - // we are connecting for the first time. - if (this._outstandingMethodBlocks.length > 0) { - // If there is an outstanding method block, we only care about the first one as that is the - // one that could have already sent messages with no response, that are not allowed to retry. - const currentMethodBlock = this._outstandingMethodBlocks[0].methods; - this._outstandingMethodBlocks[0].methods = currentMethodBlock.filter( - methodInvoker => { - // Methods with 'noRetry' option set are not allowed to re-send after - // recovering dropped connection. - if (methodInvoker.sentMessage && methodInvoker.noRetry) { - // Make sure that the method is told that it failed. - methodInvoker.receiveResult( - new Meteor.Error( - 'invocation-failed', - 'Method invocation might have failed due to dropped connection. ' + - 'Failing because `noRetry` option was passed to Meteor.apply.' - ) - ); - } - - // Only keep a method if it wasn't sent or it's allowed to retry. - // This may leave the block empty, but we don't move on to the next - // block until the callback has been delivered, in _outstandingMethodFinished. - return !(methodInvoker.sentMessage && methodInvoker.noRetry); - } - ); - } - - // Now, to minimize setup latency, go ahead and blast out all of - // our pending methods ands subscriptions before we've even taken - // the necessary RTT to know if we successfully reconnected. (1) - // They're supposed to be idempotent, and where they are not, - // they can block retry in apply; (2) even if we did reconnect, - // we're not sure what messages might have gotten lost - // (in either direction) since we were disconnected (TCP being - // sloppy about that.) - - // If the current block of methods all got their results (but didn't all get - // their data visible), discard the empty block now. - if ( - this._outstandingMethodBlocks.length > 0 && - this._outstandingMethodBlocks[0].methods.length === 0 - ) { - this._outstandingMethodBlocks.shift(); - } - - // Mark all messages as unsent, they have not yet been sent on this - // connection. - keys(this._methodInvokers).forEach(id => { - this._methodInvokers[id].sentMessage = false; - }); - - // If an `onReconnect` handler is set, call it first. Go through - // some hoops to ensure that methods that are called from within - // `onReconnect` get executed _before_ ones that were originally - // outstanding (since `onReconnect` is used to re-establish auth - // certificates) - this._callOnReconnectAndSendAppropriateOutstandingMethods(); - - // add new subscriptions at the end. this way they take effect after - // the handlers and we don't see flicker. - Object.entries(this._subscriptions).forEach(([id, sub]) => { - this._sendQueued({ - msg: 'sub', - id: id, - name: sub.name, - params: sub.params - }); - }); - } } diff --git a/packages/ddp-client/common/mongo_id_map.js b/packages/ddp-client/common/mongo_id_map.js new file mode 100644 index 0000000000..179aa214f1 --- /dev/null +++ b/packages/ddp-client/common/mongo_id_map.js @@ -0,0 +1,7 @@ +import { MongoID } from 'meteor/mongo-id'; + +export class MongoIDMap extends IdMap { + constructor() { + super(MongoID.idStringify, MongoID.idParse); + } +} \ No newline at end of file From 959e7abe1a4f53c762f678579d6907e21e105800 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Wed, 6 Nov 2024 14:15:59 -0400 Subject: [PATCH 14/48] extract processors --- .../ddp-client/common/document_processors.js | 206 ++++++++ .../ddp-client/common/livedata_connection.js | 468 +----------------- .../ddp-client/common/message_processors.js | 336 +++++++++++++ 3 files changed, 568 insertions(+), 442 deletions(-) create mode 100644 packages/ddp-client/common/document_processors.js create mode 100644 packages/ddp-client/common/message_processors.js diff --git a/packages/ddp-client/common/document_processors.js b/packages/ddp-client/common/document_processors.js new file mode 100644 index 0000000000..11c4b2f8c0 --- /dev/null +++ b/packages/ddp-client/common/document_processors.js @@ -0,0 +1,206 @@ +import { MongoID } from 'meteor/mongo-id'; +import { DiffSequence } from 'meteor/diff-sequence'; +import { hasOwn } from "meteor/ddp-common/utils"; +import { isEmpty } from "meteor/ddp-common/utils"; + +export class DocumentProcessors { + constructor(connection) { + this._connection = connection; + } + + /** + * @summary Process an 'added' message from the server + * @param {Object} msg The added message + * @param {Object} updates The updates accumulator + */ + async _process_added(msg, updates) { + const self = this._connection; + const id = MongoID.idParse(msg.id); + const serverDoc = self._getServerDoc(msg.collection, id); + + if (serverDoc) { + // Some outstanding stub wrote here. + const isExisting = serverDoc.document !== undefined; + + serverDoc.document = msg.fields || Object.create(null); + serverDoc.document._id = id; + + if (self._resetStores) { + // During reconnect the server is sending adds for existing ids. + // Always push an update so that document stays in the store after + // reset. Use current version of the document for this update, so + // that stub-written values are preserved. + const currentDoc = await self._stores[msg.collection].getDoc(msg.id); + if (currentDoc !== undefined) msg.fields = currentDoc; + + self._pushUpdate(updates, msg.collection, msg); + } else if (isExisting) { + throw new Error('Server sent add for existing id: ' + msg.id); + } + } else { + self._pushUpdate(updates, msg.collection, msg); + } + } + + /** + * @summary Process a 'changed' message from the server + * @param {Object} msg The changed message + * @param {Object} updates The updates accumulator + */ + _process_changed(msg, updates) { + const self = this._connection; + const serverDoc = self._getServerDoc(msg.collection, MongoID.idParse(msg.id)); + + if (serverDoc) { + if (serverDoc.document === undefined) { + throw new Error('Server sent changed for nonexisting id: ' + msg.id); + } + DiffSequence.applyChanges(serverDoc.document, msg.fields); + } else { + self._pushUpdate(updates, msg.collection, msg); + } + } + + /** + * @summary Process a 'removed' message from the server + * @param {Object} msg The removed message + * @param {Object} updates The updates accumulator + */ + _process_removed(msg, updates) { + const self = this._connection; + const serverDoc = self._getServerDoc(msg.collection, MongoID.idParse(msg.id)); + + if (serverDoc) { + // Some outstanding stub wrote here. + if (serverDoc.document === undefined) { + throw new Error('Server sent removed for nonexisting id:' + msg.id); + } + serverDoc.document = undefined; + } else { + self._pushUpdate(updates, msg.collection, { + msg: 'removed', + collection: msg.collection, + id: msg.id + }); + } + } + + /** + * @summary Process a 'ready' message from the server + * @param {Object} msg The ready message + * @param {Object} updates The updates accumulator + */ + _process_ready(msg, updates) { + const self = this._connection; + + // Process "sub ready" messages. "sub ready" messages don't take effect + // until all current server documents have been flushed to the local + // database. We can use a write fence to implement this. + msg.subs.forEach((subId) => { + self._runWhenAllServerDocsAreFlushed(() => { + const subRecord = self._subscriptions[subId]; + // Did we already unsubscribe? + if (!subRecord) return; + // Did we already receive a ready message? (Oops!) + if (subRecord.ready) return; + subRecord.ready = true; + subRecord.readyCallback && subRecord.readyCallback(); + subRecord.readyDeps.changed(); + }); + }); + } + + /** + * @summary Process an 'updated' message from the server + * @param {Object} msg The updated message + * @param {Object} updates The updates accumulator + */ + _process_updated(msg, updates) { + const self = this._connection; + // Process "method done" messages. + msg.methods.forEach((methodId) => { + const docs = self._documentsWrittenByStub[methodId] || {}; + Object.values(docs).forEach((written) => { + const serverDoc = self._getServerDoc(written.collection, written.id); + if (!serverDoc) { + throw new Error('Lost serverDoc for ' + JSON.stringify(written)); + } + if (!serverDoc.writtenByStubs[methodId]) { + throw new Error( + 'Doc ' + + JSON.stringify(written) + + ' not written by method ' + + methodId + ); + } + delete serverDoc.writtenByStubs[methodId]; + if (isEmpty(serverDoc.writtenByStubs)) { + // All methods whose stubs wrote this method have completed! We can + // now copy the saved document to the database (reverting the stub's + // change if the server did not write to this object, or applying the + // server's writes if it did). + + // This is a fake ddp 'replace' message. It's just for talking + // between livedata connections and minimongo. (We have to stringify + // the ID because it's supposed to look like a wire message.) + self._pushUpdate(updates, written.collection, { + msg: 'replace', + id: MongoID.idStringify(written.id), + replace: serverDoc.document + }); + // Call all flush callbacks. + serverDoc.flushCallbacks.forEach((c) => { + c(); + }); + + // Delete this completed serverDocument. Don't bother to GC empty + // IdMaps inside self._serverDocuments, since there probably aren't + // many collections and they'll be written repeatedly. + self._serverDocuments[written.collection].remove(written.id); + } + }); + delete self._documentsWrittenByStub[methodId]; + + // We want to call the data-written callback, but we can't do so until all + // currently buffered messages are flushed. + const callbackInvoker = self._methodInvokers[methodId]; + if (!callbackInvoker) { + throw new Error('No callback invoker for method ' + methodId); + } + + self._runWhenAllServerDocsAreFlushed( + (...args) => callbackInvoker.dataVisible(...args) + ); + }); + } + + /** + * @summary Push an update to the buffer + * @private + * @param {Object} updates The updates accumulator + * @param {String} collection The collection name + * @param {Object} msg The update message + */ + _pushUpdate(updates, collection, msg) { + if (!hasOwn.call(updates, collection)) { + updates[collection] = []; + } + updates[collection].push(msg); + } + + /** + * @summary Get a server document by collection and id + * @private + * @param {String} collection The collection name + * @param {String} id The document id + * @returns {Object|null} The server document or null + */ + _getServerDoc(collection, id) { + const self = this._connection; + if (!hasOwn.call(self._serverDocuments, collection)) { + return null; + } + const serverDocsForCollection = self._serverDocuments[collection]; + return serverDocsForCollection.get(id) || null; + } +} \ No newline at end of file diff --git a/packages/ddp-client/common/livedata_connection.js b/packages/ddp-client/common/livedata_connection.js index d7c67c2038..abe1161d21 100644 --- a/packages/ddp-client/common/livedata_connection.js +++ b/packages/ddp-client/common/livedata_connection.js @@ -15,6 +15,8 @@ import { } from "meteor/ddp-common/utils"; import { ConnectionStreamHandlers } from './connection_stream_handlers'; import { MongoIDMap } from './mongo_id_map'; +import { MessageProcessors } from './message_processors'; +import { DocumentProcessors } from './document_processors'; // @param url {String|Object} URL to Meteor app, // or an object as a test hook (see code) @@ -272,6 +274,30 @@ export class Connection { this._stream.on('reset', () => this._streamHandlers.onReset()); this._stream.on('disconnect', onDisconnect); } + + this._messageProcessors = new MessageProcessors(this); + + // Expose message processor methods to maintain backward compatibility + this._livedata_connected = (msg) => this._messageProcessors._livedata_connected(msg); + this._livedata_data = (msg) => this._messageProcessors._livedata_data(msg); + this._livedata_nosub = (msg) => this._messageProcessors._livedata_nosub(msg); + this._livedata_result = (msg) => this._messageProcessors._livedata_result(msg); + this._livedata_error = (msg) => this._messageProcessors._livedata_error(msg); + + this._documentProcessors = new DocumentProcessors(this); + + // Expose document processor methods to maintain backward compatibility + this._process_added = (msg, updates) => this._documentProcessors._process_added(msg, updates); + this._process_changed = (msg, updates) => this._documentProcessors._process_changed(msg, updates); + this._process_removed = (msg, updates) => this._documentProcessors._process_removed(msg, updates); + this._process_ready = (msg, updates) => this._documentProcessors._process_ready(msg, updates); + this._process_updated = (msg, updates) => this._documentProcessors._process_updated(msg, updates); + + // Also expose utility methods used by other parts of the system + this._pushUpdate = (updates, collection, msg) => + this._documentProcessors._pushUpdate(updates, collection, msg); + this._getServerDoc = (collection, id) => + this._documentProcessors._getServerDoc(collection, id); } // 'name' is the name of the data on the wire that should go in the @@ -1094,121 +1120,6 @@ export class Connection { return Object.values(invokers).some((invoker) => !!invoker.sentMessage); } - async _livedata_connected(msg) { - const self = this; - - if (self._version !== 'pre1' && self._heartbeatInterval !== 0) { - self._heartbeat = new DDPCommon.Heartbeat({ - heartbeatInterval: self._heartbeatInterval, - heartbeatTimeout: self._heartbeatTimeout, - onTimeout() { - self._lostConnection( - new DDP.ConnectionError('DDP heartbeat timed out') - ); - }, - sendPing() { - self._send({ msg: 'ping' }); - } - }); - self._heartbeat.start(); - } - - // If this is a reconnect, we'll have to reset all stores. - if (self._lastSessionId) self._resetStores = true; - - let reconnectedToPreviousSession; - if (typeof msg.session === 'string') { - reconnectedToPreviousSession = self._lastSessionId === msg.session; - self._lastSessionId = msg.session; - } - - if (reconnectedToPreviousSession) { - // Successful reconnection -- pick up where we left off. Note that right - // now, this never happens: the server never connects us to a previous - // session, because DDP doesn't provide enough data for the server to know - // what messages the client has processed. We need to improve DDP to make - // this possible, at which point we'll probably need more code here. - return; - } - - // Server doesn't have our data any more. Re-sync a new session. - - // Forget about messages we were buffering for unknown collections. They'll - // be resent if still relevant. - self._updatesForUnknownStores = Object.create(null); - - if (self._resetStores) { - // Forget about the effects of stubs. We'll be resetting all collections - // anyway. - self._documentsWrittenByStub = Object.create(null); - self._serverDocuments = Object.create(null); - } - - // Clear _afterUpdateCallbacks. - self._afterUpdateCallbacks = []; - - // Mark all named subscriptions which are ready (ie, we already called the - // ready callback) as needing to be revived. - // XXX We should also block reconnect quiescence until unnamed subscriptions - // (eg, autopublish) are done re-publishing to avoid flicker! - self._subsBeingRevived = Object.create(null); - Object.entries(self._subscriptions).forEach(([id, sub]) => { - if (sub.ready) { - self._subsBeingRevived[id] = true; - } - }); - - // Arrange for "half-finished" methods to have their callbacks run, and - // track methods that were sent on this connection so that we don't - // quiesce until they are all done. - // - // Start by clearing _methodsBlockingQuiescence: methods sent before - // reconnect don't matter, and any "wait" methods sent on the new connection - // that we drop here will be restored by the loop below. - self._methodsBlockingQuiescence = Object.create(null); - if (self._resetStores) { - const invokers = self._methodInvokers; - keys(invokers).forEach(id => { - const invoker = invokers[id]; - if (invoker.gotResult()) { - // This method already got its result, but it didn't call its callback - // because its data didn't become visible. We did not resend the - // method RPC. We'll call its callback when we get a full quiesce, - // since that's as close as we'll get to "data must be visible". - self._afterUpdateCallbacks.push( - (...args) => invoker.dataVisible(...args) - ); - } else if (invoker.sentMessage) { - // This method has been sent on this connection (maybe as a resend - // from the last connection, maybe from onReconnect, maybe just very - // quickly before processing the connected message). - // - // We don't need to do anything special to ensure its callbacks get - // called, but we'll count it as a method which is preventing - // reconnect quiescence. (eg, it might be a login method that was run - // from onReconnect, and we don't want to see flicker by seeing a - // logged-out state.) - self._methodsBlockingQuiescence[invoker.methodId] = true; - } - }); - } - - self._messagesBufferedUntilQuiescence = []; - - // If we're not waiting on any methods or subs, we can reset the stores and - // call the callbacks immediately. - if (! self._waitingForQuiescence()) { - if (self._resetStores) { - for (const store of Object.values(self._stores)) { - await store.beginUpdate(0, true); - await store.endUpdate(); - } - self._resetStores = false; - } - self._runAfterUpdateCallbacks(); - } - } - async _processOneDataMessage(msg, updates) { const messageType = msg.msg; @@ -1230,87 +1141,6 @@ export class Connection { } } - async _livedata_data(msg) { - const self = this; - - if (self._waitingForQuiescence()) { - self._messagesBufferedUntilQuiescence.push(msg); - - if (msg.msg === 'nosub') { - delete self._subsBeingRevived[msg.id]; - } - - if (msg.subs) { - msg.subs.forEach(subId => { - delete self._subsBeingRevived[subId]; - }); - } - - if (msg.methods) { - msg.methods.forEach(methodId => { - delete self._methodsBlockingQuiescence[methodId]; - }); - } - - if (self._waitingForQuiescence()) { - return; - } - - // No methods or subs are blocking quiescence! - // We'll now process and all of our buffered messages, reset all stores, - // and apply them all at once. - - const bufferedMessages = self._messagesBufferedUntilQuiescence; - for (const bufferedMessage of Object.values(bufferedMessages)) { - await self._processOneDataMessage( - bufferedMessage, - self._bufferedWrites - ); - } - - self._messagesBufferedUntilQuiescence = []; - - } else { - await self._processOneDataMessage(msg, self._bufferedWrites); - } - - // Immediately flush writes when: - // 1. Buffering is disabled. Or; - // 2. any non-(added/changed/removed) message arrives. - const standardWrite = - msg.msg === "added" || - msg.msg === "changed" || - msg.msg === "removed"; - - if (self._bufferedWritesInterval === 0 || ! standardWrite) { - await self._flushBufferedWrites(); - return; - } - - if (self._bufferedWritesFlushAt === null) { - self._bufferedWritesFlushAt = - new Date().valueOf() + self._bufferedWritesMaxAge; - } else if (self._bufferedWritesFlushAt < new Date().valueOf()) { - await self._flushBufferedWrites(); - return; - } - - if (self._bufferedWritesFlushHandle) { - clearTimeout(self._bufferedWritesFlushHandle); - } - self._bufferedWritesFlushHandle = setTimeout(() => { - // __flushBufferedWrites is a promise, so with this we can wait the promise to finish - // before doing something - self._liveDataWritesPromise = self._flushBufferedWrites(); - - if (Meteor._isPromise(self._liveDataWritesPromise)) { - self._liveDataWritesPromise.finally( - () => (self._liveDataWritesPromise = undefined) - ); - } - }, self._bufferedWritesInterval); - } - _prepareBuffersToFlush() { const self = this; if (self._bufferedWritesFlushHandle) { @@ -1438,160 +1268,6 @@ export class Connection { }); } - _pushUpdate(updates, collection, msg) { - if (! hasOwn.call(updates, collection)) { - updates[collection] = []; - } - updates[collection].push(msg); - } - - _getServerDoc(collection, id) { - const self = this; - if (! hasOwn.call(self._serverDocuments, collection)) { - return null; - } - const serverDocsForCollection = self._serverDocuments[collection]; - return serverDocsForCollection.get(id) || null; - } - - async _process_added(msg, updates) { - const self = this; - const id = MongoID.idParse(msg.id); - const serverDoc = self._getServerDoc(msg.collection, id); - if (serverDoc) { - // Some outstanding stub wrote here. - const isExisting = serverDoc.document !== undefined; - - serverDoc.document = msg.fields || Object.create(null); - serverDoc.document._id = id; - - if (self._resetStores) { - // During reconnect the server is sending adds for existing ids. - // Always push an update so that document stays in the store after - // reset. Use current version of the document for this update, so - // that stub-written values are preserved. - const currentDoc = await self._stores[msg.collection].getDoc(msg.id); - if (currentDoc !== undefined) msg.fields = currentDoc; - - self._pushUpdate(updates, msg.collection, msg); - } else if (isExisting) { - throw new Error('Server sent add for existing id: ' + msg.id); - } - } else { - self._pushUpdate(updates, msg.collection, msg); - } - } - - _process_changed(msg, updates) { - const self = this; - const serverDoc = self._getServerDoc(msg.collection, MongoID.idParse(msg.id)); - if (serverDoc) { - if (serverDoc.document === undefined) - throw new Error('Server sent changed for nonexisting id: ' + msg.id); - DiffSequence.applyChanges(serverDoc.document, msg.fields); - } else { - self._pushUpdate(updates, msg.collection, msg); - } - } - - _process_removed(msg, updates) { - const self = this; - const serverDoc = self._getServerDoc(msg.collection, MongoID.idParse(msg.id)); - if (serverDoc) { - // Some outstanding stub wrote here. - if (serverDoc.document === undefined) - throw new Error('Server sent removed for nonexisting id:' + msg.id); - serverDoc.document = undefined; - } else { - self._pushUpdate(updates, msg.collection, { - msg: 'removed', - collection: msg.collection, - id: msg.id - }); - } - } - - _process_updated(msg, updates) { - const self = this; - // Process "method done" messages. - - msg.methods.forEach((methodId) => { - const docs = self._documentsWrittenByStub[methodId] || {}; - Object.values(docs).forEach((written) => { - const serverDoc = self._getServerDoc(written.collection, written.id); - if (! serverDoc) { - throw new Error('Lost serverDoc for ' + JSON.stringify(written)); - } - if (! serverDoc.writtenByStubs[methodId]) { - throw new Error( - 'Doc ' + - JSON.stringify(written) + - ' not written by method ' + - methodId - ); - } - delete serverDoc.writtenByStubs[methodId]; - if (isEmpty(serverDoc.writtenByStubs)) { - // All methods whose stubs wrote this method have completed! We can - // now copy the saved document to the database (reverting the stub's - // change if the server did not write to this object, or applying the - // server's writes if it did). - - // This is a fake ddp 'replace' message. It's just for talking - // between livedata connections and minimongo. (We have to stringify - // the ID because it's supposed to look like a wire message.) - self._pushUpdate(updates, written.collection, { - msg: 'replace', - id: MongoID.idStringify(written.id), - replace: serverDoc.document - }); - // Call all flush callbacks. - - serverDoc.flushCallbacks.forEach((c) => { - c(); - }); - - // Delete this completed serverDocument. Don't bother to GC empty - // IdMaps inside self._serverDocuments, since there probably aren't - // many collections and they'll be written repeatedly. - self._serverDocuments[written.collection].remove(written.id); - } - }); - delete self._documentsWrittenByStub[methodId]; - - // We want to call the data-written callback, but we can't do so until all - // currently buffered messages are flushed. - const callbackInvoker = self._methodInvokers[methodId]; - if (! callbackInvoker) { - throw new Error('No callback invoker for method ' + methodId); - } - - self._runWhenAllServerDocsAreFlushed( - (...args) => callbackInvoker.dataVisible(...args) - ); - }); - } - - _process_ready(msg, updates) { - const self = this; - // Process "sub ready" messages. "sub ready" messages don't take effect - // until all current server documents have been flushed to the local - // database. We can use a write fence to implement this. - - msg.subs.forEach((subId) => { - self._runWhenAllServerDocsAreFlushed(() => { - const subRecord = self._subscriptions[subId]; - // Did we already unsubscribe? - if (!subRecord) return; - // Did we already receive a ready message? (Oops!) - if (subRecord.ready) return; - subRecord.ready = true; - subRecord.readyCallback && subRecord.readyCallback(); - subRecord.readyDeps.changed(); - }); - }); - } - // Ensures that "f" will be called after all documents currently in // _serverDocuments have been written to the local cache. f will not be called // if the connection is lost before then! @@ -1631,93 +1307,6 @@ export class Connection { } } - async _livedata_nosub(msg) { - const self = this; - - // First pass it through _livedata_data, which only uses it to help get - // towards quiescence. - await self._livedata_data(msg); - - // Do the rest of our processing immediately, with no - // buffering-until-quiescence. - - // we weren't subbed anyway, or we initiated the unsub. - if (! hasOwn.call(self._subscriptions, msg.id)) { - return; - } - - // XXX COMPAT WITH 1.0.3.1 #errorCallback - const errorCallback = self._subscriptions[msg.id].errorCallback; - const stopCallback = self._subscriptions[msg.id].stopCallback; - - self._subscriptions[msg.id].remove(); - - const meteorErrorFromMsg = msgArg => { - return ( - msgArg && - msgArg.error && - new Meteor.Error( - msgArg.error.error, - msgArg.error.reason, - msgArg.error.details - ) - ); - }; - - // XXX COMPAT WITH 1.0.3.1 #errorCallback - if (errorCallback && msg.error) { - errorCallback(meteorErrorFromMsg(msg)); - } - - if (stopCallback) { - stopCallback(meteorErrorFromMsg(msg)); - } - } - - async _livedata_result(msg) { - // id, result or error. error has error (code), reason, details - - const self = this; - - // Lets make sure there are no buffered writes before returning result. - if (! isEmpty(self._bufferedWrites)) { - await self._flushBufferedWrites(); - } - - // find the outstanding request - // should be O(1) in nearly all realistic use cases - if (isEmpty(self._outstandingMethodBlocks)) { - Meteor._debug('Received method result but no methods outstanding'); - return; - } - const currentMethodBlock = self._outstandingMethodBlocks[0].methods; - let i; - const m = currentMethodBlock.find((method, idx) => { - const found = method.methodId === msg.id; - if (found) i = idx; - return found; - }); - if (!m) { - Meteor._debug("Can't match method response to original method call", msg); - return; - } - - // Remove from current method block. This may leave the block empty, but we - // don't move on to the next block until the callback has been delivered, in - // _outstandingMethodFinished. - currentMethodBlock.splice(i, 1); - - if (hasOwn.call(msg, 'error')) { - m.receiveResult( - new Meteor.Error(msg.error.error, msg.error.reason, msg.error.details) - ); - } else { - // msg.result may be undefined if the method didn't return a - // value - m.receiveResult(undefined, msg.result); - } - } - _addOutstandingMethod(methodInvoker, options) { if (options?.wait) { // It's a wait method! Wait methods go in their own block. @@ -1786,11 +1375,6 @@ export class Connection { }); } - _livedata_error(msg) { - Meteor._debug('Received error from server: ', msg.reason); - if (msg.offendingMessage) Meteor._debug('For: ', msg.offendingMessage); - } - _sendOutstandingMethodBlocksMessages(oldOutstandingMethodBlocks) { const self = this; if (isEmpty(oldOutstandingMethodBlocks)) return; diff --git a/packages/ddp-client/common/message_processors.js b/packages/ddp-client/common/message_processors.js new file mode 100644 index 0000000000..09b13f742e --- /dev/null +++ b/packages/ddp-client/common/message_processors.js @@ -0,0 +1,336 @@ +import { DDPCommon } from 'meteor/ddp-common'; +import { Meteor } from 'meteor/meteor'; +import { DDP } from './namespace.js'; +import { EJSON } from 'meteor/ejson'; +import { isEmpty, hasOwn } from "meteor/ddp-common/utils"; + +export class MessageProcessors { + constructor(connection) { + this._connection = connection; + } + + /** + * @summary Process the connection message and set up the session + * @param {Object} msg The connection message + */ + async _livedata_connected(msg) { + const self = this._connection; + + if (self._version !== 'pre1' && self._heartbeatInterval !== 0) { + self._heartbeat = new DDPCommon.Heartbeat({ + heartbeatInterval: self._heartbeatInterval, + heartbeatTimeout: self._heartbeatTimeout, + onTimeout() { + self._lostConnection( + new DDP.ConnectionError('DDP heartbeat timed out') + ); + }, + sendPing() { + self._send({ msg: 'ping' }); + } + }); + self._heartbeat.start(); + } + + // If this is a reconnect, we'll have to reset all stores. + if (self._lastSessionId) self._resetStores = true; + + let reconnectedToPreviousSession; + if (typeof msg.session === 'string') { + reconnectedToPreviousSession = self._lastSessionId === msg.session; + self._lastSessionId = msg.session; + } + + if (reconnectedToPreviousSession) { + // Successful reconnection -- pick up where we left off. + return; + } + + // Server doesn't have our data anymore. Re-sync a new session. + + // Forget about messages we were buffering for unknown collections. They'll + // be resent if still relevant. + self._updatesForUnknownStores = Object.create(null); + + if (self._resetStores) { + // Forget about the effects of stubs. We'll be resetting all collections + // anyway. + self._documentsWrittenByStub = Object.create(null); + self._serverDocuments = Object.create(null); + } + + // Clear _afterUpdateCallbacks. + self._afterUpdateCallbacks = []; + + // Mark all named subscriptions which are ready as needing to be revived. + self._subsBeingRevived = Object.create(null); + Object.entries(self._subscriptions).forEach(([id, sub]) => { + if (sub.ready) { + self._subsBeingRevived[id] = true; + } + }); + + // Arrange for "half-finished" methods to have their callbacks run, and + // track methods that were sent on this connection so that we don't + // quiesce until they are all done. + // + // Start by clearing _methodsBlockingQuiescence: methods sent before + // reconnect don't matter, and any "wait" methods sent on the new connection + // that we drop here will be restored by the loop below. + self._methodsBlockingQuiescence = Object.create(null); + if (self._resetStores) { + const invokers = self._methodInvokers; + Object.keys(invokers).forEach(id => { + const invoker = invokers[id]; + if (invoker.gotResult()) { + // This method already got its result, but it didn't call its callback + // because its data didn't become visible. We did not resend the + // method RPC. We'll call its callback when we get a full quiesce, + // since that's as close as we'll get to "data must be visible". + self._afterUpdateCallbacks.push( + (...args) => invoker.dataVisible(...args) + ); + } else if (invoker.sentMessage) { + // This method has been sent on this connection (maybe as a resend + // from the last connection, maybe from onReconnect, maybe just very + // quickly before processing the connected message). + // + // We don't need to do anything special to ensure its callbacks get + // called, but we'll count it as a method which is preventing + // reconnect quiescence. (eg, it might be a login method that was run + // from onReconnect, and we don't want to see flicker by seeing a + // logged-out state.) + self._methodsBlockingQuiescence[invoker.methodId] = true; + } + }); + } + + self._messagesBufferedUntilQuiescence = []; + + // If we're not waiting on any methods or subs, we can reset the stores and + // call the callbacks immediately. + if (!self._waitingForQuiescence()) { + if (self._resetStores) { + for (const store of Object.values(self._stores)) { + await store.beginUpdate(0, true); + await store.endUpdate(); + } + self._resetStores = false; + } + self._runAfterUpdateCallbacks(); + } + } + + /** + * @summary Process various data messages from the server + * @param {Object} msg The data message + */ + async _livedata_data(msg) { + const self = this._connection; + + if (self._waitingForQuiescence()) { + self._messagesBufferedUntilQuiescence.push(msg); + + if (msg.msg === 'nosub') { + delete self._subsBeingRevived[msg.id]; + } + + if (msg.subs) { + msg.subs.forEach(subId => { + delete self._subsBeingRevived[subId]; + }); + } + + if (msg.methods) { + msg.methods.forEach(methodId => { + delete self._methodsBlockingQuiescence[methodId]; + }); + } + + if (self._waitingForQuiescence()) { + return; + } + + // No methods or subs are blocking quiescence! + // We'll now process and all of our buffered messages, reset all stores, + // and apply them all at once. + const bufferedMessages = self._messagesBufferedUntilQuiescence; + for (const bufferedMessage of Object.values(bufferedMessages)) { + await this._processOneDataMessage( + bufferedMessage, + self._bufferedWrites + ); + } + self._messagesBufferedUntilQuiescence = []; + } else { + await this._processOneDataMessage(msg, self._bufferedWrites); + } + + // Immediately flush writes when: + // 1. Buffering is disabled. Or; + // 2. any non-(added/changed/removed) message arrives. + const standardWrite = + msg.msg === "added" || + msg.msg === "changed" || + msg.msg === "removed"; + + if (self._bufferedWritesInterval === 0 || !standardWrite) { + await self._flushBufferedWrites(); + return; + } + + if (self._bufferedWritesFlushAt === null) { + self._bufferedWritesFlushAt = + new Date().valueOf() + self._bufferedWritesMaxAge; + } else if (self._bufferedWritesFlushAt < new Date().valueOf()) { + await self._flushBufferedWrites(); + return; + } + + if (self._bufferedWritesFlushHandle) { + clearTimeout(self._bufferedWritesFlushHandle); + } + self._bufferedWritesFlushHandle = setTimeout(() => { + self._liveDataWritesPromise = self._flushBufferedWrites(); + if (Meteor._isPromise(self._liveDataWritesPromise)) { + self._liveDataWritesPromise.finally( + () => (self._liveDataWritesPromise = undefined) + ); + } + }, self._bufferedWritesInterval); + } + + /** + * @summary Process individual data messages by type + * @private + */ + async _processOneDataMessage(msg, updates) { + const messageType = msg.msg; + + switch (messageType) { + case 'added': + await this._connection._process_added(msg, updates); + break; + case 'changed': + this._connection._process_changed(msg, updates); + break; + case 'removed': + this._connection._process_removed(msg, updates); + break; + case 'ready': + this._connection._process_ready(msg, updates); + break; + case 'updated': + this._connection._process_updated(msg, updates); + break; + case 'nosub': + // ignore this + break; + default: + Meteor._debug('discarding unknown livedata data message type', msg); + } + } + + /** + * @summary Handle method results arriving from the server + * @param {Object} msg The method result message + */ + async _livedata_result(msg) { + const self = this._connection; + + // Lets make sure there are no buffered writes before returning result. + if (!isEmpty(self._bufferedWrites)) { + await self._flushBufferedWrites(); + } + + // find the outstanding request + // should be O(1) in nearly all realistic use cases + if (isEmpty(self._outstandingMethodBlocks)) { + Meteor._debug('Received method result but no methods outstanding'); + return; + } + const currentMethodBlock = self._outstandingMethodBlocks[0].methods; + let i; + const m = currentMethodBlock.find((method, idx) => { + const found = method.methodId === msg.id; + if (found) i = idx; + return found; + }); + if (!m) { + Meteor._debug("Can't match method response to original method call", msg); + return; + } + + // Remove from current method block. This may leave the block empty, but we + // don't move on to the next block until the callback has been delivered, in + // _outstandingMethodFinished. + currentMethodBlock.splice(i, 1); + + if (hasOwn.call(msg, 'error')) { + m.receiveResult( + new Meteor.Error(msg.error.error, msg.error.reason, msg.error.details) + ); + } else { + // msg.result may be undefined if the method didn't return a value + m.receiveResult(undefined, msg.result); + } + } + + /** + * @summary Handle "nosub" messages arriving from the server + * @param {Object} msg The nosub message + */ + async _livedata_nosub(msg) { + const self = this._connection; + + // First pass it through _livedata_data, which only uses it to help get + // towards quiescence. + await this._livedata_data(msg); + + // Do the rest of our processing immediately, with no + // buffering-until-quiescence. + + // we weren't subbed anyway, or we initiated the unsub. + if (!hasOwn.call(self._subscriptions, msg.id)) { + return; + } + + // XXX COMPAT WITH 1.0.3.1 #errorCallback + const errorCallback = self._subscriptions[msg.id].errorCallback; + const stopCallback = self._subscriptions[msg.id].stopCallback; + + self._subscriptions[msg.id].remove(); + + const meteorErrorFromMsg = msgArg => { + return ( + msgArg && + msgArg.error && + new Meteor.Error( + msgArg.error.error, + msgArg.error.reason, + msgArg.error.details + ) + ); + }; + + // XXX COMPAT WITH 1.0.3.1 #errorCallback + if (errorCallback && msg.error) { + errorCallback(meteorErrorFromMsg(msg)); + } + + if (stopCallback) { + stopCallback(meteorErrorFromMsg(msg)); + } + } + + /** + * @summary Handle errors from the server + * @param {Object} msg The error message + */ + _livedata_error(msg) { + Meteor._debug('Received error from server: ', msg.reason); + if (msg.offendingMessage) Meteor._debug('For: ', msg.offendingMessage); + } + + // Document change message processors will be defined in a separate class +} \ No newline at end of file From 6b5248e2367c061f0c8c34704f93166ca7f1c9d8 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Wed, 6 Nov 2024 15:27:04 -0400 Subject: [PATCH 15/48] run adds in parallel --- packages/mongo/observe_handle.ts | 10 +++++----- packages/mongo/observe_multiplex.ts | 19 ++++++++++++------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/packages/mongo/observe_handle.ts b/packages/mongo/observe_handle.ts index b2d1924088..1ff2248815 100644 --- a/packages/mongo/observe_handle.ts +++ b/packages/mongo/observe_handle.ts @@ -15,11 +15,11 @@ export class ObserveHandle { nonMutatingCallbacks: boolean; _stopped: boolean; - _added?: (...args: any[]) => void; - _addedBefore?: (...args: any[]) => void; - _changed?: (...args: any[]) => void; - _movedBefore?: (...args: any[]) => void; - _removed?: (...args: any[]) => void; + _added?: (...args: any[]) => Promise; + _addedBefore?: (...args: any[]) => Promise; + _changed?: (...args: any[]) => Promise; + _movedBefore?: (...args: any[]) => Promise; + _removed?: (...args: any[]) => Promise; constructor(multiplexer: any, callbacks: Record, nonMutatingCallbacks: boolean) { this._multiplexer = multiplexer; diff --git a/packages/mongo/observe_multiplex.ts b/packages/mongo/observe_multiplex.ts index 559c983ab1..b17a9e993d 100644 --- a/packages/mongo/observe_multiplex.ts +++ b/packages/mongo/observe_multiplex.ts @@ -164,19 +164,24 @@ export class ObserveMultiplexer { async _sendAdds(handle: ObserveHandle): Promise { const add = this._ordered ? handle._addedBefore : handle._added; - if (!add) return; - await this._cache.docs.forEachAsync(async (doc: any, id: string) => { - if (!(handle._id in this._handles!)) + const addPromises: Promise[] = []; + + this._cache.docs.forEach((doc: any, id: string) => { + if (!(handle._id in this._handles!)) { throw Error("handle got removed before sending initial adds!"); + } const { _id, ...fields } = handle.nonMutatingCallbacks ? doc : EJSON.clone(doc); - if (this._ordered) - await add(id, fields, null); - else - await add(id, fields); + const promise = this._ordered ? + add(id, fields, null) : + add(id, fields); + + addPromises.push(promise); }); + + await Promise.all(addPromises); } } \ No newline at end of file From 12993e9f2e8c53112b37c81f5bca7319d1745e1a Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Thu, 7 Nov 2024 08:30:31 -0400 Subject: [PATCH 16/48] send initial adds first; parallelize and batch asynchronous queue --- packages/meteor/async_helpers.js | 139 ----------------------- packages/meteor/asynchronous_queue.js | 154 ++++++++++++++++++++++++++ packages/meteor/package.js | 1 + packages/mongo/observe_handle.ts | 10 ++ packages/mongo/observe_multiplex.ts | 13 ++- 5 files changed, 175 insertions(+), 142 deletions(-) create mode 100644 packages/meteor/asynchronous_queue.js diff --git a/packages/meteor/async_helpers.js b/packages/meteor/async_helpers.js index 240915eeed..bbf8bdc1bf 100644 --- a/packages/meteor/async_helpers.js +++ b/packages/meteor/async_helpers.js @@ -24,145 +24,6 @@ FakeDoubleEndedQueue.prototype.isEmpty = function () { Meteor._DoubleEndedQueue = Meteor.isServer ? Npm.require('denque') : FakeDoubleEndedQueue; -// Meteor._SynchronousQueue is a queue which runs task functions serially. -// Tasks are assumed to be synchronous: ie, it's assumed that they are -// done when they return. -// -// It has two methods: -// - queueTask queues a task to be run, and returns immediately. -// - runTask queues a task to be run, and then yields. It returns -// when the task finishes running. -// -// It's safe to call queueTask from within a task, but not runTask (unless -// you're calling runTask from a nested Fiber). -// -// Somewhat inspired by async.queue, but specific to blocking tasks. -// XXX break this out into an NPM module? -// XXX could maybe use the npm 'schlock' module instead, which would -// also support multiple concurrent "read" tasks -// -function AsynchronousQueue () { - this._taskHandles = new Meteor._DoubleEndedQueue(); - this._runningOrRunScheduled = false; - // This is true if we're currently draining. While we're draining, a further - // drain is a noop, to prevent infinite loops. "drain" is a heuristic type - // operation, that has a meaning like unto "what a naive person would expect - // when modifying a table from an observe" - this._draining = false; -} -Object.assign(AsynchronousQueue.prototype, { - queueTask(task) { - const self = this; - self._taskHandles.push({ - task: Meteor.bindEnvironment(task, function (e) { - Meteor._debug('Exception from task', e); - throw e; - }), - name: task.name - }); - self._scheduleRun(); - }, - - async _scheduleRun() { - // Already running or scheduled? Do nothing. - if (this._runningOrRunScheduled) - return; - - this._runningOrRunScheduled = true; - - let resolve; - const promise = new Promise(r => resolve = r); - const runImmediateHandle = (fn) => { - if (Meteor.isServer) { - Meteor._runFresh(() => setImmediate(fn)) - return; - } - setTimeout(fn, 0); - }; - runImmediateHandle(() => { - this._run().finally(resolve); - }); - return promise; - }, - - async _run() { - if (!this._runningOrRunScheduled) - throw new Error("expected to be _runningOrRunScheduled"); - - if (this._taskHandles.isEmpty()) { - // Done running tasks! Don't immediately schedule another run, but - // allow future tasks to do so. - this._runningOrRunScheduled = false; - return; - } - const taskHandle = this._taskHandles.shift(); - let exception; - // Run the task. - try { - await taskHandle.task(); - } catch (err) { - if (taskHandle.resolver) { - // We'll throw this exception through runTask. - exception = err; - } else { - Meteor._debug("Exception in queued task", err); - } - } - - // Soon, run the next task, if there is any. - this._runningOrRunScheduled = false; - this._scheduleRun(); - - if (taskHandle.resolver) { - if (exception) { - taskHandle.resolver(null, exception); - } else { - taskHandle.resolver(); - } - } - }, - - async runTask(task) { - let resolver; - const promise = new Promise( - (resolve, reject) => - (resolver = (res, rej) => { - if (rej) { - reject(rej); - return; - } - resolve(res); - }) - ); - - const handle = { - task, - name: task.name, - resolver, - }; - this._taskHandles.push(handle); - await this._scheduleRun(); - return promise; - }, - - flush() { - return this.runTask(() => { }); - }, - - async drain() { - if (this._draining) - return; - - this._draining = true; - while (!this._taskHandles.isEmpty()) { - await this.flush(); - } - this._draining = false; - } -}); - -Meteor._AsynchronousQueue = AsynchronousQueue; - // Sleep. Mostly used for debugging (eg, inserting latency into server // methods). diff --git a/packages/meteor/asynchronous_queue.js b/packages/meteor/asynchronous_queue.js new file mode 100644 index 0000000000..fe1a30c783 --- /dev/null +++ b/packages/meteor/asynchronous_queue.js @@ -0,0 +1,154 @@ +class AsynchronousQueue { + /** + * Creates a queue that processes tasks in parallel batches while preserving completion order + * when needed. Configurable batch size and concurrency limits help optimize throughput. + */ + constructor({ + batchSize = 50, + maxConcurrent = 10, + orderMatters = false + } = {}) { + this._taskHandles = new Meteor._DoubleEndedQueue(); + this._runningOrRunScheduled = false; + this._draining = false; + this._batchSize = batchSize; + this._maxConcurrent = maxConcurrent; + this._orderMatters = orderMatters; + this._activePromises = new Set(); + } + + queueTask(task) { + const wrappedTask = Meteor.bindEnvironment(task, function (e) { + Meteor._debug('Exception from task', e); + throw e; + }); + + this._taskHandles.push({ + task: wrappedTask, + name: task.name + }); + + this._scheduleRun(); + } + + async _scheduleRun() { + if (this._runningOrRunScheduled) return; + this._runningOrRunScheduled = true; + + const runImmediateHandle = (fn) => { + if (Meteor.isServer) { + Meteor._runFresh(() => setImmediate(fn)); + return; + } + setTimeout(fn, 0); + }; + + return new Promise(resolve => { + runImmediateHandle(() => { + this._run().finally(resolve); + }); + }); + } + + async _run() { + if (!this._runningOrRunScheduled) { + throw new Error("expected to be _runningOrRunScheduled"); + } + + if (this._taskHandles.isEmpty()) { + this._runningOrRunScheduled = false; + return; + } + + // Collect tasks for the current batch + const batch = []; + while (batch.length < this._batchSize && !this._taskHandles.isEmpty()) { + batch.push(this._taskHandles.shift()); + } + + // Process batch + if (this._orderMatters) { + await this._processOrderedBatch(batch); + } else { + await this._processParallelBatch(batch); + } + + // Schedule next batch if there are more tasks + this._runningOrRunScheduled = false; + if (!this._taskHandles.isEmpty()) { + this._scheduleRun(); + } + } + + async _processParallelBatch(batch) { + const taskPromises = batch.map(async taskHandle => { + try { + const promise = taskHandle.task(); + this._activePromises.add(promise); + const result = await promise; + this._activePromises.delete(promise); + + if (taskHandle.resolver) { + taskHandle.resolver(result); + } + } catch (err) { + if (taskHandle.resolver) { + taskHandle.resolver(null, err); + } else { + Meteor._debug("Exception in queued task", err); + } + } + }); + + // Process in chunks to control concurrency + for (let i = 0; i < taskPromises.length; i += this._maxConcurrent) { + const chunk = taskPromises.slice(i, i + this._maxConcurrent); + await Promise.all(chunk); + } + } + + async _processOrderedBatch(batch) { + for (const taskHandle of batch) { + try { + const result = await taskHandle.task(); + if (taskHandle.resolver) { + taskHandle.resolver(result); + } + } catch (err) { + if (taskHandle.resolver) { + taskHandle.resolver(null, err); + } else { + Meteor._debug("Exception in queued task", err); + } + } + } + } + + async runTask(task) { + return new Promise((resolve, reject) => { + const resolver = (res, err) => err ? reject(err) : resolve(res); + this._taskHandles.push({ task, name: task.name, resolver }); + this._scheduleRun(); + }); + } + + flush() { + return this.runTask(() => {}); + } + + async drain() { + if (this._draining) return; + this._draining = true; + + while (!this._taskHandles.isEmpty() || this._activePromises.size > 0) { + await this.flush(); + if (this._activePromises.size > 0) { + await Promise.all(Array.from(this._activePromises)); + } + } + + this._draining = false; + } +} + +Meteor._AsynchronousQueue = AsynchronousQueue; \ No newline at end of file diff --git a/packages/meteor/package.js b/packages/meteor/package.js index 9071ad502c..5a27379ec4 100644 --- a/packages/meteor/package.js +++ b/packages/meteor/package.js @@ -34,6 +34,7 @@ Package.onUse(function (api) { api.addFiles('timers.js', ['client', 'server']); api.addFiles('errors.js', ['client', 'server']); api.addFiles('asl-helpers.js', 'server'); + api.addFiles('asynchronous_queue.js', 'server'); api.addFiles('async_helpers.js', ['client', 'server']); api.addFiles('fiber_stubs_client.js', 'client'); api.addFiles('asl-helpers-client.js', 'client'); diff --git a/packages/mongo/observe_handle.ts b/packages/mongo/observe_handle.ts index 1ff2248815..a18f213400 100644 --- a/packages/mongo/observe_handle.ts +++ b/packages/mongo/observe_handle.ts @@ -15,6 +15,9 @@ export class ObserveHandle { nonMutatingCallbacks: boolean; _stopped: boolean; + public initialAddsSentResolver: (value: void) => void = () => {}; + public initialAddsSent: Promise + _added?: (...args: any[]) => Promise; _addedBefore?: (...args: any[]) => Promise; _changed?: (...args: any[]) => Promise; @@ -40,6 +43,13 @@ export class ObserveHandle { this._stopped = false; this._id = nextObserveHandleId++; this.nonMutatingCallbacks = nonMutatingCallbacks; + + this.initialAddsSent = new Promise(resolve => { + return this.initialAddsSentResolver = () => { + resolve(); + this.initialAddsSent = Promise.resolve(); + }; + }); } async stop() { diff --git a/packages/mongo/observe_multiplex.ts b/packages/mongo/observe_multiplex.ts index b17a9e993d..da8bda0bd9 100644 --- a/packages/mongo/observe_multiplex.ts +++ b/packages/mongo/observe_multiplex.ts @@ -140,7 +140,7 @@ export class ObserveMultiplexer { return !!this._isReady; } - _applyCallback(callbackName: string, args: any[]): void { + async _applyCallback(callbackName: string, args: any[]) { this._queue.queueTask(async () => { if (!this._handles) return; @@ -152,12 +152,17 @@ export class ObserveMultiplexer { for (const handleId of Object.keys(this._handles)) { const handle = this._handles && this._handles[handleId]; + if (!handle) return; + const callback = (handle as any)[`_${callbackName}`]; - callback && (await callback.apply( + + if (!callback) continue; + + handle.initialAddsSent.then(callback.apply( null, handle.nonMutatingCallbacks ? args : EJSON.clone(args) - )); + )) } }); } @@ -183,5 +188,7 @@ export class ObserveMultiplexer { }); await Promise.all(addPromises); + + handle.initialAddsSentResolver(); } } \ No newline at end of file From de7eaf79b74c1eb8fb13c977cceba31c1bf98b2a Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Thu, 7 Nov 2024 16:53:24 -0400 Subject: [PATCH 17/48] fix check running twice --- .github/workflows/check-syntax.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/check-syntax.yml b/.github/workflows/check-syntax.yml index 90aa5285bd..a20bb011ca 100644 --- a/.github/workflows/check-syntax.yml +++ b/.github/workflows/check-syntax.yml @@ -1,6 +1,5 @@ name: Check legacy syntax on: - - push - pull_request jobs: check-code-style: From e8d6f848c21bab69b9cf96548d2bde2c387daef3 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Thu, 7 Nov 2024 16:55:16 -0400 Subject: [PATCH 18/48] ignore asynchronous queue from check --- scripts/admin/check-legacy-syntax/check-syntax.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/admin/check-legacy-syntax/check-syntax.js b/scripts/admin/check-legacy-syntax/check-syntax.js index 66fb4fd815..fdbe82b061 100644 --- a/scripts/admin/check-legacy-syntax/check-syntax.js +++ b/scripts/admin/check-legacy-syntax/check-syntax.js @@ -34,6 +34,7 @@ const packages = { // Ignored server files that has a features > 2016 ignoredFiles: [ "async_helpers.js", + "asynchronous_queue.js", ] }, "accounts-ui": {}, From b11977bbacf6653f0ef7eb5a2c01cdcf0ba2c877 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Thu, 7 Nov 2024 17:01:34 -0400 Subject: [PATCH 19/48] add timeout mechanism --- packages/mongo/observe_handle.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/mongo/observe_handle.ts b/packages/mongo/observe_handle.ts index a18f213400..d084322a61 100644 --- a/packages/mongo/observe_handle.ts +++ b/packages/mongo/observe_handle.ts @@ -45,9 +45,16 @@ export class ObserveHandle { this.nonMutatingCallbacks = nonMutatingCallbacks; this.initialAddsSent = new Promise(resolve => { - return this.initialAddsSentResolver = () => { + const ready = () => { resolve(); this.initialAddsSent = Promise.resolve(); + } + + const timeout = setTimeout(ready, 30000) + + this.initialAddsSentResolver = () => { + ready(); + clearTimeout(timeout); }; }); } From 86a07cc9eb329bad61645da191dc573487460d30 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Fri, 8 Nov 2024 07:58:17 -0400 Subject: [PATCH 20/48] disable punycode warning on app process --- tools/runners/run-app.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/runners/run-app.js b/tools/runners/run-app.js index bd76e05317..38f904224f 100644 --- a/tools/runners/run-app.js +++ b/tools/runners/run-app.js @@ -10,8 +10,8 @@ var Profile = require('../tool-env/profile').Profile; var release = require('../packaging/release.js'); import { pluginVersionsFromStarManifest } from '../cordova/index.js'; import { closeAllWatchers } from "../fs/safe-watcher"; -import { eachline } from "../utils/eachline"; import { loadIsopackage } from '../tool-env/isopackets.js'; +import { eachline } from "../utils/eachline"; // Parse out s as if it were a bash command line. var bashParse = function (s) { @@ -250,6 +250,8 @@ Object.assign(AppProcess.prototype, { opts.push("--inspect=" + self.inspect.port); } + opts.push(`--require=${files.convertToOSPath(files.pathJoin(__dirname, '../node-process-warnings.js'))}`) + opts.push(entryPoint); // Call node From 69683dafb883c6dc80f4a9bb92839a306c824855 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Fri, 8 Nov 2024 08:21:44 -0400 Subject: [PATCH 21/48] exclude roles from travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 4d9997a4d7..a13c416d89 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,7 @@ env: - CXX=g++-12 - phantom=false - PUPPETEER_DOWNLOAD_PATH=~/.npm/chromium + - TEST_PACKAGES_EXCLUDE=roles addons: apt: sources: From 92329e78bb68a0f580130baf94139b4a4a00b664 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Fri, 8 Nov 2024 08:31:37 -0400 Subject: [PATCH 22/48] remove shrinkwraps from git (annoying things!) --- .../.npm/package/npm-shrinkwrap.json | 45 -- .../.npm/package/npm-shrinkwrap.json | 306 ---------- .../.npm/package/npm-shrinkwrap.json | 10 - .../.npm/package/npm-shrinkwrap.json | 45 -- .../.npm/package/npm-shrinkwrap.json | 45 -- .../.npm/package/npm-shrinkwrap.json | 30 - .../.npm/package/npm-shrinkwrap.json | 70 --- .../http/.npm/package/npm-shrinkwrap.json | 20 - .../plugin/lintJshint/npm-shrinkwrap.json | 154 ----- .../compileStylusBatch/npm-shrinkwrap.json | 177 ------ .../.npm/package/npm-shrinkwrap.json | 10 - .../.npm/package/npm-shrinkwrap.json | 10 - .../.npm/package/npm-shrinkwrap.json | 10 - .../.npm/package/npm-shrinkwrap.json | 15 - .../.npm/package/npm-shrinkwrap.json | 15 - .../email/.npm/package/npm-shrinkwrap.json | 65 -- .../es5-shim/.npm/package/npm-shrinkwrap.json | 10 - .../fetch/.npm/package/npm-shrinkwrap.json | 30 - .../.npm/package/npm-shrinkwrap.json | 384 ------------ .../.npm/package/npm-shrinkwrap.json | 15 - .../logging/.npm/package/npm-shrinkwrap.json | 45 -- .../.npm/package/npm-shrinkwrap.json | 10 - .../meteor/.npm/package/npm-shrinkwrap.json | 10 - .../.npm/package/npm-shrinkwrap.json | 65 -- .../.npm/package/npm-shrinkwrap.json | 10 - .../modules/.npm/package/npm-shrinkwrap.json | 55 -- .../mongo/.npm/package/npm-shrinkwrap.json | 45 -- .../compileLessBatch/npm-shrinkwrap.json | 115 ---- .../.npm/package/npm-shrinkwrap.json | 10 - .../.npm/package/npm-shrinkwrap.json | 65 -- .../oauth/.npm/package/npm-shrinkwrap.json | 115 ---- .../.npm/package/npm-shrinkwrap.json | 20 - .../promise/.npm/package/npm-shrinkwrap.json | 15 - .../.npm/package/npm-shrinkwrap.json | 25 - .../.npm/package/npm-shrinkwrap.json | 55 -- .../.npm/package/npm-shrinkwrap.json | 45 -- .../.npm/package/npm-shrinkwrap.json | 10 - .../tinytest/.npm/package/npm-shrinkwrap.json | 10 - packages/url/.npm/package/npm-shrinkwrap.json | 10 - .../webapp/.npm/package/npm-shrinkwrap.json | 576 ------------------ 40 files changed, 2777 deletions(-) delete mode 100644 packages/accounts-2fa/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/accounts-password/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/boilerplate-generator-tests/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/boilerplate-generator/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/constraint-solver/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/ddp-client/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/ddp-server/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/deprecated/http/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/deprecated/jshint/.npm/plugin/lintJshint/npm-shrinkwrap.json delete mode 100644 packages/deprecated/stylus/.npm/plugin/compileStylusBatch/npm-shrinkwrap.json delete mode 100644 packages/deprecated/underscore/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/ecmascript-runtime-client/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/ecmascript-runtime-server/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/ecmascript-runtime/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/ecmascript/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/email/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/es5-shim/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/fetch/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/force-ssl-common/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/inter-process-messaging/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/logging/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/logic-solver/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/meteor/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/minifier-js/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/modules-runtime/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/modules/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/mongo/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/non-core/less/.npm/plugin/compileLessBatch/npm-shrinkwrap.json delete mode 100644 packages/non-core/mongo-decimal/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/npm-mongo/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/oauth/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/package-version-parser/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/promise/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/react-fast-refresh/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/server-render/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/socket-stream-client/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/test-server-tests-in-console-once/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/tinytest/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/url/.npm/package/npm-shrinkwrap.json delete mode 100644 packages/webapp/.npm/package/npm-shrinkwrap.json diff --git a/packages/accounts-2fa/.npm/package/npm-shrinkwrap.json b/packages/accounts-2fa/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index c9264049b9..0000000000 --- a/packages/accounts-2fa/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "@types/node": { - "version": "22.8.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.7.tgz", - "integrity": "sha512-LidcG+2UeYIWcMuMUpBKOnryBWG/rnmOHQR5apjn8myTQcx3rinFRn7DcIFhMnS0PPFSC6OafdIKEad0lj6U0Q==" - }, - "@types/notp": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/notp/-/notp-2.0.5.tgz", - "integrity": "sha512-ZsZS0PYUa6ZE4K3yOGerBvaxCp4ePf6ZmkFbPeilcqz2Ui/lmXox7KlRt7XZkXzqUgXhFLkc09ixyVmFLCU3gQ==" - }, - "node-2fa": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/node-2fa/-/node-2fa-2.0.3.tgz", - "integrity": "sha512-PQldrOhjuoZyoydMvMSctllPN1ZPZ1/NwkEcgYwY9faVqE/OymxR+3awPpbWZxm6acLKqvmNqQmdqTsqYyflFw==" - }, - "notp": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/notp/-/notp-2.0.3.tgz", - "integrity": "sha512-oBig/2uqkjQ5AkBuw4QJYwkEWa/q+zHxI5/I5z6IeP2NT0alpJFsP/trrfCC+9xOAgQSZXssNi962kp5KBmypQ==" - }, - "qrcode-svg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/qrcode-svg/-/qrcode-svg-1.1.0.tgz", - "integrity": "sha512-XyQCIXux1zEIA3NPb0AeR8UMYvXZzWEhgdBgBjH9gO7M48H9uoHzviNz8pXw3UzrAcxRRRn9gxHewAVK7bn9qw==" - }, - "thirty-two": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz", - "integrity": "sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA==" - }, - "tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - }, - "undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" - } - } -} diff --git a/packages/accounts-password/.npm/package/npm-shrinkwrap.json b/packages/accounts-password/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 4960480477..0000000000 --- a/packages/accounts-password/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,306 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "@mapbox/node-pre-gyp": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", - "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==" - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==" - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" - }, - "are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==" - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "bcrypt": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.1.tgz", - "integrity": "sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw==" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==" - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" - }, - "debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==" - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" - }, - "detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==" - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==" - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==" - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==" - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - } - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==" - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==" - } - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" - }, - "node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==" - }, - "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==" - }, - "npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==" - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==" - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==" - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==" - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==" - }, - "tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==" - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==" - }, - "wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==" - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } -} diff --git a/packages/boilerplate-generator-tests/.npm/package/npm-shrinkwrap.json b/packages/boilerplate-generator-tests/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index d749aa7131..0000000000 --- a/packages/boilerplate-generator-tests/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" - } - } -} diff --git a/packages/boilerplate-generator/.npm/package/npm-shrinkwrap.json b/packages/boilerplate-generator/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index e9ca2307b4..0000000000 --- a/packages/boilerplate-generator/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "bluebird": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", - "integrity": "sha512-UfFSr22dmHPQqPP9XWHRhq+gWnHCYguQGkXQlbyPtW5qTnhFWA8/iXg765tH0cAjy7l/zPJ1aBTO0g5XgA7kvQ==" - }, - "combined-stream2": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/combined-stream2/-/combined-stream2-1.1.2.tgz", - "integrity": "sha512-sVqUHJmbdVm+HZWy4l34BPLczxI4fltN4Bm2vcvASsqBIXW4xFb4TRkwM8bw/UUXK9/OdHdAwi2cRYVEKrxzbg==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==" - }, - "lodash.template": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", - "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==" - }, - "lodash.templatesettings": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", - "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "stream-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-length/-/stream-length-1.0.2.tgz", - "integrity": "sha512-aI+qKFiwoDV4rsXiS7WRoCt+v2RX1nUj17+KJC5r2gfh5xoSJIfP6Y3Do/HtvesFcTSWthIuJ3l1cvKQY/+nZg==" - } - } -} diff --git a/packages/constraint-solver/.npm/package/npm-shrinkwrap.json b/packages/constraint-solver/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 2ecd80adff..0000000000 --- a/packages/constraint-solver/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "lodash.groupby": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.groupby/-/lodash.groupby-4.6.0.tgz", - "integrity": "sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==" - }, - "lodash.has": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", - "integrity": "sha512-rnYUdIo6xRCJnQmbVFEwcxF144erlD+M3YcJUVesflU9paQaE8p+fJDcIQrlMYbxoANFL+AB9hZrzSBBk5PL+g==" - }, - "lodash.isempty": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", - "integrity": "sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==" - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" - }, - "lodash.isobject": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", - "integrity": "sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA==" - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" - }, - "lodash.zip": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz", - "integrity": "sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg==" - } - } -} diff --git a/packages/ddp-client/.npm/package/npm-shrinkwrap.json b/packages/ddp-client/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 1fa71b508b..0000000000 --- a/packages/ddp-client/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "@sinonjs/commons": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==" - }, - "@sinonjs/fake-timers": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.0.5.tgz", - "integrity": "sha512-fUt6b15bjV/VW93UP5opNXJxdwZSbK1EdiwnhN7XrQrcpaOhMJpZ/CjwFpM3THpxwA+YviBUJKSuEqKlCK5alw==" - }, - "lodash.has": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", - "integrity": "sha512-rnYUdIo6xRCJnQmbVFEwcxF144erlD+M3YcJUVesflU9paQaE8p+fJDcIQrlMYbxoANFL+AB9hZrzSBBk5PL+g==" - }, - "lodash.identity": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash.identity/-/lodash.identity-3.0.0.tgz", - "integrity": "sha512-AupTIzdLQxJS5wIYUQlgGyk2XRTfGXA+MCghDHqZk0pzUNYvd3EESS6dkChNauNYVIutcb0dfHw1ri9Q1yPV8Q==" - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" - } - } -} diff --git a/packages/ddp-server/.npm/package/npm-shrinkwrap.json b/packages/ddp-server/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 542ff6f6fe..0000000000 --- a/packages/ddp-server/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==" - }, - "http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" - }, - "lodash.isempty": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", - "integrity": "sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==" - }, - "lodash.isobject": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", - "integrity": "sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA==" - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" - }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" - }, - "lru_map": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.4.1.tgz", - "integrity": "sha512-I+lBvqMMFfqaV8CJCISjI3wbjmwVu/VyOoU7+qtu9d7ioW5klMgsTTiUOUp+DJvfTTzKXoPbyC6YfgkNcyPSOg==" - }, - "permessage-deflate": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/permessage-deflate/-/permessage-deflate-0.1.7.tgz", - "integrity": "sha512-EUNi/RIsyJ1P1u9QHFwMOUWMYetqlE22ZgGbad7YP856WF4BFF0B7DuNy6vEGsgNNud6c/SkdWzkne71hH8MjA==" - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, - "websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==" - }, - "websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" - } - } -} diff --git a/packages/deprecated/http/.npm/package/npm-shrinkwrap.json b/packages/deprecated/http/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index dbac0874ce..0000000000 --- a/packages/deprecated/http/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==" - }, - "express-basic-auth": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/express-basic-auth/-/express-basic-auth-1.2.1.tgz", - "integrity": "sha512-L6YQ1wQ/mNjVLAmK3AG1RK6VkokA1BIY6wmiH304Xtt/cLTps40EusZsU1Uop+v9lTDPxdtzbFmdXfFO3KEnwA==" - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } -} diff --git a/packages/deprecated/jshint/.npm/plugin/lintJshint/npm-shrinkwrap.json b/packages/deprecated/jshint/.npm/plugin/lintJshint/npm-shrinkwrap.json deleted file mode 100644 index a7e2c547b5..0000000000 --- a/packages/deprecated/jshint/.npm/plugin/lintJshint/npm-shrinkwrap.json +++ /dev/null @@ -1,154 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==" - }, - "cli": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/cli/-/cli-0.6.6.tgz", - "integrity": "sha512-4H6IzYk78R+VBeJ3fH3VQejcQRkGPR+kMjA9n30srEN+YVMPJLHfoQDtLquIzcLnfrlUrVA8qSQRB9fdgWpUBw==" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha512-duS7VP5pvfsNLDvL1O4VOEbw37AI3A4ZUQYemvDlnpGrNu9tprR7BYWpDYwC0Xia0Zxz5ZupdiIrUp0GH1aXfg==" - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha512-AsElvov3LoNB7tf5k37H2jYSB+ZZPMT5sG2QjJCcdlV5chIv6htBUBUui2IKRjgtKAKtCBN7Zbwa+MtwLjSeNw==" - }, - "dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", - "dependencies": { - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" - } - } - }, - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha512-q9bUwjfp7Eif8jWxxxPSykdRZAb6GkguBGSgvvCrhI9wB71W2K/Kvv4E61CF/mcCfnVJDeDWx/Vb/uAqbDj6UQ==" - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==" - }, - "entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha512-LbLqfXgJMmy81t+7c14mnulFHJ170cM6E+0vMXR9k/ZiZwgX8i5pNgjTCX3SO4VeUsFLV+8InixoretwU+MjBQ==" - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==" - }, - "glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", - "integrity": "sha512-hVb0zwEZwC1FXSKRPFTeOtN7AArJcJlI6ULGLtrstaswKNlrTJqAA+1lYlSUop4vjA423xlBzqfVS3iWGlqJ+g==", - "dependencies": { - "minimatch": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", - "integrity": "sha512-WFX1jI1AaxNTZVOHLBVazwTWKaQjoykSzCBNXB72vDTCzopQGtyP91tKdFK5cv1+qMwPyiTu1HqUriqplI8pcA==" - } - } - }, - "htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha512-hBxEg3CYXe+rPIua8ETe7tmG3XDn9B0edOE/e9wH2nLczxzgdu0m0aNHY+5wFZiviLWLdANPJTssa92dMcXQ5Q==" - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" - }, - "jshint": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.7.0.tgz", - "integrity": "sha512-omn1ROF3q3//EWz+XkKMT1P7pHnJE8wqcpJ8AUk13nNFugVzzDeGJW8S4dtGXW6hYB5dlSy90zVbRojolLMSwA==" - }, - "lodash": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.6.0.tgz", - "integrity": "sha512-fysFKsJtaOtRGZT/b3Xx03iyEmO0zjU+d1HBH5NcEaUjtg7XO0wDY5I7IJFfr2rguJt0Rve2V32426Za3zYyRw==" - }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha512-WpibWJ60c3AgAz8a2iYErDrcT2C7OmKnsWhIcHOjkUHFjkXncJhtLxNSqUmxRxRunpb5I8Vprd7aNSd2NtksJQ==" - }, - "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha512-jQo6o1qSVLEWaw3l+bwYA2X0uLuK2KjNh2wjgO7Q/9UJnXr1Q3yQKR8BI0/Bt/rPg75e6SMW4hW/6cBHVTZUjA==" - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==" - }, - "shelljs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", - "integrity": "sha512-Ny0KN4dyT8ZSCE0frtcbAJGoM/HTArpyPkeli1/00aYfm0sbD/Gk/4x7N2DP9QKGpBsiQH7n6rpm1L79RtviEQ==" - }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha512-fCvEXfh6NWpm+YSuY2bpXb/VIihqWA6hLsgboC+0nl71Q7N7o2eaCW8mJa/NLvQhs6jpd3VZV4UiUQlV6+lc8g==" - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" - }, - "strip-json-comments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", - "integrity": "sha512-AOPG8EBc5wAikaG1/7uFCNFJwnKOuQwFTpYBdTW6OvWHeZBQBrAA/amefHGrEiOnCPcLFZK6FUPtWVKpQVIRgg==" - } - } -} diff --git a/packages/deprecated/stylus/.npm/plugin/compileStylusBatch/npm-shrinkwrap.json b/packages/deprecated/stylus/.npm/plugin/compileStylusBatch/npm-shrinkwrap.json deleted file mode 100644 index 1fe92eee26..0000000000 --- a/packages/deprecated/stylus/.npm/plugin/compileStylusBatch/npm-shrinkwrap.json +++ /dev/null @@ -1,177 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==" - }, - "autoprefixer": { - "version": "6.3.7", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.3.7.tgz", - "integrity": "sha512-xnArQBxKETltXW1R/ZrmlaslmU5vF4huqAw0iARn1VXXc8TztdtWQJ9myUe/ywZbG7tvErKQ7hZORBf7G8fArQ==" - }, - "autoprefixer-stylus": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/autoprefixer-stylus/-/autoprefixer-stylus-0.9.4.tgz", - "integrity": "sha512-LTcjRdT4sRvfA6FkhRS6HuEtRm/GNFDr3+egHSr4/7oyKUjYJpZCCakpO4hhi/l3NahnJihokz0iaGb1boA4rw==" - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==" - }, - "browserslist": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.3.6.tgz", - "integrity": "sha512-fKSWtyNQTclfi1A+s2KU91/r1mfANG1ZibxTdCwJGfV1J9UwcV22plFOm0wkaq4WzqW87zxiAkyp2Ho1Wn1NnA==" - }, - "caniuse-db": { - "version": "1.0.30001669", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30001669.tgz", - "integrity": "sha512-GK+G6CnRZ7IY2J2H3bcm9kshwHcJ4ZWDC5u9WaIh7DQAAHHeuxIPtaZd15GMTmGvGbDx/u1AcQs3MYur9Tem7A==" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "css-parse": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz", - "integrity": "sha512-OI38lO4JQQX2GSisTqwiSFxiWNmLajXdW4tCCxAuiwGKjusHALQadSHBSxGlU8lrFp47IkLuU2AfSYz31qpETQ==" - }, - "debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==" - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "glob": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", - "integrity": "sha512-f8c0rE8JiCxpa52kWPAOa3ZaYEnzofDzCQLCn3Vdk0Z5OVLq3BsRFJI4S4ykpeVW6QMGBUkMeUpoEgWnMTnw5Q==" - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==" - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "js-base64": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", - "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==" - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==" - }, - "minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==" - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "multi-stage-sourcemap": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/multi-stage-sourcemap/-/multi-stage-sourcemap-0.2.1.tgz", - "integrity": "sha512-umaOM+8BZByZIB/ciD3dQLzTv50rEkkGJV78ta/tIVc/J/rfGZY5y1R+fBD3oTaolx41mK8rRcyGtYbDXlzx8Q==" - }, - "nib": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/nib/-/nib-1.1.2.tgz", - "integrity": "sha512-xBpZ9XU0vLOxp0GBTuUHt6Kcl37ZpC/rXPpKcK4LYOUnSmqp2CXkcNiJxf9bgNZeivYR6bxsaZkNHZ9deEMupQ==" - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==" - }, - "num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - }, - "postcss": { - "version": "5.0.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.0.21.tgz", - "integrity": "sha512-/UdnZhOe5WC0Kvts13bNLPREqhaU0ntLQ1v29S5ofLx38zP+WhM0sjhVzrPrIQwKwXhtf8byfH+BROc3t2YQRg==", - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" - } - } - }, - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" - }, - "sax": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz", - "integrity": "sha512-c0YL9VcSfcdH3F1Qij9qpYJFpKFKMXNOkLWFssBL3RuF7ZS8oZhllR2rWlCRjDTJsfq3R6wbSsaRU6o0rkEdNw==" - }, - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha512-VtCvB9SIQhk3aF6h+N85EaqIaBFIAfZ9Cu+NJHHVvc8BbEcnvDcFw6sqQ2dQrT6SlOrZq3tIvyD9+EGq/lJryQ==" - }, - "stylus": { - "version": "0.54.5", - "resolved": "https://github.com/meteor/stylus/tarball/bb47a357d132ca843718c63998eb37b90013a449", - "integrity": "sha512-j6fvtoNfjx/TEIlIOZ53OqbP6uDdF5HsQidsRfvp0IfW0D5PCtV8IeHVQa4jjbhF9PbjOXX/rrt5lP4CGpgtfw==" - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==" - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - } - } -} diff --git a/packages/deprecated/underscore/.npm/package/npm-shrinkwrap.json b/packages/deprecated/underscore/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 9533a246ae..0000000000 --- a/packages/deprecated/underscore/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "@types/underscore": { - "version": "1.11.9", - "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.9.tgz", - "integrity": "sha512-M63wKUdsjDFUfyFt1TCUZHGFk9KDAa5JP0adNUErbm0U45Lr06HtANdYRP+GyleEopEoZ4UyBcdAC5TnW4Uz2w==" - } - } -} diff --git a/packages/ecmascript-runtime-client/.npm/package/npm-shrinkwrap.json b/packages/ecmascript-runtime-client/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index ace6e4eb63..0000000000 --- a/packages/ecmascript-runtime-client/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "core-js": { - "version": "3.15.2", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.15.2.tgz", - "integrity": "sha512-tKs41J7NJVuaya8DxIOCnl8QuPHx5/ZVbFo1oKgVl1qHFBBrDctzQGtuLjPpRdNTWmKPH6oEvgN/MUID+l485Q==" - } - } -} diff --git a/packages/ecmascript-runtime-server/.npm/package/npm-shrinkwrap.json b/packages/ecmascript-runtime-server/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 22efd2d68d..0000000000 --- a/packages/ecmascript-runtime-server/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "core-js": { - "version": "3.38.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.38.1.tgz", - "integrity": "sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==" - } - } -} diff --git a/packages/ecmascript-runtime/.npm/package/npm-shrinkwrap.json b/packages/ecmascript-runtime/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 10a5a04a0e..0000000000 --- a/packages/ecmascript-runtime/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "@babel/runtime": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", - "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==" - }, - "regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - } - } -} diff --git a/packages/ecmascript/.npm/package/npm-shrinkwrap.json b/packages/ecmascript/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 10a5a04a0e..0000000000 --- a/packages/ecmascript/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "@babel/runtime": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", - "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==" - }, - "regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - } - } -} diff --git a/packages/email/.npm/package/npm-shrinkwrap.json b/packages/email/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 0f30d4b785..0000000000 --- a/packages/email/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "@types/node": { - "version": "22.8.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.7.tgz", - "integrity": "sha512-LidcG+2UeYIWcMuMUpBKOnryBWG/rnmOHQR5apjn8myTQcx3rinFRn7DcIFhMnS0PPFSC6OafdIKEad0lj6U0Q==" - }, - "@types/nodemailer": { - "version": "6.4.14", - "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.14.tgz", - "integrity": "sha512-fUWthHO9k9DSdPCSPRqcu6TWhYyxTBg382vlNIttSe9M7XfsT06y0f24KHXtbnijPGGRIcVvdKHTNikOI6qiHA==" - }, - "asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==" - }, - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "nodemailer": { - "version": "6.9.10", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.10.tgz", - "integrity": "sha512-qtoKfGFhvIFW5kLfrkw2R6Nm6Ur4LNUMykyqu6n9BRKJuyQrqEGwdXXUAbwWEKt33dlWUGXb7rzmJP/p4+O+CA==" - }, - "nodemailer-openpgp": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/nodemailer-openpgp/-/nodemailer-openpgp-2.2.0.tgz", - "integrity": "sha512-e6+pgGVpMEZ2ywHcAtTdKhUCU5HwZI23RFoNUA/mJPytUW369mQqEcHFLUoxEITOLrzeoLjn5wOYFYzSpef+Tg==" - }, - "openpgp": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/openpgp/-/openpgp-5.9.0.tgz", - "integrity": "sha512-wEI6TAinCAq8ZLZA4oZ3ZtJ2BhhHj+CiPCd8TzE7zCicr0V8tvG5UF76OtddLLOJcK63w3Aj3KiRd+VLMScirQ==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "stream-buffers": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.2.tgz", - "integrity": "sha512-DQi1h8VEBA/lURbSwFtEHnSTb9s2/pwLEaFuNhXwy1Dx3Sa0lOuYT2yNUr4/j2fs8oCAMANtrZ5OrPZtyVs3MQ==" - }, - "undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" - } - } -} diff --git a/packages/es5-shim/.npm/package/npm-shrinkwrap.json b/packages/es5-shim/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 9883bd8fbe..0000000000 --- a/packages/es5-shim/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "es5-shim": { - "version": "4.5.10", - "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.10.tgz", - "integrity": "sha512-vmryBdqKRO8Ei9LJ4yyEk/EOmAOGIagcHDYPpTAi6pot4IMHS1AC2q5cTKPmydpijg2iX8DVmCuqgrNxIWj8Yg==" - } - } -} diff --git a/packages/fetch/.npm/package/npm-shrinkwrap.json b/packages/fetch/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index ec19012504..0000000000 --- a/packages/fetch/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==" - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "whatwg-fetch": { - "version": "3.6.17", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.17.tgz", - "integrity": "sha512-c4ghIvG6th0eudYwKZY5keb81wtFz9/WeAHAoy8+r18kcWlitUIrmGFQ2rWEl4UCKUilD3zCLHOIPheHx5ypRQ==" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==" - } - } -} diff --git a/packages/force-ssl-common/.npm/package/npm-shrinkwrap.json b/packages/force-ssl-common/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index cff63db95a..0000000000 --- a/packages/force-ssl-common/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,384 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha512-dtXTVMkh6VkEEA7OhXnN1Ecb8aAGFdZ1LFxtOCoqj4qkyOJMt7+qs6Ahdy6p/NQCPYsRSXXivhSB/J5E9jmYKA==" - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" - }, - "arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha512-tVqVTHt+Q5Xb09qRkbu+DidW1yYzz5izWS2Xm2yFm7qJnmUfz4HPzNxbHkdRJbz2lrqI7S+z17xNYdFcBBO8Hw==" - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha512-G2n5bG5fSUCpnsXz4+8FUkYsGPkNfLn9YvS66U5qbTIXI2Ynnlo4Bi42bWv+omKUCqz+ejzfClwne0alJWJPhg==" - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha512-xU7bpz2ytJl1bH9cgIurjpg/n8Gohy9GTw81heDYLJQ4RU60dlyJsa+atVF2pI0yMMvKxI9HkKwjePCj5XI1hw==" - }, - "call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==" - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" - }, - "deep-equal": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz", - "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==" - }, - "define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==" - }, - "define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==" - }, - "es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==" - }, - "es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha512-hxx03P2dJxss6ceIeri9cmYOT4SRs3Zk3afZwWpOsRqLqprhTR8u++SlC+sFGsQr7WGFPdMF7Gjc1njDLDK6UA==" - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha512-AFASGfIlnIbkKPQwX1yHaDjFvh/1gyKJODme52V6IORh69uEYgZp0o9C+qsIGNVEiuuhQU0CSSl++Rlegg1qvA==" - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha512-1FOj1LOwn42TMrruOHGt18HemVnbwAmAak7krWk+wa93KXxGbK+2jpezm+ytJYDaBX0/SPLZFHKM7m+tKobWGg==" - }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha512-BTCqyBaWBTsauvnHiE8i562+EdJj+oUpkqWp2R1iCoR8f6oo8STRu3of7WJJ0TqWtxN50a5YFpzYK4Jj9esYfQ==" - }, - "fill-range": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==" - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==" - }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==" - }, - "forwarded-http": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/forwarded-http/-/forwarded-http-0.3.0.tgz", - "integrity": "sha512-mlx71SLFQNGSjhK2ADs+N6ED8RH8HPcgsbr1pa3/Qmaw5yPI0K1hQKmn5ECEjKWXo5NfdFvwBpQrWCkMoUWvIQ==" - }, - "function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" - }, - "functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" - }, - "get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==" - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha512-ab1S1g1EbO7YzauaJLkgLp7DZVAqj9M/dvKlTt8DkXA2tiOIcSMrlVI2J1RZyB5iJVccEscjGn+kpOG9788MHA==" - }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha512-JDYOvfxio/t42HKdxkAYaCiBN7oYiuxykOxKxdaUW5Qn0zaYN3gRQWolrwdnf0shM9/EP0ebuuTmyoXNr1cC5w==" - }, - "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==" - }, - "has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==" - }, - "has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==" - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" - }, - "has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==" - }, - "hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==" - }, - "ip": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/ip/-/ip-0.3.3.tgz", - "integrity": "sha512-VXpBTSFo8wNvJVwCxlncVwd2hYbzX8egxidocX2oKt6H5tJzLjrzG6gTNoHSNsKtIyelb528n/7sa86kqlnNiA==" - }, - "ip-filter": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ip-filter/-/ip-filter-1.0.2.tgz", - "integrity": "sha512-MBT35bC0RnP9Q7TKZKBieE6XaELqWEf1iPS9y4zLtncoZbxA0AxyllbTEruaFOeBlee722u7pYatrjoPX6Y6lQ==" - }, - "ip-port-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ip-port-regex/-/ip-port-regex-1.0.0.tgz", - "integrity": "sha512-RGlDctlcwEV5IXeLYcAq9/LwhEcese6YBFP8TwEzlPNv6lC/dkHYFEgnFom6LjB81iWdAggHEOHSm4aBfuGdXw==" - }, - "ip-regex": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz", - "integrity": "sha512-HjpCHTuxbR/6jWJroc/VN+npo5j0T4Vv2TAI5qdEHQx7hsL767MeccGFSsLtF694EiZKTSEqgoeU6DtGFCcuqQ==" - }, - "is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==" - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==" - }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha512-9YclgOGtN/f8zx0Pr4FQYMdibBiTaH3sn52vjYip4ZSf6C4/6RfTEZ+MR4GvKhCxdPh21Bg42/WL55f6KSnKpg==" - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha512-0EygVC5qPvIyb+gSz7zdD5/AAoS6Qrx1e//6N4yv4oNm30kqvdmG66oZFWVlQHUWe5OjP08FuTw2IdT0EOTcYA==" - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==" - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==" - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==" - }, - "is-match": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/is-match/-/is-match-0.4.1.tgz", - "integrity": "sha512-Ds3ju1fPePDIfT9guPIaacKD2f0l6SCiY6hfQg6pDqcernEFCyGfyJaB5CPKHxE7qxc2Igd/5QdSNCYFHFhKow==" - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg==" - }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha512-Yu68oeXJ7LeWNmZ3Zov/xg/oDBnBK2RNxwYY1ilNJX+tKKZqgPK+qOn/Gs9jEu66KDY9Netf5XLKNGzas/vPfQ==" - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha512-N3w1tFaRfk3UrPfqeRyD+GYDASU3W5VinKhlORy8EWVf/sIdDL9GAcew85XmktCfH+ngG7SRXEVDoO18WMdB/Q==" - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==" - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==" - }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==" - }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dependencies": { - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" - } - } - }, - "math-random": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", - "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==" - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha512-LnU2XFEk9xxSJ6rfgAry/ty5qwUTyHYOBU0g4R6tIw5ljwgGIBmiKhRWLw5NpMOnrgUNcDJ4WMp8rl3sYVHLNA==" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==" - }, - "object-is": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", - "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==" - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha512-UiAM5mhmIuKLsOvrL+B0U2d1hXHF3bFYWIuH1LMpuV2EJEHG1Ntz06PgLEHjm6VFd87NpH8rastvPoyv6UW2fA==" - }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha512-FC5TeK0AwXzq3tUBFtH74naWkPQCEWs4K+xMxWZBlKDWu0bVHXGZa+KKqxKidd7xwhdZ19ZNuF2uO1M/r196HA==" - }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha512-s/46sYeylUfHNjI+sA/78FAHlmIuKqI9wNnzEOGehAlUUYeObv5C2mOinXBjyUyWmJ2SfcS2/ydApH4hTF4WXQ==" - }, - "randomatic": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", - "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" - } - } - }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==" - }, - "regexp.prototype.flags": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", - "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==" - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==" - }, - "repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==" - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==" - }, - "set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==" - }, - "set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==" - }, - "to-file-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-file-path/-/to-file-path-1.0.0.tgz", - "integrity": "sha512-wXi4ugrrAjifQOuTf3Hh2CDEfFQtaxnLjfXZUHtVLrmOpkgr7N7EsN2kR+0C0Y+yPuAgbYev0mjAZnTYBrErww==" - } - } -} diff --git a/packages/inter-process-messaging/.npm/package/npm-shrinkwrap.json b/packages/inter-process-messaging/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 55a5e00ced..0000000000 --- a/packages/inter-process-messaging/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "arson": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/arson/-/arson-0.2.6.tgz", - "integrity": "sha512-wVRnIfjOaCWu3jrf3j1CU/eotDf7tuM34cBswo32EwyLPaMiaWgETfROdYVv47VWEbWSOaZaDnkypGQtQduLbw==" - }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" - } - } -} diff --git a/packages/logging/.npm/package/npm-shrinkwrap.json b/packages/logging/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index e2ea56dfae..0000000000 --- a/packages/logging/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "@babel/runtime": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", - "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==" - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==" - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==" - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==" - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==" - } - } -} diff --git a/packages/logic-solver/.npm/package/npm-shrinkwrap.json b/packages/logic-solver/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 51c79d70fa..0000000000 --- a/packages/logic-solver/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "lodash.has": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", - "integrity": "sha512-rnYUdIo6xRCJnQmbVFEwcxF144erlD+M3YcJUVesflU9paQaE8p+fJDcIQrlMYbxoANFL+AB9hZrzSBBk5PL+g==" - } - } -} diff --git a/packages/meteor/.npm/package/npm-shrinkwrap.json b/packages/meteor/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index cf4663cb36..0000000000 --- a/packages/meteor/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==" - } - } -} diff --git a/packages/minifier-js/.npm/package/npm-shrinkwrap.json b/packages/minifier-js/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 06ede9f967..0000000000 --- a/packages/minifier-js/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==" - }, - "@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==" - }, - "@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==" - }, - "@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==" - }, - "@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" - }, - "@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==" - }, - "acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==" - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==" - }, - "terser": { - "version": "5.31.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.0.tgz", - "integrity": "sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==" - } - } -} diff --git a/packages/modules-runtime/.npm/package/npm-shrinkwrap.json b/packages/modules-runtime/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 4b73e7927f..0000000000 --- a/packages/modules-runtime/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "install": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/install/-/install-0.13.0.tgz", - "integrity": "sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA==" - } - } -} diff --git a/packages/modules/.npm/package/npm-shrinkwrap.json b/packages/modules/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index bd86daae17..0000000000 --- a/packages/modules/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "@meteorjs/reify": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@meteorjs/reify/-/reify-0.25.4.tgz", - "integrity": "sha512-/HwynJK85QtS2Rm26M9TS8aEMnqVJ2TIzJNJTGAQz+G6cTYmJGWaU4nFH96oxiDIBbnT6Y3TfX92HDuS9TtNRg==" - }, - "@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" - }, - "acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==" - }, - "estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" - }, - "is-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==" - }, - "magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==" - }, - "meteor-babel-helpers": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/meteor-babel-helpers/-/meteor-babel-helpers-0.0.3.tgz", - "integrity": "sha512-PgfmiyT/HiBaxwGHxS4t3Qi0fpmEW3O0WW2VfrgekiMGz3aZPd9/4PRIaMMZsfyjQ1vyEm6dZqTAFZENbuoTxw==" - }, - "periscopic": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-2.0.3.tgz", - "integrity": "sha512-FuCZe61mWxQOJAQFEfmt9FjzebRlcpFz8sFPbyaCKtdusPkMEbA9ey0eARnRav5zAhmXznhaQkKGFAPn7X9NUw==" - }, - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" - }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" - } - } -} diff --git a/packages/mongo/.npm/package/npm-shrinkwrap.json b/packages/mongo/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 123f660516..0000000000 --- a/packages/mongo/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "lodash.clone": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", - "integrity": "sha512-GhrVeweiTD6uTmmn5hV/lzgCQhccwReIVRLHp7LT4SopOjqEZ5BbX8b5WWEtAKasjmy8hR7ZPwsYlxRCku5odg==" - }, - "lodash.has": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", - "integrity": "sha512-rnYUdIo6xRCJnQmbVFEwcxF144erlD+M3YcJUVesflU9paQaE8p+fJDcIQrlMYbxoANFL+AB9hZrzSBBk5PL+g==" - }, - "lodash.isempty": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", - "integrity": "sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==" - }, - "lodash.isobject": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", - "integrity": "sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA==" - }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" - }, - "lodash.throttle": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", - "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==" - }, - "lodash.times": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.times/-/lodash.times-4.3.2.tgz", - "integrity": "sha512-FfaJzl0SA35CRPDh5SWe2BTght6y5KSK7yJv166qIp/8q7qOwBDCvuDZE2RUSMRpBkLF6rZKbLEUoTmaP3qg6A==" - }, - "mongodb-uri": { - "version": "0.9.7", - "resolved": "https://registry.npmjs.org/mongodb-uri/-/mongodb-uri-0.9.7.tgz", - "integrity": "sha512-s6BdnqNoEYfViPJgkH85X5Nw5NpzxN8hoflKLweNa7vBxt2V7kaS06d74pAtqDxde8fn4r9h4dNdLiFGoNV0KA==" - } - } -} diff --git a/packages/non-core/less/.npm/plugin/compileLessBatch/npm-shrinkwrap.json b/packages/non-core/less/.npm/plugin/compileLessBatch/npm-shrinkwrap.json deleted file mode 100644 index 4c4ca06f64..0000000000 --- a/packages/non-core/less/.npm/plugin/compileLessBatch/npm-shrinkwrap.json +++ /dev/null @@ -1,115 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "@babel/runtime": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.8.tgz", - "integrity": "sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==" - }, - "copy-anything": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", - "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==" - }, - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==" - }, - "errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==" - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==" - }, - "image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==" - }, - "is-what": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", - "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==" - }, - "less": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/less/-/less-4.1.1.tgz", - "integrity": "sha512-w09o8tZFPThBscl5d0Ggp3RcrKIouBoQscnOMgFH3n5V3kN/CXGHNfCkRPtxJk6nKryDXaV9aHLK55RXuH4sAw==" - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==" - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "needle": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz", - "integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==" - }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==" - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==" - }, - "regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sax": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" - }, - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } -} diff --git a/packages/non-core/mongo-decimal/.npm/package/npm-shrinkwrap.json b/packages/non-core/mongo-decimal/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index d50fde8c41..0000000000 --- a/packages/non-core/mongo-decimal/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "decimal.js": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", - "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==" - } - } -} diff --git a/packages/npm-mongo/.npm/package/npm-shrinkwrap.json b/packages/npm-mongo/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 471827971a..0000000000 --- a/packages/npm-mongo/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "@mongodb-js/saslprep": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", - "integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==" - }, - "@types/webidl-conversions": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", - "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" - }, - "@types/whatwg-url": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", - "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==" - }, - "bson": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-6.9.0.tgz", - "integrity": "sha512-X9hJeyeM0//Fus+0pc5dSUMhhrrmWwQUtdavaQeF3Ta6m69matZkGWV/MrBcnwUeLC8W9kwwc2hfkZgUuCX3Ig==" - }, - "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==" - }, - "mongodb": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.10.0.tgz", - "integrity": "sha512-gP9vduuYWb9ZkDM546M+MP2qKVk5ZG2wPF63OvSRuUbqCR+11ZCAE1mOfllhlAG0wcoJY5yDL/rV3OmYEwXIzg==" - }, - "mongodb-connection-string-url": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz", - "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==" - }, - "punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" - }, - "sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==" - }, - "tr46": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", - "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==" - }, - "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": "13.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", - "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==" - } - } -} diff --git a/packages/oauth/.npm/package/npm-shrinkwrap.json b/packages/oauth/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 2a953aaaf9..0000000000 --- a/packages/oauth/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,115 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==" - }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" - }, - "content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==" - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==" - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==" - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" - }, - "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==" - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" - } - } -} diff --git a/packages/package-version-parser/.npm/package/npm-shrinkwrap.json b/packages/package-version-parser/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index ea7fc351e9..0000000000 --- a/packages/package-version-parser/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==" - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } -} diff --git a/packages/promise/.npm/package/npm-shrinkwrap.json b/packages/promise/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 6a86573c60..0000000000 --- a/packages/promise/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" - }, - "promise": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz", - "integrity": "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==" - } - } -} diff --git a/packages/react-fast-refresh/.npm/package/npm-shrinkwrap.json b/packages/react-fast-refresh/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 9476a975cd..0000000000 --- a/packages/react-fast-refresh/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==" - }, - "react-refresh": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", - "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==" - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } -} diff --git a/packages/server-render/.npm/package/npm-shrinkwrap.json b/packages/server-render/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 1b3236a19a..0000000000 --- a/packages/server-render/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "bluebird": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", - "integrity": "sha512-UfFSr22dmHPQqPP9XWHRhq+gWnHCYguQGkXQlbyPtW5qTnhFWA8/iXg765tH0cAjy7l/zPJ1aBTO0g5XgA7kvQ==" - }, - "combined-stream2": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/combined-stream2/-/combined-stream2-1.1.2.tgz", - "integrity": "sha512-sVqUHJmbdVm+HZWy4l34BPLczxI4fltN4Bm2vcvASsqBIXW4xFb4TRkwM8bw/UUXK9/OdHdAwi2cRYVEKrxzbg==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" - }, - "magic-string": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", - "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "parse5": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==" - }, - "promise-polyfill": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-1.1.6.tgz", - "integrity": "sha512-7rrONfyLkDEc7OJ5QBkqa4KI4EBhCd340xRuIUPGCfu13znS+vx+VDdrT9ODAJHlXm7w4lbxN3DRjyv58EuzDg==" - }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" - }, - "stream-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-length/-/stream-length-1.0.2.tgz", - "integrity": "sha512-aI+qKFiwoDV4rsXiS7WRoCt+v2RX1nUj17+KJC5r2gfh5xoSJIfP6Y3Do/HtvesFcTSWthIuJ3l1cvKQY/+nZg==" - }, - "stream-to-string": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/stream-to-string/-/stream-to-string-1.2.0.tgz", - "integrity": "sha512-8drZlFIKBHSMdX9GCWv8V9AAWnQcTqw0iAI6/GC7UJ0H0SwKeFKjOoZfGY1tOU00GGU7FYZQoJ/ZCUEoXhD7yQ==" - } - } -} diff --git a/packages/socket-stream-client/.npm/package/npm-shrinkwrap.json b/packages/socket-stream-client/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index eaf34702ea..0000000000 --- a/packages/socket-stream-client/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==" - }, - "http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" - }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" - }, - "permessage-deflate": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/permessage-deflate/-/permessage-deflate-0.1.7.tgz", - "integrity": "sha512-EUNi/RIsyJ1P1u9QHFwMOUWMYetqlE22ZgGbad7YP856WF4BFF0B7DuNy6vEGsgNNud6c/SkdWzkne71hH8MjA==" - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==" - }, - "websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" - } - } -} diff --git a/packages/test-server-tests-in-console-once/.npm/package/npm-shrinkwrap.json b/packages/test-server-tests-in-console-once/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 51c79d70fa..0000000000 --- a/packages/test-server-tests-in-console-once/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "lodash.has": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", - "integrity": "sha512-rnYUdIo6xRCJnQmbVFEwcxF144erlD+M3YcJUVesflU9paQaE8p+fJDcIQrlMYbxoANFL+AB9hZrzSBBk5PL+g==" - } - } -} diff --git a/packages/tinytest/.npm/package/npm-shrinkwrap.json b/packages/tinytest/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index b0da3142b7..0000000000 --- a/packages/tinytest/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" - } - } -} diff --git a/packages/url/.npm/package/npm-shrinkwrap.json b/packages/url/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 22efd2d68d..0000000000 --- a/packages/url/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "core-js": { - "version": "3.38.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.38.1.tgz", - "integrity": "sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==" - } - } -} diff --git a/packages/webapp/.npm/package/npm-shrinkwrap.json b/packages/webapp/.npm/package/npm-shrinkwrap.json deleted file mode 100644 index 6a7731a654..0000000000 --- a/packages/webapp/.npm/package/npm-shrinkwrap.json +++ /dev/null @@ -1,576 +0,0 @@ -{ - "lockfileVersion": 4, - "dependencies": { - "@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==" - }, - "@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==" - }, - "@types/express": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz", - "integrity": "sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==" - }, - "@types/express-serve-static-core": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.1.tgz", - "integrity": "sha512-CRICJIl0N5cXDONAdlTv5ShATZ4HEwk6kDDIW2/w9qOWKg+NU/5F8wYRWCrONad0/UKkloNSmmyN/wX4rtpbVA==" - }, - "@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" - }, - "@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" - }, - "@types/node": { - "version": "22.8.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.7.tgz", - "integrity": "sha512-LidcG+2UeYIWcMuMUpBKOnryBWG/rnmOHQR5apjn8myTQcx3rinFRn7DcIFhMnS0PPFSC6OafdIKEad0lj6U0Q==" - }, - "@types/qs": { - "version": "6.9.16", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz", - "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==" - }, - "@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" - }, - "@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==" - }, - "@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==" - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==" - }, - "array-flatten": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-3.0.0.tgz", - "integrity": "sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA==" - }, - "body-parser": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.0.2.tgz", - "integrity": "sha512-SNMk0OONlQ01uk8EPeiBvTW7W4ovpL5b1O3t1sjpPgfxOQ6BqQJ6XjxinDPR79Z6HdcD5zBBwr5ssiTlgdNztQ==", - "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==" - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==" - } - } - }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==" - }, - "call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==" - }, - "compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==" - }, - "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==" - }, - "content-disposition": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - } - } - }, - "content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" - }, - "cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" - }, - "cookie-parser": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", - "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" - }, - "define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==" - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==" - }, - "errorhandler": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.1.tgz", - "integrity": "sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A==" - }, - "es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==" - }, - "es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" - }, - "express": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/express/-/express-5.0.1.tgz", - "integrity": "sha512-ORF7g6qGnD+YtUG9yx4DFoqCShNMmUKiXuT5oWMHiOvt/4WFbHC6yCwQMTSBMno7AqntNCAzzcnnjowRkTL9eQ==", - "dependencies": { - "accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==" - }, - "cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==" - }, - "cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==" - }, - "debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==" - }, - "mime-types": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.0.tgz", - "integrity": "sha512-XqoSHeCGjVClAmoGFG3lVFqQFRIrTVw2OH3axRqAcfaw+gHWIfnASS92AV+Rl/mk0MupgZTRHQOjxY6YVnzK5w==" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==" - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - } - } - }, - "finalhandler": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.0.0.tgz", - "integrity": "sha512-MX6Zo2adDViYh+GcxxB1dpO43eypOGUOL12rLCOTMQv/DfIbpSJUy4oQIIZhVZkH9e+bZWKMon0XHFEju16tkQ==", - "dependencies": { - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" - } - } - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==" - }, - "function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" - }, - "get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==" - }, - "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==" - }, - "has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==" - }, - "has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==" - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" - }, - "hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==" - }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==" - }, - "iconv-lite": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", - "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==" - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" - }, - "lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==" - }, - "media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==" - }, - "merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" - }, - "mime-db": { - "version": "1.53.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz", - "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - } - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" - }, - "object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==" - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==" - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==" - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "path-to-regexp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==" - }, - "promise-polyfill": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-1.1.6.tgz", - "integrity": "sha512-7rrONfyLkDEc7OJ5QBkqa4KI4EBhCd340xRuIUPGCfu13znS+vx+VDdrT9ODAJHlXm7w4lbxN3DRjyv58EuzDg==" - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==" - }, - "qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==" - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", - "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", - "dependencies": { - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==" - } - } - }, - "router": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/router/-/router-2.0.0.tgz", - "integrity": "sha512-dIM5zVoG8xhC6rnSN8uoAgFARwTE7BQs8YwHEvK0VCmfxQXMaOuA1uiR1IPwsW7JyK5iTt7Od/TC9StasS2NPQ==" - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "send": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/send/-/send-1.1.0.tgz", - "integrity": "sha512-v67WcEouB5GxbTWL/4NeToqcZiAWEq90N888fczVArY8A79J0L4FD7vj5hm3eUMua5EpoQ59wa/oovY6TLvRUA==", - "dependencies": { - "debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - } - } - }, - "serve-static": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.1.0.tgz", - "integrity": "sha512-A3We5UfEjG8Z7VkDv6uItWw6HY2bBSBJT1KtVESn6EOoOr2jAxNhxWCLY3jDE2WcuHXByWju74ck3ZgLwL8xmA==" - }, - "set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==" - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==" - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - }, - "stream-to-string": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/stream-to-string/-/stream-to-string-1.2.1.tgz", - "integrity": "sha512-WsvTDNF8UYs369Yko3pcdTducQtYpzEZeOV7cTuReyFvOoA9S/DLJ6sYK+xPafSPHhUMpaxiljKYnT6JSFztIA==" - }, - "tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==" - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" - }, - "type-is": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.0.tgz", - "integrity": "sha512-gd0sGezQYCbWSbkZr75mln4YBidWUN60+devscpLF5mtRDUpiaTvKpBNrdaCvel1NdR2k6vclXybU5fBd2i+nw==", - "dependencies": { - "mime-types": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.0.tgz", - "integrity": "sha512-XqoSHeCGjVClAmoGFG3lVFqQFRIrTVw2OH3axRqAcfaw+gHWIfnASS92AV+Rl/mk0MupgZTRHQOjxY6YVnzK5w==" - } - } - }, - "uap-core": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/uap-core/-/uap-core-0.16.0.tgz", - "integrity": "sha512-NwObJD5EgDPGWp86fvpyu94UBlYtHUIrk7F2n5J7bf3Cpu8X80qB7n6taM2gFhZGiKmlU/zUQ09Mc/yFgewnLg==" - }, - "undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" - }, - "useragent-ng": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/useragent-ng/-/useragent-ng-2.4.3.tgz", - "integrity": "sha512-X08x6u8G/ZSVqQiN7f0KODtXq0HFUmjkmRdSaez0w350E6zCesLk/dZ7Sme7EQRHE6TSHo27DBxEHKbKEErWMg==" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "yamlparser": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/yamlparser/-/yamlparser-0.0.2.tgz", - "integrity": "sha512-Cou9FCGblEENtn1/8La5wkDM/ISMh2bzu5Wh7dYzCzA0o9jD4YGyLkUJxe84oPBGoB92f+Oy4ZjVhA8S0C2wlQ==" - } - } -} From 557f8d3546fa3ffaad90f6bfbbc003a94c772f8c Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Fri, 8 Nov 2024 08:32:39 -0400 Subject: [PATCH 23/48] bump package versions so the sub deps are updated --- packages/ecmascript/package.js | 2 +- packages/minifier-js/package.js | 2 +- packages/non-core/coffeescript-compiler/package.js | 2 +- packages/non-core/coffeescript/package.js | 2 +- packages/shell-server/package.js | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/ecmascript/package.js b/packages/ecmascript/package.js index 1ad724b508..1d171485ae 100644 --- a/packages/ecmascript/package.js +++ b/packages/ecmascript/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'ecmascript', - version: '0.16.9', + version: '0.16.10-beta310.1', summary: 'Compiler plugin that supports ES2015+ in all .js files', documentation: 'README.md', }); diff --git a/packages/minifier-js/package.js b/packages/minifier-js/package.js index e3128e55df..c4e1973b19 100644 --- a/packages/minifier-js/package.js +++ b/packages/minifier-js/package.js @@ -1,6 +1,6 @@ Package.describe({ summary: "JavaScript minifier", - version: '3.0.0', + version: '3.0.1-beta310.0', }); Npm.depends({ diff --git a/packages/non-core/coffeescript-compiler/package.js b/packages/non-core/coffeescript-compiler/package.js index 807f74a64e..3bb80863c5 100644 --- a/packages/non-core/coffeescript-compiler/package.js +++ b/packages/non-core/coffeescript-compiler/package.js @@ -3,7 +3,7 @@ Package.describe({ summary: 'Compiler for CoffeeScript code, supporting the coffeescript package', // This version of NPM `coffeescript` module, with _1, _2 etc. // If you change this, make sure to also update ../coffeescript/package.js to match. - version: '2.4.1' + version: '2.4.2-beta310.0' }); Npm.depends({ diff --git a/packages/non-core/coffeescript/package.js b/packages/non-core/coffeescript/package.js index eae0b138ac..230c19f999 100644 --- a/packages/non-core/coffeescript/package.js +++ b/packages/non-core/coffeescript/package.js @@ -6,7 +6,7 @@ Package.describe({ // so bumping the version of this package will be how they get newer versions // of `coffeescript-compiler`. If you change this, make sure to also update // ../coffeescript-compiler/package.js to match. - version: '2.7.1-rc300.0' + version: '2.7.2-beta310.0' }); Package.registerBuildPlugin({ diff --git a/packages/shell-server/package.js b/packages/shell-server/package.js index 2475bd39a0..99d54f9bcc 100644 --- a/packages/shell-server/package.js +++ b/packages/shell-server/package.js @@ -1,6 +1,6 @@ Package.describe({ name: "shell-server", - version: '0.6.0', + version: '0.6.1-beta310.0', summary: "Server-side component of the `meteor shell` command.", documentation: "README.md" }); From e00a11181944d0e080fc16a3732eb8dcce1aad95 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Fri, 8 Nov 2024 08:32:48 -0400 Subject: [PATCH 24/48] exclude roles in command --- .envrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.envrc b/.envrc index 47ab5b6410..0ea9402d01 100644 --- a/.envrc +++ b/.envrc @@ -20,7 +20,7 @@ function @get-ready { } function @test-packages { - TINYTEST_FILTER="$1" @meteor test-packages --exclude-archs=web.browser.legacy,web.cordova + TINYTEST_FILTER="$1" @meteor test-packages --exclude-archs=web.browser.legacy,web.cordova --exclude=roles } function @test-self { From 4954976d9d0811f5bc6210d7df032e62a102af1e Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Fri, 1 Nov 2024 11:13:13 -0400 Subject: [PATCH 25/48] add test --- packages/ddp-client/test/livedata_tests.js | 98 ++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/packages/ddp-client/test/livedata_tests.js b/packages/ddp-client/test/livedata_tests.js index 426c5bf832..1fb6c0aa1e 100644 --- a/packages/ddp-client/test/livedata_tests.js +++ b/packages/ddp-client/test/livedata_tests.js @@ -1193,6 +1193,104 @@ testAsyncMulti('livedata - methods with nested stubs', [ }, ]); +const collName = `test-collection`; +const coll = new Mongo.Collection(collName); + +if (Meteor.isServer) { + Meteor.publish(`pub-${collName}`, function () { + return coll.find(); + }); +} + +Meteor.methods({ + [`insert-${collName}`]: async function() { + return await coll.insertAsync({ value: 1 }); + }, + [`update-${collName}`]: async function(id) { + return await coll.updateAsync(id, { $set: { value: 2 } }); + }, + [`remove-${collName}`]: async function(id) { + return await coll.removeAsync(id); + } +}); + +if (Meteor.isClient) { + Tinytest.addAsync('livedata - method updated message with subscriptions', async function (test) { + let messages = []; + + const onMessage = message => messages.push(EJSON.parse(message)); + + Meteor.connection._stream.on('message', onMessage); + + const sub = Meteor.subscribe(`pub-${collName}`); + + await new Promise(resolve => { + const id = setInterval(() => { + if (sub.ready()) { + clearInterval(id); + resolve(); + } + }, 10); + }); + + let insertId; + + try { + for (let i = 0; i < 100; i++) { + messages = []; + + insertId = await Meteor.callAsync(`insert-${collName}`); + + await Meteor.sleep(1) + + const hasResult = messages.some(msg => msg.msg === 'result'); + const hasAdded = messages.some(msg => msg.msg === 'added'); + const hasUpdated = messages.some(msg => + msg.msg === 'updated' && msg.methods?.includes(messages[0].id) + ); + + test.isTrue(hasResult, `Iteration ${i}: Should receive RESULT message for insert`); + test.isTrue(hasAdded, `Iteration ${i}: Should receive ADDED message for insert`); + test.isTrue(hasUpdated, `Iteration ${i}: Should receive UPDATED message for insert`); + + messages = []; + + await Meteor.callAsync(`update-${collName}`, insertId); + + await Meteor.sleep(1) + + const hasUpdateResult = messages.some(msg => msg.msg === 'result'); + const hasChanged = messages.some(msg => msg.msg === 'changed'); + const hasUpdateUpdated = messages.some(msg => + msg.msg === 'updated' && msg.methods?.includes(messages[0].id) + ); + + test.isTrue(hasUpdateResult, `Iteration ${i}: Should receive RESULT message for update`); + test.isTrue(hasChanged, `Iteration ${i}: Should receive CHANGED message`); + test.isTrue(hasUpdateUpdated, `Iteration ${i}: Should receive UPDATED message for update`); + + messages = []; + + await Meteor.callAsync(`remove-${collName}`, insertId); + + await Meteor.sleep(1) + + const hasRemoveResult = messages.some(msg => msg.msg === 'result'); + const hasRemoved = messages.some(msg => msg.msg === 'removed'); + const hasRemoveUpdated = messages.some(msg => + msg.msg === 'updated' && msg.methods?.includes(messages[0].id) + ); + + test.isTrue(hasRemoveResult, `Iteration ${i}: Should receive RESULT message for remove`); + test.isTrue(hasRemoved, `Iteration ${i}: Should receive REMOVED message`); + test.isTrue(hasRemoveUpdated, `Iteration ${i}: Should receive UPDATED message for remove`); + } + } finally { + sub.stop(); + } + }); +} + // TODO [FIBERS] - check if this still makes sense to have // Tinytest.addAsync('livedata - isAsync call', async function (test) { From 855cfa712a7744f8f1e3b302c86cd7804710c6ea Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Fri, 1 Nov 2024 11:39:29 -0400 Subject: [PATCH 26/48] the result message is out of order --- packages/ddp-client/test/livedata_tests.js | 24 +++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/ddp-client/test/livedata_tests.js b/packages/ddp-client/test/livedata_tests.js index 1fb6c0aa1e..d297aafe58 100644 --- a/packages/ddp-client/test/livedata_tests.js +++ b/packages/ddp-client/test/livedata_tests.js @@ -1234,19 +1234,21 @@ if (Meteor.isClient) { }); let insertId; + let resultId try { - for (let i = 0; i < 100; i++) { + for (let i = 0; i < 250; i++) { messages = []; insertId = await Meteor.callAsync(`insert-${collName}`); - await Meteor.sleep(1) - const hasResult = messages.some(msg => msg.msg === 'result'); + + resultId = messages.find(msg => msg.msg === 'result').id; + const hasAdded = messages.some(msg => msg.msg === 'added'); const hasUpdated = messages.some(msg => - msg.msg === 'updated' && msg.methods?.includes(messages[0].id) + msg.msg === 'updated' && msg.methods?.includes(resultId) ); test.isTrue(hasResult, `Iteration ${i}: Should receive RESULT message for insert`); @@ -1257,12 +1259,13 @@ if (Meteor.isClient) { await Meteor.callAsync(`update-${collName}`, insertId); - await Meteor.sleep(1) - const hasUpdateResult = messages.some(msg => msg.msg === 'result'); + + resultId = messages.find(msg => msg.msg === 'result').id; + const hasChanged = messages.some(msg => msg.msg === 'changed'); const hasUpdateUpdated = messages.some(msg => - msg.msg === 'updated' && msg.methods?.includes(messages[0].id) + msg.msg === 'updated' && msg.methods?.includes(resultId) ); test.isTrue(hasUpdateResult, `Iteration ${i}: Should receive RESULT message for update`); @@ -1273,12 +1276,13 @@ if (Meteor.isClient) { await Meteor.callAsync(`remove-${collName}`, insertId); - await Meteor.sleep(1) - const hasRemoveResult = messages.some(msg => msg.msg === 'result'); + + resultId = messages.find(msg => msg.msg === 'result').id; + const hasRemoved = messages.some(msg => msg.msg === 'removed'); const hasRemoveUpdated = messages.some(msg => - msg.msg === 'updated' && msg.methods?.includes(messages[0].id) + msg.msg === 'updated' && msg.methods?.includes(resultId) ); test.isTrue(hasRemoveResult, `Iteration ${i}: Should receive RESULT message for remove`); From ea082b0417b8b3790f36c2bedeabeb769eacefff Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Wed, 30 Oct 2024 13:53:55 -0400 Subject: [PATCH 27/48] simplify code --- packages/accounts-password/password_server.js | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/packages/accounts-password/password_server.js b/packages/accounts-password/password_server.js index e2537f2c5c..5e15f66fcb 100644 --- a/packages/accounts-password/password_server.js +++ b/packages/accounts-password/password_server.js @@ -1074,17 +1074,7 @@ Accounts.createUserVerifyingEmail = // method calling Accounts.createUser could set? // -Accounts.createUserAsync = - async (options, callback) => { - options = { ...options }; - - // XXX allow an optional callback? - if (callback) { - throw new Error("Accounts.createUser with callback not supported on the server yet."); - } - - return createUser(options); - }; +Accounts.createUserAsync = createUser // Create user directly on the server. // From 8fee802b8b48b8c6127b934eb4163eea8c2890db Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Wed, 30 Oct 2024 13:54:07 -0400 Subject: [PATCH 28/48] adjust doc --- packages/accounts-base/accounts_common.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/accounts-base/accounts_common.js b/packages/accounts-base/accounts_common.js index fdd45a2890..210fc004c7 100644 --- a/packages/accounts-base/accounts_common.js +++ b/packages/accounts-base/accounts_common.js @@ -244,7 +244,7 @@ export class AccountsCommon { * @param {Number} options.passwordResetTokenExpiration The number of milliseconds from when a link to reset password is sent until token expires and user can't reset password with the link anymore. If `passwordResetTokenExpirationInDays` is set, it takes precedent. * @param {Number} options.passwordEnrollTokenExpirationInDays The number of days from when a link to set initial password is sent until token expires and user can't set password with the link anymore. Defaults to 30. * @param {Number} options.passwordEnrollTokenExpiration The number of milliseconds from when a link to set initial password is sent until token expires and user can't set password with the link anymore. If `passwordEnrollTokenExpirationInDays` is set, it takes precedent. - * @param {Boolean} options.ambiguousErrorMessages Return ambiguous error messages from login failures to prevent user enumeration. Defaults to `false`, but in production environments it is recommended it defaults to `true`. + * @param {Boolean} options.ambiguousErrorMessages Return ambiguous error messages from login failures to prevent user enumeration. Defaults to `true`. * @param {Number} options.bcryptRounds Allows override of number of bcrypt rounds (aka work factor) used to store passwords. The default is 10. * @param {MongoFieldSpecifier} options.defaultFieldSelector To exclude by default large custom fields from `Meteor.user()` and `Meteor.findUserBy...()` functions when called without a field selector, and all `onLogin`, `onLoginFailure` and `onLogout` callbacks. Example: `Accounts.config({ defaultFieldSelector: { myBigArray: 0 }})`. Beware when using this. If, for instance, you do not include `email` when excluding the fields, you can have problems with functions like `forgotPassword` that will break because they won't have the required data available. It's recommend that you always keep the fields `_id`, `username`, and `email`. * @param {String|Mongo.Collection} options.collection A collection name or a Mongo.Collection object to hold the users. From a75a89acfdd78c46b1dea7d0e927c1c1f64428df Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Wed, 30 Oct 2024 13:54:12 -0400 Subject: [PATCH 29/48] add test --- packages/accounts-password/password_tests.js | 28 ++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/packages/accounts-password/password_tests.js b/packages/accounts-password/password_tests.js index 88461e7d91..b21b4e6d3d 100644 --- a/packages/accounts-password/password_tests.js +++ b/packages/accounts-password/password_tests.js @@ -1896,4 +1896,32 @@ if (Meteor.isServer) (() => { test.equal(url.searchParams.get('test'), extraParams.test); }); + Tinytest.addAsync('passwords - createUserAsync', async test => { + const username = Random.id(); + const email = `${username}-intercept@example.com`; + const password = 'password'; + + const userId = await Accounts.createUserAsync({ + username: username, + email: email, + password: password + }); + + test.isTrue(userId, 'User ID should be returned'); + const user = await Meteor.users.findOneAsync(userId); + test.equal(user.username, username, 'Username should match'); + test.equal(user.emails[0].address, email, 'Email should match'); + + Accounts.config({ + ambiguousErrorMessages: false, + }) + + await test.throwsAsync(async () => { + await Accounts.createUserAsync({ + username: username, + email: email, + password: password + }); + }, 'already exists'); + }); })(); From 825379a1a21f05eea1bd81dbde5dd78203ebca5c Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Fri, 8 Nov 2024 13:32:01 -0400 Subject: [PATCH 30/48] update versions --- packages/deprecated/http/.versions | 115 +++++++++++++++-------------- 1 file changed, 58 insertions(+), 57 deletions(-) diff --git a/packages/deprecated/http/.versions b/packages/deprecated/http/.versions index e434868a96..579d0d042d 100644 --- a/packages/deprecated/http/.versions +++ b/packages/deprecated/http/.versions @@ -1,57 +1,58 @@ -allow-deny@2.0.0-alpha300.18 -babel-compiler@7.11.0-alpha300.18 -babel-runtime@1.5.2-alpha300.18 -base64@1.0.13-alpha300.18 -binary-heap@1.0.12-alpha300.18 -blaze@3.0.0-alpha300.16 -boilerplate-generator@2.0.0-alpha300.18 -callback-hook@1.6.0-alpha300.18 -check@1.3.3-alpha300.18 -core-runtime@1.0.0-alpha300.18 -ddp@1.4.2-alpha300.18 -ddp-client@3.0.0-alpha300.18 -ddp-common@1.4.1-alpha300.18 -ddp-server@3.0.0-alpha300.18 -diff-sequence@1.1.3-alpha300.18 -dynamic-import@0.7.4-alpha300.18 -ecmascript@0.16.8-alpha300.18 -ecmascript-runtime@0.8.2-alpha300.18 -ecmascript-runtime-client@0.12.2-alpha300.18 -ecmascript-runtime-server@0.11.1-alpha300.18 -ejson@1.1.4-alpha300.18 -facts-base@1.0.2-alpha300.18 -fetch@0.1.4-alpha300.18 -geojson-utils@1.0.12-alpha300.18 -htmljs@2.0.0-alpha300.16 -http@3.0.0-alpha300.18 -id-map@1.2.0-alpha300.18 -inter-process-messaging@0.1.2-alpha300.18 -local-test:http@3.0.0-alpha300.18 -logging@1.3.3-alpha300.18 -meteor@2.0.0-alpha300.18 -minimongo@2.0.0-alpha300.18 -modern-browsers@0.1.10-alpha300.18 -modules@0.19.1-alpha300.18 -modules-runtime@0.13.2-alpha300.18 -mongo@2.0.0-alpha300.18 -mongo-decimal@0.1.4-alpha300.18 -mongo-dev-server@1.1.1-alpha300.18 -mongo-id@1.0.9-alpha300.18 -npm-mongo@4.16.1-alpha300.18 -observe-sequence@2.0.0-alpha300.16 -ordered-dict@1.2.0-alpha300.18 -promise@1.0.0-alpha300.18 -random@1.2.2-alpha300.18 -react-fast-refresh@0.2.8-alpha300.18 -reactive-var@1.0.13-alpha300.18 -reload@1.3.2-alpha300.18 -retry@1.1.1-alpha300.18 -routepolicy@1.1.2-alpha300.18 -socket-stream-client@0.5.2-alpha300.18 -test-helpers@2.0.0-alpha300.18 -tinytest@2.0.0-alpha300.18 -tracker@1.3.3-alpha300.18 -underscore@1.0.14-alpha300.18 -url@1.3.2 -webapp@2.0.0-alpha300.18 -webapp-hashing@1.1.2-alpha300.18 +allow-deny@2.0.0 +babel-compiler@7.11.1 +babel-runtime@1.5.2 +base64@1.0.13 +binary-heap@1.0.12 +blaze@3.0.0 +boilerplate-generator@2.0.0 +callback-hook@1.6.0 +check@1.4.4 +core-runtime@1.0.0 +ddp@1.4.2 +ddp-client@3.0.2 +ddp-common@1.4.4 +ddp-server@3.0.2 +diff-sequence@1.1.3 +dynamic-import@0.7.4 +ecmascript@0.16.9 +ecmascript-runtime@0.8.3 +ecmascript-runtime-client@0.12.2 +ecmascript-runtime-server@0.11.1 +ejson@1.1.4 +facts-base@1.0.2 +fetch@0.1.5 +geojson-utils@1.0.12 +htmljs@2.0.1 +http@3.0.0 +id-map@1.2.0 +inter-process-messaging@0.1.2 +local-test:http@3.0.0 +logging@1.3.5 +meteor@2.0.1 +minimongo@2.0.1 +modern-browsers@0.1.11 +modules@0.20.2 +modules-runtime@0.13.2 +mongo@2.0.2 +mongo-decimal@0.1.4 +mongo-dev-server@1.1.1 +mongo-id@1.0.9 +npm-mongo@4.17.4 +observe-sequence@2.0.0 +ordered-dict@1.2.0 +promise@1.0.0 +random@1.2.2 +react-fast-refresh@0.2.9 +reactive-var@1.0.13 +reload@1.3.2 +retry@1.1.1 +routepolicy@1.1.2 +socket-stream-client@0.5.3 +test-helpers@2.0.1 +tinytest@1.3.0 +tracker@1.3.4 +typescript@5.4.3 +underscore@1.6.4 +url@1.3.4 +webapp@2.0.3 +webapp-hashing@1.1.2 From b5fd7ac4308bec917d041bec3b75bab8b56dfa25 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Sat, 9 Nov 2024 22:13:13 -0400 Subject: [PATCH 31/48] adjust compression parameters and use permessage-deflate2 with threshold (only messages larger than 1kb (512 chars) are compressed by default) --- package-lock.json | 17 +++++++++++++++++ package.json | 2 ++ packages/ddp-server/package.js | 2 +- packages/ddp-server/stream_server.js | 17 ++++++++++++----- packages/socket-stream-client/node.js | 4 ++-- packages/socket-stream-client/package.js | 2 +- 6 files changed, 35 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index c9d647ebc5..2f50dcb896 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,8 @@ "@babel/preset-react": "^7.18.6", "@types/lodash.isempty": "^4.4.9", "@types/node": "^18.16.18", + "@types/sockjs": "^0.3.36", + "@types/sockjs-client": "^1.5.4", "@typescript-eslint/eslint-plugin": "^5.56.0", "@typescript-eslint/parser": "^5.56.0", "eslint": "^8.36.0", @@ -1127,6 +1129,21 @@ "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/sockjs-client": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/sockjs-client/-/sockjs-client-1.5.4.tgz", + "integrity": "sha512-zk+uFZeWyvJ5ZFkLIwoGA/DfJ+pYzcZ8eH4H/EILCm2OBZyHH6Hkdna1/UWL/CFruh5wj6ES7g75SvUB0VsH5w==", + "dev": true + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", diff --git a/package.json b/package.json index 5b0390a9b6..a21df794cd 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,8 @@ "@babel/preset-react": "^7.18.6", "@types/lodash.isempty": "^4.4.9", "@types/node": "^18.16.18", + "@types/sockjs": "^0.3.36", + "@types/sockjs-client": "^1.5.4", "@typescript-eslint/eslint-plugin": "^5.56.0", "@typescript-eslint/parser": "^5.56.0", "eslint": "^8.36.0", diff --git a/packages/ddp-server/package.js b/packages/ddp-server/package.js index a6ceaa8c90..8f72e3b8e2 100644 --- a/packages/ddp-server/package.js +++ b/packages/ddp-server/package.js @@ -5,7 +5,7 @@ Package.describe({ }); Npm.depends({ - "permessage-deflate": "0.1.7", + "permessage-deflate2": "0.1.8-alpha.1", sockjs: "0.3.24", "lodash.once": "4.1.1", "lodash.isempty": "4.4.0", diff --git a/packages/ddp-server/stream_server.js b/packages/ddp-server/stream_server.js index d57b81456c..6b3fad8de1 100644 --- a/packages/ddp-server/stream_server.js +++ b/packages/ddp-server/stream_server.js @@ -1,4 +1,5 @@ import once from 'lodash.once'; +import zlib from 'node:zlib'; // By default, we use the permessage-deflate extension with default // configuration. If $SERVER_WEBSOCKET_COMPRESSION is set, then it must be valid @@ -14,12 +15,18 @@ import once from 'lodash.once'; var websocketExtensions = once(function () { var extensions = []; - var websocketCompressionConfig = process.env.SERVER_WEBSOCKET_COMPRESSION - ? JSON.parse(process.env.SERVER_WEBSOCKET_COMPRESSION) : {}; + var websocketCompressionConfig = process.env.SERVER_WEBSOCKET_COMPRESSION ? + JSON.parse(process.env.SERVER_WEBSOCKET_COMPRESSION) : {}; + if (websocketCompressionConfig) { - extensions.push(Npm.require('permessage-deflate').configure( - websocketCompressionConfig - )); + extensions.push(Npm.require('permessage-deflate2').configure({ + threshold: 512, + level: zlib.constants.Z_BEST_SPEED, + memLevel: zlib.constants.Z_MIN_MEMLEVEL, + noContextTakeover: true, + maxWindowBits: zlib.constants.Z_MIN_WINDOWBITS, + ...(websocketCompressionConfig || {}) + })); } return extensions; diff --git a/packages/socket-stream-client/node.js b/packages/socket-stream-client/node.js index 708c8a1711..26bae21b50 100644 --- a/packages/socket-stream-client/node.js +++ b/packages/socket-stream-client/node.js @@ -1,6 +1,6 @@ import { Meteor } from "meteor/meteor"; -import { toWebsocketUrl } from "./urls.js"; import { StreamClientCommon } from "./common.js"; +import { toWebsocketUrl } from "./urls.js"; // @param endpoint {String} URL to Meteor app // "http://subdomain.meteor.com/" or "/" or @@ -132,7 +132,7 @@ export class ClientStream extends StreamClientCommon { // require the module if we actually create a server-to-server // connection. var FayeWebSocket = Npm.require('faye-websocket'); - var deflate = Npm.require('permessage-deflate'); + var deflate = Npm.require('permessage-deflate2'); var targetUrl = toWebsocketUrl(this.endpoint); var fayeOptions = { diff --git a/packages/socket-stream-client/package.js b/packages/socket-stream-client/package.js index a49c533e6d..ab4c7781f3 100644 --- a/packages/socket-stream-client/package.js +++ b/packages/socket-stream-client/package.js @@ -7,7 +7,7 @@ Package.describe({ Npm.depends({ "faye-websocket": "0.11.4", - "permessage-deflate": "0.1.7", + "permessage-deflate2": "0.1.8-alpha.1", "lodash.isequal": "4.5.0", "lodash.once": "4.1.1" }); From 216d12cf576404ebbace6979f60915327c9f54d7 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Mon, 25 Nov 2024 11:21:27 -0400 Subject: [PATCH 32/48] add summarization command --- .envrc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.envrc b/.envrc index b1f3cbd76f..f1b1524541 100644 --- a/.envrc +++ b/.envrc @@ -55,3 +55,19 @@ function @docs-start { function @docs-migration-start { npm run docs:dev --prefix "$ROOT_DIR/v3-docs/v3-migration-docs" } + +function @get-changes { + git diff --numstat HEAD~1 HEAD | awk '($1 + $2) <= 5000 {print $3}' +} + +function @summarize-changes { + changes=$(@get-changes) + + if [ -n "$changes" ]; then + changes=$(git diff HEAD~1 HEAD -- $(echo "$changes" | tr '\n' ' ')) + else + changes=$(git diff HEAD~1 HEAD) + fi + + echo "$changes" | llm -s "Summarize the following changes in a few sentences:" +} From 06ad0b278447fa2c4d3c51677d44c300f3783aeb Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Mon, 25 Nov 2024 12:16:39 -0400 Subject: [PATCH 33/48] make asynchronous queue name backwards compatible --- packages/meteor/asynchronous_queue.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/meteor/asynchronous_queue.js b/packages/meteor/asynchronous_queue.js index fe1a30c783..ba5bfd2ca5 100644 --- a/packages/meteor/asynchronous_queue.js +++ b/packages/meteor/asynchronous_queue.js @@ -151,4 +151,9 @@ class AsynchronousQueue { } } -Meteor._AsynchronousQueue = AsynchronousQueue; \ No newline at end of file +Meteor._AsynchronousQueue = AsynchronousQueue; + +/** + * Backwards compatibility + */ +Meteor._SynchronousQueue = AsynchronousQueue; \ No newline at end of file From 29caff3410a77945fe429542238a4604f4b85330 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Tue, 26 Nov 2024 10:35:11 -0400 Subject: [PATCH 34/48] use original logic instead of the one with lru map --- packages/ddp-server/dummy_document_view.ts | 40 +++ packages/ddp-server/livedata_server.js | 21 +- packages/ddp-server/package.js | 3 +- .../ddp-server/session_collection_view.ts | 245 ++++++++---------- packages/ddp-server/session_document_view.ts | 117 +++++---- 5 files changed, 213 insertions(+), 213 deletions(-) create mode 100644 packages/ddp-server/dummy_document_view.ts diff --git a/packages/ddp-server/dummy_document_view.ts b/packages/ddp-server/dummy_document_view.ts new file mode 100644 index 0000000000..f87f0839aa --- /dev/null +++ b/packages/ddp-server/dummy_document_view.ts @@ -0,0 +1,40 @@ +interface ChangeCollector { + [key: string]: any; +} + +interface DataEntry { + subscriptionHandle: string; + value: any; +} + +export class DummyDocumentView { + private existsIn: Set; + private dataByKey: Map; + + constructor() { + this.existsIn = new Set(); // set of subscriptionHandle + this.dataByKey = new Map(); // key-> [ {subscriptionHandle, value} by precedence] + } + + getFields(): Record { + return {}; + } + + clearField( + subscriptionHandle: string, + key: string, + changeCollector: ChangeCollector + ): void { + changeCollector[key] = undefined; + } + + changeField( + subscriptionHandle: string, + key: string, + value: any, + changeCollector: ChangeCollector, + isAdd?: boolean + ): void { + changeCollector[key] = value; + } +} \ No newline at end of file diff --git a/packages/ddp-server/livedata_server.js b/packages/ddp-server/livedata_server.js index 75406778b8..d9b49a164c 100644 --- a/packages/ddp-server/livedata_server.js +++ b/packages/ddp-server/livedata_server.js @@ -1,6 +1,6 @@ import isEmpty from 'lodash.isempty'; -import isString from 'lodash.isstring'; import isObject from 'lodash.isobject'; +import isString from 'lodash.isstring'; import { SessionCollectionView } from './session_collection_view'; import { SessionDocumentView } from './session_document_view'; @@ -57,26 +57,7 @@ DDPServer.publicationStrategies = publicationStrategies; // Session and Subscription are file scope. For now, until we freeze // the interface, Server is package scope (in the future it should be // exported). -var DummyDocumentView = function () { - var self = this; - self.existsIn = new Set(); // set of subscriptionHandle - self.dataByKey = new Map(); // key-> [ {subscriptionHandle, value} by precedence] -}; -Object.assign(DummyDocumentView.prototype, { - getFields: function () { - return {} - }, - - clearField: function (subscriptionHandle, key, changeCollector) { - changeCollector[key] = undefined - }, - - changeField: function (subscriptionHandle, key, value, - changeCollector, isAdd) { - changeCollector[key] = value - } -}); DDPServer._SessionDocumentView = SessionDocumentView; diff --git a/packages/ddp-server/package.js b/packages/ddp-server/package.js index 8f72e3b8e2..e9aadfc9e4 100644 --- a/packages/ddp-server/package.js +++ b/packages/ddp-server/package.js @@ -10,8 +10,7 @@ Npm.depends({ "lodash.once": "4.1.1", "lodash.isempty": "4.4.0", "lodash.isstring": "4.0.1", - "lodash.isobject": "3.0.2", - "lru_map": '0.4.1' + "lodash.isobject": "3.0.2" }); Package.onUse(function (api) { diff --git a/packages/ddp-server/session_collection_view.ts b/packages/ddp-server/session_collection_view.ts index add76cda85..6e5c4c7533 100644 --- a/packages/ddp-server/session_collection_view.ts +++ b/packages/ddp-server/session_collection_view.ts @@ -1,77 +1,114 @@ -import { SessionDocumentView } from './session_document_view'; -import { LRUMap } from 'lru_map' -import isEmpty from 'lodash.isempty'; +import { DummyDocumentView } from "./dummy_document_view"; +import { SessionDocumentView } from "./session_document_view"; + +interface SessionCallbacks { + added: (collectionName: string, id: string, fields: Record) => void; + changed: (collectionName: string, id: string, fields: Record) => void; + removed: (collectionName: string, id: string) => void; +} + +interface DiffSequence { + diffMaps: ( + previous: Map, + current: Map, + callbacks: { + both: (id: string, prev: DocumentView, now: DocumentView) => void; + rightOnly: (id: string, now: DocumentView) => void; + leftOnly: (id: string, prev: DocumentView) => void; + } + ) => void; + diffObjects: ( + previous: Record, + current: Record, + callbacks: { + both: (key: string, prev: any, now: any) => void; + rightOnly: (key: string, now: any) => void; + leftOnly: (key: string, prev: any) => void; + } + ) => void; +} + +interface DocumentView { + existsIn: Set; + dataByKey: Map; + getFields: () => Record; + changeField: ( + subscriptionHandle: string, + key: string, + value: any, + changeCollector: Record, + isAdd?: boolean + ) => void; + clearField: ( + subscriptionHandle: string, + key: string, + changeCollector: Record + ) => void; +} -/** - * Represents a client's view of documents within a single collection - * @class SessionCollectionView - */ export class SessionCollectionView { private readonly collectionName: string; + private readonly documents: Map; private readonly callbacks: SessionCallbacks; - private readonly documents: LRUMap; - private readonly options: ViewOptions; /** - * @param collectionName - Name of the collection this view represents - * @param callbacks - Callbacks for document changes (added/changed/removed) - * @param options - Configuration options for the view + * Represents a client's view of a single collection + * @param collectionName - Name of the collection it represents + * @param sessionCallbacks - The callbacks for added, changed, removed */ - constructor( - collectionName: string, - callbacks: SessionCallbacks, - options: ViewOptions = {} - ) { + constructor(collectionName: string, sessionCallbacks: SessionCallbacks) { this.collectionName = collectionName; - this.callbacks = callbacks; - this.options = { - maxDocuments: options.maxDocuments || 10000, - documentTTL: options.documentTTL || 3600000, // 1 hour in ms - cleanupInterval: options.cleanupInterval || 300000 // 5 minutes in ms - }; - - // Use LRU cache with max size limit - this.documents = new LRUMap(this.options.maxDocuments); - - // Start periodic cleanup - this.startCleanup(); + this.documents = new Map(); + this.callbacks = sessionCallbacks; } - /** - * Periodically removes stale documents and frees memory - * @private - */ - private startCleanup(): void { - const cleanup = (): void => { - const now = Date.now(); - this.documents.forEach((doc, id) => { - if (now - doc.lastAccessed > this.options.documentTTL) { - this.documents.delete(id); - } - }); - }; - - if (typeof setInterval !== 'undefined') { - setInterval(cleanup, this.options.cleanupInterval); - } - } - - /** - * Checks if the view is empty - */ public isEmpty(): boolean { return this.documents.size === 0; } - /** - * Adds or updates a document in the view - */ + public diff(previous: SessionCollectionView): void { + DiffSequence.diffMaps(previous.documents, this.documents, { + both: this.diffDocument.bind(this), + rightOnly: (id: string, nowDV: DocumentView) => { + this.callbacks.added(this.collectionName, id, nowDV.getFields()); + }, + leftOnly: (id: string, prevDV: DocumentView) => { + this.callbacks.removed(this.collectionName, id); + } + }); + } + + private diffDocument(id: string, prevDV: DocumentView, nowDV: DocumentView): void { + const fields: Record = {}; + + DiffSequence.diffObjects(prevDV.getFields(), nowDV.getFields(), { + both: (key: string, prev: any, now: any) => { + if (!EJSON.equals(prev, now)) { + fields[key] = now; + } + }, + rightOnly: (key: string, now: any) => { + fields[key] = now; + }, + leftOnly: (key: string, prev: any) => { + fields[key] = undefined; + } + }); + + this.callbacks.changed(this.collectionName, id, fields); + } + public added(subscriptionHandle: string, id: string, fields: Record): void { let docView = this.documents.get(id); - const added = !docView; + let added = false; if (!docView) { - docView = new SessionDocumentView(); + added = true; + if (Meteor.server.getPublicationStrategy(this.collectionName).useDummyDocumentView) { + docView = new DummyDocumentView(); + } else { + docView = new SessionDocumentView(); + } this.documents.set(id, docView); } @@ -79,7 +116,13 @@ export class SessionCollectionView { const changeCollector: Record = {}; Object.entries(fields).forEach(([key, value]) => { - docView.changeField(subscriptionHandle, key, value, changeCollector, true); + docView!.changeField( + subscriptionHandle, + key, + value, + changeCollector, + true + ); }); if (added) { @@ -89,16 +132,14 @@ export class SessionCollectionView { } } - /** - * Updates an existing document in the view - */ public changed(subscriptionHandle: string, id: string, changed: Record): void { + const changedResult: Record = {}; const docView = this.documents.get(id); + if (!docView) { - throw new Error(`Changed called on document ${id} that does not exist`); + throw new Error(`Could not find element with id ${id} to change`); } - const changedResult: Record = {}; Object.entries(changed).forEach(([key, value]) => { if (value === undefined) { docView.clearField(subscriptionHandle, key, changedResult); @@ -107,94 +148,30 @@ export class SessionCollectionView { } }); - if (!isEmpty(changedResult)) { - this.callbacks.changed(this.collectionName, id, changedResult); - } + this.callbacks.changed(this.collectionName, id, changedResult); } - /** - * Removes a document from the view - */ public removed(subscriptionHandle: string, id: string): void { const docView = this.documents.get(id); + if (!docView) { - throw new Error(`Removed called on document ${id} that does not exist`); + throw new Error(`Removed nonexistent document ${id}`); } docView.existsIn.delete(subscriptionHandle); if (docView.existsIn.size === 0) { - this.documents.delete(id); + // it is gone from everyone this.callbacks.removed(this.collectionName, id); + this.documents.delete(id); } else { const changed: Record = {}; + // remove this subscription from every precedence list + // and record the changes docView.dataByKey.forEach((precedenceList, key) => { docView.clearField(subscriptionHandle, key, changed); }); - - if (!isEmpty(changed)) { - this.callbacks.changed(this.collectionName, id, changed); - } + this.callbacks.changed(this.collectionName, id, changed); } } - - /** - * Compares this view with another and sends appropriate callbacks - */ - public diff(previous: SessionCollectionView): void { - DiffSequence.diffMaps(previous.documents, this.documents, { - both: (id, prevDocView, newDocView) => { - this.diffDocument(id, prevDocView, newDocView); - }, - rightOnly: (id, newDocView) => { - this.callbacks.added(this.collectionName, id, newDocView.getFields()); - }, - leftOnly: (id) => { - this.callbacks.removed(this.collectionName, id); - } - }); - } - - /** - * Cleans up resources used by this view - */ - public destroy(): void { - this.documents.clear(); - } - - /** - * @private - */ - private diffDocument(id: string, prevDocView: SessionDocumentView, newDocView: SessionDocumentView): void { - const fields: Record = {}; - DiffSequence.diffObjects(prevDocView.getFields(), newDocView.getFields(), { - both: (key, prev, now) => { - if (!EJSON.equals(prev, now)) { - fields[key] = now; - } - }, - rightOnly: (key, now) => { - fields[key] = now; - }, - leftOnly: (key) => { - fields[key] = undefined; - } - }); - - if (!isEmpty(fields)) { - this.callbacks.changed(this.collectionName, id, fields); - } - } -} - -interface ViewOptions { - maxDocuments?: number; - documentTTL?: number; - cleanupInterval?: number; -} - -interface SessionCallbacks { - added: (collection: string, id: string, fields: Record) => void; - changed: (collection: string, id: string, fields: Record) => void; - removed: (collection: string, id: string) => void; } \ No newline at end of file diff --git a/packages/ddp-server/session_document_view.ts b/packages/ddp-server/session_document_view.ts index b4cd3801b7..8cdfb91c55 100644 --- a/packages/ddp-server/session_document_view.ts +++ b/packages/ddp-server/session_document_view.ts @@ -1,49 +1,51 @@ -/** - * Represents a single document in a SessionCollectionView - * @class SessionDocumentView - */ +interface PrecedenceItem { + subscriptionHandle: string; + value: any; +} + +interface ChangeCollector { + [key: string]: any; +} + export class SessionDocumentView { - public existsIn: Set; - public dataByKey: Map>; - public lastAccessed: number; + private existsIn: Set; + private dataByKey: Map; constructor() { - this.existsIn = new Set(); - this.dataByKey = new Map(); - this.lastAccessed = Date.now(); + this.existsIn = new Set(); // set of subscriptionHandle + // Memory Growth + this.dataByKey = new Map(); // key-> [ {subscriptionHandle, value} by precedence] } - /** - * Gets the current fields of the document - */ - public getFields(): Record { - this.lastAccessed = Date.now(); - const fields: Record = {}; - + getFields(): Record { + const ret: Record = {}; this.dataByKey.forEach((precedenceList, key) => { - if (precedenceList.length > 0) { - fields[key] = precedenceList[0].value; - } + ret[key] = precedenceList[0].value; }); - - return fields; + return ret; } - /** - * Clears a field from the document - */ - public clearField(subscriptionHandle: string, key: string, changeCollector: Record): void { - if (key === '_id') return; + clearField( + subscriptionHandle: string, + key: string, + changeCollector: ChangeCollector + ): void { + // Publish API ignores _id if present in fields + if (key === "_id") return; const precedenceList = this.dataByKey.get(key); + // It's okay to clear fields that didn't exist. No need to throw + // an error. if (!precedenceList) return; - let removedValue: any; + let removedValue: any = undefined; + for (let i = 0; i < precedenceList.length; i++) { - if (precedenceList[i].subscriptionHandle === subscriptionHandle) { - if (i === 0) { - removedValue = precedenceList[i].value; - } + const precedence = precedenceList[i]; + if (precedence.subscriptionHandle === subscriptionHandle) { + // The view's value can only change if this subscription is the one that + // used to have precedence. + if (i === 0) removedValue = precedence.value; precedenceList.splice(i, 1); break; } @@ -52,52 +54,53 @@ export class SessionDocumentView { if (precedenceList.length === 0) { this.dataByKey.delete(key); changeCollector[key] = undefined; - } else if (removedValue !== undefined && - !EJSON.equals(removedValue, precedenceList[0].value)) { + } else if ( + removedValue !== undefined && + !EJSON.equals(removedValue, precedenceList[0].value) + ) { changeCollector[key] = precedenceList[0].value; } } - /** - * Changes a field value in the document - */ - public changeField( + changeField( subscriptionHandle: string, key: string, value: any, - changeCollector: Record, - isAdd: boolean = false + changeCollector: ChangeCollector, + isAdd: boolean ): void { - if (key === '_id') return; + // Publish API ignores _id if present in fields + if (key === "_id") return; + // Don't share state with the data passed in by the user. value = EJSON.clone(value); if (!this.dataByKey.has(key)) { - this.dataByKey.set(key, [{ - subscriptionHandle, - value - }]); + this.dataByKey.set(key, [ + { subscriptionHandle: subscriptionHandle, value: value }, + ]); changeCollector[key] = value; return; } const precedenceList = this.dataByKey.get(key)!; - let item = !isAdd && precedenceList.find( - p => p.subscriptionHandle === subscriptionHandle - ); + let elt: PrecedenceItem | undefined; - if (item) { - if (item === precedenceList[0] && !EJSON.equals(value, item.value)) { + if (!isAdd) { + elt = precedenceList.find( + (precedence) => precedence.subscriptionHandle === subscriptionHandle + ); + } + + if (elt) { + if (elt === precedenceList[0] && !EJSON.equals(value, elt.value)) { + // this subscription is changing the value of this field. changeCollector[key] = value; } - item.value = value; + elt.value = value; } else { - precedenceList.push({ subscriptionHandle, value }); + // this subscription is newly caring about this field + precedenceList.push({ subscriptionHandle: subscriptionHandle, value: value }); } } -} - -interface PrecedenceItem { - subscriptionHandle: string; - value: any; } \ No newline at end of file From 748dbba2a63383a5f3e1933ce70bb8ce28f03533 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Tue, 26 Nov 2024 10:41:34 -0400 Subject: [PATCH 35/48] bump threshold --- packages/ddp-server/stream_server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ddp-server/stream_server.js b/packages/ddp-server/stream_server.js index 6b3fad8de1..3691f59e1d 100644 --- a/packages/ddp-server/stream_server.js +++ b/packages/ddp-server/stream_server.js @@ -20,7 +20,7 @@ var websocketExtensions = once(function () { if (websocketCompressionConfig) { extensions.push(Npm.require('permessage-deflate2').configure({ - threshold: 512, + threshold: 1024, level: zlib.constants.Z_BEST_SPEED, memLevel: zlib.constants.Z_MIN_MEMLEVEL, noContextTakeover: true, From 9f5de61f7c93f6b9fa6e5863d5c7723c0f88006a Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Tue, 26 Nov 2024 11:00:03 -0400 Subject: [PATCH 36/48] adjust types --- .../ddp-server/session_collection_view.ts | 41 +------------------ packages/ddp-server/session_document_view.ts | 2 +- 2 files changed, 3 insertions(+), 40 deletions(-) diff --git a/packages/ddp-server/session_collection_view.ts b/packages/ddp-server/session_collection_view.ts index 6e5c4c7533..153c569bd0 100644 --- a/packages/ddp-server/session_collection_view.ts +++ b/packages/ddp-server/session_collection_view.ts @@ -7,44 +7,7 @@ interface SessionCallbacks { removed: (collectionName: string, id: string) => void; } -interface DiffSequence { - diffMaps: ( - previous: Map, - current: Map, - callbacks: { - both: (id: string, prev: DocumentView, now: DocumentView) => void; - rightOnly: (id: string, now: DocumentView) => void; - leftOnly: (id: string, prev: DocumentView) => void; - } - ) => void; - diffObjects: ( - previous: Record, - current: Record, - callbacks: { - both: (key: string, prev: any, now: any) => void; - rightOnly: (key: string, now: any) => void; - leftOnly: (key: string, prev: any) => void; - } - ) => void; -} - -interface DocumentView { - existsIn: Set; - dataByKey: Map; - getFields: () => Record; - changeField: ( - subscriptionHandle: string, - key: string, - value: any, - changeCollector: Record, - isAdd?: boolean - ) => void; - clearField: ( - subscriptionHandle: string, - key: string, - changeCollector: Record - ) => void; -} +type DocumentView = SessionDocumentView | DummyDocumentView; export class SessionCollectionView { private readonly collectionName: string; @@ -99,7 +62,7 @@ export class SessionCollectionView { } public added(subscriptionHandle: string, id: string, fields: Record): void { - let docView = this.documents.get(id); + let docView: DocumentView | undefined = this.documents.get(id); let added = false; if (!docView) { diff --git a/packages/ddp-server/session_document_view.ts b/packages/ddp-server/session_document_view.ts index 8cdfb91c55..4bd838c177 100644 --- a/packages/ddp-server/session_document_view.ts +++ b/packages/ddp-server/session_document_view.ts @@ -67,7 +67,7 @@ export class SessionDocumentView { key: string, value: any, changeCollector: ChangeCollector, - isAdd: boolean + isAdd: boolean = false ): void { // Publish API ignores _id if present in fields if (key === "_id") return; From d86ba5c20d138fffa67fa28626b32175ed0609e8 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Tue, 26 Nov 2024 11:15:54 -0400 Subject: [PATCH 37/48] fix order of operations --- packages/mongo/observe_multiplex.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/mongo/observe_multiplex.ts b/packages/mongo/observe_multiplex.ts index da8bda0bd9..ddc9bc9896 100644 --- a/packages/mongo/observe_multiplex.ts +++ b/packages/mongo/observe_multiplex.ts @@ -1,5 +1,5 @@ -import { ObserveHandle } from './observe_handle'; import isEmpty from 'lodash.isempty'; +import { ObserveHandle } from './observe_handle'; interface ObserveMultiplexerOptions { ordered: boolean; @@ -34,8 +34,7 @@ export class ObserveMultiplexer { this._ordered = ordered; this._onStop = onStop; - // @ts-ignore - this._queue = new Meteor._AsynchronousQueue(); + this._queue = new Meteor._AsynchronousQueue({ orderMatters: true }); this._handles = {}; this._resolver = null; this._isReady = false; From 3c1391d50d8fe5a856f6973206741855cefce72d Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Tue, 26 Nov 2024 12:17:43 -0400 Subject: [PATCH 38/48] no need for async here --- packages/mongo/observe_multiplex.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mongo/observe_multiplex.ts b/packages/mongo/observe_multiplex.ts index ddc9bc9896..33182a2e22 100644 --- a/packages/mongo/observe_multiplex.ts +++ b/packages/mongo/observe_multiplex.ts @@ -139,7 +139,7 @@ export class ObserveMultiplexer { return !!this._isReady; } - async _applyCallback(callbackName: string, args: any[]) { + _applyCallback(callbackName: string, args: any[]) { this._queue.queueTask(async () => { if (!this._handles) return; From e526c52fb76c2d3bc173cb14ca39d1c6a61b08c9 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Tue, 26 Nov 2024 12:33:00 -0400 Subject: [PATCH 39/48] order matters unless told otherwise --- packages/meteor/asynchronous_queue.js | 2 +- packages/mongo/observe_multiplex.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/meteor/asynchronous_queue.js b/packages/meteor/asynchronous_queue.js index ba5bfd2ca5..f2b1482554 100644 --- a/packages/meteor/asynchronous_queue.js +++ b/packages/meteor/asynchronous_queue.js @@ -6,7 +6,7 @@ class AsynchronousQueue { constructor({ batchSize = 50, maxConcurrent = 10, - orderMatters = false + orderMatters = true } = {}) { this._taskHandles = new Meteor._DoubleEndedQueue(); this._runningOrRunScheduled = false; diff --git a/packages/mongo/observe_multiplex.ts b/packages/mongo/observe_multiplex.ts index 33182a2e22..a99d64d562 100644 --- a/packages/mongo/observe_multiplex.ts +++ b/packages/mongo/observe_multiplex.ts @@ -34,7 +34,7 @@ export class ObserveMultiplexer { this._ordered = ordered; this._onStop = onStop; - this._queue = new Meteor._AsynchronousQueue({ orderMatters: true }); + this._queue = new Meteor._AsynchronousQueue(); this._handles = {}; this._resolver = null; this._isReady = false; From 93319b9d1125f114bcf972994e37d192725e451a Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Tue, 26 Nov 2024 15:17:18 -0400 Subject: [PATCH 40/48] add adding tasks to beginning of queue --- packages/meteor/asynchronous_queue.js | 19 ++++++++++++++++++- packages/mongo/observe_multiplex.ts | 4 ++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/packages/meteor/asynchronous_queue.js b/packages/meteor/asynchronous_queue.js index f2b1482554..773958a378 100644 --- a/packages/meteor/asynchronous_queue.js +++ b/packages/meteor/asynchronous_queue.js @@ -4,7 +4,7 @@ class AsynchronousQueue { * when needed. Configurable batch size and concurrency limits help optimize throughput. */ constructor({ - batchSize = 50, + batchSize = 256, maxConcurrent = 10, orderMatters = true } = {}) { @@ -149,6 +149,23 @@ class AsynchronousQueue { this._draining = false; } + + unshiftTasks(tasks) { + const wrappedTasks = tasks.map(task => ({ + task: Meteor.bindEnvironment(task, function (e) { + Meteor._debug('Exception from task', e); + throw e; + }), + name: task.name + })); + + // Add all tasks to the front of the queue + wrappedTasks.reverse().forEach(wrappedTask => { + this._taskHandles.unshift(wrappedTask); + }); + + this._scheduleRun(); + } } Meteor._AsynchronousQueue = AsynchronousQueue; diff --git a/packages/mongo/observe_multiplex.ts b/packages/mongo/observe_multiplex.ts index a99d64d562..0fd4d39eba 100644 --- a/packages/mongo/observe_multiplex.ts +++ b/packages/mongo/observe_multiplex.ts @@ -61,11 +61,11 @@ export class ObserveMultiplexer { Package['facts-base'] && Package['facts-base'].Facts.incrementServerFact( "mongo-livedata", "observe-handles", 1); - await this._queue.runTask(async () => { + await this._queue.unshiftTasks([async () => { this._handles![handle._id] = handle; await this._sendAdds(handle); --this._addHandleTasksScheduledButNotPerformed; - }); + }]); await this._readyPromise; } From 750fca9883174cf51702e62698b32ac924f2ca86 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Mon, 2 Dec 2024 10:20:40 -0400 Subject: [PATCH 41/48] Revert "add adding tasks to beginning of queue" This reverts commit 93319b9d1125f114bcf972994e37d192725e451a. --- packages/meteor/asynchronous_queue.js | 19 +------------------ packages/mongo/observe_multiplex.ts | 4 ++-- 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/packages/meteor/asynchronous_queue.js b/packages/meteor/asynchronous_queue.js index 773958a378..f2b1482554 100644 --- a/packages/meteor/asynchronous_queue.js +++ b/packages/meteor/asynchronous_queue.js @@ -4,7 +4,7 @@ class AsynchronousQueue { * when needed. Configurable batch size and concurrency limits help optimize throughput. */ constructor({ - batchSize = 256, + batchSize = 50, maxConcurrent = 10, orderMatters = true } = {}) { @@ -149,23 +149,6 @@ class AsynchronousQueue { this._draining = false; } - - unshiftTasks(tasks) { - const wrappedTasks = tasks.map(task => ({ - task: Meteor.bindEnvironment(task, function (e) { - Meteor._debug('Exception from task', e); - throw e; - }), - name: task.name - })); - - // Add all tasks to the front of the queue - wrappedTasks.reverse().forEach(wrappedTask => { - this._taskHandles.unshift(wrappedTask); - }); - - this._scheduleRun(); - } } Meteor._AsynchronousQueue = AsynchronousQueue; diff --git a/packages/mongo/observe_multiplex.ts b/packages/mongo/observe_multiplex.ts index 0fd4d39eba..a99d64d562 100644 --- a/packages/mongo/observe_multiplex.ts +++ b/packages/mongo/observe_multiplex.ts @@ -61,11 +61,11 @@ export class ObserveMultiplexer { Package['facts-base'] && Package['facts-base'].Facts.incrementServerFact( "mongo-livedata", "observe-handles", 1); - await this._queue.unshiftTasks([async () => { + await this._queue.runTask(async () => { this._handles![handle._id] = handle; await this._sendAdds(handle); --this._addHandleTasksScheduledButNotPerformed; - }]); + }); await this._readyPromise; } From 605faa91297572964052f8e6fd8ff2399f9aadfd Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Mon, 2 Dec 2024 10:33:24 -0400 Subject: [PATCH 42/48] Refactor AsynchronousQueue constructor to use environment variables for batch size and concurrency limits - Updated the constructor to read batch size and maximum concurrent tasks from environment variables (METEOR_ASYNC_QUEUE_BATCH_SIZE and METEOR_ASYNC_QUEUE_MAX_CONCURRENT) with default values. - Improved documentation to clarify configuration options for batch processing and task order preservation. --- packages/meteor/asynchronous_queue.js | 28 +++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/packages/meteor/asynchronous_queue.js b/packages/meteor/asynchronous_queue.js index f2b1482554..3d0a80de35 100644 --- a/packages/meteor/asynchronous_queue.js +++ b/packages/meteor/asynchronous_queue.js @@ -2,18 +2,30 @@ class AsynchronousQueue { /** * Creates a queue that processes tasks in parallel batches while preserving completion order * when needed. Configurable batch size and concurrency limits help optimize throughput. + * + * Batch size and concurrency are configured via environment variables: + * - METEOR_ASYNC_QUEUE_BATCH_SIZE: Number of tasks to process in each batch (default: 128) + * - METEOR_ASYNC_QUEUE_MAX_CONCURRENT: Maximum number of concurrent tasks (default: 16) + * + * @param {Object} options + * @param {boolean} [options.orderMatters=true] Whether task completion order should be preserved */ - constructor({ - batchSize = 50, - maxConcurrent = 10, - orderMatters = true - } = {}) { + constructor({ orderMatters = true } = {}) { + this._batchSize = parseInt( + process.env.METEOR_ASYNC_QUEUE_BATCH_SIZE || + '128' + ); + + this._maxConcurrent = parseInt( + process.env.METEOR_ASYNC_QUEUE_MAX_CONCURRENT || + '16' + ); + + this._orderMatters = orderMatters; + this._taskHandles = new Meteor._DoubleEndedQueue(); this._runningOrRunScheduled = false; this._draining = false; - this._batchSize = batchSize; - this._maxConcurrent = maxConcurrent; - this._orderMatters = orderMatters; this._activePromises = new Set(); } From 060799c67a71f958fb2665b245ffbc9186af332d Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Mon, 2 Dec 2024 10:44:42 -0400 Subject: [PATCH 43/48] adjust types --- packages/mongo/observe_handle.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/mongo/observe_handle.ts b/packages/mongo/observe_handle.ts index d084322a61..66235fa920 100644 --- a/packages/mongo/observe_handle.ts +++ b/packages/mongo/observe_handle.ts @@ -4,12 +4,15 @@ let nextObserveHandleId = 1; export type ObserveHandleCallbackInternal = '_added' | '_addedBefore' | '_changed' | '_movedBefore' | '_removed'; + +export type Callback = (...args: T[]) => Promise | void; + /** * The "observe handle" returned from observeChanges. * Contains a reference to an ObserveMultiplexer. * Used to stop observation and clean up resources. */ -export class ObserveHandle { +export class ObserveHandle { _id: number; _multiplexer: ObserveMultiplexer; nonMutatingCallbacks: boolean; @@ -18,13 +21,13 @@ export class ObserveHandle { public initialAddsSentResolver: (value: void) => void = () => {}; public initialAddsSent: Promise - _added?: (...args: any[]) => Promise; - _addedBefore?: (...args: any[]) => Promise; - _changed?: (...args: any[]) => Promise; - _movedBefore?: (...args: any[]) => Promise; - _removed?: (...args: any[]) => Promise; + _added?: Callback; + _addedBefore?: Callback; + _changed?: Callback; + _movedBefore?: Callback; + _removed?: Callback; - constructor(multiplexer: any, callbacks: Record, nonMutatingCallbacks: boolean) { + constructor(multiplexer: any, callbacks: Record>, nonMutatingCallbacks: boolean) { this._multiplexer = multiplexer; multiplexer.callbackNames().forEach((name: ObserveHandleCallback) => { From c73515470f5a4a623b8403231fbfa6c8472cd5b1 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Mon, 2 Dec 2024 11:24:45 -0400 Subject: [PATCH 44/48] add compression docs --- v3-docs/docs/.vitepress/config.mts | 9 +++ .../docs/performance/websocket-compression.md | 57 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 v3-docs/docs/performance/websocket-compression.md diff --git a/v3-docs/docs/.vitepress/config.mts b/v3-docs/docs/.vitepress/config.mts index a004c2867b..b199d78b91 100644 --- a/v3-docs/docs/.vitepress/config.mts +++ b/v3-docs/docs/.vitepress/config.mts @@ -431,6 +431,15 @@ export default defineConfig({ ], collapsed: true, }, + { + text: "Performance", + items: [ + { + text: "WebSocket Compression", + link: "/performance/websocket-compression", + }, + ], + }, ], socialLinks: [ diff --git a/v3-docs/docs/performance/websocket-compression.md b/v3-docs/docs/performance/websocket-compression.md new file mode 100644 index 0000000000..e466c9ff6a --- /dev/null +++ b/v3-docs/docs/performance/websocket-compression.md @@ -0,0 +1,57 @@ +# Websocket Compression in Meteor + +Meteor's stream server uses the permessage-deflate extension for websocket compression by default. While compression can help reduce bandwidth usage, it may impact performance in reactivity-intensive applications due to the computational overhead of compressing numerous DDP messages. + +## Configuration + +### Disabling Compression + +You can disable websocket compression by setting the `SERVER_WEBSOCKET_COMPRESSION` environment variable to `false`: + +```bash +SERVER_WEBSOCKET_COMPRESSION=false +``` + +### Custom Compression Settings + +To customize compression settings, set `SERVER_WEBSOCKET_COMPRESSION` to a JSON string with your desired configuration: + +```bash +# Example with custom settings +SERVER_WEBSOCKET_COMPRESSION='{"threshold": 2048, "level": 1}' +``` + +Available configuration options: + +- `threshold`: Minimum message size (in bytes) before compression is applied (default: 1024) +- `level`: Compression level (0-9, where 0=none, 1=fastest, 9=best compression) +- `memLevel`: Memory level (1-9, lower uses less memory) +- `noContextTakeover`: When true, compressor resets for each message (default: true) +- `maxWindowBits`: Window size for compression (9-15, lower uses less memory) + +## Verifying Compression Status + +You can check if compression is enabled through the Meteor shell: + +```javascript +Meteor.server.stream_server.server.options.faye_server_options.extensions +``` + +Results interpretation: +- `[]` (empty array): Compression is disabled +- `[{}]` (array with object): Compression is enabled + +## Performance Considerations + +- For apps with high message throughput or frequent small updates, disabling compression may improve performance +- Large message payloads may benefit from compression, especially over slower network connections +- Consider monitoring CPU usage and response times when adjusting compression settings + +## Default Configuration + +When enabled, the default configuration uses: +- Compression threshold: 1024 bytes +- Compression level: Z_BEST_SPEED (fastest) +- Memory level: Z_MIN_MEMLEVEL (minimum memory usage) +- Context takeover: Disabled +- Window bits: Z_MIN_WINDOWBITS (minimum window size) From 085587d7537aea121d3a60364ac2558994adc6c1 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Wed, 4 Dec 2024 10:54:22 -0400 Subject: [PATCH 45/48] add examples --- .../docs/performance/websocket-compression.md | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/v3-docs/docs/performance/websocket-compression.md b/v3-docs/docs/performance/websocket-compression.md index e466c9ff6a..c1c28c09a7 100644 --- a/v3-docs/docs/performance/websocket-compression.md +++ b/v3-docs/docs/performance/websocket-compression.md @@ -29,6 +29,46 @@ Available configuration options: - `noContextTakeover`: When true, compressor resets for each message (default: true) - `maxWindowBits`: Window size for compression (9-15, lower uses less memory) +## Configuration Examples + +Here are recommended configurations for different types of applications: + +### High-Frequency Updates / Real-Time Dashboard + +For applications with frequent small updates (e.g., real-time dashboards, trading platforms): + +```bash +# Disable compression for optimal performance with small, frequent updates +SERVER_WEBSOCKET_COMPRESSION=false +``` + +### Large Data Transfers + +For applications transferring large datasets (e.g., file sharing, data visualization): + +```bash +# Optimize for large data transfers +SERVER_WEBSOCKET_COMPRESSION='{"threshold": 1024, "level": 6, "memLevel": 8}' +``` + +### Memory-Constrained Environment + +For deployments with limited memory resources: + +```bash +# Minimize memory usage while maintaining compression +SERVER_WEBSOCKET_COMPRESSION='{"threshold": 2048, "level": 1, "memLevel": 1, "maxWindowBits": 9}' +``` + +### Balanced Configuration + +For typical applications with mixed message sizes: + +```bash +# Balance between compression and performance +SERVER_WEBSOCKET_COMPRESSION='{"threshold": 1536, "level": 3, "memLevel": 4}' +``` + ## Verifying Compression Status You can check if compression is enabled through the Meteor shell: From 5fcf8e6d99a182a6dca3a76ac107ed9ba78cb462 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Wed, 4 Dec 2024 10:54:36 -0400 Subject: [PATCH 46/48] update permessage-deflate2 --- packages/ddp-server/package.js | 2 +- packages/socket-stream-client/package.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ddp-server/package.js b/packages/ddp-server/package.js index 7b3408d31b..2f847a0801 100644 --- a/packages/ddp-server/package.js +++ b/packages/ddp-server/package.js @@ -5,7 +5,7 @@ Package.describe({ }); Npm.depends({ - "permessage-deflate2": "0.1.8-alpha.1", + "permessage-deflate2": "0.1.8", sockjs: "0.3.24", "lodash.once": "4.1.1", "lodash.isempty": "4.4.0", diff --git a/packages/socket-stream-client/package.js b/packages/socket-stream-client/package.js index ab4c7781f3..b15e88267a 100644 --- a/packages/socket-stream-client/package.js +++ b/packages/socket-stream-client/package.js @@ -7,7 +7,7 @@ Package.describe({ Npm.depends({ "faye-websocket": "0.11.4", - "permessage-deflate2": "0.1.8-alpha.1", + "permessage-deflate2": "0.1.8", "lodash.isequal": "4.5.0", "lodash.once": "4.1.1" }); From af8e8ef31701ab52ee78fea10eb05f52bc8b2995 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Wed, 4 Dec 2024 11:03:29 -0400 Subject: [PATCH 47/48] add disclaimer --- v3-docs/docs/performance/websocket-compression.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/v3-docs/docs/performance/websocket-compression.md b/v3-docs/docs/performance/websocket-compression.md index c1c28c09a7..e7c117f155 100644 --- a/v3-docs/docs/performance/websocket-compression.md +++ b/v3-docs/docs/performance/websocket-compression.md @@ -1,5 +1,12 @@ # Websocket Compression in Meteor +::: warning +Modifying websocket compression settings without understanding your application's DDP messaging patterns can negatively impact performance. Before changing these settings, you should: +- Use [Meteor DevTools Evolved](https://chromewebstore.google.com/detail/meteor-devtools-evolved/ibniinmoafhgbifjojidlagmggecmpgf) or your browser's Network tab to monitor WebSocket traffic +- Analyze your DDP message frequency and payload sizes +- Test changes in a staging environment with realistic data and user load +::: + Meteor's stream server uses the permessage-deflate extension for websocket compression by default. While compression can help reduce bandwidth usage, it may impact performance in reactivity-intensive applications due to the computational overhead of compressing numerous DDP messages. ## Configuration From 3dac12a5990c10c6995b015e3c4500b0b451c9b5 Mon Sep 17 00:00:00 2001 From: Leonardo Venturini Date: Wed, 4 Dec 2024 11:45:06 -0400 Subject: [PATCH 48/48] downgrade mongo driver minor due to connection issue with old databases --- packages/npm-mongo/package.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/npm-mongo/package.js b/packages/npm-mongo/package.js index cc7a598051..1e546f940b 100644 --- a/packages/npm-mongo/package.js +++ b/packages/npm-mongo/package.js @@ -3,12 +3,12 @@ Package.describe({ summary: "Wrapper around the mongo npm package", - version: "6.10.0", + version: "6.10.1", documentation: null, }); Npm.depends({ - mongodb: "6.10.0" + mongodb: "6.9.0" }); Package.onUse(function (api) {