Skip to content

Commit

Permalink
feat(autoIncrement::AutoIncrementID): support "overwriteModelName" to…
Browse files Browse the repository at this point in the history
… be a function

fixes #16
  • Loading branch information
hasezoey committed Sep 23, 2022
1 parent 8da7534 commit 46bcc45
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 4 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,12 @@ Set the starting number of the counter.

### overwriteModelName

`string` default's to the documents's model-name
`string` default's to the documents's model-name
`(modelName: string, model: Model) => string`

Overwrite the used value for the `modelName` property on the tracker-document, this can be used when wanting to use the same tracker document across different models.
If the value is falsy, then it will default to the `modelName`.
If the value is falsy, then it will default to the `modelName`.
Can also be used as a function to generate a name to use based on `modelName` or the `model` itself, needs to return a non-empty string, when wanting to default back to default behavior just return the parameter `modelName`.

## Notes

Expand Down
13 changes: 12 additions & 1 deletion src/autoIncrement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,18 @@ export function AutoIncrementID(schema: mongoose.Schema<any>, options: AutoIncre
schema.pre('save', async function AutoIncrementPreSaveID(): Promise<void> {
logger.info('AutoIncrementID PreSave');

const modelName: string = opt.overwriteModelName || (this.constructor as any).modelName;
const originalModelName: string = (this.constructor as any).modelName;
let modelName: string;

if (typeof opt.overwriteModelName === 'function') {
modelName = opt.overwriteModelName(originalModelName, this.constructor as any);

if (!modelName || typeof modelName !== 'string') {
throw new Error('"overwriteModelname" is a function, but did return a falsy type or is not a string!');
}
} else {
modelName = opt.overwriteModelName || originalModelName;
}

if (!model) {
logger.info('Creating idtracker model named "%s"', opt.trackerModelName);
Expand Down
9 changes: 8 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import mongoose from 'mongoose';

export interface AutoIncrementOptionsSimple {
/** Which Field to increment on save */
field: string;
Expand Down Expand Up @@ -42,9 +44,14 @@ export interface AutoIncrementIDOptions {
* This can be overwritten when wanting to use a single tracker for multiple models
* Defaults to `document.constructor.modelName`
*/
overwriteModelName?: string;
overwriteModelName?: string | OverwriteModelNameFunction;
}

/**
* A function to generate the name used for the auto-increment "modelName" field
*/
export type OverwriteModelNameFunction = (modelName: string, model: mongoose.Model<any>) => string;

export interface AutoIncrementIDTrackerSpec {
/** The ModelName from the current model */
modelName: string;
Expand Down
4 changes: 4 additions & 0 deletions test/__snapshots__/basic.test.ts.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Basic Suite AutoIncrementID should throw a error if "overwriteModelName" is a function but returns a empty string 1`] = `"\\"overwriteModelname\\" is a function, but did return a falsy type or is not a string!"`;

exports[`Basic Suite AutoIncrementID should throw a error if "overwriteModelName" is a function but returns not a string 1`] = `"\\"overwriteModelname\\" is a function, but did return a falsy type or is not a string!"`;

exports[`Errors should Error if the schema path does not exist 1`] = `"Field \\"SomeNonExistingField\\" does not exists on the Schema!"`;

exports[`Errors should Error if the schema path is not an number 1`] = `"Field \\"nonNumberField\\" is not an SchemaNumber!"`;
99 changes: 99 additions & 0 deletions test/basic.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getModelForClass, modelOptions, plugin, prop } from '@typegoose/typegoose';
import { assertion } from '@typegoose/typegoose/lib/internal/utils';
import * as mongoose from 'mongoose';
import { AutoIncrementID, AutoIncrementSimple } from '../src/autoIncrement';

Expand Down Expand Up @@ -287,6 +288,104 @@ describe('Basic Suite', () => {
const foundTracker = await trackerModel.findOne({ modelName: 'AutoIncrementID-EOMN' }).orFail();
expect(foundTracker.count).toEqual(0);
});

it('should support "overwriteModelName" being a function', async () => {
let fcalled = 0;

const schema = new mongoose.Schema({
_id: Number,
somefield: Number,
});
schema.plugin(AutoIncrementID, {
overwriteModelName: (modelName, model) => {
fcalled += 1;
expect(modelName).toStrictEqual('AutoIncrementID-OMNF');
expect(Object.getPrototypeOf(model)).toStrictEqual(mongoose.Model);

return 'AutoIncrementID-OMNF-test';
},
});
const model = mongoose.model('AutoIncrementID-OMNF', schema);

expect(fcalled).toStrictEqual(0);
const doc = await model.create({ somefield: 10 });
expect(fcalled).toStrictEqual(1);
expect(doc.somefield).toBe(10);
expect(doc._id).toBe(0);

expect(fcalled).toStrictEqual(1);
await doc.save();
expect(fcalled).toStrictEqual(2);
expect(doc.somefield).toBe(10);
expect(doc._id).toBe(0);

const trackerModel = mongoose.connection.models['identitycounter'];
expect(Object.getPrototypeOf(trackerModel)).toStrictEqual(mongoose.Model);

const foundTracker = await trackerModel.findOne({ modelName: 'AutoIncrementID-OMNF-test' }).orFail();
expect(foundTracker.count).toEqual(0);
});

it('should throw a error if "overwriteModelName" is a function but returns a empty string', async () => {
let fcalled = 0;

const schema = new mongoose.Schema({
_id: Number,
somefield: Number,
});
schema.plugin(AutoIncrementID, {
overwriteModelName: (modelName, model) => {
fcalled += 1;
expect(modelName).toStrictEqual('AutoIncrementID-OMNFEE');
expect(Object.getPrototypeOf(model)).toStrictEqual(mongoose.Model);

return '';
},
});
const model = mongoose.model('AutoIncrementID-OMNFEE', schema);

expect(fcalled).toStrictEqual(0);
try {
await model.create({ somefield: 10 });
fail('Expected .create to fail');
} catch (err) {
expect(fcalled).toStrictEqual(1);
expect(err).toBeInstanceOf(Error);
assertion(err instanceof Error); // jest types do not do this for typescript
expect(err.message).toMatchSnapshot();
}
});

it('should throw a error if "overwriteModelName" is a function but returns not a string', async () => {
let fcalled = 0;

const schema = new mongoose.Schema({
_id: Number,
somefield: Number,
});
schema.plugin(AutoIncrementID, {
// @ts-expect-error ReturnType should be string
overwriteModelName: (modelName, model) => {
fcalled += 1;
expect(modelName).toStrictEqual('AutoIncrementID-OMNFENS');
expect(Object.getPrototypeOf(model)).toStrictEqual(mongoose.Model);

return 0;
},
});
const model = mongoose.model('AutoIncrementID-OMNFENS', schema);

expect(fcalled).toStrictEqual(0);
try {
await model.create({ somefield: 10 });
fail('Expected .create to fail');
} catch (err) {
expect(fcalled).toStrictEqual(1);
expect(err).toBeInstanceOf(Error);
assertion(err instanceof Error); // jest types do not do this for typescript
expect(err.message).toMatchSnapshot();
}
});
});
});

Expand Down

0 comments on commit 46bcc45

Please sign in to comment.