Skip to content

Commit

Permalink
feat(schema): add alias() method that makes it easier to define mul…
Browse files Browse the repository at this point in the history
…tiple aliases for a given path

Fix #12368
  • Loading branch information
vkarpov15 committed Sep 30, 2022
1 parent c91dd0c commit 8287161
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 11 deletions.
68 changes: 57 additions & 11 deletions lib/schema.js
Expand Up @@ -170,20 +170,25 @@ function Schema(obj, options) {
* @api private
*/
function aliasFields(schema, paths) {
paths = paths || Object.keys(schema.paths);
for (const path of paths) {
const options = get(schema.paths[path], 'options');
if (options == null) {
continue;
}
for (const path of Object.keys(paths)) {
let alias = null;
if (typeof paths[path] === 'string') {
alias = paths[path];
} else {
const options = get(schema.paths[path], 'options');
if (options == null) {
continue;
}

const prop = schema.paths[path].path;
const alias = options.alias;
alias = options.alias;
}

if (!alias) {
continue;
}

const prop = schema.paths[path].path;

if (typeof alias !== 'string') {
throw new Error('Invalid value for alias option on ' + prop + ', got ' + alias);
}
Expand Down Expand Up @@ -663,9 +668,50 @@ Schema.prototype.add = function add(obj, prefix) {
}
}

const addedKeys = Object.keys(obj).
map(key => prefix ? prefix + key : key);
aliasFields(this, addedKeys);
const aliasObj = Object.fromEntries(
Object.entries(obj).map(([key]) => ([prefix + key, null]))
);
aliasFields(this, aliasObj);
return this;
};

/**
* Add an alias for `path`. This means getting or setting the `alias`
* is equivalent to getting or setting the `path`.
*
* #### Example:
*
* const toySchema = new Schema({ n: String });
*
* // Make 'name' an alias for 'n'
* toySchema.alias('n', 'name');
*
* const Toy = mongoose.model('Toy', ToySchema);
* const turboMan = new Toy({ n: 'Turbo Man' });
*
* turboMan.name; // 'Turbo Man'
* turboMan.n; // 'Turbo Man'
*
* turboMan.name = 'Turbo Man Action Figure';
* turboMan.n; // 'Turbo Man Action Figure'
*
* await turboMan.save(); // Saves { _id: ..., n: 'Turbo Man Action Figure' }
*
*
* @param {string} path real path to alias
* @param {string|string[]} alias the path(s) to use as an alias for `path`
* @return {Schema} the Schema instance
* @api public
*/

Schema.prototype.alias = function alias(path, alias) {
if (Array.isArray(alias)) {
for (const a of alias) {
this.alias(path, a);
}
return this;
}
aliasFields(this, { [path]: alias });
return this;
};

Expand Down
14 changes: 14 additions & 0 deletions test/schema.test.js
Expand Up @@ -2867,4 +2867,18 @@ describe('schema', function() {
assert.equal(doc1.domain, mongooseDomain);
assert.equal(doc1.domain, doc2.domain);
});

it('alias (gh-12368)', function() {
const schema = new Schema({ name: String });

schema.alias('name', 'otherName');
assert.equal(schema.aliases['otherName'], 'name');
assert.ok(schema.virtuals['otherName']);

schema.alias('name', ['name1', 'name2']);
assert.equal(schema.aliases['name1'], 'name');
assert.equal(schema.aliases['name2'], 'name');
assert.ok(schema.virtuals['name1']);
assert.ok(schema.virtuals['name2']);
});
});

0 comments on commit 8287161

Please sign in to comment.