diff --git a/.changeset/cool-peas-sin.md b/.changeset/cool-peas-sin.md new file mode 100644 index 0000000..d347670 --- /dev/null +++ b/.changeset/cool-peas-sin.md @@ -0,0 +1,5 @@ +--- +'@lowdefy/community-plugin-mongodb': minor +--- + +Add mongodb change log requests. diff --git a/.gitignore b/.gitignore index 969c452..84a16c0 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ **/.env **/node_modules/** **/dist/** +**/coverage/* diff --git a/.swcrc.test b/.swcrc.test new file mode 100644 index 0000000..f29995c --- /dev/null +++ b/.swcrc.test @@ -0,0 +1,18 @@ +{ + "jsc": { + "parser": { + "syntax": "ecmascript", + "jsx": true, + "dynamicImport": true + }, + "target": "es2020", + "keepClassNames": true, + "transform": { "react": { "runtime": "classic" } } + }, + "module": { + "type": "es6", + "noInterop": true, + "ignoreDynamic": true + }, + "sourceMaps": true +} diff --git a/apps/docs/community-plugin-mongodb/MongoDB.yaml b/apps/docs/community-plugin-mongodb/MongoDB.yaml index d9e6c98..48c20f0 100644 --- a/apps/docs/community-plugin-mongodb/MongoDB.yaml +++ b/apps/docs/community-plugin-mongodb/MongoDB.yaml @@ -9,7 +9,7 @@ _ref: type: MarkdownWithCode properties: content: | - This plugin extends the [Lowdefy MongoDB connection](https://docs.lowdefy.com/MongoDB) with additional request types. + This plugin extends the [Lowdefy MongoDB connection](https://docs.lowdefy.com/MongoDB) with additional request types. Additionally all create, update and delete requests are modified to include change tracking functionality. - _ref: path: templates/plugin_usage.yaml vars: @@ -19,6 +19,25 @@ _ref: type: MarkdownWithCode properties: content: | + ## Connections + + The `MongoDBCollection` connection adds change tracking functionality to the following request types: + - MongoDBDeleteMany + - MongoDBDeleteOne + - MongoDBInsertMany + - MongoDBInsertOne + - MongoDBUpdateMany + - MongoDBUpdateOne + + When the `logCollection.collection` property is defined. Each connection will write changes specifics to the change log collection to improve data change tracking. + + All other functionality, connection and request properties remains the same as defined in the [MongoDB Lowdefy connector](https://docs.lowdefy.com/MongoDB) documentation. + + #### Additional Connection Properties + - `logCollection: object`: Optional log collection for logging changes. + - `collection: string`: __Required__ - The name of the MongoDB log collection. + - `meta: object`: Optional attributes object for user and other information. + ## Requests Request types: diff --git a/plugins/community-plugin-mongodb/jest-mongodb-config.js b/plugins/community-plugin-mongodb/jest-mongodb-config.js new file mode 100644 index 0000000..dbb1006 --- /dev/null +++ b/plugins/community-plugin-mongodb/jest-mongodb-config.js @@ -0,0 +1,11 @@ +export default { + mongodbMemoryServerOptions: { + instance: { + dbName: 'test', + }, + binary: { + version: '5.0.3', + }, + autoStart: false, + }, +}; diff --git a/plugins/community-plugin-mongodb/jest.config.js b/plugins/community-plugin-mongodb/jest.config.js new file mode 100644 index 0000000..106efae --- /dev/null +++ b/plugins/community-plugin-mongodb/jest.config.js @@ -0,0 +1,20 @@ +export default { + clearMocks: true, + collectCoverage: true, + collectCoverageFrom: ['src/**/*.js'], + coverageDirectory: 'coverage', + coveragePathIgnorePatterns: [ + '/dist/', + '/src/index.js', + '/src/connections.js', + '/src/types.js', + ], + coverageReporters: [['lcov', { projectRoot: '../..' }], 'text', 'clover'], + errorOnDeprecated: true, + preset: '@shelf/jest-mongodb', + testEnvironment: 'node', + testPathIgnorePatterns: ['/dist/'], + transform: { + '^.+\\.(t|j)sx?$': ['@swc/jest', { configFile: '../../.swcrc.test' }], + }, +}; diff --git a/plugins/community-plugin-mongodb/package.json b/plugins/community-plugin-mongodb/package.json index c3a2da6..cfe8f7d 100644 --- a/plugins/community-plugin-mongodb/package.json +++ b/plugins/community-plugin-mongodb/package.json @@ -13,7 +13,8 @@ ], "scripts": { "build": "swc src --out-dir dist --config-file ../../.swcrc --delete-dir-on-start --copy-files", - "prepare": "pnpm build" + "prepare": "pnpm build", + "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js" }, "dependencies": { "@lowdefy/helpers": "4.0.0-rc.10", @@ -24,8 +25,13 @@ "uuid": "9.0.0" }, "devDependencies": { + "@lowdefy/ajv": "4.0.0-rc.10", + "@shelf/jest-mongodb": "4.1.4", "@swc/cli": "0.1.62", - "@swc/core": "1.3.66" + "@swc/core": "1.3.66", + "@swc/jest": "0.2.27", + "jest": "28.1.3", + "jest-environment-node": "28.1.3" }, "publishConfig": { "access": "public" diff --git a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBCollection.js b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBCollection.js index c653f51..3472bb2 100644 --- a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBCollection.js +++ b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBCollection.js @@ -18,8 +18,9 @@ import { MongoDBCollection } from '@lowdefy/connection-mongodb/connections'; import MongoDBInsertConsecutiveId from './MongoDBInsertConsecutiveId/MongoDBInsertConsecutiveId.js'; import MongoDBInsertManyConsecutiveIds from './MongoDBInsertManyConsecutiveIds/MongoDBInsertManyConsecutiveIds.js'; +import schema from './schema.js'; -const { schema, requests } = MongoDBCollection; +const { requests } = MongoDBCollection; export default { schema, diff --git a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBDeleteMany/MongoDBDeleteMany.js b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBDeleteMany/MongoDBDeleteMany.js new file mode 100644 index 0000000..0e27f12 --- /dev/null +++ b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBDeleteMany/MongoDBDeleteMany.js @@ -0,0 +1,56 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import getCollection from '../getCollection.js'; +import { serialize, deserialize } from '../serialize.js'; +import schema from './schema.js'; + +async function MongodbDeleteMany({ blockId, connection, pageId, request, requestId, payload }) { + const deserializedRequest = deserialize(request); + const { filter, options } = deserializedRequest; + const { collection, client, logCollection } = await getCollection({ connection }); + let response; + try { + response = await collection.deleteMany(filter, options); + if (logCollection) { + await logCollection.insertOne({ + args: { filter, options }, + blockId, + pageId, + payload, + requestId, + response, + timestamp: new Date(), + type: 'MongoDBDeleteMany', + meta: connection.changeLog?.meta, + }); + } + } catch (error) { + await client.close(); + throw error; + } + await client.close(); + const { acknowledged, deletedCount } = serialize(response); + return { acknowledged, deletedCount }; +} + +MongodbDeleteMany.schema = schema; +MongodbDeleteMany.meta = { + checkRead: false, + checkWrite: true, +}; + +export default MongodbDeleteMany; diff --git a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBDeleteMany/MongoDBDeleteMany.test.js b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBDeleteMany/MongoDBDeleteMany.test.js new file mode 100644 index 0000000..7b6deaa --- /dev/null +++ b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBDeleteMany/MongoDBDeleteMany.test.js @@ -0,0 +1,279 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import { validate } from '@lowdefy/ajv'; +import MongoDBDeleteMany from './MongoDBDeleteMany.js'; +import findLogCollectionRecordTestMongoDb from '../../../test/findLogCollectionRecordTestMongoDb.js'; +import populateTestMongoDb from '../../../test/populateTestMongoDb.js'; + +const { checkRead, checkWrite } = MongoDBDeleteMany.meta; +const schema = MongoDBDeleteMany.schema; + +const databaseUri = process.env.MONGO_URL; +const databaseName = 'test'; +const collection = 'deleteMany'; +const logCollection = 'logCollection'; +const documents = [ + { _id: 'deleteMany' }, + { _id: 'deleteMany_1' }, + { _id: 'deleteMany_2' }, + { _id: 'deleteMany_3' }, + { _id: 'deleteMany_4', f: 'deleteMany' }, + { _id: 'deleteMany_5', f: 'deleteMany' }, + { _id: 'deleteMany_6', f: 'deleteMany' }, + { _id: 'deleteMany_log' }, + { _id: 'deleteMany_1_log' }, + { _id: 'deleteMany_2_log' }, + { _id: 'deleteMany_3_log' }, + { _id: 'deleteMany_4_log', f: 'deleteMany_log' }, + { _id: 'deleteMany_5_log', f: 'deleteMany_log' }, + { _id: 'deleteMany_6_log', f: 'deleteMany_log' }, +]; + +beforeAll(() => { + return populateTestMongoDb({ collection, documents }); +}); + +test('deleteMany - Single Document', async () => { + const request = { + filter: { _id: 'deleteMany' }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBDeleteMany({ request, connection }); + expect(res).toEqual({ + acknowledged: true, + deletedCount: 1, + }); +}); + +test('deleteMany logCollection - Single Document', async () => { + const request = { + filter: { _id: 'deleteMany_log' }, + }; + const connection = { + databaseUri, + databaseName, + collection, + changeLog: { collection: logCollection, meta: { meta: true } }, + write: true, + }; + const res = await MongoDBDeleteMany({ + request, + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'deleteMany_log', + connection, + }); + expect(res).toEqual({ + acknowledged: true, + deletedCount: 1, + }); + const logged = await findLogCollectionRecordTestMongoDb({ + logCollection, + requestId: 'deleteMany_log', + }); + expect(logged).toMatchObject({ + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'deleteMany_log', + type: 'MongoDBDeleteMany', + meta: { meta: true }, + }); +}); + +test('deleteMany - Multiple Documents', async () => { + const request = { + filter: { _id: { $in: ['deleteMany_1', 'deleteMany_2', 'deleteMany_3'] } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBDeleteMany({ request, connection }); + expect(res).toEqual({ + acknowledged: true, + deletedCount: 3, + }); +}); + +test('deleteMany logCollection - Multiple Documents', async () => { + const request = { + filter: { _id: { $in: ['deleteMany_1_log', 'deleteMany_2_log', 'deleteMany_3_log'] } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + changeLog: { collection: logCollection, meta: { meta: true } }, + write: true, + }; + const res = await MongoDBDeleteMany({ + request, + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'deleteMany_multiple', + connection, + }); + expect(res).toEqual({ + acknowledged: true, + deletedCount: 3, + }); + const logged = await findLogCollectionRecordTestMongoDb({ + logCollection, + requestId: 'deleteMany_multiple', + }); + expect(logged).toMatchObject({ + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'deleteMany_multiple', + type: 'MongoDBDeleteMany', + meta: { meta: true }, + }); +}); + +test('deleteMany - Multiple Documents one field', async () => { + const request = { + filter: { f: 'deleteMany' }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBDeleteMany({ request, connection }); + expect(res).toEqual({ + acknowledged: true, + deletedCount: 3, + }); +}); + +test('deleteMany logCollection - Multiple Documents one field', async () => { + const request = { + filter: { f: 'deleteMany_log' }, + }; + const connection = { + databaseUri, + databaseName, + collection, + changeLog: { collection: logCollection, meta: { meta: true } }, + write: true, + }; + const res = await MongoDBDeleteMany({ + request, + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'deleteMany_multiple_one_field', + connection, + }); + expect(res).toEqual({ + acknowledged: true, + deletedCount: 3, + }); + const logged = await findLogCollectionRecordTestMongoDb({ + logCollection, + requestId: 'deleteMany_multiple_one_field', + }); + expect(logged).toMatchObject({ + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'deleteMany_multiple_one_field', + type: 'MongoDBDeleteMany', + meta: { meta: true }, + }); +}); + +test('deleteMany connection error', async () => { + const request = { + filter: { _id: 'test' }, + }; + const connection = { + databaseUri: 'bad_uri', + databaseName, + collection, + write: true, + }; + await expect(MongoDBDeleteMany({ request, connection })).rejects.toThrow( + 'Invalid scheme, expected connection string to start with "mongodb://" or "mongodb+srv://"' + ); +}); + +test('deleteMany mongodb error', async () => { + const request = { + filter: { _id: 'test' }, + options: { writeConcern: { w: false } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBDeleteMany({ request, connection }); + expect(res).toEqual({ + acknowledged: false, + deletedCount: 0, + }); +}); + +test('checkRead should be false', async () => { + expect(checkRead).toBe(false); +}); + +test('checkWrite should be true', async () => { + expect(checkWrite).toBe(true); +}); + +test('request not an object', async () => { + const request = 'request'; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBDeleteMany request properties should be an object.' + ); +}); + +test('request no filter', async () => { + const request = {}; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBDeleteMany request should have required property "filter".' + ); +}); + +test('request filter not an object', async () => { + const request = { filter: 'filter' }; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBDeleteMany request property "filter" should be an object.' + ); +}); + +test('request options not an object', async () => { + const request = { filter: { _id: 'test' }, options: 'options' }; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBDeleteMany request property "options" should be an object.' + ); +}); diff --git a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBDeleteMany/schema.js b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBDeleteMany/schema.js new file mode 100644 index 0000000..bc51159 --- /dev/null +++ b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBDeleteMany/schema.js @@ -0,0 +1,42 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +export default { + $schema: 'http://json-schema.org/draft-07/schema#', + title: 'Lowdefy Request Schema - MongoDBDeleteMany', + type: 'object', + required: ['filter'], + properties: { + filter: { + type: 'object', + description: 'The filter used to select the document to update.', + errorMessage: { + type: 'MongoDBDeleteMany request property "filter" should be an object.', + }, + }, + options: { + type: 'object', + description: 'Optional settings.', + errorMessage: { + type: 'MongoDBDeleteMany request property "options" should be an object.', + }, + }, + }, + errorMessage: { + type: 'MongoDBDeleteMany request properties should be an object.', + required: 'MongoDBDeleteMany request should have required property "filter".', + }, +}; diff --git a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBDeleteOne/MongoDBDeleteOne.js b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBDeleteOne/MongoDBDeleteOne.js new file mode 100644 index 0000000..a6c872c --- /dev/null +++ b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBDeleteOne/MongoDBDeleteOne.js @@ -0,0 +1,58 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import getCollection from '../getCollection.js'; +import { serialize, deserialize } from '../serialize.js'; +import schema from './schema.js'; + +async function MongodbDeleteOne({ blockId, connection, pageId, request, requestId, payload }) { + const deserializedRequest = deserialize(request); + const { filter, options } = deserializedRequest; + const { collection, client, logCollection } = await getCollection({ connection }); + let response; + try { + if (logCollection) { + const { value, ...responseWithoutValue } = await collection.findOneAndDelete(filter, options); + response = responseWithoutValue; + await logCollection.insertOne({ + args: { filter, options }, + blockId, + pageId, + payload, + requestId, + before: value, + timestamp: new Date(), + type: 'MongoDBDeleteOne', + meta: connection.changeLog?.meta, + }); + } else { + response = await collection.deleteOne(filter, options); + } + } catch (error) { + await client.close(); + throw error; + } + await client.close(); + return serialize(response); +} + +MongodbDeleteOne.schema = schema; +MongodbDeleteOne.meta = { + checkRead: false, + checkWrite: true, +}; + +export default MongodbDeleteOne; diff --git a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBDeleteOne/MongoDBDeleteOne.test.js b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBDeleteOne/MongoDBDeleteOne.test.js new file mode 100644 index 0000000..a1a828f --- /dev/null +++ b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBDeleteOne/MongoDBDeleteOne.test.js @@ -0,0 +1,159 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import { validate } from '@lowdefy/ajv'; +import MongoDBDeleteOne from './MongoDBDeleteOne.js'; +import findLogCollectionRecordTestMongoDb from '../../../test/findLogCollectionRecordTestMongoDb.js'; +import populateTestMongoDb from '../../../test/populateTestMongoDb.js'; + +const { checkRead, checkWrite } = MongoDBDeleteOne.meta; +const schema = MongoDBDeleteOne.schema; + +const databaseUri = process.env.MONGO_URL; +const databaseName = 'test'; +const collection = 'deleteOne'; +const logCollection = 'logCollection'; +const documents = [{ _id: 'deleteOne' }, { _id: 'deleteOne_log' }]; + +beforeAll(() => { + return populateTestMongoDb({ collection, documents }); +}); + +test('deleteOne', async () => { + const request = { + filter: { _id: 'deleteOne' }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBDeleteOne({ request, connection }); + expect(res).toEqual({ + acknowledged: true, + deletedCount: 1, + }); +}); + +test('deleteOne logCollection', async () => { + const request = { + filter: { _id: 'deleteOne_log' }, + }; + const connection = { + databaseUri, + databaseName, + collection, + changeLog: { collection: logCollection, meta: { meta: true } }, + write: true, + }; + const res = await MongoDBDeleteOne({ + request, + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'deleteOne_log', + connection, + }); + expect(res).toEqual({ + lastErrorObject: { + n: 1, + }, + ok: 1, + }); + const logged = await findLogCollectionRecordTestMongoDb({ + logCollection, + requestId: 'deleteOne_log', + }); + expect(logged).toMatchObject({ + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'deleteOne_log', + before: { _id: 'deleteOne_log' }, + type: 'MongoDBDeleteOne', + meta: { meta: true }, + }); +}); + +test('deleteOne connection error', async () => { + const request = { + filter: { _id: 'test' }, + }; + const connection = { + databaseUri: 'bad_uri', + databaseName, + collection, + write: true, + }; + await expect(MongoDBDeleteOne({ request, connection })).rejects.toThrow( + 'Invalid scheme, expected connection string to start with "mongodb://" or "mongodb+srv://"' + ); +}); + +test('checkRead should be false', async () => { + expect(checkRead).toBe(false); +}); + +test('checkWrite should be true', async () => { + expect(checkWrite).toBe(true); +}); + +test('deleteOne catch invalid options', async () => { + const request = { + filter: { _id: 'test' }, + options: { writeConcern: { w: false } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBDeleteOne({ request, connection }); + expect(res).toEqual({ + acknowledged: false, + deletedCount: 0, + }); +}); + +test('request not an object', async () => { + const request = 'request'; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBDeleteOne request properties should be an object.' + ); +}); + +test('request no filter', async () => { + const request = {}; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBDeleteOne request should have required property "filter".' + ); +}); + +test('request filter not an object', async () => { + const request = { filter: 'filter' }; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBDeleteOne request property "filter" should be an object.' + ); +}); + +test('request options not an object', async () => { + const request = { filter: { _id: 'test' }, options: 'options' }; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBDeleteOne request property "options" should be an object.' + ); +}); diff --git a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBDeleteOne/schema.js b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBDeleteOne/schema.js new file mode 100644 index 0000000..36703d2 --- /dev/null +++ b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBDeleteOne/schema.js @@ -0,0 +1,42 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +export default { + $schema: 'http://json-schema.org/draft-07/schema#', + title: 'Lowdefy Request Schema - MongoDBDeleteOne', + type: 'object', + required: ['filter'], + properties: { + filter: { + type: 'object', + description: 'The filter used to select the document to update.', + errorMessage: { + type: 'MongoDBDeleteOne request property "filter" should be an object.', + }, + }, + options: { + type: 'object', + description: 'Optional settings.', + errorMessage: { + type: 'MongoDBDeleteOne request property "options" should be an object.', + }, + }, + }, + errorMessage: { + type: 'MongoDBDeleteOne request properties should be an object.', + required: 'MongoDBDeleteOne request should have required property "filter".', + }, +}; diff --git a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBInsertMany/MongoDBInsertMany.js b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBInsertMany/MongoDBInsertMany.js new file mode 100644 index 0000000..e1315df --- /dev/null +++ b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBInsertMany/MongoDBInsertMany.js @@ -0,0 +1,56 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import getCollection from '../getCollection.js'; +import { serialize, deserialize } from '../serialize.js'; +import schema from './schema.js'; + +async function MongodbInsertMany({ blockId, connection, pageId, request, requestId, payload }) { + const deserializedRequest = deserialize(request); + const { docs, options } = deserializedRequest; + const { collection, client, logCollection } = await getCollection({ connection }); + let response; + try { + response = await collection.insertMany(docs, options); + if (logCollection) { + await logCollection.insertOne({ + args: { docs, options }, + blockId, + pageId, + payload, + requestId, + response, + timestamp: new Date(), + type: 'MongoDBInsertMany', + meta: connection.changeLog?.meta, + }); + } + } catch (error) { + await client.close(); + throw error; + } + await client.close(); + const { acknowledged, insertedCount } = serialize(response); + return { acknowledged, insertedCount }; +} + +MongodbInsertMany.schema = schema; +MongodbInsertMany.meta = { + checkRead: false, + checkWrite: true, +}; + +export default MongodbInsertMany; diff --git a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBInsertMany/MongoDBInsertMany.test.js b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBInsertMany/MongoDBInsertMany.test.js new file mode 100644 index 0000000..d4918fe --- /dev/null +++ b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBInsertMany/MongoDBInsertMany.test.js @@ -0,0 +1,216 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import { validate } from '@lowdefy/ajv'; +import MongoDBInsertMany from './MongoDBInsertMany.js'; +import clearTestMongoDb from '../../../test/clearTestMongoDb.js'; +import findLogCollectionRecordTestMongoDb from '../../../test/findLogCollectionRecordTestMongoDb.js'; + +const { checkRead, checkWrite } = MongoDBInsertMany.meta; +const schema = MongoDBInsertMany.schema; + +const databaseUri = process.env.MONGO_URL; +const databaseName = 'test'; +const collection = 'insertMany'; +const logCollection = 'logCollection'; + +beforeAll(() => { + return clearTestMongoDb({ collection }); +}); + +test('insertMany', async () => { + const request = { + docs: [{ _id: 'insertMany1-1' }, { _id: 'insertMany1-2' }, { _id: 'insertMany1-3' }], + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBInsertMany({ request, connection }); + expect(res).toEqual({ + acknowledged: true, + insertedCount: 3, + }); +}); + +test('insertMany logCollection', async () => { + const request = { + docs: [ + { _id: 'insertMany1-1_log' }, + { _id: 'insertMany1-2_log' }, + { _id: 'insertMany1-3_log' }, + ], + }; + const connection = { + databaseUri, + databaseName, + collection, + changeLog: { collection: logCollection, meta: { meta: true } }, + write: true, + }; + const res = await MongoDBInsertMany({ + request, + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'insertMany_log', + connection, + }); + expect(res).toEqual({ + acknowledged: true, + insertedCount: 3, + }); + const logged = await findLogCollectionRecordTestMongoDb({ + logCollection, + requestId: 'insertMany_log', + }); + expect(logged).toMatchObject({ + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'insertMany_log', + type: 'MongoDBInsertMany', + meta: { meta: true }, + }); +}); + +test('insertMany options', async () => { + const request = { + docs: [{ _id: 'insertMany2-1' }, { _id: 'insertMany2-2' }], + options: { writeConcern: { w: 'majority' } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBInsertMany({ request, connection }); + expect(res).toEqual({ + acknowledged: true, + insertedCount: 2, + }); +}); + +test('insertMany logCollection options', async () => { + const request = { + docs: [{ _id: 'insertMany2-1_log' }, { _id: 'insertMany2-2_log' }], + options: { writeConcern: { w: 'majority' } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + changeLog: { collection: logCollection, meta: { meta: true } }, + write: true, + }; + const res = await MongoDBInsertMany({ + request, + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'insertMany_options_log', + connection, + }); + expect(res).toEqual({ + acknowledged: true, + insertedCount: 2, + }); + const logged = await findLogCollectionRecordTestMongoDb({ + logCollection, + requestId: 'insertMany_options_log', + }); + expect(logged).toMatchObject({ + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'insertMany_options_log', + type: 'MongoDBInsertMany', + meta: { meta: true }, + }); +}); + +test('insertMany connection error', async () => { + const request = { docs: [{ _id: 'insertMany8-1' }, { _id: 'insertMany8-2' }] }; + const connection = { + databaseUri: 'bad_uri', + databaseName, + collection, + write: true, + }; + await expect(MongoDBInsertMany({ request, connection })).rejects.toThrow( + 'Invalid scheme, expected connection string to start with "mongodb://" or "mongodb+srv://"' + ); +}); + +test('insertMany mongodb error', async () => { + const request = { docs: [{ _id: 'insertMany9-1' }, { _id: 'insertMany9-2' }] }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + await MongoDBInsertMany({ request, connection }); + await expect(MongoDBInsertMany({ request, connection })).rejects.toThrow( + 'E11000 duplicate key error' + ); +}); + +test('checkRead should be false', async () => { + expect(checkRead).toBe(false); +}); + +test('checkWrite should be true', async () => { + expect(checkWrite).toBe(true); +}); + +test('request not an object', async () => { + const request = 'request'; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBInsertMany request properties should be an object.' + ); +}); + +test('request no docs', async () => { + const request = {}; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBInsertMany request should have required property "docs".' + ); +}); + +test('request docs not an array', async () => { + const request = { docs: 'docs' }; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBInsertMany request property "docs" should be an array.' + ); +}); + +test('request docs not an array of objects', async () => { + const request = { docs: [1, 2, 3] }; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBInsertMany request property "docs" should be an array of documents to insert.' + ); +}); + +test('request options not an object', async () => { + const request = { docs: [], options: 'options' }; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBInsertMany request property "options" should be an object.' + ); +}); diff --git a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBInsertMany/schema.js b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBInsertMany/schema.js new file mode 100644 index 0000000..4025203 --- /dev/null +++ b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBInsertMany/schema.js @@ -0,0 +1,48 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +export default { + $schema: 'http://json-schema.org/draft-07/schema#', + title: 'Lowdefy Request Schema - MongoDBInsertMany', + type: 'object', + required: ['docs'], + properties: { + docs: { + type: 'array', + description: 'The array of documents to be inserted.', + errorMessage: { + type: 'MongoDBInsertMany request property "docs" should be an array.', + }, + items: { + type: 'object', + errorMessage: { + type: 'MongoDBInsertMany request property "docs" should be an array of documents to insert.', + }, + }, + }, + options: { + type: 'object', + description: 'Optional settings.', + errorMessage: { + type: 'MongoDBInsertMany request property "options" should be an object.', + }, + }, + }, + errorMessage: { + type: 'MongoDBInsertMany request properties should be an object.', + required: 'MongoDBInsertMany request should have required property "docs".', + }, +}; diff --git a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBInsertOne/MongoDBInsertOne.js b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBInsertOne/MongoDBInsertOne.js new file mode 100644 index 0000000..e00d406 --- /dev/null +++ b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBInsertOne/MongoDBInsertOne.js @@ -0,0 +1,56 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import getCollection from '../getCollection.js'; +import { serialize, deserialize } from '../serialize.js'; +import schema from './schema.js'; + +async function MongodbInsertOne({ blockId, connection, pageId, request, requestId, payload }) { + const deserializedRequest = deserialize(request); + const { doc, options } = deserializedRequest; + const { collection, client, logCollection } = await getCollection({ connection }); + let response; + try { + response = await collection.insertOne(doc, options); + if (logCollection) { + await logCollection.insertOne({ + args: { doc, options }, + blockId, + pageId, + payload, + requestId, + response, + timestamp: new Date(), + type: 'MongoDBInsertOne', + meta: connection.changeLog?.meta, + }); + } + } catch (error) { + await client.close(); + throw error; + } + await client.close(); + const { acknowledged, insertedId } = serialize(response); + return { acknowledged, insertedId }; +} + +MongodbInsertOne.schema = schema; +MongodbInsertOne.meta = { + checkRead: false, + checkWrite: true, +}; + +export default MongodbInsertOne; diff --git a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBInsertOne/MongoDBInsertOne.test.js b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBInsertOne/MongoDBInsertOne.test.js new file mode 100644 index 0000000..c58ca94 --- /dev/null +++ b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBInsertOne/MongoDBInsertOne.test.js @@ -0,0 +1,240 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import { validate } from '@lowdefy/ajv'; +import { MongoClient } from 'mongodb'; +import MongoDBInsertOne from './MongoDBInsertOne.js'; +import clearTestMongoDb from '../../../test/clearTestMongoDb.js'; +import findLogCollectionRecordTestMongoDb from '../../../test/findLogCollectionRecordTestMongoDb.js'; + +const { checkRead, checkWrite } = MongoDBInsertOne.meta; +const schema = MongoDBInsertOne.schema; + +const databaseUri = process.env.MONGO_URL; +const databaseName = 'test'; +const collection = 'insertOne'; +const logCollection = 'logCollection'; + +beforeAll(() => { + return clearTestMongoDb({ collection }); +}); + +test('insertOne', async () => { + const request = { doc: { _id: 'insertOne' } }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBInsertOne({ request, connection }); + expect(res).toEqual({ + acknowledged: true, + insertedId: 'insertOne', + }); +}); + +test('insertOne logCollection', async () => { + const request = { doc: { _id: 'insertOne_log' } }; + const connection = { + databaseUri, + databaseName, + collection, + changeLog: { collection: logCollection, meta: { meta: true } }, + write: true, + }; + const res = await MongoDBInsertOne({ + request, + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'insertOne_log', + connection, + }); + expect(res).toEqual({ + acknowledged: true, + insertedId: 'insertOne_log', + }); + const logged = await findLogCollectionRecordTestMongoDb({ + logCollection, + requestId: 'insertOne_log', + }); + expect(logged).toMatchObject({ + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'insertOne_log', + type: 'MongoDBInsertOne', + meta: { meta: true }, + }); +}); + +test('insertOne options', async () => { + const request = { + doc: { _id: 'insertOne_options' }, + options: { writeConcern: { w: 'majority' } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBInsertOne({ request, connection }); + expect(res).toEqual({ + acknowledged: true, + insertedId: 'insertOne_options', + }); +}); + +test('insertOne logCollection options', async () => { + const request = { + doc: { _id: 'insertOne_options_log' }, + options: { writeConcern: { w: 'majority' } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + changeLog: { collection: logCollection, meta: { meta: true } }, + write: true, + }; + const res = await MongoDBInsertOne({ + request, + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'insertOne_options_log', + connection, + }); + expect(res).toEqual({ + acknowledged: true, + insertedId: 'insertOne_options_log', + }); + const logged = await findLogCollectionRecordTestMongoDb({ + logCollection, + requestId: 'insertOne_options_log', + }); + expect(logged).toMatchObject({ + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'insertOne_options_log', + type: 'MongoDBInsertOne', + meta: { meta: true }, + }); +}); + +test('insertOne connection error', async () => { + const request = { doc: { _id: 'insertOne_connection_error' } }; + const connection = { + databaseUri: 'bad_uri', + databaseName, + collection, + write: true, + }; + await expect(MongoDBInsertOne({ request, connection })).rejects.toThrow( + 'Invalid scheme, expected connection string to start with "mongodb://" or "mongodb+srv://"' + ); +}); + +test('insertOne mongodb error', async () => { + const request = { doc: { _id: 'insertOne_mongodb_error' } }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + await MongoDBInsertOne({ request, connection }); + await expect(MongoDBInsertOne({ request, connection })).rejects.toThrow( + 'E11000 duplicate key error' + ); +}); + +test('checkRead should be false', async () => { + expect(checkRead).toBe(false); +}); + +test('checkWrite should be true', async () => { + expect(checkWrite).toBe(true); +}); + +test('insertOne insert a date', async () => { + const request = { + doc: { + _id: 'insertOneDate', + date: new Date('2020-01-01'), + }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBInsertOne({ request, connection }); + expect(res).toEqual({ + acknowledged: true, + insertedId: 'insertOneDate', + }); + let client; + let inserted; + try { + client = new MongoClient(process.env.MONGO_URL, { + useNewUrlParser: true, + useUnifiedTopology: true, + }); + await client.connect(); + const db = client.db(); + inserted = await db.collection(collection).findOne({ _id: 'insertOneDate' }); + await client.close(); + } catch (error) { + await client.close(); + } + expect(inserted).toEqual({ + _id: 'insertOneDate', + date: new Date('2020-01-01'), + }); +}); + +test('request not an object', async () => { + const request = 'request'; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBInsertOne request properties should be an object.' + ); +}); + +test('request no doc', async () => { + const request = {}; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBInsertOne request should have required property "doc".' + ); +}); + +test('request doc not an object', async () => { + const request = { doc: 'doc' }; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBInsertOne request property "doc" should be an object.' + ); +}); + +test('request options not an object', async () => { + const request = { doc: {}, options: 'options' }; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBInsertOne request property "options" should be an object.' + ); +}); diff --git a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBInsertOne/schema.js b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBInsertOne/schema.js new file mode 100644 index 0000000..18c83c0 --- /dev/null +++ b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBInsertOne/schema.js @@ -0,0 +1,42 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +export default { + $schema: 'http://json-schema.org/draft-07/schema#', + title: 'Lowdefy Request Schema - MongoDBInsertOne', + type: 'object', + required: ['doc'], + properties: { + doc: { + type: 'object', + description: 'The document to be inserted.', + errorMessage: { + type: 'MongoDBInsertOne request property "doc" should be an object.', + }, + }, + options: { + type: 'object', + description: 'Optional settings.', + errorMessage: { + type: 'MongoDBInsertOne request property "options" should be an object.', + }, + }, + }, + errorMessage: { + type: 'MongoDBInsertOne request properties should be an object.', + required: 'MongoDBInsertOne request should have required property "doc".', + }, +}; diff --git a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBUpdateMany/MongoDBUpdateMany.js b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBUpdateMany/MongoDBUpdateMany.js new file mode 100644 index 0000000..d90d7aa --- /dev/null +++ b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBUpdateMany/MongoDBUpdateMany.js @@ -0,0 +1,56 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import getCollection from '../getCollection.js'; +import { serialize, deserialize } from '../serialize.js'; +import schema from './schema.js'; + +async function MongodbUpdateMany({ blockId, connection, pageId, request, requestId, payload }) { + const deserializedRequest = deserialize(request); + const { filter, update, options } = deserializedRequest; + const { collection, client, logCollection } = await getCollection({ connection }); + let response; + try { + response = await collection.updateMany(filter, update, options); + if (logCollection) { + await logCollection.insertOne({ + args: { filter, update, options }, + blockId, + pageId, + payload, + requestId, + response, + timestamp: new Date(), + type: 'MongoDBUpdateMany', + meta: connection.changeLog?.meta, + }); + } + } catch (error) { + await client.close(); + throw error; + } + await client.close(); + const { modifiedCount, upsertedId, upsertedCount, matchedCount } = serialize(response); + return { modifiedCount, upsertedId, upsertedCount, matchedCount }; +} + +MongodbUpdateMany.schema = schema; +MongodbUpdateMany.meta = { + checkRead: false, + checkWrite: true, +}; + +export default MongodbUpdateMany; diff --git a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBUpdateMany/MongoDBUpdateMany.test.js b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBUpdateMany/MongoDBUpdateMany.test.js new file mode 100644 index 0000000..a20c8b7 --- /dev/null +++ b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBUpdateMany/MongoDBUpdateMany.test.js @@ -0,0 +1,487 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import { validate } from '@lowdefy/ajv'; +import MongoDBUpdateMany from './MongoDBUpdateMany.js'; +import findLogCollectionRecordTestMongoDb from '../../../test/findLogCollectionRecordTestMongoDb.js'; +import populateTestMongoDb from '../../../test/populateTestMongoDb.js'; + +const { checkRead, checkWrite } = MongoDBUpdateMany.meta; +const schema = MongoDBUpdateMany.schema; + +const databaseUri = process.env.MONGO_URL; +const databaseName = 'test'; +const collection = 'updateMany'; +const logCollection = 'logCollection'; +const documents = [ + { _id: 'updateMany', v: 'before' }, + { _id: 'updateMany_1', v: 'before' }, + { _id: 'updateMany_2', v: 'before' }, + { _id: 'updateMany_3', v: 'before' }, + { _id: 'updateMany_4', v: 'before', f: 'updateMany' }, + { _id: 'updateMany_5', v: 'before', f: 'updateMany' }, + { _id: 'updateMany_6', v: 'before', f: 'updateMany' }, +]; + +beforeAll(() => { + return populateTestMongoDb({ collection, documents }); +}); + +test('updateMany - Single Document', async () => { + const request = { + filter: { _id: 'updateMany' }, + update: { $set: { v: 'after' } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBUpdateMany({ request, connection }); + expect(res).toEqual({ + modifiedCount: 1, + upsertedId: null, + upsertedCount: 0, + matchedCount: 1, + }); +}); + +test('updateMany logCollection - Single Document', async () => { + const request = { + filter: { _id: 'updateMany' }, + update: { $set: { v: 'afterLog' } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + changeLog: { collection: logCollection, meta: { meta: true } }, + write: true, + }; + const res = await MongoDBUpdateMany({ + request, + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'updateMany', + connection, + }); + expect(res).toEqual({ + modifiedCount: 1, + upsertedId: null, + upsertedCount: 0, + matchedCount: 1, + }); + const logged = await findLogCollectionRecordTestMongoDb({ + logCollection, + requestId: 'updateMany', + }); + expect(logged).toMatchObject({ + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'updateMany', + type: 'MongoDBUpdateMany', + meta: { meta: true }, + }); +}); + +test('updateMany - Multiple Documents', async () => { + const request = { + filter: { _id: { $in: ['updateMany_1', 'updateMany_2', 'updateMany_3'] } }, + update: { $set: { v: 'after' } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBUpdateMany({ request, connection }); + expect(res).toEqual({ + modifiedCount: 3, + upsertedId: null, + upsertedCount: 0, + matchedCount: 3, + }); +}); + +test('updateMany logCollection - Multiple Documents', async () => { + const request = { + filter: { _id: { $in: ['updateMany_1', 'updateMany_2', 'updateMany_3'] } }, + update: { $set: { v: 'afterLog' } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + changeLog: { collection: logCollection, meta: { meta: true } }, + write: true, + }; + const res = await MongoDBUpdateMany({ + request, + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'updateMany_multiple', + connection, + }); + expect(res).toEqual({ + modifiedCount: 3, + upsertedId: null, + upsertedCount: 0, + matchedCount: 3, + }); + const logged = await findLogCollectionRecordTestMongoDb({ + logCollection, + requestId: 'updateMany_multiple', + }); + expect(logged).toMatchObject({ + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'updateMany_multiple', + type: 'MongoDBUpdateMany', + meta: { meta: true }, + }); +}); + +test('updateMany - Multiple Documents one field', async () => { + const request = { + filter: { f: 'updateMany' }, + update: { $set: { v: 'after' } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBUpdateMany({ request, connection }); + expect(res).toEqual({ + modifiedCount: 3, + upsertedId: null, + upsertedCount: 0, + matchedCount: 3, + }); +}); + +test('updateMany logCollection - Multiple Documents one field', async () => { + const request = { + filter: { f: 'updateMany' }, + update: { $set: { v: 'afterLog' } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + changeLog: { collection: logCollection, meta: { meta: true } }, + write: true, + }; + const res = await MongoDBUpdateMany({ + request, + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'updateMany_multiple_one_field', + connection, + }); + expect(res).toEqual({ + modifiedCount: 3, + upsertedId: null, + upsertedCount: 0, + matchedCount: 3, + }); + const logged = await findLogCollectionRecordTestMongoDb({ + logCollection, + requestId: 'updateMany_multiple_one_field', + }); + expect(logged).toMatchObject({ + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'updateMany_multiple_one_field', + type: 'MongoDBUpdateMany', + meta: { meta: true }, + }); +}); + +test('updateMany upsert', async () => { + const request = { + filter: { _id: 'updateMany_upsert' }, + update: { $set: { v: 'after' } }, + options: { upsert: true }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBUpdateMany({ request, connection }); + expect(res).toEqual({ + modifiedCount: 0, + upsertedId: 'updateMany_upsert', + upsertedCount: 1, + matchedCount: 0, + }); +}); + +test('updateMany logCollection upsert', async () => { + const request = { + filter: { _id: 'updateMany_upsert_log' }, + update: { $set: { v: 'after' } }, + options: { upsert: true }, + }; + const connection = { + databaseUri, + databaseName, + collection, + changeLog: { collection: logCollection, meta: { meta: true } }, + write: true, + }; + const res = await MongoDBUpdateMany({ + request, + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'updateMany_upsert_log', + connection, + }); + expect(res).toEqual({ + modifiedCount: 0, + upsertedId: 'updateMany_upsert_log', + upsertedCount: 1, + matchedCount: 0, + }); + const logged = await findLogCollectionRecordTestMongoDb({ + logCollection, + requestId: 'updateMany_upsert_log', + }); + expect(logged).toMatchObject({ + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'updateMany_upsert_log', + type: 'MongoDBUpdateMany', + meta: { meta: true }, + }); +}); + +test('updateMany upsert false', async () => { + const request = { + filter: { _id: 'updateMany_upsert_false' }, + update: { $set: { v: 'after' } }, + options: { upsert: false }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBUpdateMany({ request, connection }); + expect(res).toEqual({ + modifiedCount: 0, + upsertedId: null, + upsertedCount: 0, + matchedCount: 0, + }); +}); + +test('updateMany logCollection upsert false', async () => { + const request = { + filter: { _id: 'updateMany_upsert_false_log' }, + update: { $set: { v: 'after' } }, + options: { upsert: false }, + }; + const connection = { + databaseUri, + databaseName, + collection, + changeLog: { collection: logCollection, meta: { meta: true } }, + write: true, + }; + const res = await MongoDBUpdateMany({ + request, + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'updateMany_upsert_false_log', + connection, + }); + expect(res).toEqual({ + modifiedCount: 0, + upsertedId: null, + upsertedCount: 0, + matchedCount: 0, + }); + const logged = await findLogCollectionRecordTestMongoDb({ + logCollection, + requestId: 'updateMany_upsert_false_log', + }); + expect(logged).toMatchObject({ + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'updateMany_upsert_false_log', + type: 'MongoDBUpdateMany', + meta: { meta: true }, + }); +}); + +test('updateMany upsert default false', async () => { + const request = { + filter: { _id: 'updateMany_upsert_default_false' }, + update: { $set: { v: 'after' } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBUpdateMany({ request, connection }); + expect(res).toEqual({ + modifiedCount: 0, + upsertedId: null, + upsertedCount: 0, + matchedCount: 0, + }); +}); + +test('updateMany logCollection upsert default false', async () => { + const request = { + filter: { _id: 'updateMany_upsert_default_false_log' }, + update: { $set: { v: 'after' } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + changeLog: { collection: logCollection, meta: { meta: true } }, + write: true, + }; + const res = await MongoDBUpdateMany({ + request, + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'updateMany_upsert_default_false_log', + connection, + }); + expect(res).toEqual({ + modifiedCount: 0, + upsertedId: null, + upsertedCount: 0, + matchedCount: 0, + }); + const logged = await findLogCollectionRecordTestMongoDb({ + logCollection, + requestId: 'updateMany_upsert_default_false_log', + }); + expect(logged).toMatchObject({ + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'updateMany_upsert_default_false_log', + type: 'MongoDBUpdateMany', + meta: { meta: true }, + }); +}); + +test('updateMany connection error', async () => { + const request = { + filter: { _id: 'updateMany_connection_error' }, + update: { $set: { v: 'after' } }, + }; + const connection = { + databaseUri: 'bad_uri', + databaseName, + collection, + write: true, + }; + await expect(MongoDBUpdateMany({ request, connection })).rejects.toThrow( + 'Invalid scheme, expected connection string to start with "mongodb://" or "mongodb+srv://"' + ); +}); + +test('updateMany mongodb error', async () => { + const request = { + filter: { _id: 'updateMany_mongodb_error' }, + update: { $badOp: { v: 'after' } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + await expect(MongoDBUpdateMany({ request, connection })).rejects.toThrow( + 'Unknown modifier: $badOp' + ); +}); + +test('checkRead should be false', async () => { + expect(checkRead).toBe(false); +}); + +test('checkWrite should be true', async () => { + expect(checkWrite).toBe(true); +}); + +test('request not an object', async () => { + const request = 'request'; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBUpdateMany request properties should be an object.' + ); +}); + +test('request no filter', async () => { + const request = { update: {} }; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBUpdateMany request should have required property "filter".' + ); +}); + +test('request no update', async () => { + const request = { filter: {} }; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBUpdateMany request should have required property "update".' + ); +}); + +test('request update not an object', async () => { + const request = { update: 'update', filter: {} }; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBUpdateMany request property "update" should be an object.' + ); +}); + +test('request filter not an object', async () => { + const request = { update: {}, filter: 'filter' }; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBUpdateMany request property "filter" should be an object.' + ); +}); + +test('request options not an object', async () => { + const request = { update: {}, filter: {}, options: 'options' }; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBUpdateMany request property "options" should be an object.' + ); +}); diff --git a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBUpdateMany/schema.js b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBUpdateMany/schema.js new file mode 100644 index 0000000..5ccef56 --- /dev/null +++ b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBUpdateMany/schema.js @@ -0,0 +1,52 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +export default { + $schema: 'http://json-schema.org/draft-07/schema#', + title: 'Lowdefy Request Schema - MongoDBUpdateMany', + type: 'object', + required: ['filter', 'update'], + properties: { + filter: { + type: 'object', + description: 'The filter used to select the documents to update.', + errorMessage: { + type: 'MongoDBUpdateMany request property "filter" should be an object.', + }, + }, + update: { + type: ['object', 'array'], + description: 'The update operations to be applied to the documents.', + errorMessage: { + type: 'MongoDBUpdateMany request property "update" should be an object.', + }, + }, + options: { + type: 'object', + description: 'Optional settings.', + errorMessage: { + type: 'MongoDBUpdateMany request property "options" should be an object.', + }, + }, + }, + errorMessage: { + type: 'MongoDBUpdateMany request properties should be an object.', + required: { + filter: 'MongoDBUpdateMany request should have required property "filter".', + update: 'MongoDBUpdateMany request should have required property "update".', + }, + }, +}; diff --git a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBUpdateOne/MongoDBUpdateOne.js b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBUpdateOne/MongoDBUpdateOne.js new file mode 100644 index 0000000..5cb1a57 --- /dev/null +++ b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBUpdateOne/MongoDBUpdateOne.js @@ -0,0 +1,66 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import getCollection from '../getCollection.js'; +import { serialize, deserialize } from '../serialize.js'; +import schema from './schema.js'; + +async function MongodbUpdateOne({ blockId, connection, pageId, request, requestId, payload }) { + const deserializedRequest = deserialize(request); + const { filter, update, options } = deserializedRequest; + const { collection, client, logCollection } = await getCollection({ connection }); + let response; + try { + if (logCollection) { + const { value, ...responseWithoutValue } = await collection.findOneAndUpdate( + filter, + update, + options + ); + response = responseWithoutValue; + const after = await collection.findOne({ + _id: value ? value._id : response.lastErrorObject?.upserted, + }); + await logCollection.insertOne({ + args: { filter, update, options }, + blockId, + pageId, + payload, + requestId, + before: value, + after, + timestamp: new Date(), + type: 'MongoDBUpdateOne', + meta: connection.changeLog?.meta, + }); + } else { + response = await collection.updateOne(filter, update, options); + } + } catch (error) { + await client.close(); + throw error; + } + await client.close(); + return serialize(response); +} + +MongodbUpdateOne.schema = schema; +MongodbUpdateOne.meta = { + checkRead: false, + checkWrite: true, +}; + +export default MongodbUpdateOne; diff --git a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBUpdateOne/MongoDBUpdateOne.test.js b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBUpdateOne/MongoDBUpdateOne.test.js new file mode 100644 index 0000000..6cac65c --- /dev/null +++ b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBUpdateOne/MongoDBUpdateOne.test.js @@ -0,0 +1,376 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import { validate } from '@lowdefy/ajv'; +import MongoDBUpdateOne from './MongoDBUpdateOne.js'; +import findLogCollectionRecordTestMongoDb from '../../../test/findLogCollectionRecordTestMongoDb.js'; +import populateTestMongoDb from '../../../test/populateTestMongoDb.js'; + +const { checkRead, checkWrite } = MongoDBUpdateOne.meta; +const schema = MongoDBUpdateOne.schema; + +const databaseUri = process.env.MONGO_URL; +const databaseName = 'test'; +const collection = 'updateOne'; +const logCollection = 'logCollection'; +const documents = [{ _id: 'updateOne', v: 'before' }]; + +beforeAll(() => { + return populateTestMongoDb({ collection, documents }); +}); + +test('updateOne', async () => { + const request = { + filter: { _id: 'updateOne' }, + update: { $set: { v: 'after' } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBUpdateOne({ request, connection }); + expect(res).toEqual({ + acknowledged: true, + modifiedCount: 1, + upsertedId: null, + upsertedCount: 0, + matchedCount: 1, + }); +}); + +test('updateOne logCollection', async () => { + const request = { + filter: { _id: 'updateOne' }, + update: { $set: { v: 'afterLog' } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + changeLog: { collection: logCollection, meta: { meta: true } }, + write: true, + }; + const res = await MongoDBUpdateOne({ + request, + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'updateOne', + connection, + }); + expect(res).toEqual({ + lastErrorObject: { + n: 1, + updatedExisting: true, + }, + ok: 1, + }); + const logged = await findLogCollectionRecordTestMongoDb({ + logCollection, + requestId: 'updateOne', + }); + expect(logged).toMatchObject({ + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'updateOne', + before: { _id: 'updateOne', v: 'after' }, + after: { _id: 'updateOne', v: 'afterLog' }, + type: 'MongoDBUpdateOne', + meta: { meta: true }, + }); +}); + +test('updateOne upsert', async () => { + const request = { + filter: { _id: 'updateOne_upsert' }, + update: { $set: { v: 'after' } }, + options: { upsert: true }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBUpdateOne({ request, connection }); + expect(res).toEqual({ + acknowledged: true, + modifiedCount: 0, + upsertedId: 'updateOne_upsert', + upsertedCount: 1, + matchedCount: 0, + }); +}); + +test('updateOne upsert logCollection', async () => { + const request = { + filter: { _id: 'updateOne_upsert_log' }, + update: { $set: { v: 'after' } }, + options: { upsert: true }, + }; + const connection = { + databaseUri, + databaseName, + collection, + changeLog: { collection: logCollection, meta: { meta: true } }, + write: true, + }; + const res = await MongoDBUpdateOne({ + request, + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'updateOne_upsert_log', + connection, + }); + expect(res).toEqual({ + lastErrorObject: { + n: 1, + updatedExisting: false, + upserted: 'updateOne_upsert_log', + }, + ok: 1, + }); + const logged = await findLogCollectionRecordTestMongoDb({ + logCollection, + requestId: 'updateOne_upsert_log', + }); + expect(logged).toMatchObject({ + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'updateOne_upsert_log', + before: null, + after: { _id: 'updateOne_upsert_log', v: 'after' }, + type: 'MongoDBUpdateOne', + meta: { meta: true }, + }); +}); + +test('updateOne upsert false', async () => { + const request = { + filter: { _id: 'updateOne_upsert_false' }, + update: { $set: { v: 'after' } }, + options: { upsert: false }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBUpdateOne({ request, connection }); + expect(res).toEqual({ + acknowledged: true, + modifiedCount: 0, + upsertedId: null, + upsertedCount: 0, + matchedCount: 0, + }); +}); + +test('updateOne upsert false logCollection', async () => { + const request = { + filter: { _id: 'updateOne_upsert_false' }, + update: { $set: { v: 'after' } }, + options: { upsert: false }, + }; + const connection = { + databaseUri, + databaseName, + collection, + changeLog: { collection: logCollection, meta: { meta: true } }, + write: true, + }; + const res = await MongoDBUpdateOne({ + request, + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'updateOne_upsert_false', + connection, + }); + expect(res).toEqual({ + lastErrorObject: { + n: 0, + updatedExisting: false, + }, + ok: 1, + }); + const logged = await findLogCollectionRecordTestMongoDb({ + logCollection, + requestId: 'updateOne_upsert_false', + }); + expect(logged).toMatchObject({ + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'updateOne_upsert_false', + before: null, + after: null, + type: 'MongoDBUpdateOne', + meta: { meta: true }, + }); +}); + +test('updateOne upsert default false', async () => { + const request = { + filter: { _id: 'updateOne_upsert_default_false' }, + update: { $set: { v: 'after' } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + const res = await MongoDBUpdateOne({ request, connection }); + expect(res).toEqual({ + acknowledged: true, + modifiedCount: 0, + upsertedId: null, + upsertedCount: 0, + matchedCount: 0, + }); +}); + +test('updateOne upsert default false logCollection', async () => { + const request = { + filter: { _id: 'updateOne_upsert_default_false' }, + update: { $set: { v: 'after' } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + changeLog: { collection: logCollection, meta: { meta: true } }, + write: true, + }; + const res = await MongoDBUpdateOne({ + request, + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'updateOne_upsert_default_false', + connection, + }); + expect(res).toEqual({ + lastErrorObject: { + n: 0, + updatedExisting: false, + }, + ok: 1, + }); + const logged = await findLogCollectionRecordTestMongoDb({ + logCollection, + requestId: 'updateOne_upsert_default_false', + }); + expect(logged).toMatchObject({ + blockId: 'blockId', + pageId: 'pageId', + payload: { payload: true }, + requestId: 'updateOne_upsert_default_false', + before: null, + after: null, + type: 'MongoDBUpdateOne', + meta: { meta: true }, + }); +}); + +test('updateOne connection error', async () => { + const request = { + filter: { _id: 'updateOne_connection_error' }, + update: { $set: { v: 'after' } }, + }; + const connection = { + databaseUri: 'bad_uri', + databaseName, + collection, + write: true, + }; + await expect(MongoDBUpdateOne({ request, connection })).rejects.toThrow( + 'Invalid scheme, expected connection string to start with "mongodb://" or "mongodb+srv://"' + ); +}); + +test('updateOne mongodb error', async () => { + const request = { + filter: { _id: 'updateOne_mongodb_error' }, + update: { $badOp: { v: 'after' } }, + }; + const connection = { + databaseUri, + databaseName, + collection, + write: true, + }; + await expect(MongoDBUpdateOne({ request, connection })).rejects.toThrow( + 'Unknown modifier: $badOp' + ); +}); + +test('checkRead should be false', async () => { + expect(checkRead).toBe(false); +}); + +test('checkWrite should be true', async () => { + expect(checkWrite).toBe(true); +}); + +test('request not an object', async () => { + const request = 'request'; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBUpdateOne request properties should be an object.' + ); +}); + +test('request no filter', async () => { + const request = { update: {} }; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBUpdateOne request should have required property "filter".' + ); +}); + +test('request no update', async () => { + const request = { filter: {} }; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBUpdateOne request should have required property "update".' + ); +}); + +test('request update not an object', async () => { + const request = { update: 'update', filter: {} }; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBUpdateOne request property "update" should be an object.' + ); +}); + +test('request filter not an object', async () => { + const request = { update: {}, filter: 'filter' }; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBUpdateOne request property "filter" should be an object.' + ); +}); + +test('request options not an object', async () => { + const request = { update: {}, filter: {}, options: 'options' }; + expect(() => validate({ schema, data: request })).toThrow( + 'MongoDBUpdateOne request property "options" should be an object.' + ); +}); diff --git a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBUpdateOne/schema.js b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBUpdateOne/schema.js new file mode 100644 index 0000000..40c5c1b --- /dev/null +++ b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/MongoDBUpdateOne/schema.js @@ -0,0 +1,52 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +export default { + $schema: 'http://json-schema.org/draft-07/schema#', + title: 'Lowdefy Request Schema - MongoDBUpdateOne', + type: 'object', + required: ['filter', 'update'], + properties: { + filter: { + type: 'object', + description: 'The filter used to select the document to update.', + errorMessage: { + type: 'MongoDBUpdateOne request property "filter" should be an object.', + }, + }, + update: { + type: ['object', 'array'], + description: 'The update operations to be applied to the document.', + errorMessage: { + type: 'MongoDBUpdateOne request property "update" should be an object.', + }, + }, + options: { + type: 'object', + description: 'Optional settings.', + errorMessage: { + type: 'MongoDBUpdateOne request property "options" should be an object.', + }, + }, + }, + errorMessage: { + type: 'MongoDBUpdateOne request properties should be an object.', + required: { + filter: 'MongoDBUpdateOne request should have required property "filter".', + update: 'MongoDBUpdateOne request should have required property "update".', + }, + }, +}; diff --git a/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/schema.js b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/schema.js new file mode 100644 index 0000000..97e5b4c --- /dev/null +++ b/plugins/community-plugin-mongodb/src/connections/MongoDBCollection/schema.js @@ -0,0 +1,81 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +export default { + $schema: 'http://json-schema.org/draft-07/schema#', + title: 'Lowdefy Connection Schema - MongoDBCollection', + type: 'object', + required: ['databaseUri', 'collection'], + properties: { + databaseUri: { + type: 'string', + description: 'Connection uri string for the MongoDb deployment.', + errorMessage: { + type: 'MongoDBCollection connection property "databaseUri" should be a string.', + }, + }, + databaseName: { + type: 'string', + description: 'Database name.', + errorMessage: { + type: 'MongoDBCollection connection property "databaseName" should be a string.', + }, + }, + changeLog: { + type: 'object', + required: ['collection'], + properties: { + collection: { + type: 'string', + description: '', + errorMessage: { + type: 'MongoDBCollection connection property "changeLog.collection" should be a string.', + }, + }, + }, + }, + collection: { + type: 'string', + description: 'Collection name.', + errorMessage: { + type: 'MongoDBCollection connection property "collection" should be a string.', + }, + }, + read: { + type: 'boolean', + default: true, + description: 'Allow reads from the collection.', + errorMessage: { + type: 'MongoDBCollection connection property "read" should be a boolean.', + }, + }, + write: { + type: 'boolean', + default: false, + description: 'Allow writes to the collection.', + errorMessage: { + type: 'MongoDBCollection connection property "write" should be a boolean.', + }, + }, + }, + errorMessage: { + type: 'MongoDBCollection connection properties should be an object.', + required: { + databaseUri: 'MongoDBCollection connection should have required property "databaseUri".', + collection: 'MongoDBCollection connection should have required property "collection".', + }, + }, +}; diff --git a/plugins/community-plugin-mongodb/src/test/clearTestMongoDb.js b/plugins/community-plugin-mongodb/src/test/clearTestMongoDb.js new file mode 100644 index 0000000..9892158 --- /dev/null +++ b/plugins/community-plugin-mongodb/src/test/clearTestMongoDb.js @@ -0,0 +1,30 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import { MongoClient } from 'mongodb'; + +async function clearTestMongoDb({ collection }) { + const client = new MongoClient(process.env.MONGO_URL, { + useNewUrlParser: true, + useUnifiedTopology: true, + }); + await client.connect(); + const db = client.db(); + await db.collection(collection).deleteMany({}); + await client.close(); +} + +export default clearTestMongoDb; diff --git a/plugins/community-plugin-mongodb/src/test/findLogCollectionRecordTestMongoDb.js b/plugins/community-plugin-mongodb/src/test/findLogCollectionRecordTestMongoDb.js new file mode 100644 index 0000000..065b9f4 --- /dev/null +++ b/plugins/community-plugin-mongodb/src/test/findLogCollectionRecordTestMongoDb.js @@ -0,0 +1,31 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import { MongoClient } from 'mongodb'; + +async function findLogCollectionRecordTestMongoDb({ logCollection, requestId }) { + const client = new MongoClient(process.env.MONGO_URL, { + useNewUrlParser: true, + useUnifiedTopology: true, + }); + await client.connect(); + const db = client.db(); + const logged = await db.collection(logCollection).findOne({ requestId }); + await client.close(); + return logged; +} + +export default findLogCollectionRecordTestMongoDb; diff --git a/plugins/community-plugin-mongodb/src/test/populateTestMongoDb.js b/plugins/community-plugin-mongodb/src/test/populateTestMongoDb.js new file mode 100644 index 0000000..bf96553 --- /dev/null +++ b/plugins/community-plugin-mongodb/src/test/populateTestMongoDb.js @@ -0,0 +1,32 @@ +/* + Copyright 2020-2023 Lowdefy, Inc + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import { MongoClient } from 'mongodb'; + +async function populateTestMongoDb({ collection, documents }) { + const client = new MongoClient(process.env.MONGO_URL, { + useNewUrlParser: true, + useUnifiedTopology: true, + }); + await client.connect(); + const db = client.db(); + await db.collection(collection).deleteMany({}); + await db.collection(collection).insertMany(documents); + + await client.close(); +} + +export default populateTestMongoDb; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cda5372..317e046 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -66,10 +66,15 @@ importers: plugins/community-plugin-mongodb: specifiers: + '@lowdefy/ajv': 4.0.0-rc.10 '@lowdefy/connection-mongodb': 4.0.0-rc.10 '@lowdefy/helpers': 4.0.0-rc.10 + '@shelf/jest-mongodb': 4.1.4 '@swc/cli': 0.1.62 '@swc/core': 1.3.66 + '@swc/jest': 0.2.27 + jest: 28.1.3 + jest-environment-node: 28.1.3 mongodb: 5.6.0 next-auth: 4.22.1 saslprep: 1.0.3 @@ -82,8 +87,13 @@ importers: saslprep: 1.0.3 uuid: 9.0.0 devDependencies: + '@lowdefy/ajv': 4.0.0-rc.10 + '@shelf/jest-mongodb': 4.1.4_gq52gshkjarkyqtsal7waw7ofm '@swc/cli': 0.1.62_@swc+core@1.3.66 '@swc/core': 1.3.66 + '@swc/jest': 0.2.27_@swc+core@1.3.66 + jest: 28.1.3 + jest-environment-node: 28.1.3 plugins/community-plugin-nodemailer: specifiers: @@ -107,6 +117,14 @@ packages: engines: {node: '>=0.10.0'} dev: true + /@ampproject/remapping/2.2.1: + resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.19 + dev: true + /@aws-crypto/crc32/3.0.0: resolution: {integrity: sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==} dependencies: @@ -571,11 +589,154 @@ packages: chalk: 2.4.2 dev: true + /@babel/code-frame/7.22.13: + resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.22.20 + chalk: 2.4.2 + dev: true + + /@babel/compat-data/7.22.20: + resolution: {integrity: sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/core/7.23.0: + resolution: {integrity: sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.22.13 + '@babel/generator': 7.23.0 + '@babel/helper-compilation-targets': 7.22.15 + '@babel/helper-module-transforms': 7.23.0_@babel+core@7.23.0 + '@babel/helpers': 7.23.1 + '@babel/parser': 7.23.0 + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.0 + '@babel/types': 7.23.0 + convert-source-map: 2.0.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/generator/7.23.0: + resolution: {integrity: sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.19 + jsesc: 2.5.2 + dev: true + + /@babel/helper-compilation-targets/7.22.15: + resolution: {integrity: sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/compat-data': 7.22.20 + '@babel/helper-validator-option': 7.22.15 + browserslist: 4.21.11 + lru-cache: 5.1.1 + semver: 6.3.1 + dev: true + + /@babel/helper-environment-visitor/7.22.20: + resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-function-name/7.23.0: + resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.15 + '@babel/types': 7.23.0 + dev: true + + /@babel/helper-hoist-variables/7.22.5: + resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + dev: true + + /@babel/helper-module-imports/7.22.15: + resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + dev: true + + /@babel/helper-module-transforms/7.23.0_@babel+core@7.23.0: + resolution: {integrity: sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.20 + dev: true + + /@babel/helper-plugin-utils/7.22.5: + resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-simple-access/7.22.5: + resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + dev: true + + /@babel/helper-split-export-declaration/7.22.6: + resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.0 + dev: true + + /@babel/helper-string-parser/7.22.5: + resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} + engines: {node: '>=6.9.0'} + dev: true + /@babel/helper-validator-identifier/7.22.15: resolution: {integrity: sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ==} engines: {node: '>=6.9.0'} dev: true + /@babel/helper-validator-identifier/7.22.20: + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-option/7.22.15: + resolution: {integrity: sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helpers/7.23.1: + resolution: {integrity: sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.0 + '@babel/types': 7.23.0 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/highlight/7.22.10: resolution: {integrity: sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==} engines: {node: '>=6.9.0'} @@ -585,12 +746,188 @@ packages: js-tokens: 4.0.0 dev: true + /@babel/highlight/7.22.20: + resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + + /@babel/parser/7.23.0: + resolution: {integrity: sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.23.0 + dev: true + + /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.23.0: + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-bigint/7.8.3_@babel+core@7.23.0: + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-class-properties/7.12.13_@babel+core@7.23.0: + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-import-meta/7.10.4_@babel+core@7.23.0: + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.23.0: + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.23.0: + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-nullish-coalescing-operator/7.8.3_@babel+core@7.23.0: + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-numeric-separator/7.10.4_@babel+core@7.23.0: + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.23.0: + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-optional-catch-binding/7.8.3_@babel+core@7.23.0: + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-optional-chaining/7.8.3_@babel+core@7.23.0: + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-top-level-await/7.14.5_@babel+core@7.23.0: + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-typescript/7.22.5_@babel+core@7.23.0: + resolution: {integrity: sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + /@babel/runtime/7.22.10: resolution: {integrity: sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ==} engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.14.0 + /@babel/template/7.22.15: + resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.22.13 + '@babel/parser': 7.23.0 + '@babel/types': 7.23.0 + dev: true + + /@babel/traverse/7.23.0: + resolution: {integrity: sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.22.13 + '@babel/generator': 7.23.0 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/parser': 7.23.0 + '@babel/types': 7.23.0 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/types/7.23.0: + resolution: {integrity: sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.22.5 + '@babel/helper-validator-identifier': 7.22.20 + to-fast-properties: 2.0.0 + dev: true + + /@bcoe/v8-coverage/0.2.3: + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + dev: true + /@changesets/apply-release-plan/6.1.4: resolution: {integrity: sha512-FMpKF1fRlJyCZVYHr3CbinpZZ+6MwvOtWUuO8uo+svcATEoc1zRDcj23pAurJ2TZ/uVz1wFHH6K3NlACy0PLew==} dependencies: @@ -832,92 +1169,376 @@ packages: resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} dev: true - /@lowdefy/connection-mongodb/4.0.0-rc.10_next-auth@4.22.1: - resolution: {integrity: sha512-OVR8rpQyRRrB0K1vUZ1odnRbQdQl+VSgCQj0UBTWl/UFiw/Ju0npEm0s7fRbTtTvo30PunegHw7r09myQvS1/A==} + /@istanbuljs/load-nyc-config/1.1.0: + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} dependencies: - '@lowdefy/helpers': 4.0.0-rc.10 - '@next-auth/mongodb-adapter': 1.1.1_kkgccujxtzejxedydtvummptby - mongodb: 4.13.0 - saslprep: 1.0.3 - transitivePeerDependencies: - - aws-crt - - next-auth - dev: false + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + dev: true - /@lowdefy/helpers/4.0.0-rc.10: - resolution: {integrity: sha512-raKg9sMJcLGfuhd3JOmlwfGyJ1npvgHJT3N4keh6kvmTcrFe8UNJGTc70gKGUCF8dhVPieMSvqzQGx7/YhfrNA==} + /@istanbuljs/schema/0.1.3: + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + dev: true + + /@jest/console/28.1.3: + resolution: {integrity: sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: - lodash.merge: 4.6.2 - query-string: 8.1.0 - dev: false + '@jest/types': 28.1.3 + '@types/node': 20.4.8 + chalk: 4.1.2 + jest-message-util: 28.1.3 + jest-util: 28.1.3 + slash: 3.0.0 + dev: true - /@lowdefy/node-utils/4.0.0-rc.10: - resolution: {integrity: sha512-+1dFBouBMjS8fZodLtWcpBR6w13kahyXFg8p0teQ4nZK2eMHe6Lgw+i4lRSsVFWrKBn86aVG4qENb4efhBx3ag==} + /@jest/core/28.1.3: + resolution: {integrity: sha512-CIKBrlaKOzA7YG19BEqCw3SLIsEwjZkeJzf5bdooVnW4bH5cktqe3JX+G2YV1aK5vP8N9na1IGWFzYaTp6k6NA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true dependencies: - '@lowdefy/helpers': 4.0.0-rc.10 - fs-extra: 11.1.1 - dev: false + '@jest/console': 28.1.3 + '@jest/reporters': 28.1.3 + '@jest/test-result': 28.1.3 + '@jest/transform': 28.1.3 + '@jest/types': 28.1.3 + '@types/node': 20.4.8 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.8.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 28.1.3 + jest-config: 28.1.3_@types+node@20.4.8 + jest-haste-map: 28.1.3 + jest-message-util: 28.1.3 + jest-regex-util: 28.0.2 + jest-resolve: 28.1.3 + jest-resolve-dependencies: 28.1.3 + jest-runner: 28.1.3 + jest-runtime: 28.1.3 + jest-snapshot: 28.1.3 + jest-util: 28.1.3 + jest-validate: 28.1.3 + jest-watcher: 28.1.3 + micromatch: 4.0.5 + pretty-format: 28.1.3 + rimraf: 3.0.2 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - supports-color + - ts-node + dev: true - /@lowdefy/nunjucks/4.0.0-rc.10: - resolution: {integrity: sha512-1vfazasVXNsuuQQNEi0le63bO7N58B02o31uRKY/d/QcYeJHY9oJt89hCnwQqxNmoplKJla9h9B4EUvxcU7F2A==} + /@jest/create-cache-key-function/27.5.1: + resolution: {integrity: sha512-dmH1yW+makpTSURTy8VzdUwFnfQh1G8R+DxO2Ho2FFmBbKFEVm+3jWdvFhE2VqB/LATCTokkP0dotjyQyw5/AQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@lowdefy/helpers': 4.0.0-rc.10 - moment: 2.29.4 - dev: false + '@jest/types': 27.5.1 + dev: true - /@manypkg/find-root/1.1.0: - resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} + /@jest/environment/28.1.3: + resolution: {integrity: sha512-1bf40cMFTEkKyEf585R9Iz1WayDjHoHqvts0XFYEqyKM3cFWDpeMoqKKTAF9LSYQModPUlh8FKptoM2YcMWAXA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: - '@babel/runtime': 7.22.10 - '@types/node': 12.20.55 - find-up: 4.1.0 - fs-extra: 8.1.0 + '@jest/fake-timers': 28.1.3 + '@jest/types': 28.1.3 + '@types/node': 20.4.8 + jest-mock: 28.1.3 dev: true - /@manypkg/get-packages/1.1.3: - resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + /@jest/expect-utils/28.1.3: + resolution: {integrity: sha512-wvbi9LUrHJLn3NlDW6wF2hvIMtd4JUl2QNVrjq+IBSHirgfrR3o9RnVtxzdEGO2n9JyIWwHnLfby5KzqBGg2YA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: - '@babel/runtime': 7.22.10 - '@changesets/types': 4.1.0 - '@manypkg/find-root': 1.1.0 - fs-extra: 8.1.0 - globby: 11.1.0 - read-yaml-file: 1.1.0 + jest-get-type: 28.0.2 dev: true - /@mole-inc/bin-wrapper/8.0.1: - resolution: {integrity: sha512-sTGoeZnjI8N4KS+sW2AN95gDBErhAguvkw/tWdCjeM8bvxpz5lqrnd0vOJABA1A+Ic3zED7PYoLP/RANLgVotA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + /@jest/expect/28.1.3: + resolution: {integrity: sha512-lzc8CpUbSoE4dqT0U+g1qODQjBRHPpCPXissXD4mS9+sWQdmmpeJ9zSH1rS1HEkrsMN0fb7nKrJ9giAR1d3wBw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: - bin-check: 4.1.0 - bin-version-check: 5.1.0 - content-disposition: 0.5.4 - ext-name: 5.0.0 - file-type: 17.1.6 - filenamify: 5.1.1 - got: 11.8.6 - os-filter-obj: 2.0.0 + expect: 28.1.3 + jest-snapshot: 28.1.3 + transitivePeerDependencies: + - supports-color dev: true - /@next-auth/mongodb-adapter/1.1.1_kkgccujxtzejxedydtvummptby: - resolution: {integrity: sha512-X5O4U4l2M8nyp/B3qF5GOr/JJw2ShKgWfTZRa80Y5CUzTPPmf09ggL5v5UwCmz9l2RIv2GUxO8hK4qrcaZvDRw==} - peerDependencies: - mongodb: ^4.1.1 - next-auth: ^4 + /@jest/fake-timers/28.1.3: + resolution: {integrity: sha512-D/wOkL2POHv52h+ok5Oj/1gOG9HSywdoPtFsRCUmlCILXNn5eIWmcnd3DIiWlJnpGvQtmajqBP95Ei0EimxfLw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: - mongodb: 4.13.0 - next-auth: 4.22.1 - dev: false + '@jest/types': 28.1.3 + '@sinonjs/fake-timers': 9.1.2 + '@types/node': 20.4.8 + jest-message-util: 28.1.3 + jest-mock: 28.1.3 + jest-util: 28.1.3 + dev: true - /@nodelib/fs.scandir/2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} + /@jest/globals/28.1.3: + resolution: {integrity: sha512-XFU4P4phyryCXu1pbcqMO0GSQcYe1IsalYCDzRNyhetyeyxMcIxa11qPNDpVNLeretItNqEmYYQn1UYz/5x1NA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 + '@jest/environment': 28.1.3 + '@jest/expect': 28.1.3 + '@jest/types': 28.1.3 + transitivePeerDependencies: + - supports-color dev: true - /@nodelib/fs.stat/2.0.5: + /@jest/reporters/28.1.3: + resolution: {integrity: sha512-JuAy7wkxQZVNU/V6g9xKzCGC5LVXx9FDcABKsSXp5MiKPEE2144a/vXTEDoyzjUpZKfVwp08Wqg5A4WfTMAzjg==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 28.1.3 + '@jest/test-result': 28.1.3 + '@jest/transform': 28.1.3 + '@jest/types': 28.1.3 + '@jridgewell/trace-mapping': 0.3.19 + '@types/node': 20.4.8 + chalk: 4.1.2 + collect-v8-coverage: 1.0.2 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.0 + istanbul-lib-instrument: 5.2.1 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.6 + jest-message-util: 28.1.3 + jest-util: 28.1.3 + jest-worker: 28.1.3 + slash: 3.0.0 + string-length: 4.0.2 + strip-ansi: 6.0.1 + terminal-link: 2.1.1 + v8-to-istanbul: 9.1.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/schemas/28.1.3: + resolution: {integrity: sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@sinclair/typebox': 0.24.51 + dev: true + + /@jest/source-map/28.1.2: + resolution: {integrity: sha512-cV8Lx3BeStJb8ipPHnqVw/IM2VCMWO3crWZzYodSIkxXnRcXJipCdx1JCK0K5MsJJouZQTH73mzf4vgxRaH9ww==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jridgewell/trace-mapping': 0.3.19 + callsites: 3.1.0 + graceful-fs: 4.2.11 + dev: true + + /@jest/test-result/28.1.3: + resolution: {integrity: sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/console': 28.1.3 + '@jest/types': 28.1.3 + '@types/istanbul-lib-coverage': 2.0.4 + collect-v8-coverage: 1.0.2 + dev: true + + /@jest/test-sequencer/28.1.3: + resolution: {integrity: sha512-NIMPEqqa59MWnDi1kvXXpYbqsfQmSJsIbnd85mdVGkiDfQ9WQQTXOLsvISUfonmnBT+w85WEgneCigEEdHDFxw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/test-result': 28.1.3 + graceful-fs: 4.2.11 + jest-haste-map: 28.1.3 + slash: 3.0.0 + dev: true + + /@jest/transform/28.1.3: + resolution: {integrity: sha512-u5dT5di+oFI6hfcLOHGTAfmUxFRrjK+vnaP0kkVow9Md/M7V/MxqQMOz/VV25UZO8pzeA9PjfTpOu6BDuwSPQA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@babel/core': 7.23.0 + '@jest/types': 28.1.3 + '@jridgewell/trace-mapping': 0.3.19 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 1.9.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 28.1.3 + jest-regex-util: 28.0.2 + jest-util: 28.1.3 + micromatch: 4.0.5 + pirates: 4.0.6 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/types/27.5.1: + resolution: {integrity: sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + '@types/istanbul-lib-coverage': 2.0.4 + '@types/istanbul-reports': 3.0.1 + '@types/node': 20.4.8 + '@types/yargs': 16.0.6 + chalk: 4.1.2 + dev: true + + /@jest/types/28.1.3: + resolution: {integrity: sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/schemas': 28.1.3 + '@types/istanbul-lib-coverage': 2.0.4 + '@types/istanbul-reports': 3.0.1 + '@types/node': 20.4.8 + '@types/yargs': 17.0.25 + chalk: 4.1.2 + dev: true + + /@jridgewell/gen-mapping/0.3.3: + resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.19 + dev: true + + /@jridgewell/resolve-uri/3.1.1: + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/set-array/1.1.2: + resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/sourcemap-codec/1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + dev: true + + /@jridgewell/trace-mapping/0.3.19: + resolution: {integrity: sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /@lowdefy/ajv/4.0.0-rc.10: + resolution: {integrity: sha512-kFD4linRFDBBezFtWuyCq8YCJRgj1oCZ8oNdHXcpYiwiUfhrVl+8yRtqIp1uwAmTr6TGazTmqeIcS/+RdSj4Zg==} + dependencies: + '@lowdefy/nunjucks': 4.0.0-rc.10 + ajv: 8.12.0 + ajv-errors: 3.0.0_ajv@8.12.0 + dev: true + + /@lowdefy/connection-mongodb/4.0.0-rc.10_next-auth@4.22.1: + resolution: {integrity: sha512-OVR8rpQyRRrB0K1vUZ1odnRbQdQl+VSgCQj0UBTWl/UFiw/Ju0npEm0s7fRbTtTvo30PunegHw7r09myQvS1/A==} + dependencies: + '@lowdefy/helpers': 4.0.0-rc.10 + '@next-auth/mongodb-adapter': 1.1.1_kkgccujxtzejxedydtvummptby + mongodb: 4.13.0 + saslprep: 1.0.3 + transitivePeerDependencies: + - aws-crt + - next-auth + dev: false + + /@lowdefy/helpers/4.0.0-rc.10: + resolution: {integrity: sha512-raKg9sMJcLGfuhd3JOmlwfGyJ1npvgHJT3N4keh6kvmTcrFe8UNJGTc70gKGUCF8dhVPieMSvqzQGx7/YhfrNA==} + dependencies: + lodash.merge: 4.6.2 + query-string: 8.1.0 + + /@lowdefy/node-utils/4.0.0-rc.10: + resolution: {integrity: sha512-+1dFBouBMjS8fZodLtWcpBR6w13kahyXFg8p0teQ4nZK2eMHe6Lgw+i4lRSsVFWrKBn86aVG4qENb4efhBx3ag==} + dependencies: + '@lowdefy/helpers': 4.0.0-rc.10 + fs-extra: 11.1.1 + dev: false + + /@lowdefy/nunjucks/4.0.0-rc.10: + resolution: {integrity: sha512-1vfazasVXNsuuQQNEi0le63bO7N58B02o31uRKY/d/QcYeJHY9oJt89hCnwQqxNmoplKJla9h9B4EUvxcU7F2A==} + dependencies: + '@lowdefy/helpers': 4.0.0-rc.10 + moment: 2.29.4 + + /@manypkg/find-root/1.1.0: + resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} + dependencies: + '@babel/runtime': 7.22.10 + '@types/node': 12.20.55 + find-up: 4.1.0 + fs-extra: 8.1.0 + dev: true + + /@manypkg/get-packages/1.1.3: + resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + dependencies: + '@babel/runtime': 7.22.10 + '@changesets/types': 4.1.0 + '@manypkg/find-root': 1.1.0 + fs-extra: 8.1.0 + globby: 11.1.0 + read-yaml-file: 1.1.0 + dev: true + + /@mole-inc/bin-wrapper/8.0.1: + resolution: {integrity: sha512-sTGoeZnjI8N4KS+sW2AN95gDBErhAguvkw/tWdCjeM8bvxpz5lqrnd0vOJABA1A+Ic3zED7PYoLP/RANLgVotA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + bin-check: 4.1.0 + bin-version-check: 5.1.0 + content-disposition: 0.5.4 + ext-name: 5.0.0 + file-type: 17.1.6 + filenamify: 5.1.1 + got: 11.8.6 + os-filter-obj: 2.0.0 + dev: true + + /@next-auth/mongodb-adapter/1.1.1_kkgccujxtzejxedydtvummptby: + resolution: {integrity: sha512-X5O4U4l2M8nyp/B3qF5GOr/JJw2ShKgWfTZRa80Y5CUzTPPmf09ggL5v5UwCmz9l2RIv2GUxO8hK4qrcaZvDRw==} + peerDependencies: + mongodb: ^4.1.1 + next-auth: ^4 + dependencies: + mongodb: 4.13.0 + next-auth: 4.22.1 + dev: false + + /@nodelib/fs.scandir/2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat/2.0.5: resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} engines: {node: '>= 8'} dev: true @@ -934,11 +1555,42 @@ packages: resolution: {integrity: sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==} dev: false + /@shelf/jest-mongodb/4.1.4_gq52gshkjarkyqtsal7waw7ofm: + resolution: {integrity: sha512-ccr9ujYN1gRSdO0v4LlJGp6dcne7UuxNgGMdqbdPbBgmUxz7L/CQy9x0olFPC0yCzAYEyF4Jh/zmMCnj8YUMXQ==} + engines: {node: '>=16'} + peerDependencies: + jest-environment-node: 27.x.x || 28.x || 29.x + mongodb: 3.x.x || 4.x + dependencies: + debug: 4.3.4 + jest-environment-node: 28.1.3 + mongodb: 5.6.0 + mongodb-memory-server: 8.9.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@sinclair/typebox/0.24.51: + resolution: {integrity: sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==} + dev: true + /@sindresorhus/is/4.6.0: resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} engines: {node: '>=10'} dev: true + /@sinonjs/commons/1.8.6: + resolution: {integrity: sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==} + dependencies: + type-detect: 4.0.8 + dev: true + + /@sinonjs/fake-timers/9.1.2: + resolution: {integrity: sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==} + dependencies: + '@sinonjs/commons': 1.8.6 + dev: true + /@smithy/abort-controller/2.0.2: resolution: {integrity: sha512-ln5Cob0mksym62sLr7NiPOSqJ0jKao4qjfcNLDdgINM1lQI12hXrZBlKdPHbXJqpKhKiECDgonMoqCM8bigq4g==} engines: {node: '>=14.0.0'} @@ -1444,6 +2096,17 @@ packages: '@swc/core-win32-x64-msvc': 1.3.66 dev: true + /@swc/jest/0.2.27_@swc+core@1.3.66: + resolution: {integrity: sha512-Xt8EJ6Wy0NYVL8KDPcDMsuUSzyV2UAByamyy28x2iDZCJw2eVz3acedCGBYxxlPR/DNr6QbA35OSymuXhC9QVA==} + engines: {npm: '>= 7.0.0'} + peerDependencies: + '@swc/core': '*' + dependencies: + '@jest/create-cache-key-function': 27.5.1 + '@swc/core': 1.3.66 + jsonc-parser: 3.2.0 + dev: true + /@szmarczak/http-timer/4.0.6: resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} engines: {node: '>=10'} @@ -1455,6 +2118,35 @@ packages: resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} dev: true + /@types/babel__core/7.20.2: + resolution: {integrity: sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==} + dependencies: + '@babel/parser': 7.23.0 + '@babel/types': 7.23.0 + '@types/babel__generator': 7.6.5 + '@types/babel__template': 7.4.2 + '@types/babel__traverse': 7.20.2 + dev: true + + /@types/babel__generator/7.6.5: + resolution: {integrity: sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w==} + dependencies: + '@babel/types': 7.23.0 + dev: true + + /@types/babel__template/7.4.2: + resolution: {integrity: sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ==} + dependencies: + '@babel/parser': 7.23.0 + '@babel/types': 7.23.0 + dev: true + + /@types/babel__traverse/7.20.2: + resolution: {integrity: sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==} + dependencies: + '@babel/types': 7.23.0 + dev: true + /@types/cacheable-request/6.0.3: resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} dependencies: @@ -1464,6 +2156,12 @@ packages: '@types/responselike': 1.0.0 dev: true + /@types/graceful-fs/4.1.7: + resolution: {integrity: sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw==} + dependencies: + '@types/node': 20.4.8 + dev: true + /@types/http-cache-semantics/4.0.1: resolution: {integrity: sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==} dev: true @@ -1474,6 +2172,22 @@ packages: ci-info: 3.8.0 dev: true + /@types/istanbul-lib-coverage/2.0.4: + resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} + dev: true + + /@types/istanbul-lib-report/3.0.0: + resolution: {integrity: sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==} + dependencies: + '@types/istanbul-lib-coverage': 2.0.4 + dev: true + + /@types/istanbul-reports/3.0.1: + resolution: {integrity: sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==} + dependencies: + '@types/istanbul-lib-report': 3.0.0 + dev: true + /@types/json5/0.0.29: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} dev: true @@ -1499,6 +2213,10 @@ packages: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} dev: true + /@types/prettier/2.7.3: + resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} + dev: true + /@types/responselike/1.0.0: resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} dependencies: @@ -1509,16 +2227,38 @@ packages: resolution: {integrity: sha512-KQf+QAMWKMrtBMsB8/24w53tEsxllMj6TuA80TT/5igJalLI/zm0L3oXRbIAl4Ohfc85gyHX/jhMwsVkmhLU4A==} dev: true + /@types/stack-utils/2.0.1: + resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} + dev: true + + /@types/tmp/0.2.4: + resolution: {integrity: sha512-Vq3rwM+2KgiLacq68EjTJD9cuJ/ne5pXntWn8B8Rxj25SLkGAhCgooCZ1lhcIcV5OFveJ+s5Cqpi+XKfFM/xZA==} + dev: true + /@types/webidl-conversions/7.0.0: resolution: {integrity: sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==} - dev: false /@types/whatwg-url/8.2.2: resolution: {integrity: sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==} dependencies: '@types/node': 20.4.8 '@types/webidl-conversions': 7.0.0 - dev: false + + /@types/yargs-parser/21.0.1: + resolution: {integrity: sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==} + dev: true + + /@types/yargs/16.0.6: + resolution: {integrity: sha512-oTP7/Q13GSPrgcwEwdlnkoZSQ1Hg9THe644qq8PG6hhJzjZ3qj1JjEFPIwWV/IXVs5XGIVqtkNOS9kh63WIJ+A==} + dependencies: + '@types/yargs-parser': 21.0.1 + dev: true + + /@types/yargs/17.0.25: + resolution: {integrity: sha512-gy7iPgwnzNvxgAEi2bXOHWCVOG6f7xsprVJH4MjlAWeBmJ7vh/Y1kwMtUrs64ztf24zVIRCpr3n/z6gm9QIkgg==} + dependencies: + '@types/yargs-parser': 21.0.1 + dev: true /acorn-jsx/5.3.2_acorn@8.10.0: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} @@ -1534,6 +2274,23 @@ packages: hasBin: true dev: true + /agent-base/6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /ajv-errors/3.0.0_ajv@8.12.0: + resolution: {integrity: sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==} + peerDependencies: + ajv: ^8.0.1 + dependencies: + ajv: 8.12.0 + dev: true + /ajv/6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} dependencies: @@ -1543,11 +2300,27 @@ packages: uri-js: 4.4.1 dev: true + /ajv/8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + dev: true + /ansi-colors/4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} dev: true + /ansi-escapes/4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + dev: true + /ansi-regex/5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -1572,6 +2345,19 @@ packages: color-convert: 2.0.1 dev: true + /ansi-styles/5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + dev: true + + /anymatch/3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + /arch/2.2.0: resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} dev: true @@ -1666,6 +2452,12 @@ packages: resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==} dev: true + /async-mutex/0.3.2: + resolution: {integrity: sha512-HuTK7E7MT7jZEh1P9GtRW9+aTWiDWWi9InbZ5hjxrnRa39KS4BW04+xLBhYNS2aXhHUIKZSw3gj4Pn1pj+qGAA==} + dependencies: + tslib: 2.6.1 + dev: true + /asynckit/0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} dev: false @@ -1696,13 +2488,84 @@ packages: dequal: 2.0.3 dev: true - /balanced-match/1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + /babel-jest/28.1.3_@babel+core@7.23.0: + resolution: {integrity: sha512-epUaPOEWMk3cWX0M/sPvCHHCe9fMFAa/9hXEgKP8nFfNl/jlGkE9ucq9NqkZGXLDduCJYS0UvSlPUwC0S+rH6Q==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + dependencies: + '@babel/core': 7.23.0 + '@jest/transform': 28.1.3 + '@types/babel__core': 7.20.2 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 28.1.3_@babel+core@7.23.0 + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color dev: true - /base64-js/1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: false + /babel-plugin-istanbul/6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + dependencies: + '@babel/helper-plugin-utils': 7.22.5 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-jest-hoist/28.1.3: + resolution: {integrity: sha512-Ys3tUKAmfnkRUpPdpa98eYrAR0nV+sSFUZZEGuQ2EbFd1y4SOLtD5QDNHAq+bb9a+bbXvYQC4b+ID/THIMcU6Q==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@babel/template': 7.22.15 + '@babel/types': 7.23.0 + '@types/babel__core': 7.20.2 + '@types/babel__traverse': 7.20.2 + dev: true + + /babel-preset-current-node-syntax/1.0.1_@babel+core@7.23.0: + resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.0 + '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.23.0 + '@babel/plugin-syntax-bigint': 7.8.3_@babel+core@7.23.0 + '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.23.0 + '@babel/plugin-syntax-import-meta': 7.10.4_@babel+core@7.23.0 + '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.23.0 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.23.0 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.23.0 + '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.23.0 + '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.23.0 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.23.0 + '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.23.0 + '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.23.0 + dev: true + + /babel-preset-jest/28.1.3_@babel+core@7.23.0: + resolution: {integrity: sha512-L+fupJvlWAHbQfn74coNX3zf60LXMJsezNvvx8eIh7iOR1luJ1poxYgQk1F8PYtNq/6QODDHCqsSnTFSWC491A==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.0 + babel-plugin-jest-hoist: 28.1.3 + babel-preset-current-node-syntax: 1.0.1_@babel+core@7.23.0 + dev: true + + /balanced-match/1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /base64-js/1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} /better-path-resolve/1.0.0: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} @@ -1743,6 +2606,14 @@ packages: safe-buffer: 5.2.1 dev: false + /bl/4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: true + /bl/5.1.0: resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} dependencies: @@ -1776,17 +2647,32 @@ packages: wcwidth: 1.0.1 dev: true + /browserslist/4.21.11: + resolution: {integrity: sha512-xn1UXOKUz7DjdGlg9RrUr0GGiWzI97UQJnugHtH0OLDfJB7jMgoIkYvRIEO1l9EeEERVqeqLYOcFBW9ldjypbQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001539 + electron-to-chromium: 1.4.528 + node-releases: 2.0.13 + update-browserslist-db: 1.0.13_browserslist@4.21.11 + dev: true + + /bser/2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + dependencies: + node-int64: 0.4.0 + dev: true + /bson/4.7.2: resolution: {integrity: sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ==} engines: {node: '>=6.9.0'} dependencies: buffer: 5.7.1 - dev: false /bson/5.4.0: resolution: {integrity: sha512-WRZ5SQI5GfUuKnPTNmAYPiKIof3ORXAF4IRU5UcgmivNIon01rWQlw5RUH954dpu8yGL8T59YShVddIPaU/gFA==} engines: {node: '>=14.20.1'} - dev: false /buffer-alloc-unsafe/1.1.0: resolution: {integrity: sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==} @@ -1801,7 +2687,6 @@ packages: /buffer-crc32/0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} - dev: false /buffer-equal-constant-time/1.0.1: resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} @@ -1811,12 +2696,15 @@ packages: resolution: {integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==} dev: false + /buffer-from/1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true + /buffer/5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} dependencies: base64-js: 1.5.1 ieee754: 1.2.1 - dev: false /buffer/6.0.3: resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} @@ -1869,6 +2757,15 @@ packages: engines: {node: '>=6'} dev: true + /camelcase/6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + dev: true + + /caniuse-lite/1.0.30001539: + resolution: {integrity: sha512-hfS5tE8bnNiNvEOEkm8HElUHroYwlqMMENEzELymy77+tJ6m+gA2krtHl5hxJaj71OlpC2cHZbdSMX1/YEqEkA==} + dev: true + /chalk/2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -1891,6 +2788,11 @@ packages: engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} dev: false + /char-regex/1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + dev: true + /chardet/0.7.0: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} dev: true @@ -1900,6 +2802,10 @@ packages: engines: {node: '>=8'} dev: true + /cjs-module-lexer/1.2.3: + resolution: {integrity: sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==} + dev: true + /cli-cursor/4.0.0: resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -1939,6 +2845,15 @@ packages: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} + /co/4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + dev: true + + /collect-v8-coverage/1.0.2: + resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + dev: true + /color-convert/1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -1981,6 +2896,10 @@ packages: engines: {node: ^12.20.0 || >=14} dev: false + /commondir/1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + dev: true + /concat-map/0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} dev: true @@ -1992,6 +2911,14 @@ packages: safe-buffer: 5.2.1 dev: true + /convert-source-map/1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + dev: true + + /convert-source-map/2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + dev: true + /cookie/0.5.0: resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} engines: {node: '>= 0.6'} @@ -2083,7 +3010,6 @@ packages: /decode-uri-component/0.4.1: resolution: {integrity: sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==} engines: {node: '>=14.16'} - dev: false /decompress-response/6.0.0: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} @@ -2145,10 +3071,19 @@ packages: strip-dirs: 2.1.0 dev: false + /dedent/0.7.0: + resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} + dev: true + /deep-is/0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true + /deepmerge/4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + dev: true + /defaults/1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} dependencies: @@ -2172,6 +3107,11 @@ packages: engines: {node: '>=0.4.0'} dev: false + /denque/2.1.0: + resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} + engines: {node: '>=0.10'} + dev: true + /dequal/2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -2182,6 +3122,16 @@ packages: engines: {node: '>=8'} dev: true + /detect-newline/3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + dev: true + + /diff-sequences/28.1.1: + resolution: {integrity: sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dev: true + /dir-glob/3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -2214,6 +3164,15 @@ packages: safe-buffer: 5.2.1 dev: false + /electron-to-chromium/1.4.528: + resolution: {integrity: sha512-UdREXMXzLkREF4jA8t89FQjA8WHI6ssP38PMY4/4KhXFQbtImnghh4GkCgrtiZwLKUKVD2iTVXvDVQjfomEQuA==} + dev: true + + /emittery/0.10.2: + resolution: {integrity: sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==} + engines: {node: '>=12'} + dev: true + /emoji-regex/8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: true @@ -2320,6 +3279,11 @@ packages: engines: {node: '>=0.8.0'} dev: true + /escape-string-regexp/2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + dev: true + /escape-string-regexp/4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -2617,6 +3581,22 @@ packages: pify: 2.3.0 dev: true + /exit/0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + dev: true + + /expect/28.1.3: + resolution: {integrity: sha512-eEh0xn8HlsuOBxFgIss+2mX85VAS4Qy3OSkjV7rlBWljtA4oWH37glVGyOZSZvErDT/yBywZdPGwCXuTvSG85g==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/expect-utils': 28.1.3 + jest-get-type: 28.0.2 + jest-matcher-utils: 28.1.3 + jest-message-util: 28.1.3 + jest-util: 28.1.3 + dev: true + /ext-list/2.2.2: resolution: {integrity: sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==} engines: {node: '>=0.10.0'} @@ -2686,11 +3666,16 @@ packages: reusify: 1.0.4 dev: true + /fb-watchman/2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + dependencies: + bser: 2.1.1 + dev: true + /fd-slicer/1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} dependencies: pend: 1.2.0 - dev: false /file-entry-cache/6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} @@ -2747,7 +3732,15 @@ packages: /filter-obj/5.1.0: resolution: {integrity: sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==} engines: {node: '>=14.16'} - dev: false + + /find-cache-dir/3.3.2: + resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} + engines: {node: '>=8'} + dependencies: + commondir: 1.0.1 + make-dir: 3.1.0 + pkg-dir: 4.2.0 + dev: true /find-up/4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} @@ -2818,7 +3811,6 @@ packages: /fs-constants/1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - dev: false /fs-extra/11.1.1: resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} @@ -2851,6 +3843,14 @@ packages: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} dev: true + /fsevents/2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + /function-bind/1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} dev: true @@ -2869,6 +3869,11 @@ packages: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} dev: true + /gensync/1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: true + /get-caller-file/2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} @@ -2883,6 +3888,16 @@ packages: has-symbols: 1.0.3 dev: true + /get-package-type/0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + dev: true + + /get-port/5.1.1: + resolution: {integrity: sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==} + engines: {node: '>=8'} + dev: true + /get-stream/2.3.1: resolution: {integrity: sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==} engines: {node: '>=0.10.0'} @@ -2941,6 +3956,11 @@ packages: path-is-absolute: 1.0.1 dev: true + /globals/11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: true + /globals/13.20.0: resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} engines: {node: '>=8'} @@ -3054,6 +4074,10 @@ packages: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} dev: true + /html-escaper/2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + dev: true + /http-cache-semantics/4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} dev: true @@ -3066,6 +4090,16 @@ packages: resolve-alpn: 1.2.1 dev: true + /https-proxy-agent/5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + /human-id/1.0.2: resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} dev: true @@ -3098,6 +4132,15 @@ packages: resolve-from: 4.0.0 dev: true + /import-local/3.1.0: + resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} + engines: {node: '>=8'} + hasBin: true + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + dev: true + /imurmurhash/0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -3129,7 +4172,6 @@ packages: /ip/2.0.0: resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==} - dev: false /is-array-buffer/3.0.2: resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} @@ -3192,6 +4234,11 @@ packages: engines: {node: '>=8'} dev: true + /is-generator-fn/2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + dev: true + /is-glob/4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -3265,53 +4312,543 @@ packages: has-tostringtag: 1.0.0 dev: true - /is-subdir/1.2.0: - resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} - engines: {node: '>=4'} + /is-subdir/1.2.0: + resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} + engines: {node: '>=4'} + dependencies: + better-path-resolve: 1.0.0 + dev: true + + /is-symbol/1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-typed-array/1.1.12: + resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.11 + dev: true + + /is-unicode-supported/1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + dev: false + + /is-weakref/1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.2 + dev: true + + /is-windows/1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + dev: true + + /isarray/1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + dev: false + + /isarray/2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + + /isexe/2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /istanbul-lib-coverage/3.2.0: + resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} + engines: {node: '>=8'} + dev: true + + /istanbul-lib-instrument/5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + dependencies: + '@babel/core': 7.23.0 + '@babel/parser': 7.23.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-lib-report/3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + dependencies: + istanbul-lib-coverage: 3.2.0 + make-dir: 4.0.0 + supports-color: 7.2.0 + dev: true + + /istanbul-lib-source-maps/4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + dependencies: + debug: 4.3.4 + istanbul-lib-coverage: 3.2.0 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-reports/3.1.6: + resolution: {integrity: sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==} + engines: {node: '>=8'} + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + dev: true + + /jest-changed-files/28.1.3: + resolution: {integrity: sha512-esaOfUWJXk2nfZt9SPyC8gA1kNfdKLkQWyzsMlqq8msYSlNKfmZxfRgZn4Cd4MGVUF+7v6dBs0d5TOAKa7iIiA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + execa: 5.1.1 + p-limit: 3.1.0 + dev: true + + /jest-circus/28.1.3: + resolution: {integrity: sha512-cZ+eS5zc79MBwt+IhQhiEp0OeBddpc1n8MBo1nMB8A7oPMKEO+Sre+wHaLJexQUj9Ya/8NOBY0RESUgYjB6fow==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/environment': 28.1.3 + '@jest/expect': 28.1.3 + '@jest/test-result': 28.1.3 + '@jest/types': 28.1.3 + '@types/node': 20.4.8 + chalk: 4.1.2 + co: 4.6.0 + dedent: 0.7.0 + is-generator-fn: 2.1.0 + jest-each: 28.1.3 + jest-matcher-utils: 28.1.3 + jest-message-util: 28.1.3 + jest-runtime: 28.1.3 + jest-snapshot: 28.1.3 + jest-util: 28.1.3 + p-limit: 3.1.0 + pretty-format: 28.1.3 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-cli/28.1.3: + resolution: {integrity: sha512-roY3kvrv57Azn1yPgdTebPAXvdR2xfezaKKYzVxZ6It/5NCxzJym6tUI5P1zkdWhfUYkxEI9uZWcQdaFLo8mJQ==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 28.1.3 + '@jest/test-result': 28.1.3 + '@jest/types': 28.1.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + import-local: 3.1.0 + jest-config: 28.1.3 + jest-util: 28.1.3 + jest-validate: 28.1.3 + prompts: 2.4.2 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - supports-color + - ts-node + dev: true + + /jest-config/28.1.3: + resolution: {integrity: sha512-MG3INjByJ0J4AsNBm7T3hsuxKQqFIiRo/AUqb1q9LRKI5UU6Aar9JHbr9Ivn1TVwfUD9KirRoM/T6u8XlcQPHQ==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + dependencies: + '@babel/core': 7.23.0 + '@jest/test-sequencer': 28.1.3 + '@jest/types': 28.1.3 + babel-jest: 28.1.3_@babel+core@7.23.0 + chalk: 4.1.2 + ci-info: 3.8.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 28.1.3 + jest-environment-node: 28.1.3 + jest-get-type: 28.0.2 + jest-regex-util: 28.0.2 + jest-resolve: 28.1.3 + jest-runner: 28.1.3 + jest-util: 28.1.3 + jest-validate: 28.1.3 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 28.1.3 + slash: 3.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-config/28.1.3_@types+node@20.4.8: + resolution: {integrity: sha512-MG3INjByJ0J4AsNBm7T3hsuxKQqFIiRo/AUqb1q9LRKI5UU6Aar9JHbr9Ivn1TVwfUD9KirRoM/T6u8XlcQPHQ==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + dependencies: + '@babel/core': 7.23.0 + '@jest/test-sequencer': 28.1.3 + '@jest/types': 28.1.3 + '@types/node': 20.4.8 + babel-jest: 28.1.3_@babel+core@7.23.0 + chalk: 4.1.2 + ci-info: 3.8.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 28.1.3 + jest-environment-node: 28.1.3 + jest-get-type: 28.0.2 + jest-regex-util: 28.0.2 + jest-resolve: 28.1.3 + jest-runner: 28.1.3 + jest-util: 28.1.3 + jest-validate: 28.1.3 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 28.1.3 + slash: 3.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-diff/28.1.3: + resolution: {integrity: sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + chalk: 4.1.2 + diff-sequences: 28.1.1 + jest-get-type: 28.0.2 + pretty-format: 28.1.3 + dev: true + + /jest-docblock/28.1.1: + resolution: {integrity: sha512-3wayBVNiOYx0cwAbl9rwm5kKFP8yHH3d/fkEaL02NPTkDojPtheGB7HZSFY4wzX+DxyrvhXz0KSCVksmCknCuA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + detect-newline: 3.1.0 + dev: true + + /jest-each/28.1.3: + resolution: {integrity: sha512-arT1z4sg2yABU5uogObVPvSlSMQlDA48owx07BDPAiasW0yYpYHYOo4HHLz9q0BVzDVU4hILFjzJw0So9aCL/g==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/types': 28.1.3 + chalk: 4.1.2 + jest-get-type: 28.0.2 + jest-util: 28.1.3 + pretty-format: 28.1.3 + dev: true + + /jest-environment-node/28.1.3: + resolution: {integrity: sha512-ugP6XOhEpjAEhGYvp5Xj989ns5cB1K6ZdjBYuS30umT4CQEETaxSiPcZ/E1kFktX4GkrcM4qu07IIlDYX1gp+A==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/environment': 28.1.3 + '@jest/fake-timers': 28.1.3 + '@jest/types': 28.1.3 + '@types/node': 20.4.8 + jest-mock: 28.1.3 + jest-util: 28.1.3 + dev: true + + /jest-get-type/28.0.2: + resolution: {integrity: sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dev: true + + /jest-haste-map/28.1.3: + resolution: {integrity: sha512-3S+RQWDXccXDKSWnkHa/dPwt+2qwA8CJzR61w3FoYCvoo3Pn8tvGcysmMF0Bj0EX5RYvAI2EIvC57OmotfdtKA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/types': 28.1.3 + '@types/graceful-fs': 4.1.7 + '@types/node': 20.4.8 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 28.0.2 + jest-util: 28.1.3 + jest-worker: 28.1.3 + micromatch: 4.0.5 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /jest-leak-detector/28.1.3: + resolution: {integrity: sha512-WFVJhnQsiKtDEo5lG2mM0v40QWnBM+zMdHHyJs8AWZ7J0QZJS59MsyKeJHWhpBZBH32S48FOVvGyOFT1h0DlqA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + jest-get-type: 28.0.2 + pretty-format: 28.1.3 + dev: true + + /jest-matcher-utils/28.1.3: + resolution: {integrity: sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + chalk: 4.1.2 + jest-diff: 28.1.3 + jest-get-type: 28.0.2 + pretty-format: 28.1.3 + dev: true + + /jest-message-util/28.1.3: + resolution: {integrity: sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@babel/code-frame': 7.22.10 + '@jest/types': 28.1.3 + '@types/stack-utils': 2.0.1 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.5 + pretty-format: 28.1.3 + slash: 3.0.0 + stack-utils: 2.0.6 + dev: true + + /jest-mock/28.1.3: + resolution: {integrity: sha512-o3J2jr6dMMWYVH4Lh/NKmDXdosrsJgi4AviS8oXLujcjpCMBb1FMsblDnOXKZKfSiHLxYub1eS0IHuRXsio9eA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/types': 28.1.3 + '@types/node': 20.4.8 + dev: true + + /jest-pnp-resolver/1.2.3_jest-resolve@28.1.3: + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + dependencies: + jest-resolve: 28.1.3 + dev: true + + /jest-regex-util/28.0.2: + resolution: {integrity: sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dev: true + + /jest-resolve-dependencies/28.1.3: + resolution: {integrity: sha512-qa0QO2Q0XzQoNPouMbCc7Bvtsem8eQgVPNkwn9LnS+R2n8DaVDPL/U1gngC0LTl1RYXJU0uJa2BMC2DbTfFrHA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + jest-regex-util: 28.0.2 + jest-snapshot: 28.1.3 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-resolve/28.1.3: + resolution: {integrity: sha512-Z1W3tTjE6QaNI90qo/BJpfnvpxtaFTFw5CDgwpyE/Kz8U/06N1Hjf4ia9quUhCh39qIGWF1ZuxFiBiJQwSEYKQ==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 28.1.3 + jest-pnp-resolver: 1.2.3_jest-resolve@28.1.3 + jest-util: 28.1.3 + jest-validate: 28.1.3 + resolve: 1.22.4 + resolve.exports: 1.1.1 + slash: 3.0.0 + dev: true + + /jest-runner/28.1.3: + resolution: {integrity: sha512-GkMw4D/0USd62OVO0oEgjn23TM+YJa2U2Wu5zz9xsQB1MxWKDOlrnykPxnMsN0tnJllfLPinHTka61u0QhaxBA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/console': 28.1.3 + '@jest/environment': 28.1.3 + '@jest/test-result': 28.1.3 + '@jest/transform': 28.1.3 + '@jest/types': 28.1.3 + '@types/node': 20.4.8 + chalk: 4.1.2 + emittery: 0.10.2 + graceful-fs: 4.2.11 + jest-docblock: 28.1.1 + jest-environment-node: 28.1.3 + jest-haste-map: 28.1.3 + jest-leak-detector: 28.1.3 + jest-message-util: 28.1.3 + jest-resolve: 28.1.3 + jest-runtime: 28.1.3 + jest-util: 28.1.3 + jest-watcher: 28.1.3 + jest-worker: 28.1.3 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-runtime/28.1.3: + resolution: {integrity: sha512-NU+881ScBQQLc1JHG5eJGU7Ui3kLKrmwCPPtYsJtBykixrM2OhVQlpMmFWJjMyDfdkGgBMNjXCGB/ebzsgNGQw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/environment': 28.1.3 + '@jest/fake-timers': 28.1.3 + '@jest/globals': 28.1.3 + '@jest/source-map': 28.1.2 + '@jest/test-result': 28.1.3 + '@jest/transform': 28.1.3 + '@jest/types': 28.1.3 + chalk: 4.1.2 + cjs-module-lexer: 1.2.3 + collect-v8-coverage: 1.0.2 + execa: 5.1.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-haste-map: 28.1.3 + jest-message-util: 28.1.3 + jest-mock: 28.1.3 + jest-regex-util: 28.0.2 + jest-resolve: 28.1.3 + jest-snapshot: 28.1.3 + jest-util: 28.1.3 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-snapshot/28.1.3: + resolution: {integrity: sha512-4lzMgtiNlc3DU/8lZfmqxN3AYD6GGLbl+72rdBpXvcV+whX7mDrREzkPdp2RnmfIiWBg1YbuFSkXduF2JcafJg==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@babel/core': 7.23.0 + '@babel/generator': 7.23.0 + '@babel/plugin-syntax-typescript': 7.22.5_@babel+core@7.23.0 + '@babel/traverse': 7.23.0 + '@babel/types': 7.23.0 + '@jest/expect-utils': 28.1.3 + '@jest/transform': 28.1.3 + '@jest/types': 28.1.3 + '@types/babel__traverse': 7.20.2 + '@types/prettier': 2.7.3 + babel-preset-current-node-syntax: 1.0.1_@babel+core@7.23.0 + chalk: 4.1.2 + expect: 28.1.3 + graceful-fs: 4.2.11 + jest-diff: 28.1.3 + jest-get-type: 28.0.2 + jest-haste-map: 28.1.3 + jest-matcher-utils: 28.1.3 + jest-message-util: 28.1.3 + jest-util: 28.1.3 + natural-compare: 1.4.0 + pretty-format: 28.1.3 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-util/28.1.3: + resolution: {integrity: sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: - better-path-resolve: 1.0.0 + '@jest/types': 28.1.3 + '@types/node': 20.4.8 + chalk: 4.1.2 + ci-info: 3.8.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 dev: true - /is-symbol/1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} + /jest-validate/28.1.3: + resolution: {integrity: sha512-SZbOGBWEsaTxBGCOpsRWlXlvNkvTkY0XxRfh7zYmvd8uL5Qzyg0CHAXiXKROflh801quA6+/DsT4ODDthOC/OA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: - has-symbols: 1.0.3 + '@jest/types': 28.1.3 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 28.0.2 + leven: 3.1.0 + pretty-format: 28.1.3 dev: true - /is-typed-array/1.1.12: - resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} - engines: {node: '>= 0.4'} + /jest-watcher/28.1.3: + resolution: {integrity: sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: - which-typed-array: 1.1.11 + '@jest/test-result': 28.1.3 + '@jest/types': 28.1.3 + '@types/node': 20.4.8 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.10.2 + jest-util: 28.1.3 + string-length: 4.0.2 dev: true - /is-unicode-supported/1.3.0: - resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} - engines: {node: '>=12'} - dev: false - - /is-weakref/1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + /jest-worker/28.1.3: + resolution: {integrity: sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: - call-bind: 1.0.2 - dev: true - - /is-windows/1.0.2: - resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} - engines: {node: '>=0.10.0'} - dev: true - - /isarray/1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - dev: false - - /isarray/2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + '@types/node': 20.4.8 + merge-stream: 2.0.0 + supports-color: 8.1.1 dev: true - /isexe/2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + /jest/28.1.3: + resolution: {integrity: sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 28.1.3 + '@jest/types': 28.1.3 + import-local: 3.1.0 + jest-cli: 28.1.3 + transitivePeerDependencies: + - '@types/node' + - supports-color + - ts-node dev: true /jose/4.14.4: @@ -3341,6 +4878,12 @@ packages: argparse: 2.0.1 dev: true + /jsesc/2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + dev: true + /json-buffer/3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} dev: true @@ -3353,6 +4896,10 @@ packages: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} dev: true + /json-schema-traverse/1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + dev: true + /json-stable-stringify-without-jsonify/1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} dev: true @@ -3364,6 +4911,16 @@ packages: minimist: 1.2.8 dev: true + /json5/2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /jsonc-parser/3.2.0: + resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + dev: true + /jsonfile/4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} optionalDependencies: @@ -3430,6 +4987,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /kleur/3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + dev: true + /kleur/4.1.5: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} @@ -3445,6 +5007,11 @@ packages: language-subtag-registry: 0.3.22 dev: true + /leven/3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + dev: true + /levn/0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -3562,6 +5129,12 @@ packages: yallist: 2.1.2 dev: true + /lru-cache/5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + dev: true + /lru-cache/6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} @@ -3575,6 +5148,26 @@ packages: pify: 3.0.0 dev: false + /make-dir/3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + dependencies: + semver: 6.3.1 + dev: true + + /make-dir/4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + dependencies: + semver: 7.5.4 + dev: true + + /makeerror/1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + dependencies: + tmpl: 1.0.5 + dev: true + /map-obj/1.0.1: resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} engines: {node: '>=0.10.0'} @@ -3585,9 +5178,14 @@ packages: engines: {node: '>=8'} dev: true + /md5-file/5.0.0: + resolution: {integrity: sha512-xbEFXCYVWrSx/gEKS1VPlg84h/4L20znVIulKw6kMfmBUAZNAnF00eczz9ICMl+/hjQGo5KSXRxbL/47X3rmMw==} + engines: {node: '>=10.13.0'} + hasBin: true + dev: true + /memory-pager/1.5.0: resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==} - dev: false /meow/6.1.1: resolution: {integrity: sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==} @@ -3679,14 +5277,47 @@ packages: /moment/2.29.4: resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==} - dev: false /mongodb-connection-string-url/2.6.0: resolution: {integrity: sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==} dependencies: '@types/whatwg-url': 8.2.2 whatwg-url: 11.0.0 - dev: false + + /mongodb-memory-server-core/8.9.3: + resolution: {integrity: sha512-z/UW/fHTDRA+qvcqBxibTonnwuxRPWsphO9BUGKvFweRxT9uj09/hCK96kjBdF9wQj6k7bj/Tqo9gkGG0XbDng==} + engines: {node: '>=12.22.0'} + dependencies: + '@types/tmp': 0.2.4 + async-mutex: 0.3.2 + camelcase: 6.3.0 + debug: 4.3.4 + find-cache-dir: 3.3.2 + get-port: 5.1.1 + https-proxy-agent: 5.0.1 + md5-file: 5.0.0 + mongodb: 4.9.1 + new-find-package-json: 2.0.0 + semver: 7.5.4 + tar-stream: 2.2.0 + tmp: 0.2.1 + tslib: 2.6.1 + uuid: 8.3.2 + yauzl: 2.10.0 + transitivePeerDependencies: + - supports-color + dev: true + + /mongodb-memory-server/8.9.3: + resolution: {integrity: sha512-k/1tbGmN6Xegj/XoSA4F/PpKpdRHyT/3HMldhGyiOXx8RNAkJdc/Q9N4+1pCK+HKHMk7BInbo42Bn4OUeAT+hw==} + engines: {node: '>=12.22.0'} + requiresBuild: true + dependencies: + mongodb-memory-server-core: 8.9.3 + tslib: 2.6.1 + transitivePeerDependencies: + - supports-color + dev: true /mongodb/4.13.0: resolution: {integrity: sha512-+taZ/bV8d1pYuHL4U+gSwkhmDrwkWbH1l4aah4YpmpscMwgFBkufIKxgP/G7m87/NUuQzc2Z75ZTI7ZOyqZLbw==} @@ -3702,6 +5333,18 @@ packages: - aws-crt dev: false + /mongodb/4.9.1: + resolution: {integrity: sha512-ZhgI/qBf84fD7sI4waZBoLBNJYPQN5IOC++SBCiPiyhzpNKOxN/fi0tBHvH2dEC42HXtNEbFB0zmNz4+oVtorQ==} + engines: {node: '>=12.9.0'} + dependencies: + bson: 4.7.2 + denque: 2.1.0 + mongodb-connection-string-url: 2.6.0 + socks: 2.7.1 + optionalDependencies: + saslprep: 1.0.3 + dev: true + /mongodb/5.6.0: resolution: {integrity: sha512-z8qVs9NfobHJm6uzK56XBZF8XwM9H294iRnB7wNjF0SnY93si5HPziIJn+qqvUR5QOff/4L0gCD6SShdR/GtVQ==} engines: {node: '>=14.20.1'} @@ -3722,7 +5365,6 @@ packages: socks: 2.7.1 optionalDependencies: saslprep: 1.0.3 - dev: false /ms/2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} @@ -3735,6 +5377,15 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true + /new-find-package-json/2.0.0: + resolution: {integrity: sha512-lDcBsjBSMlj3LXH2v/FW3txlh2pYTjmbOXPYJD93HI5EwuLzI11tdHSIpUMmfq/IOsldj4Ps8M8flhm+pCK4Ew==} + engines: {node: '>=12.22.0'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + /next-auth/4.22.1: resolution: {integrity: sha512-NTR3f6W7/AWXKw8GSsgSyQcDW6jkslZLH8AiZa5PQ09w1kR8uHtR9rez/E9gAq/o17+p0JYHE8QjF3RoniiObA==} peerDependencies: @@ -3780,6 +5431,14 @@ packages: uuid: 8.3.2 dev: false + /node-int64/0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + dev: true + + /node-releases/2.0.13: + resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} + dev: true + /nodemailer/6.9.3: resolution: {integrity: sha512-fy9v3NgTzBngrMFkDsKEj0r02U7jm6XfC3b52eoNV+GCrGj+s8pt5OqhiJdWKuw51zCTdiNR/IUD1z33LIIGpg==} engines: {node: '>=6.0.0'} @@ -3794,6 +5453,11 @@ packages: validate-npm-package-license: 3.0.4 dev: true + /normalize-path/3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + /normalize-url/6.1.0: resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} engines: {node: '>=10'} @@ -4055,7 +5719,10 @@ packages: /pend/1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} - dev: false + + /picocolors/1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true /picomatch/2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} @@ -4088,6 +5755,11 @@ packages: engines: {node: '>=0.10.0'} dev: false + /pirates/4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + dev: true + /pkg-dir/4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} @@ -4136,6 +5808,16 @@ packages: hasBin: true dev: true + /pretty-format/28.1.3: + resolution: {integrity: sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + dependencies: + '@jest/schemas': 28.1.3 + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 18.2.0 + dev: true + /pretty-format/3.8.0: resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==} dev: false @@ -4144,6 +5826,14 @@ packages: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} dev: false + /prompts/2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + dev: true + /prop-types/15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} dependencies: @@ -4178,7 +5868,6 @@ packages: decode-uri-component: 0.4.1 filter-obj: 5.1.0 split-on-first: 3.0.0 - dev: false /queue-microtask/1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -4198,6 +5887,10 @@ packages: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} dev: true + /react-is/18.2.0: + resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + dev: true + /read-pkg-up/7.0.1: resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} engines: {node: '>=8'} @@ -4279,6 +5972,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /require-from-string/2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + dev: true + /require-main-filename/2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} dev: true @@ -4287,6 +5985,13 @@ packages: resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} dev: true + /resolve-cwd/3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + dependencies: + resolve-from: 5.0.0 + dev: true + /resolve-from/4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -4297,6 +6002,11 @@ packages: engines: {node: '>=8'} dev: true + /resolve.exports/1.1.1: + resolution: {integrity: sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==} + engines: {node: '>=10'} + dev: true + /resolve/1.22.4: resolution: {integrity: sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==} hasBin: true @@ -4381,7 +6091,6 @@ packages: engines: {node: '>=6'} dependencies: sparse-bitfield: 3.0.3 - dev: false /seek-bzip/1.0.6: resolution: {integrity: sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==} @@ -4466,6 +6175,10 @@ packages: /signal-exit/3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + /sisteransi/1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + dev: true + /slash/3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -4474,7 +6187,6 @@ packages: /smart-buffer/4.2.0: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - dev: false /smartwrap/2.0.2: resolution: {integrity: sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==} @@ -4495,7 +6207,6 @@ packages: dependencies: ip: 2.0.0 smart-buffer: 4.2.0 - dev: false /sort-keys-length/1.0.1: resolution: {integrity: sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==} @@ -4511,6 +6222,18 @@ packages: is-plain-obj: 1.1.0 dev: true + /source-map-support/0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map/0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + /source-map/0.7.4: resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} engines: {node: '>= 8'} @@ -4520,7 +6243,6 @@ packages: resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==} dependencies: memory-pager: 1.5.0 - dev: false /spawndamnit/2.0.0: resolution: {integrity: sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==} @@ -4554,18 +6276,32 @@ packages: /split-on-first/3.0.0: resolution: {integrity: sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==} engines: {node: '>=12'} - dev: false /sprintf-js/1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} dev: true + /stack-utils/2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + dependencies: + escape-string-regexp: 2.0.0 + dev: true + /stream-transform/2.1.3: resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} dependencies: mixme: 0.5.9 dev: true + /string-length/4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + dev: true + /string-width/4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -4643,6 +6379,11 @@ packages: engines: {node: '>=4'} dev: true + /strip-bom/4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + dev: true + /strip-dirs/2.1.0: resolution: {integrity: sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==} dependencies: @@ -4703,6 +6444,21 @@ packages: has-flag: 4.0.0 dev: true + /supports-color/8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-hyperlinks/2.3.0: + resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + dev: true + /supports-preserve-symlinks-flag/1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} @@ -4721,11 +6477,39 @@ packages: xtend: 4.0.2 dev: false + /tar-stream/2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: true + /term-size/2.2.1: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} dev: true + /terminal-link/2.1.1: + resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} + engines: {node: '>=8'} + dependencies: + ansi-escapes: 4.3.2 + supports-hyperlinks: 2.3.0 + dev: true + + /test-exclude/6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + dev: true + /text-table/0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: true @@ -4741,10 +6525,26 @@ packages: os-tmpdir: 1.0.2 dev: true + /tmp/0.2.1: + resolution: {integrity: sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==} + engines: {node: '>=8.17.0'} + dependencies: + rimraf: 3.0.2 + dev: true + + /tmpl/1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + dev: true + /to-buffer/1.1.1: resolution: {integrity: sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==} dev: false + /to-fast-properties/2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + dev: true + /to-regex-range/5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -4765,7 +6565,6 @@ packages: engines: {node: '>=12'} dependencies: punycode: 2.3.0 - dev: false /trim-newlines/3.0.1: resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} @@ -4795,8 +6594,6 @@ packages: /tslib/2.6.1: resolution: {integrity: sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==} - dev: false - optional: true /tty-table/4.2.1: resolution: {integrity: sha512-xz0uKo+KakCQ+Dxj1D/tKn2FSyreSYWzdkL/BYhgN6oMW808g8QRMuh1atAV9fjTPbWBjfbkKQpI/5rEcnAc7g==} @@ -4819,6 +6616,11 @@ packages: prelude-ls: 1.2.1 dev: true + /type-detect/4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + dev: true + /type-fest/0.13.1: resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} engines: {node: '>=10'} @@ -4829,6 +6631,11 @@ packages: engines: {node: '>=10'} dev: true + /type-fest/0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + dev: true + /type-fest/0.6.0: resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} engines: {node: '>=8'} @@ -4903,6 +6710,17 @@ packages: engines: {node: '>= 10.0.0'} dev: false + /update-browserslist-db/1.0.13_browserslist@4.21.11: + resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.21.11 + escalade: 3.1.1 + picocolors: 1.0.0 + dev: true + /uri-js/4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: @@ -4915,13 +6733,21 @@ packages: /uuid/8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true - dev: false /uuid/9.0.0: resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} hasBin: true dev: false + /v8-to-istanbul/9.1.0: + resolution: {integrity: sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==} + engines: {node: '>=10.12.0'} + dependencies: + '@jridgewell/trace-mapping': 0.3.19 + '@types/istanbul-lib-coverage': 2.0.4 + convert-source-map: 1.9.0 + dev: true + /validate-npm-package-license/3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} dependencies: @@ -4929,6 +6755,12 @@ packages: spdx-expression-parse: 3.0.1 dev: true + /walker/1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + dependencies: + makeerror: 1.0.12 + dev: true + /wcwidth/1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} dependencies: @@ -4937,7 +6769,6 @@ packages: /webidl-conversions/7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} - dev: false /whatwg-url/11.0.0: resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} @@ -4945,7 +6776,6 @@ packages: dependencies: tr46: 3.0.0 webidl-conversions: 7.0.0 - dev: false /which-boxed-primitive/1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} @@ -5016,6 +6846,14 @@ packages: /wrappy/1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + /write-file-atomic/4.0.2: + resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + dev: true + /xtend/4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} @@ -5034,6 +6872,10 @@ packages: resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} dev: true + /yallist/3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: true + /yallist/4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} @@ -5090,7 +6932,6 @@ packages: dependencies: buffer-crc32: 0.2.13 fd-slicer: 1.1.0 - dev: false /yocto-queue/0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}