diff --git a/packages/_example/package.json b/packages/_example/package.json index 01305de0a6..0335b90394 100644 --- a/packages/_example/package.json +++ b/packages/_example/package.json @@ -23,7 +23,7 @@ "fastify2": "npm:fastify@^2.15.3", "koa": "^2.14.1", "mariadb": "^3.0.2", - "mongoose": "^7.0.1", + "mongoose": "8.8.4", "mysql2": "^3.0.1", "pg": "^8.8.0", "reflect-metadata": "^0.1.13", diff --git a/packages/datasource-mongo/package.json b/packages/datasource-mongo/package.json index c123b34490..970760c402 100644 --- a/packages/datasource-mongo/package.json +++ b/packages/datasource-mongo/package.json @@ -15,7 +15,7 @@ "@forestadmin/datasource-mongoose": "1.8.9", "@forestadmin/datasource-toolkit": "1.46.0", "json-stringify-pretty-compact": "^3.0.0", - "mongoose": "^7.0.1", + "mongoose": "8.8.4", "tunnel-ssh": "^5.2.0" }, "files": [ diff --git a/packages/datasource-mongo/test/create.integration.test.ts b/packages/datasource-mongo/test/create.integration.test.ts index 847827d339..bf78d7a705 100644 --- a/packages/datasource-mongo/test/create.integration.test.ts +++ b/packages/datasource-mongo/test/create.integration.test.ts @@ -32,9 +32,9 @@ describe('create', () => { it('should allow to create a new movie', async () => { const dataSource = await createDataSource(); - const movies = dataSource.collections.find(c => c.name === 'movies'); + const movies = dataSource.getCollection('movies'); - const created = await movies!.create(null as unknown as Caller, [{ title: 'Interstellar' }]); + const created = await movies.create(null as unknown as Caller, [{ title: 'Interstellar' }]); expect(created).toEqual([{ _id: expect.any(String), title: 'Interstellar' }]); }); diff --git a/packages/datasource-mongo/test/introspection/reference-candidates-verifier.unit.test.ts b/packages/datasource-mongo/test/introspection/reference-candidates-verifier.unit.test.ts index 83d65cbe43..1d93fccfb7 100644 --- a/packages/datasource-mongo/test/introspection/reference-candidates-verifier.unit.test.ts +++ b/packages/datasource-mongo/test/introspection/reference-candidates-verifier.unit.test.ts @@ -1,4 +1,3 @@ -import { randomUUID } from 'crypto'; import mongoose from 'mongoose'; import ReferenceCandidatesVerifier from '../../src/introspection/reference-candidates-verifier'; @@ -160,8 +159,8 @@ describe('Unit > Introspection > ReferenceCandidatesVerifier', () => { }); it('should detect matching ids when using binary type', async () => { - const publisherId1 = new Binary(randomUUID()); - const publisherId2 = new Binary(randomUUID()); + const publisherId1 = new Binary(mongoose.mongo.UUID.generate()); + const publisherId2 = new Binary(mongoose.mongo.UUID.generate()); const { connection } = setupCollectionMock({ publisher: [{ _id: publisherId1 }, { _id: publisherId2 }], }); @@ -186,8 +185,8 @@ describe('Unit > Introspection > ReferenceCandidatesVerifier', () => { publisher: [ { referenceSamples: new Set([ - new Binary(publisherId1.toString()), - new Binary(publisherId2.toString()), + new Binary(publisherId1.value()), + new Binary(publisherId2.value()), ]), isReferenceCandidate: true, seen: 2, diff --git a/packages/datasource-mongo/test/version-manager.unit.test.ts b/packages/datasource-mongo/test/version-manager.unit.test.ts index abc326b119..d4ca29f964 100644 --- a/packages/datasource-mongo/test/version-manager.unit.test.ts +++ b/packages/datasource-mongo/test/version-manager.unit.test.ts @@ -1,15 +1,7 @@ describe('VersionManager', () => { beforeEach(() => jest.resetModules()); - it('should return "ObjectID" for mongoose 6', () => { - jest.mock('mongoose', () => ({ version: '6.0.0' })); - // eslint-disable-next-line @typescript-eslint/no-var-requires,global-require - const VersionManager = require('../src/version-manager').default; - expect(VersionManager.ObjectIdTypeName).toEqual('ObjectID'); - }); - - it('should return "ObjectId" for mongoose 7', () => { - jest.mock('mongoose', () => ({ version: '7.0.0' })); + it('should dynamically return type name for current mongoose version', () => { // eslint-disable-next-line @typescript-eslint/no-var-requires,global-require const VersionManager = require('../src/version-manager').default; diff --git a/packages/datasource-mongoose/package.json b/packages/datasource-mongoose/package.json index 9f2c506548..52a129b725 100644 --- a/packages/datasource-mongoose/package.json +++ b/packages/datasource-mongoose/package.json @@ -20,10 +20,10 @@ "luxon": "^3.2.1" }, "devDependencies": { - "mongoose": "^7.0.1" + "mongoose": "8.8.4" }, "peerDependencies": { - "mongoose": "6.x || 7.x" + "mongoose": "6.x || 7.x || 8.x" }, "scripts": { "build": "tsc", diff --git a/packages/datasource-mongoose/src/mongoose/schema.ts b/packages/datasource-mongoose/src/mongoose/schema.ts index 998fe0743e..9d11083c85 100644 --- a/packages/datasource-mongoose/src/mongoose/schema.ts +++ b/packages/datasource-mongoose/src/mongoose/schema.ts @@ -4,6 +4,7 @@ import { Model, Schema, SchemaType } from 'mongoose'; import { Stack } from '../types'; import { recursiveDelete, recursiveSet } from '../utils/helpers'; +import VersionManager from '../utils/version-manager'; export type SchemaBranch = { [key: string]: SchemaNode }; export type SchemaNode = SchemaType | SchemaBranch; @@ -173,7 +174,7 @@ export default class MongooseSchema { // Exclude mixedFieldPattern $* and privateFieldPattern __ if (!name.startsWith('$*') && !name.includes('__') && (name !== '_id' || level === 0)) { // Flatten nested schemas and arrays - if (field.constructor.name === 'SubdocumentPath') { + if (VersionManager.isSubDocument(field)) { const subPaths = this.buildFields(field.schema as Schema, level + 1); for (const [subName, subField] of Object.entries(subPaths)) { @@ -185,8 +186,16 @@ export default class MongooseSchema { for (const [subName, subField] of Object.entries(subPaths)) { recursiveSet(paths, `${name}.[].${subName}`, subField); } - } else if (field.constructor.name === 'SchemaArray') { - recursiveSet(paths, `${name}.[]`, (field as any).caster); + } else if (VersionManager.isSubDocumentArray(field)) { + if (VersionManager.isSubDocument(field.caster)) { + const subPaths = this.buildFields((field as any).caster.schema, level + 1); + + for (const [subName, subField] of Object.entries(subPaths)) { + recursiveSet(paths, `${name}.[].${subName}`, subField); + } + } else { + recursiveSet(paths, `${name}.[]`, (field as any).caster); + } } else { recursiveSet(paths, name, field); } diff --git a/packages/datasource-mongoose/src/utils/version-manager.ts b/packages/datasource-mongoose/src/utils/version-manager.ts index f08fd20e03..81e03175e6 100644 --- a/packages/datasource-mongoose/src/utils/version-manager.ts +++ b/packages/datasource-mongoose/src/utils/version-manager.ts @@ -1,7 +1,20 @@ -import mongoose from 'mongoose'; +import mongoose, { Schema, SchemaType } from 'mongoose'; export default class VersionManager { - static readonly ObjectIdTypeName: 'ObjectId' | 'ObjectID' = mongoose.version.startsWith('6') - ? 'ObjectID' - : 'ObjectId'; + static readonly ObjectIdTypeName = mongoose.Schema.Types.ObjectId.schemaName; + + public static isSubDocument(field): field is Schema.Types.Subdocument { + return ( + field?.name === 'EmbeddedDocument' || + field?.constructor?.name === 'SubdocumentPath' || + (field?.instance === 'Embedded' && field instanceof SchemaType) + ); + } + + public static isSubDocumentArray(field): field is Schema.Types.DocumentArray { + return ( + (field?.instance === 'Array' || field?.instance === 'DocumentArray') && + field instanceof SchemaType + ); + } } diff --git a/packages/datasource-mongoose/test/utils/version-manager.test.ts b/packages/datasource-mongoose/test/utils/version-manager.test.ts index a5ec6776aa..6062969c72 100644 --- a/packages/datasource-mongoose/test/utils/version-manager.test.ts +++ b/packages/datasource-mongoose/test/utils/version-manager.test.ts @@ -1,15 +1,7 @@ describe('VersionManager', () => { beforeEach(() => jest.resetModules()); - it('should return "ObjectID" for mongoose 6', () => { - jest.mock('mongoose', () => ({ version: '6.0.0' })); - // eslint-disable-next-line @typescript-eslint/no-var-requires,global-require - const VersionManager = require('../../src/utils/version-manager').default; - expect(VersionManager.ObjectIdTypeName).toEqual('ObjectID'); - }); - - it('should return "ObjectId" for mongoose 7', () => { - jest.mock('mongoose', () => ({ version: '7.0.0' })); + it('should dynamically return type name for current mongoose version', () => { // eslint-disable-next-line @typescript-eslint/no-var-requires,global-require const VersionManager = require('../../src/utils/version-manager').default; diff --git a/yarn.lock b/yarn.lock index 8807594745..6394e2c9b4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2122,6 +2122,13 @@ dependencies: sparse-bitfield "^3.0.3" +"@mongodb-js/saslprep@^1.1.5": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz#e974bab8eca9faa88677d4ea4da8d09a52069004" + integrity sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw== + dependencies: + sparse-bitfield "^3.0.3" + "@nestjs/common@^9.2.1": version "9.4.3" resolved "https://registry.yarnpkg.com/@nestjs/common/-/common-9.4.3.tgz#f907c5315b4273f7675864a05c4dda7056632b87" @@ -4340,6 +4347,13 @@ resolved "https://registry.yarnpkg.com/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz#1306dbfa53768bcbcfc95a1c8cde367975581859" integrity sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA== +"@types/whatwg-url@^11.0.2": + version "11.0.5" + resolved "https://registry.yarnpkg.com/@types/whatwg-url/-/whatwg-url-11.0.5.tgz#aaa2546e60f0c99209ca13360c32c78caf2c409f" + integrity sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ== + dependencies: + "@types/webidl-conversions" "*" + "@types/whatwg-url@^8.2.1": version "8.2.2" resolved "https://registry.yarnpkg.com/@types/whatwg-url/-/whatwg-url-8.2.2.tgz#749d5b3873e845897ada99be4448041d4cc39e63" @@ -5314,10 +5328,10 @@ bson@^4.7.2: dependencies: buffer "^5.6.0" -bson@^5.5.0: - version "5.5.1" - resolved "https://registry.yarnpkg.com/bson/-/bson-5.5.1.tgz#f5849d405711a7f23acdda9a442375df858e6833" - integrity sha512-ix0EwukN2EpC0SRWIj/7B5+A6uQMQy6KMREI9qQqvgpkV2frH63T0UDVd1SYedL6dNCmDBYB3QtXi4ISk9YT+g== +bson@^6.7.0: + version "6.10.1" + resolved "https://registry.yarnpkg.com/bson/-/bson-6.10.1.tgz#dcd04703178f5ecf5b25de04edd2a95ec79385d3" + integrity sha512-P92xmHDQjSKPLHqFxefqMxASNq/aWJMEZugpCjf+AF/pgcUpMMQCg7t7+ewko0/u8AapvF3luf/FoehddEK+sA== buffer-equal-constant-time@1.0.1: version "1.0.1" @@ -9979,10 +9993,10 @@ jwt-decode@2.2.0: resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-2.2.0.tgz#7d86bd56679f58ce6a84704a657dd392bba81a79" integrity sha512-86GgN2vzfUu7m9Wcj63iUkuDzFNYFVmjeDm2GzWpUk+opB0pEpMsw6ePCMrhYkumz2C1ihqtZzOMAg7FiXcNoQ== -kareem@2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.5.1.tgz#7b8203e11819a8e77a34b3517d3ead206764d15d" - integrity sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA== +kareem@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.6.3.tgz#23168ec8ffb6c1abfd31b7169a6fb1dd285992ac" + integrity sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q== keygrip@~1.1.0: version "1.1.0" @@ -11295,6 +11309,14 @@ mongodb-connection-string-url@^2.6.0: "@types/whatwg-url" "^8.2.1" whatwg-url "^11.0.0" +mongodb-connection-string-url@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz#c13e6ac284ae401752ebafdb8cd7f16c6723b141" + integrity sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg== + dependencies: + "@types/whatwg-url" "^11.0.2" + whatwg-url "^13.0.0" + mongodb@4.17.2: version "4.17.2" resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-4.17.2.tgz#237c0534e36a3449bd74c6bf6d32f87a1ca7200c" @@ -11307,29 +11329,27 @@ mongodb@4.17.2: "@aws-sdk/credential-providers" "^3.186.0" "@mongodb-js/saslprep" "^1.1.0" -mongodb@5.9.2: - version "5.9.2" - resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-5.9.2.tgz#39a73b9fbc87ac9d9c1aaf8aab5c5bb69e2b913e" - integrity sha512-H60HecKO4Bc+7dhOv4sJlgvenK4fQNqqUIlXxZYQNbfEWSALGAwGoyJd/0Qwk4TttFXUOHJ2ZJQe/52ScaUwtQ== +mongodb@~6.10.0: + version "6.10.0" + resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-6.10.0.tgz#20a9f1cf3c6829e75fc39e6d8c1c19f164209c2e" + integrity sha512-gP9vduuYWb9ZkDM546M+MP2qKVk5ZG2wPF63OvSRuUbqCR+11ZCAE1mOfllhlAG0wcoJY5yDL/rV3OmYEwXIzg== dependencies: - bson "^5.5.0" - mongodb-connection-string-url "^2.6.0" - socks "^2.7.1" - optionalDependencies: - "@mongodb-js/saslprep" "^1.1.0" + "@mongodb-js/saslprep" "^1.1.5" + bson "^6.7.0" + mongodb-connection-string-url "^3.0.0" -mongoose@^7.0.1: - version "7.8.3" - resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-7.8.3.tgz#d6d3305268fc93a425c4a5f41478b0c1771a5b1c" - integrity sha512-eFnbkKgyVrICoHB6tVJ4uLanS7d5AIo/xHkEbQeOv6g2sD7gh/1biRwvFifsmbtkIddQVNr3ROqHik6gkknN3g== +mongoose@8.8.4: + version "8.8.4" + resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-8.8.4.tgz#11e3991a7fd03596a79bc9f9b2fe8f3e75b7a30d" + integrity sha512-yJbn695qCsqDO+xyPII29x2R7flzXhxCDv09mMZPSGllf0sm4jKw3E9s9uvQ9hjO6bL2xjU8KKowYqcY9eSTMQ== dependencies: - bson "^5.5.0" - kareem "2.5.1" - mongodb "5.9.2" + bson "^6.7.0" + kareem "2.6.3" + mongodb "~6.10.0" mpath "0.9.0" mquery "5.0.0" ms "2.1.3" - sift "16.0.1" + sift "17.1.3" mpath@0.9.0: version "0.9.0" @@ -13166,7 +13186,7 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" -punycode@2.x.x, punycode@^2.1.0, punycode@^2.1.1: +punycode@2.x.x, punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== @@ -14032,10 +14052,10 @@ side-channel@^1.0.6: get-intrinsic "^1.2.4" object-inspect "^1.13.1" -sift@16.0.1: - version "16.0.1" - resolved "https://registry.yarnpkg.com/sift/-/sift-16.0.1.tgz#e9c2ccc72191585008cf3e36fc447b2d2633a053" - integrity sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ== +sift@17.1.3: + version "17.1.3" + resolved "https://registry.yarnpkg.com/sift/-/sift-17.1.3.tgz#9d2000d4d41586880b0079b5183d839c7a142bf7" + integrity sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ== signal-exit@3.0.7, signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" @@ -14852,6 +14872,13 @@ tr46@^3.0.0: dependencies: punycode "^2.1.1" +tr46@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-4.1.1.tgz#281a758dcc82aeb4fe38c7dfe4d11a395aac8469" + integrity sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw== + dependencies: + punycode "^2.3.0" + tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -15555,6 +15582,14 @@ whatwg-url@^11.0.0: tr46 "^3.0.0" webidl-conversions "^7.0.0" +whatwg-url@^13.0.0: + version "13.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-13.0.0.tgz#b7b536aca48306394a34e44bda8e99f332410f8f" + integrity sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig== + dependencies: + tr46 "^4.1.1" + webidl-conversions "^7.0.0" + whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"