From 14afc12c67a2fa4d9d5fc2dd7bd5b7ef795664dc Mon Sep 17 00:00:00 2001 From: hasezoey Date: Mon, 14 Oct 2019 21:05:39 +0200 Subject: [PATCH 1/8] Update Dependencies --- package-lock.json | 12 ++++++------ package.json | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index ab8ae9eba..8519e9433 100644 --- a/package-lock.json +++ b/package-lock.json @@ -598,9 +598,9 @@ "dev": true }, "coveralls": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.6.tgz", - "integrity": "sha512-Pgh4v3gCI4T/9VijVrm8Ym5v0OgjvGLKj3zTUwkvsCiwqae/p6VLzpsFNjQS2i6ewV7ef+DjFJ5TSKxYt/mCrA==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.7.tgz", + "integrity": "sha512-mUuH2MFOYB2oBaA4D4Ykqi9LaEYpMMlsiOMJOrv358yAjP6enPIk55fod2fNJ8AvwoYXStWQls37rA+s5e7boA==", "dev": true, "requires": { "growl": "~> 1.10.0", @@ -2014,9 +2014,9 @@ } }, "mongoose": { - "version": "5.7.4", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.7.4.tgz", - "integrity": "sha512-IgqQS5HIaZ8tG2cib6QllfIw2Wc/A0QVOsdKLsSqRolqJFWOjI0se3vsKXLNkbEcuJ1xziW3e/jPhBs65678Hg==", + "version": "5.7.5", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.7.5.tgz", + "integrity": "sha512-BZ4FxtnbTurc/wcm/hLltLdI4IDxo4nsE0D9q58YymTdZwreNzwO62CcjVtaHhmr8HmJtOInp2W/T12FZaMf8g==", "dev": true, "requires": { "bson": "~1.1.1", diff --git a/package.json b/package.json index c14a4f9a6..5a72a3d77 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ ], "license": "MIT", "peerDependencies": { - "mongoose": "^5.7.4" + "mongoose": "^5.7.5" }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^0.1.3", @@ -45,10 +45,10 @@ "@types/node": "^8.10.53", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", - "coveralls": "^3.0.6", + "coveralls": "^3.0.7", "mocha": "^6.2.1", "mongodb-memory-server-global": "^5.2.8", - "mongoose": "^5.7.4", + "mongoose": "^5.7.5", "mongoose-findorcreate": "^3.0.0", "nyc": "^14.1.1", "prettier": "^1.18.2", From a1a91fdffe358e599d79431c82417d8701d52f38 Mon Sep 17 00:00:00 2001 From: hasezoey Date: Mon, 14 Oct 2019 21:48:10 +0200 Subject: [PATCH 2/8] WIP --- src/internal/utils.ts | 47 ++++++++++++++++++++++++ src/prop.ts | 3 +- src/types.ts | 18 +++++++++ test/index.test.ts | 3 ++ test/models/arrayValidators.ts | 29 +++++++++++++++ test/tests/arrayValidator.test.ts | 61 +++++++++++++++++++++++++++++++ 6 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 test/models/arrayValidators.ts create mode 100644 test/tests/arrayValidator.test.ts diff --git a/src/internal/utils.ts b/src/internal/utils.ts index c72ff2cbf..9172a6dcd 100644 --- a/src/internal/utils.ts +++ b/src/internal/utils.ts @@ -1,6 +1,7 @@ import * as mongoose from 'mongoose'; import { isNullOrUndefined } from 'util'; +import { logger } from '../logSettings'; import { AnyParamConstructor, IModelOptions, @@ -287,3 +288,49 @@ export function createUniqueID(cl: any) { return false; } + +/** + * Map Options to "inner" & "outer" + * -> inner: means inner of "type: [{here})" + * -> outer: means outer of "type: [{}], here" + * @param rawOptions The raw options + * @param Type The Type of the array + */ +export function mapArrayOptions(rawOptions: any, Type: AnyParamConstructor): mongoose.SchemaTypeOpts { + if (getName(Type) in mongoose.Schema.Types) { + logger.info('Converting %s to mongoose Type', getName(Type)); + Type = mongoose.Schema.Types[getName(Type)]; + } + + const options = Object.assign({}, rawOptions); // for sanity + + delete options.items; + + const returnObject = { + type: [{ + type: Type + }] + }; + + // TODO: get answer to https://github.com/Automattic/mongoose/issues/8012#issuecomment-541868507 + + // @ts-ignore + if (Type.prototype.OptionsConstructor instanceof mongoose.SchemaTypeOptions) { + for (const [key, value] of Object.entries(options)) { + logger.debug('HI', key, value); + if (key in Type.prototype.OptionsConstructor) { + logger.debug('Value is in OC:', key); + returnObject.type[0][key] = value; + } else { + logger.debug('Value is not in OC:', key); + returnObject[key] = value; + } + } + + logger.debug('final obj', returnObject); + } else { + logger.debug('NOPE'); + } + + return returnObject; +} diff --git a/src/prop.ts b/src/prop.ts index 192750501..883db752e 100644 --- a/src/prop.ts +++ b/src/prop.ts @@ -235,8 +235,7 @@ export function _buildPropMetadata(input: DecoratedPropertyMetadata) { case WhatIsIt.ARRAY: schemas.get(name)[key] = { ...schemas.get(name)[key][0], - ...options, - type: [Type] + ...utils.mapArrayOptions(rawOptions, Type) }; return; diff --git a/src/types.ts b/src/types.ts index f01418bea..aabcc7c83 100644 --- a/src/types.ts +++ b/src/types.ts @@ -243,6 +243,24 @@ export interface ArrayPropOptions extends BasePropOptions { itemsRefPath?: any; /** Same as {@link PropOptions.refType}, only that it is for an array */ itemsRefType?: RefSchemaType; + /** + * Use this to define inner-options + * Use this if the auto-mapping is not correct + * + * Please open a new issue if some option is mismatched or not existing / mapped + */ + innerOptions?: { + [key: string]: any; + }; + /** + * Use this to define outer-options + * Use this if the auto-mapping is not correct + * + * Please open a new issue if some option is mismatched or not existing / mapped + */ + outerOptions?: { + [key: string]: any; + }; } export interface MapPropOptions extends BasePropOptions { diff --git a/test/index.test.ts b/test/index.test.ts index 154572e16..68c2766f5 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -1,6 +1,7 @@ import { use } from 'chai'; import * as cap from 'chai-as-promised'; +import { suite as ArrayValidatorTests } from './tests/arrayValidator.test'; import { suite as BigUserTest } from './tests/biguser.test'; import { suite as customNameTests } from './tests/customName.test'; import { suite as IndexTests } from './tests/dbIndex.test'; @@ -36,6 +37,8 @@ describe('Typegoose', () => { describe('String Validators', StringValidatorTests.bind(this)); + describe.only('Array Validators', ArrayValidatorTests.bind(this)); + describe('getClassForDocument()', GCFDTest.bind(this)); describe('Should Error', ErrorTests.bind(this)); diff --git a/test/models/arrayValidators.ts b/test/models/arrayValidators.ts new file mode 100644 index 000000000..5dc3e3ef2 --- /dev/null +++ b/test/models/arrayValidators.ts @@ -0,0 +1,29 @@ +import { logger } from '../../src/logSettings'; +import { arrayProp, getModelForClass } from '../../src/typegoose'; + +logger.setLevel('DEBUG'); + +export class ArrayValidators { + @arrayProp({ items: String, maxlength: 3 }) + public maxLength: string[]; + + @arrayProp({ items: String, minlength: 10 }) + public minLength: string[]; + + @arrayProp({ items: String, trim: true }) + public trimmed: string[]; + + @arrayProp({ items: String, uppercase: true }) + public uppercased: string[]; + + @arrayProp({ items: String, lowercase: true }) + public lowercased: string[]; + + @arrayProp({ items: String, enum: ['one', 'two', 'three'] }) + public enumed: string[]; + + @arrayProp({ items: String, default: ['hello'], lowercase: true }) + public defaulted: string[]; +} + +export const model = getModelForClass(ArrayValidators); diff --git a/test/tests/arrayValidator.test.ts b/test/tests/arrayValidator.test.ts new file mode 100644 index 000000000..0047bbef2 --- /dev/null +++ b/test/tests/arrayValidator.test.ts @@ -0,0 +1,61 @@ +import { expect } from 'chai'; +import * as mongoose from 'mongoose'; + +import { model as ArrayValidators } from '../models/arrayValidators'; + +/** + * Function to pass into describe + * ->Important: you need to always bind this + * @example + * ``` + * import { suite as StringValidatorTests } from './stringValidator.test' + * ... + * describe('String Validators', StringValidatorTests.bind(this)); + * ... + * ``` + */ +export function suite() { + it('should respect maxlength', (done) => { + expect(ArrayValidators.create({ + maxLength: ['this is too long'] + })).to.eventually.rejectedWith(mongoose.Error.ValidationError).and.notify(done); + }); + + it('should respect minlength', (done) => { + expect(ArrayValidators.create({ + minLength: ['too short'] + })).to.eventually.rejectedWith(mongoose.Error.ValidationError).and.notify(done); + }); + + it('should trim', async () => { + const trimmed = await ArrayValidators.create({ + trimmed: ['trim my end '] + }); + expect(trimmed.trimmed[0]).equals('trim my end'); + }); + + it('should uppercase', async () => { + const uppercased = await ArrayValidators.create({ + uppercased: ['make me uppercase'] + }); + expect(uppercased.uppercased[0]).equals('MAKE ME UPPERCASE'); + }); + + it('should lowercase', async () => { + const lowercased = await ArrayValidators.create({ + lowercased: ['MAKE ME LOWERCASE'] + }); + expect(lowercased.lowercased[0]).equals('make me lowercase'); + }); + + it('should respect enum', (done) => { + expect(ArrayValidators.create({ + enumed: ['not in the enum'] + })).to.eventually.rejectedWith(mongoose.Error).and.notify(done); + }); + + it('should lowercase & have a default', async () => { + const defaulted = await ArrayValidators.create({}); + expect(defaulted.defaulted[0]).equals('hello'); + }); +} From ab29c38a1cff5f3abbd4d5c01b8bc96180a5ca32 Mon Sep 17 00:00:00 2001 From: hasezoey Date: Fri, 18 Oct 2019 00:15:44 +0200 Subject: [PATCH 3/8] Implement using the "OptionsConstructor" for array options --- src/internal/utils.ts | 11 ++++++----- test/index.test.ts | 2 +- test/test.ts | 15 +++++++++++++++ 3 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 test/test.ts diff --git a/src/internal/utils.ts b/src/internal/utils.ts index 9172a6dcd..9a21559cb 100644 --- a/src/internal/utils.ts +++ b/src/internal/utils.ts @@ -300,6 +300,8 @@ export function mapArrayOptions(rawOptions: any, Type: AnyParamConstructor) if (getName(Type) in mongoose.Schema.Types) { logger.info('Converting %s to mongoose Type', getName(Type)); Type = mongoose.Schema.Types[getName(Type)]; + } else if (isNullOrUndefined(Type.prototype.OptionsConstructor)) { + throw new TypeError('Type does not have an valid "OptionsConstructor"!'); } const options = Object.assign({}, rawOptions); // for sanity @@ -312,13 +314,12 @@ export function mapArrayOptions(rawOptions: any, Type: AnyParamConstructor) }] }; - // TODO: get answer to https://github.com/Automattic/mongoose/issues/8012#issuecomment-541868507 - - // @ts-ignore - if (Type.prototype.OptionsConstructor instanceof mongoose.SchemaTypeOptions) { + // "mongoose as any" is because the types package does not yet have an entry for "SchemaTypeOptions" + if (Type.prototype.OptionsConstructor.prototype instanceof (mongoose as any).SchemaTypeOptions) { for (const [key, value] of Object.entries(options)) { logger.debug('HI', key, value); - if (key in Type.prototype.OptionsConstructor) { + logger.debug('Type is', Type.name); + if (Object.getOwnPropertyNames(Type.prototype.OptionsConstructor.prototype).includes(key)) { logger.debug('Value is in OC:', key); returnObject.type[0][key] = value; } else { diff --git a/test/index.test.ts b/test/index.test.ts index 68c2766f5..6d3f0a104 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -37,7 +37,7 @@ describe('Typegoose', () => { describe('String Validators', StringValidatorTests.bind(this)); - describe.only('Array Validators', ArrayValidatorTests.bind(this)); + describe('Array Validators', ArrayValidatorTests.bind(this)); describe('getClassForDocument()', GCFDTest.bind(this)); diff --git a/test/test.ts b/test/test.ts new file mode 100644 index 000000000..2baf1b84a --- /dev/null +++ b/test/test.ts @@ -0,0 +1,15 @@ +import { use } from 'chai'; +import * as cap from 'chai-as-promised'; + +import { suite as ArrayValidatorTests } from './tests/arrayValidator.test'; + +import { connect, disconnect } from './utils/mongooseConnect'; + +use(cap); + +describe('Typegoose', () => { + before(connect); + after(disconnect); + + describe('Array Validators', ArrayValidatorTests.bind(this)); +}); From 8f47131389ab8d02f6e823252b5fa4fe0807964e Mon Sep 17 00:00:00 2001 From: hasezoey Date: Fri, 18 Oct 2019 00:30:26 +0200 Subject: [PATCH 4/8] Add SemVer to check mongoose version - logger cleanup - add semver as package to check mongoose version --- package-lock.json | 57 ++++++++++++++++++++++++++++++++++++++++--- package.json | 4 ++- src/internal/utils.ts | 16 ++++++------ src/typegoose.ts | 5 ++++ 4 files changed, 70 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8519e9433..e7b722fa4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -196,6 +196,12 @@ "integrity": "sha512-kaYyLYf6ICn6/isAyD4K1MyWWd5Q3JgH6bnMN089LUx88+s4W8GvK9Q6JMBVu5vsFFp7pMdSxdKmlBXwH/VFRg==", "dev": true }, + "@types/semver": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-6.0.2.tgz", + "integrity": "sha512-G1Ggy7/9Nsa1Jt2yiBR2riEuyK2DFNnqow6R7cromXPMNynackRY1vqFTLz/gwnef1LHokbXThcPhqMRjUbkpQ==", + "dev": true + }, "agent-base": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", @@ -643,6 +649,14 @@ "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "dashdash": { @@ -1723,6 +1737,12 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true } } }, @@ -2132,6 +2152,14 @@ "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "npm-run-path": { @@ -2210,6 +2238,14 @@ "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "execa": { @@ -2926,6 +2962,14 @@ "requires": { "resolve-from": "^2.0.0", "semver": "^5.1.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "resolve": { @@ -2990,10 +3034,9 @@ } }, "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", - "dev": true + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" }, "set-blocking": { "version": "2.0.0", @@ -3431,6 +3474,12 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==", "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true } } }, diff --git a/package.json b/package.json index 5a72a3d77..e05cc444e 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "@types/mocha": "^5.2.7", "@types/mongoose": "^5.5.20", "@types/node": "^8.10.53", + "@types/semver": "^6.0.2", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", "coveralls": "^3.0.7", @@ -62,7 +63,8 @@ }, "dependencies": { "loglevel": "^1.6.4", - "reflect-metadata": "^0.1.13" + "reflect-metadata": "^0.1.13", + "semver": "^6.3.0" }, "publishConfig": { "access": "public" diff --git a/src/internal/utils.ts b/src/internal/utils.ts index 9a21559cb..582a0c60b 100644 --- a/src/internal/utils.ts +++ b/src/internal/utils.ts @@ -317,21 +317,23 @@ export function mapArrayOptions(rawOptions: any, Type: AnyParamConstructor) // "mongoose as any" is because the types package does not yet have an entry for "SchemaTypeOptions" if (Type.prototype.OptionsConstructor.prototype instanceof (mongoose as any).SchemaTypeOptions) { for (const [key, value] of Object.entries(options)) { - logger.debug('HI', key, value); - logger.debug('Type is', Type.name); + // logger.debug('HI', key, value); + // logger.debug('Type is', Type.name); if (Object.getOwnPropertyNames(Type.prototype.OptionsConstructor.prototype).includes(key)) { - logger.debug('Value is in OC:', key); + // logger.debug('Value is in OC:', key); returnObject.type[0][key] = value; } else { - logger.debug('Value is not in OC:', key); + // logger.debug('Value is not in OC:', key); returnObject[key] = value; } } - logger.debug('final obj', returnObject); - } else { + // logger.debug('final obj', returnObject); + } /* else { logger.debug('NOPE'); - } + } */ + + logger.debug('Final mapped Options for Type "%s"', getName(Type), returnObject); return returnObject; } diff --git a/src/typegoose.ts b/src/typegoose.ts index 723835f96..a94fe7b1b 100644 --- a/src/typegoose.ts +++ b/src/typegoose.ts @@ -1,8 +1,13 @@ /* imports */ import * as mongoose from 'mongoose'; import 'reflect-metadata'; +import * as semver from 'semver'; import { deprecate, isNullOrUndefined } from 'util'; +if (semver.lt(mongoose.version, '5.7.5')) { + throw new Error('Please use mongoose 5.7.5 or higher'); +} + import * as defaultClasses from './defaultClasses'; import { DecoratorKeys } from './internal/constants'; import { constructors, models } from './internal/data'; From db48288be6b2231a885655d44ecce0469fea4b15 Mon Sep 17 00:00:00 2001 From: hasezoey Date: Mon, 21 Oct 2019 23:50:26 +0200 Subject: [PATCH 5/8] Update dependencies - upgrade mongoose to 5.7.6 --- package-lock.json | 78 ++++++++++++++++++++++++++++++++++++----------- package.json | 8 ++--- src/typegoose.ts | 4 +-- 3 files changed, 66 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index b3c7608fb..49f6f6c13 100644 --- a/package-lock.json +++ b/package-lock.json @@ -181,9 +181,9 @@ } }, "@types/mongoose": { - "version": "5.5.20", - "resolved": "https://registry.npmjs.org/@types/mongoose/-/mongoose-5.5.20.tgz", - "integrity": "sha512-vaLVDjfuNp2LMfqHGMss4hN/K9puZfql/Rh6yXFvJvex3jKP646CXtvSKT8FM9uOUb2P4me266fmpPovBhEJXQ==", + "version": "5.5.22", + "resolved": "https://registry.npmjs.org/@types/mongoose/-/mongoose-5.5.22.tgz", + "integrity": "sha512-1AXWXzpt7MZTxsm0cg2Nd6vkZHtKF5poHESJAIp31AKDxN6YXTThg1LRUmKC9tIsdKHD+y8v2KeoO/sZeR/+OQ==", "dev": true, "requires": { "@types/mongodb": "*", @@ -905,9 +905,9 @@ } }, "es-abstract": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.14.2.tgz", - "integrity": "sha512-DgoQmbpFNOofkjJtKwr87Ma5EW4Dc8fWhD0R+ndq7Oc456ivUfGOOP6oAZTTKl5/CcNMP+EN+e3/iUzgE0veZg==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz", + "integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==", "dev": true, "requires": { "es-to-primitive": "^1.2.0", @@ -918,8 +918,8 @@ "is-regex": "^1.0.4", "object-inspect": "^1.6.0", "object-keys": "^1.1.1", - "string.prototype.trimleft": "^2.0.0", - "string.prototype.trimright": "^2.0.0" + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" } }, "es-to-primitive": { @@ -1347,9 +1347,9 @@ "dev": true }, "is-buffer": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", - "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", "dev": true }, "is-callable": { @@ -1773,6 +1773,13 @@ "integrity": "sha512-UC0qFwyAjn4YdPpKaDNw6gNxRf7Mcx7jC1UGCY4boCzgvU2Aoc1mOGzTtrjjLKhM5ivsnhoKpQVxKPp+1j1qwg==", "dev": true }, + "memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "dev": true, + "optional": true + }, "merge-source-map": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", @@ -1838,9 +1845,9 @@ } }, "mocha": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.1.tgz", - "integrity": "sha512-VCcWkLHwk79NYQc8cxhkmI8IigTIhsCwZ6RTxQsqK6go4UvEhzJkYuHm8B2YtlSxcYq2fY+ucr4JBwoD6ci80A==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.2.tgz", + "integrity": "sha512-FgDS9Re79yU1xz5d+C4rv1G7QagNGHZ+iXF81hO8zY35YZZcLEsJVfFolfsqKFWunATEvNzMK0r/CwWd/szO9A==", "dev": true, "requires": { "ansi-colors": "3.2.3", @@ -1904,6 +1911,7 @@ "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.3.2.tgz", "integrity": "sha512-fqJt3iywelk4yKu/lfwQg163Bjpo5zDKhXiohycvon4iQHbrfflSAz9AIlRE6496Pm/dQKQK5bMigdVo2s6gBg==", "dev": true, + "optional": true, "requires": { "bson": "^1.1.1", "require_optional": "^1.0.1", @@ -2034,14 +2042,14 @@ } }, "mongoose": { - "version": "5.7.5", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.7.5.tgz", - "integrity": "sha512-BZ4FxtnbTurc/wcm/hLltLdI4IDxo4nsE0D9q58YymTdZwreNzwO62CcjVtaHhmr8HmJtOInp2W/T12FZaMf8g==", + "version": "5.7.6", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.7.6.tgz", + "integrity": "sha512-2r87HmQMDCeZocoFmYGnJSpCW9ut95iQyPUcseG2B6EiAJjJBmR3pA01QyDF2+zQWpA8Ui4wH7xOq05U1nF6wg==", "dev": true, "requires": { "bson": "~1.1.1", "kareem": "2.3.1", - "mongodb": "3.3.2", + "mongodb": "3.3.3", "mongoose-legacy-pluralize": "1.0.2", "mpath": "0.6.0", "mquery": "3.2.2", @@ -2050,6 +2058,20 @@ "safe-buffer": "5.1.2", "sift": "7.0.1", "sliced": "1.0.1" + }, + "dependencies": { + "mongodb": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.3.3.tgz", + "integrity": "sha512-MdRnoOjstmnrKJsK8PY0PjP6fyF/SBS4R8coxmhsfEU7tQ46/J6j+aSHF2n4c2/H8B+Hc/Klbfp8vggZfI0mmA==", + "dev": true, + "requires": { + "bson": "^1.1.1", + "require_optional": "^1.0.1", + "safe-buffer": "^5.1.2", + "saslprep": "^1.0.0" + } + } } }, "mongoose-findorcreate": { @@ -3024,6 +3046,16 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "dev": true, + "optional": true, + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, "seek-bzip": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", @@ -3112,6 +3144,16 @@ } } }, + "sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", + "dev": true, + "optional": true, + "requires": { + "memory-pager": "^1.0.2" + } + }, "spawn-wrap": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.2.tgz", diff --git a/package.json b/package.json index 06a304e75..d6ea6a11d 100644 --- a/package.json +++ b/package.json @@ -34,22 +34,22 @@ ], "license": "MIT", "peerDependencies": { - "mongoose": "^5.7.5" + "mongoose": "^5.7.6" }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^0.1.3", "@types/chai": "^4.2.3", "@types/chai-as-promised": "^7.1.2", "@types/mocha": "^5.2.7", - "@types/mongoose": "^5.5.20", + "@types/mongoose": "^5.5.22", "@types/node": "^8.10.53", "@types/semver": "^6.0.2", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", "coveralls": "^3.0.7", - "mocha": "^6.2.1", + "mocha": "^6.2.2", "mongodb-memory-server-global": "^5.2.8", - "mongoose": "^5.7.5", + "mongoose": "^5.7.6", "mongoose-findorcreate": "^3.0.0", "nyc": "^14.1.1", "prettier": "^1.18.2", diff --git a/src/typegoose.ts b/src/typegoose.ts index a94fe7b1b..7fe2ac0c8 100644 --- a/src/typegoose.ts +++ b/src/typegoose.ts @@ -4,8 +4,8 @@ import 'reflect-metadata'; import * as semver from 'semver'; import { deprecate, isNullOrUndefined } from 'util'; -if (semver.lt(mongoose.version, '5.7.5')) { - throw new Error('Please use mongoose 5.7.5 or higher'); +if (semver.lt(mongoose.version, '5.7.6')) { + throw new Error('Please use mongoose 5.7.6 or higher'); } import * as defaultClasses from './defaultClasses'; From 1b0b488da0a9c2ba7abae1e373d6b496644eebf4 Mon Sep 17 00:00:00 2001 From: hasezoey Date: Mon, 21 Oct 2019 23:56:40 +0200 Subject: [PATCH 6/8] Cleanup --- src/internal/utils.ts | 12 +++--------- test/models/arrayValidators.ts | 3 +-- test/models/stringValidators.ts | 2 ++ test/test.ts | 15 --------------- test/tests/arrayValidator.test.ts | 2 ++ test/tests/stringValidator.test.ts | 2 ++ 6 files changed, 10 insertions(+), 26 deletions(-) delete mode 100644 test/test.ts diff --git a/src/internal/utils.ts b/src/internal/utils.ts index ee718bcd3..1defa0c25 100644 --- a/src/internal/utils.ts +++ b/src/internal/utils.ts @@ -324,21 +324,15 @@ export function mapArrayOptions(rawOptions: any, Type: AnyParamConstructor) // "mongoose as any" is because the types package does not yet have an entry for "SchemaTypeOptions" if (Type.prototype.OptionsConstructor.prototype instanceof (mongoose as any).SchemaTypeOptions) { for (const [key, value] of Object.entries(options)) { - // logger.debug('HI', key, value); - // logger.debug('Type is', Type.name); if (Object.getOwnPropertyNames(Type.prototype.OptionsConstructor.prototype).includes(key)) { - // logger.debug('Value is in OC:', key); returnObject.type[0][key] = value; } else { - // logger.debug('Value is not in OC:', key); returnObject[key] = value; } } - - // logger.debug('final obj', returnObject); - } /* else { - logger.debug('NOPE'); - } */ + } else { + logger.info('The Type "%s" does not have an OptionsConstructor', getName(Type)); + } logger.debug('Final mapped Options for Type "%s"', getName(Type), returnObject); diff --git a/test/models/arrayValidators.ts b/test/models/arrayValidators.ts index 5dc3e3ef2..12f94733f 100644 --- a/test/models/arrayValidators.ts +++ b/test/models/arrayValidators.ts @@ -1,7 +1,6 @@ -import { logger } from '../../src/logSettings'; import { arrayProp, getModelForClass } from '../../src/typegoose'; -logger.setLevel('DEBUG'); +// Please try to keep this file in sync with ./stringValidators.ts export class ArrayValidators { @arrayProp({ items: String, maxlength: 3 }) diff --git a/test/models/stringValidators.ts b/test/models/stringValidators.ts index 1112591c6..1e1935f34 100644 --- a/test/models/stringValidators.ts +++ b/test/models/stringValidators.ts @@ -1,5 +1,7 @@ import { getModelForClass, prop } from '../../src/typegoose'; +// Please try to keep this file in sync with ./arrayValidators.ts + export class StringValidators { @prop({ maxlength: 3 }) public maxLength: string; diff --git a/test/test.ts b/test/test.ts deleted file mode 100644 index 2baf1b84a..000000000 --- a/test/test.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { use } from 'chai'; -import * as cap from 'chai-as-promised'; - -import { suite as ArrayValidatorTests } from './tests/arrayValidator.test'; - -import { connect, disconnect } from './utils/mongooseConnect'; - -use(cap); - -describe('Typegoose', () => { - before(connect); - after(disconnect); - - describe('Array Validators', ArrayValidatorTests.bind(this)); -}); diff --git a/test/tests/arrayValidator.test.ts b/test/tests/arrayValidator.test.ts index 0047bbef2..1e2bd0dc1 100644 --- a/test/tests/arrayValidator.test.ts +++ b/test/tests/arrayValidator.test.ts @@ -3,6 +3,8 @@ import * as mongoose from 'mongoose'; import { model as ArrayValidators } from '../models/arrayValidators'; +// Please try to keep this file in sync with ./stringValidator.test.ts + /** * Function to pass into describe * ->Important: you need to always bind this diff --git a/test/tests/stringValidator.test.ts b/test/tests/stringValidator.test.ts index 4e8dc4af5..1fc442e28 100644 --- a/test/tests/stringValidator.test.ts +++ b/test/tests/stringValidator.test.ts @@ -3,6 +3,8 @@ import * as mongoose from 'mongoose'; import { model as StringValidators } from '../models/stringValidators'; +// Please try to keep this file in sync with ./arrayValidator.test.ts + /** * Function to pass into describe * ->Important: you need to always bind this From daac0e0b5480a51922a4a8ec538ee47750a2d3e3 Mon Sep 17 00:00:00 2001 From: hasezoey Date: Tue, 22 Oct 2019 00:14:25 +0200 Subject: [PATCH 7/8] Add Documentation about "innerOptions" & "outerOptions" - arrayProp(gh-page): add "innerOptions" & "outerOptions" - changelog(gh-page): add note that "Array Validators" are now integrated - utils(src): actually allow the use of "innerOptions" & "outerOptions" --- github-page/_docs/decorators/arrayProp.md | 62 +++++++++++++++++++++++ github-page/changelog.md | 1 + src/internal/utils.ts | 11 ++++ src/types.ts | 4 +- 4 files changed, 76 insertions(+), 2 deletions(-) diff --git a/github-page/_docs/decorators/arrayProp.md b/github-page/_docs/decorators/arrayProp.md index a4422035b..53a79cb9a 100644 --- a/github-page/_docs/decorators/arrayProp.md +++ b/github-page/_docs/decorators/arrayProp.md @@ -61,6 +61,68 @@ class Another extends Typegoose { } ``` +### innerOptions + +`innerOptions` is used to overwrite here the options in this object go +-> Use this only when absolutly needed and please open a new issue about it - or for plugins + +Example: + +```ts +class Something { + @arrayProp({ required: true }) + public propy: string; +} + +// This would be mapped to +{ + type: [{ type: String }], + required: true +} + +// when using the overwrite +class Something { + @arrayProp({ innerOptions: { required: true } }) + public propy: string; +} + +// This would be mapped to +{ + type: [{ type: String, required: true }] +} +``` + +### outerOptions + +`outerOptions` is used to overwrite here the options in this object go +-> Use this only when absolutly needed and please open a new issue about it - or for plugins + +Example: + +```ts +class Something { + @arrayProp({ maxlength: 1 }) + public propy: string; +} + +// This would be mapped to +{ + type: [{ type: String, maxlength: 1 }] +} + +// when using the overwrite +class Something { + @arrayProp({ outerOptions: { maxlength: 1 } }) + public propy: string; +} + +// This would be mapped to +{ + type: [{ type: String }], + maxlength: 1 +} +``` + ## Options from @prop that do **NOT** work on @arrayProp - `ref` does not work, instead use `itemsRef` (please let us know if you are interested in combining them into one) diff --git a/github-page/changelog.md b/github-page/changelog.md index 08e030036..47d653606 100644 --- a/github-page/changelog.md +++ b/github-page/changelog.md @@ -18,6 +18,7 @@ redirect_from: - `@prop({ validate })` now accepts `{ validator, message }` as an array - Add function "deleteModel" & "deleteModelWithClass" - allow Prop Option "type" to overwrite the inferred type [look here for an example](https://typegoose.github.io/typegoose/docs/decorators/prop/#type) +- integrate "Array Validators & Transform" tests {% include gitissue repo="typegoose" num=29 %} - [IC] Refactor how "isPrimitive" works, some types like `Buffer` & `Decimal` now work - [IC] Added more debug logs to `prop.ts` - [IC] Move Decorator Cache to the class itself diff --git a/src/internal/utils.ts b/src/internal/utils.ts index 1defa0c25..47ff4b3dc 100644 --- a/src/internal/utils.ts +++ b/src/internal/utils.ts @@ -334,6 +334,17 @@ export function mapArrayOptions(rawOptions: any, Type: AnyParamConstructor) logger.info('The Type "%s" does not have an OptionsConstructor', getName(Type)); } + if (typeof options.innerOptions === 'object') { + for (const [key, value] of Object.entries(options.innerOptions)) { + returnObject.type[0][key] = value; + } + } + if (typeof options.outerOptions === 'object') { + for (const [key, value] of Object.entries(options.outerOptions)) { + returnObject[key] = value; + } + } + logger.debug('Final mapped Options for Type "%s"', getName(Type), returnObject); return returnObject; diff --git a/src/types.ts b/src/types.ts index aabcc7c83..59ebc3d7f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -245,7 +245,7 @@ export interface ArrayPropOptions extends BasePropOptions { itemsRefType?: RefSchemaType; /** * Use this to define inner-options - * Use this if the auto-mapping is not correct + * Use this if the auto-mapping is not correct or for plugin options * * Please open a new issue if some option is mismatched or not existing / mapped */ @@ -254,7 +254,7 @@ export interface ArrayPropOptions extends BasePropOptions { }; /** * Use this to define outer-options - * Use this if the auto-mapping is not correct + * Use this if the auto-mapping is not correct or for plugin options * * Please open a new issue if some option is mismatched or not existing / mapped */ From 1bf7a0dadb3eed5438520ebeb44a8cf297323fea Mon Sep 17 00:00:00 2001 From: hasezoey Date: Tue, 22 Oct 2019 00:24:12 +0200 Subject: [PATCH 8/8] Remove Some example on test's tsdoc --- test/tests/arrayValidator.test.ts | 7 ------- test/tests/stringValidator.test.ts | 7 ------- 2 files changed, 14 deletions(-) diff --git a/test/tests/arrayValidator.test.ts b/test/tests/arrayValidator.test.ts index 1e2bd0dc1..d9ade2439 100644 --- a/test/tests/arrayValidator.test.ts +++ b/test/tests/arrayValidator.test.ts @@ -8,13 +8,6 @@ import { model as ArrayValidators } from '../models/arrayValidators'; /** * Function to pass into describe * ->Important: you need to always bind this - * @example - * ``` - * import { suite as StringValidatorTests } from './stringValidator.test' - * ... - * describe('String Validators', StringValidatorTests.bind(this)); - * ... - * ``` */ export function suite() { it('should respect maxlength', (done) => { diff --git a/test/tests/stringValidator.test.ts b/test/tests/stringValidator.test.ts index 1fc442e28..be6316595 100644 --- a/test/tests/stringValidator.test.ts +++ b/test/tests/stringValidator.test.ts @@ -8,13 +8,6 @@ import { model as StringValidators } from '../models/stringValidators'; /** * Function to pass into describe * ->Important: you need to always bind this - * @example - * ``` - * import { suite as StringValidatorTests } from './stringValidator.test' - * ... - * describe('String Validators', StringValidatorTests.bind(this)); - * ... - * ``` */ export function suite() { it('should respect maxlength', (done) => {