mongoose-slug-updater
Advanced tools
Comparing version 2.5.4 to 2.6.0
@@ -14,2 +14,3 @@ 'use strict'; | ||
truncate: 120, | ||
backwardCompatible: true//will be false in the next major version | ||
}, | ||
@@ -21,15 +22,5 @@ options | ||
// console.log(' === schema === '); | ||
// if(schema.paths.children){ | ||
// console.log(schema.paths.children.constructor.name); | ||
// } | ||
function schemaTraversal(schema, basePath, cb) { | ||
if (basePath) basePath += '.'; | ||
schema.eachPath(function(schemaPath, schemaType) { | ||
/* console.log( | ||
basePath + schemaPath + ':' + schemaType.constructor.schemaName | ||
); */ | ||
if (schemaType.constructor.schemaName === undefined) { | ||
// console.log(schemaType); | ||
} | ||
if (schemaType.caster && schemaType.caster.schema) { | ||
@@ -48,13 +39,40 @@ schemaTraversal( | ||
} | ||
function renameOldOptions(opts) { | ||
if(!options.backwardCompatible) | ||
return opts; | ||
let res = _.cloneDeep(opts); | ||
let deprecated = ['unique_slug', 'slug_padding_size']; | ||
let found = []; | ||
_.each(deprecated, oldo => { | ||
if (res[oldo] !== undefined) { | ||
let newo = _.camelCase(oldo); | ||
found.push([oldo, newo]); | ||
res[newo] = res[oldo]; | ||
delete res[oldo]; | ||
} | ||
}); | ||
if (found.length) { | ||
console.log( | ||
'Deprecated "snake_case" options found by slug updater plugin. Please update to camelCase.', | ||
found | ||
); | ||
} | ||
if(res.uniqueGroup){ | ||
res.uniqueGroupSlug = res.uniqueGroup; | ||
delete res.uniqueGroup; | ||
console.log('Deprecated option "uniqueGroup" found by slug updater. Please update to uniqueGroupSlug.') | ||
} | ||
if(res.force_id){ | ||
res.forceIdSlug = res.force_id; | ||
delete res.force_id | ||
console.log('Deprecated option "force_id" found by slug updater. Please update to forceIdSlug.') | ||
} | ||
if(res.on){ | ||
res.slugOn = res.on; | ||
delete res.on | ||
console.log('Deprecated option "on" found by slug updater. Please update to slugOn.') | ||
} | ||
return res; | ||
} | ||
schemaTraversal(schema, '', (schemaPath, schemaType) => { | ||
// console.log(schemaType.constructor.schemaName); | ||
// if(schemaType.constructor.schemaName=="DocumentArray"){ | ||
// console.log(schemaType.caster.schema.obj); | ||
// console.log(schema); | ||
// } | ||
// console.log(schemaPath, schemaType.constructor.name); | ||
// console.log(Object.keys(schemaType)); | ||
if (schemaType.instance == 'Array') { | ||
// console.log(schemaType.getters); | ||
} | ||
if ( | ||
@@ -65,2 +83,3 @@ schemaType.instance == 'String' && | ||
) { | ||
let opts = renameOldOptions(schemaType.options); | ||
let basePath = schemaPath.replace(/[\.][^\.]+$/, ''); | ||
@@ -77,38 +96,37 @@ if (basePath == schemaPath) basePath = ''; | ||
findOneAndUpdate: true, | ||
...(schemaType.options.on || {}), | ||
...(opts.slugOn || {}), | ||
}, | ||
}; | ||
if (typeof schemaType.options.slug === 'string') { | ||
slug.fields = [schemaType.options.slug]; | ||
} else if (schemaType.options.slug instanceof Array) { | ||
slug.fields = schemaType.options.slug; | ||
if (typeof opts.slug === 'string') { | ||
slug.fields = [opts.slug]; | ||
} else if (opts.slug instanceof Array) { | ||
slug.fields = opts.slug; | ||
} else { | ||
return; | ||
} | ||
// slug.fields = slug.fields.map(v => { | ||
// if (_.startsWith(v, '/')) return v.substr(1); | ||
// return (slug.path && slug.path + '.') + v; | ||
// }); | ||
if (schemaType.options.unique || schemaType.options.unique_slug) { | ||
if (opts.unique || opts.uniqueSlug) { | ||
slug.unique = true; | ||
} | ||
if (schemaType.options.permanent) { | ||
if (opts.permanent) { | ||
slug.permanent = true; | ||
} | ||
if (schemaType.options.slug_padding_size === undefined) { | ||
if (opts.slugPaddingSize === undefined) { | ||
slug.isShortIdMode = true; | ||
} else { | ||
slug.isShortIdMode = false; | ||
slug.padding = schemaType.options.slug_padding_size; | ||
slug.padding = opts.slugPaddingSize; | ||
} | ||
if (schemaType.options.uniqueGroup) { | ||
if (_.isArray(schemaType.options.uniqueGroup)) { | ||
slug.uniqueGroupFields = schemaType.options.uniqueGroup; | ||
if (opts.uniqueGroupSlug) { | ||
if (_.isArray(opts.uniqueGroupSlug)) { | ||
slug.uniqueGroupFields = opts.uniqueGroupSlug; | ||
} else { | ||
slug.uniqueGroupFields = [schemaType.options.uniqueGroup]; | ||
slug.uniqueGroupFields = [opts.uniqueGroupSlug]; | ||
} | ||
} | ||
if (schemaType.options.force_id) { | ||
if (opts.uniqueNestedSlug) { | ||
slug.uniqueNested = opts.uniqueNestedSlug; | ||
} | ||
if (opts.forceIdSlug) { | ||
slug.unique = true; | ||
@@ -121,8 +139,3 @@ slug.isShortIdMode = true; | ||
}); | ||
// | ||
// schema.post('save', function(error, res, next) { | ||
// console.log('post save', this); | ||
// next(); | ||
// }); | ||
// console.log(slugs); | ||
schema.pre('update', async function() { | ||
@@ -146,8 +159,5 @@ return onUpdate.bind(this)('update'); | ||
const me = this; | ||
// console.log('pre-'+operation,me.getUpdate()); | ||
let upd = me.getUpdate(); | ||
// console.debug('preupdateOne before',me.getQuery(), upd); | ||
let doc = _.cloneDeep(upd); | ||
if (doc.$set) { | ||
// console.log(doc.$set); | ||
_.forOwn(doc.$set, (v, k) => { | ||
@@ -157,3 +167,2 @@ _.set(doc, k, v); | ||
delete doc.$set; | ||
// console.log(doc); | ||
} | ||
@@ -169,6 +178,4 @@ let docs = [_.cloneDeep(doc)]; | ||
if (!unwoundSlugs.length) { | ||
// console.log('no slugs'); | ||
return; | ||
} | ||
// console.log(_.map(unwoundSlugs,'path')); | ||
@@ -179,5 +186,2 @@ let updFields = _.keysDeep(doc); | ||
); | ||
// console.log(updFields); | ||
// console.log(updPaths); | ||
// console.log("unwoundSlugs",unwoundSlugs); | ||
let involvedPaths = _.uniq( | ||
@@ -188,5 +192,3 @@ unwoundSlugs.reduce( | ||
) | ||
).map(p=>p.replace(/^\//,'')); | ||
// .filter(val => updPaths.indexOf(val) == -1); | ||
// console.log('involvedPaths', involvedPaths); | ||
).map(p => p.replace(/^\//, '')); | ||
@@ -202,3 +204,2 @@ let involvedValuesDocs = await me.model[ | ||
); | ||
// console.log("involvedValuesDocs",_.map(involvedValuesDocs,v => v&&v.child&&v.child.subChildren&&v.child.subChildren[4]||"")); | ||
if (involvedValuesDocs) { | ||
@@ -210,11 +211,4 @@ if (!_.isArray(involvedValuesDocs)) | ||
involvedPaths.forEach(function(f) { | ||
let fs = unwindPath(freshDoc,f,docGet); | ||
_.each(fs,f=>{ | ||
// if(f=="child.slug"){ | ||
// console.log(f); | ||
// console.log(_.get(docs[i], f)); | ||
// console.log(_.get(freshDoc, f)); | ||
// console.log(upd); | ||
// } | ||
let fs = unwindPath(freshDoc, f, docGet); | ||
_.each(fs, f => { | ||
if (_.get(docs[i], f) === undefined) | ||
@@ -227,3 +221,3 @@ _.set(docs[i], f, _.get(freshDoc, f)); | ||
} | ||
// console.log("docs",docs); | ||
let slugsUpd = []; | ||
@@ -237,17 +231,13 @@ async function findOne(query, sort) { | ||
if (slugsUpd.length && sort) { | ||
// console.log("findOne res",res); | ||
let field = _.first(_.keys(sort)); | ||
let top = _.maxBy(slugsUpd, (u)=>{ | ||
// if(_.get(u,field)===undefined){ | ||
// console.log(field); | ||
// console.log(u); | ||
// } | ||
return extractCounter(_.get(u,field),options.separator); | ||
let top = _.maxBy(slugsUpd, u => { | ||
return extractCounter(_.get(u, field), options.separator); | ||
}); | ||
// console.log("findOne top",top); | ||
if (_.has(top, field)) { | ||
let localCounter = extractCounter(_.get(top,field),options.separator); | ||
let dbCounter = extractCounter(res.get(field),options.separator); | ||
if(localCounter>dbCounter) | ||
res = top; | ||
let localCounter = extractCounter( | ||
_.get(top, field), | ||
options.separator | ||
); | ||
let dbCounter = extractCounter(res.get(field), options.separator); | ||
if (localCounter > dbCounter) res = top; | ||
} | ||
@@ -257,6 +247,9 @@ } | ||
} | ||
// console.log("docs",docs); | ||
// console.log("doc",doc); | ||
for (let i = 0; i < docs.length; i++) { | ||
let currentUnwoundFields = unwindSlugs(docs[i],unwoundSlugs,_.get,updIsModified); | ||
let currentUnwoundFields = unwindSlugs( | ||
docs[i], | ||
unwoundSlugs, | ||
_.get, | ||
updIsModified | ||
); | ||
let actualSlugs = currentUnwoundFields; | ||
@@ -266,3 +259,2 @@ if (involvedValuesDocs && involvedValuesDocs.length) { | ||
.filter(f => { | ||
// console.log(_.get(doc, f),_.get(docs[i], f)); | ||
return _.get(doc, f) != _.get(involvedValuesDocs[i], f); | ||
@@ -272,35 +264,18 @@ }) | ||
.value(); | ||
// console.log("actualUpdFields",actualUpdFields,updFields); | ||
actualSlugs = _.filter(currentUnwoundFields, s => { | ||
// if(s.path=="child.slug"){ | ||
// console.log(_.intersection( | ||
// s.fields.concat(s.uniqueGroupFields || []), | ||
// actualUpdFields | ||
// )); | ||
// } | ||
return _.intersection( | ||
_.map(s.fields.concat(s.uniqueGroupFields || []),p=>p.replace(/^\//,'')), | ||
_.map(s.fields.concat(s.uniqueGroupFields || []), p => | ||
p.replace(/^\//, '') | ||
), | ||
actualUpdFields | ||
).length; | ||
}); | ||
// console.log('child.slug b4',_.filter(actualSlugs,['path','child.slug'])); | ||
// console.log('child.subChildren.4.slug get',_.get(docs[i],'child.subChildren.4.slug')); | ||
// console.log('child.subChildren.4.slug befor',_.filter(unwoundSlugs,['path','child.subChildren.4.slug'])); | ||
// console.log('child.subChildren.4.slug after',_.filter(unwoundSlugs,['path','child.subChildren.4.slug'])); | ||
// console.log("actualSlugs",actualSlugs); | ||
} | ||
// console.log('child.slug',_.indexOf(_.map(unwoundSlugs,'path'),'child.slug')); | ||
// console.log("before setSlugs",actualSlugs); | ||
if (actualSlugs.length){ | ||
if (actualSlugs.length) { | ||
await setSlugs(docs[i], actualSlugs, options, _.get, _.set, findOne); | ||
} | ||
// console.log("after setSlugs",docs[i]); | ||
slugsUpd[i] = _.cloneDeep(upd.$set || upd); | ||
actualSlugs.forEach(slug => { | ||
let slugVal = _.get(docs[i], slug.path); | ||
if(slug.path=='child.subChildren.4.slug'){ | ||
// console.log(slug.path,slugVal); | ||
} | ||
if (slugVal != undefined) _.set(slugsUpd[i], slug.path, slugVal); | ||
@@ -313,6 +288,2 @@ }); | ||
if (val !== undefined) _.set(slugsUpd[i], us.path, val); | ||
// else{ | ||
// console.log("not found",us.path); | ||
// console.log(involvedValuesDocs[i]); | ||
// } | ||
} | ||
@@ -324,4 +295,2 @@ }); | ||
if (upd.$set) { | ||
// console.log(_.indexate(slugsUpd[i],{ leafsOnly: true })); | ||
// console.log(slugsUpd[i]); | ||
let slugPaths = _(slugsUpd[i]) | ||
@@ -334,7 +303,5 @@ .indexate({ leafsOnly: true }) | ||
} | ||
// console.log('upd',doUpd); | ||
if (docs.length == 1) { | ||
if (slugsUpd[i]) me[operation]({}, doUpd); | ||
// console.log(me.getUpdate()); | ||
} else { | ||
@@ -345,6 +312,3 @@ if (!docs[i]._id) | ||
); | ||
if (doUpd){ | ||
// if(operation=="updateMany") | ||
// console.log("updateMany"); | ||
// console.log(slugsUpd[i].child&&slugsUpd[i].child.slugShort||null); | ||
if (doUpd) { | ||
await me.model.updateOne({ _id: docs[i]._id }, doUpd); | ||
@@ -356,15 +320,8 @@ } | ||
/** | ||
* Executed before save value | ||
*/ | ||
schema.pre('save', async function() { | ||
let doc = this; | ||
if (!doc.model) { | ||
// console.log('skip childs, process root only.'); | ||
return; | ||
} | ||
let reSlug = false; | ||
// let logslug = _.filter(slugs,['path','children.$.relativeSiblingSlug']); | ||
// if(logslug.length) | ||
// console.log(logslug); | ||
let unwoundSlugs = unwindSlugs( | ||
@@ -376,4 +333,2 @@ doc, | ||
); | ||
// if(logslug.length) | ||
// console.log(_.filter(unwoundSlugs,s=>_.endsWith(s.path,'relativeSiblingSlug'))); | ||
@@ -383,3 +338,3 @@ if (!unwoundSlugs.length) { | ||
} | ||
// console.log('slugs',slugs); | ||
doc = await setSlugs( | ||
@@ -394,8 +349,5 @@ doc, | ||
if (sort) res = res.sort(sort); | ||
res = await res; | ||
// console.log("save findOne res", res&&res.get('uniqueSlug')||null); | ||
return res; | ||
return await res; | ||
} | ||
); | ||
// console.log('slugs set',doc); | ||
}); | ||
@@ -411,28 +363,16 @@ }; | ||
function unwindSlugs(doc, slugs, get, isModified) { | ||
// console.log("unwindSlugs",slugs); | ||
let unwoundSlugs = []; | ||
slugs.forEach(slug => { | ||
let say = false;//slug.path=="children.$.relativeSiblingSlug"; | ||
let slugPaths = unwindPath(doc, slug.path, get); | ||
if(say) | ||
console.log("slugPaths",slugPaths); | ||
if (!slugPaths.length) slugPaths.push(slug.path); | ||
let basePath = slug.basePath; | ||
if(!slugPaths.length) | ||
slugPaths.push(slug.path); | ||
let basePath = slug.basePath; | ||
// console.log(slug.path,slugPaths,doc); | ||
if (_.endsWith(basePath, '.$')) basePath += '.'; | ||
slugPaths.forEach(slugPath => { | ||
let unwoundBasePath = slugPath.replace(/\.[^\.]+$/, ''); | ||
if(say) | ||
console.log("unwoundBasePath",unwoundBasePath); | ||
if (unwoundBasePath == slugPath) unwoundBasePath = ''; | ||
// console.log("unwoundBasePath",unwoundBasePath); | ||
function unwindFieldPath(fieldPath) { | ||
if(say) | ||
console.log(fieldPath+"->"); | ||
let slugValueBasePath = unwoundBasePath; | ||
let originalBasePath = _.trimEnd(basePath,'.'); | ||
let originalBasePath = _.trimEnd(basePath, '.'); | ||
while (_.startsWith(fieldPath, ':')) { | ||
// console.log("relative path ",slugValueBasePath,fieldPath); | ||
let prevValueBasePath = slugValueBasePath; | ||
@@ -448,7 +388,3 @@ let prevOriginalBasePath = originalBasePath; | ||
} | ||
if(say){ | ||
console.log(fieldPath); | ||
console.log(slugValueBasePath); | ||
console.log(originalBasePath); | ||
} | ||
slugValueBasePath = slugValueBasePath.replace(/\.[^\.]+$/, ''); | ||
@@ -459,12 +395,14 @@ originalBasePath = originalBasePath.replace(/\.[^\.]+$/, ''); | ||
fieldPath = fieldPath.substr(1); | ||
// console.log("unwind relative path ",slugValueBasePath,fieldPath); | ||
} | ||
if (!_.startsWith(fieldPath, '/')){ | ||
fieldPath ='/'+ | ||
((slugValueBasePath && slugValueBasePath + '.') || '') + fieldPath; | ||
if (!_.startsWith(fieldPath, '/')) { | ||
fieldPath = | ||
'/' + | ||
((slugValueBasePath && slugValueBasePath + '.') || '') + | ||
fieldPath; | ||
} | ||
if(_.startsWith(fieldPath,'/'+originalBasePath)) | ||
fieldPath = fieldPath.replace('/'+originalBasePath,'/'+slugValueBasePath); | ||
if(say) | ||
console.log("->"+fieldPath,originalBasePath,slugValueBasePath); | ||
if (_.startsWith(fieldPath, '/' + originalBasePath)) | ||
fieldPath = fieldPath.replace( | ||
'/' + originalBasePath, | ||
'/' + slugValueBasePath | ||
); | ||
return fieldPath; | ||
@@ -476,6 +414,5 @@ } | ||
); | ||
// console.log("unwoundGroupPaths",unwoundGroupPaths); | ||
if ( | ||
_.some(unwoundFields.concat(unwoundGroupPaths), path => { | ||
return isModified(doc, path.replace(/^\//,'')); | ||
return isModified(doc, path.replace(/^\//, '')); | ||
}) | ||
@@ -489,9 +426,2 @@ ) { | ||
unwoundSlugs.push(s); | ||
if(say){ | ||
console.log("YEYE:",s); | ||
} | ||
} else { | ||
if(slug.path=="child.subChildren.4.slug"){ | ||
// console.log("NONO:",unwoundFields,unwoundGroupPaths); | ||
} | ||
} | ||
@@ -509,11 +439,9 @@ }); | ||
} | ||
// console.log('isNestedModified',path,restPathParts); | ||
let res = []; | ||
let value = get(doc, path); | ||
// console.log("unwindPath",doc,path,value); | ||
if (_.isArray(value)) { | ||
// console.log('value is array?',_.isArray(value),value.length); | ||
for (let i = 0; i < value.length; i++) { | ||
let childPath = path + '.' + i + '.' + restPathParts[0]; | ||
// console.log('lets check', childPath); | ||
res = res.concat(unwindPath(doc, childPath, get, _.drop(restPathParts))); | ||
@@ -528,3 +456,2 @@ } | ||
async function setSlugs(doc, slugs, options, get, set, findOne) { | ||
// console.log('setSlugs',_.filter(slugs,s=>_.startsWith(s.path,'child.subChildren.'))); | ||
await Promise.all( | ||
@@ -535,8 +462,7 @@ slugs.map(async slug => { | ||
slug.fields.forEach(slugField => { | ||
// console.log("get",slugField,slugField.replace(/^\//,'')); | ||
fields.push(get(doc, slugField.replace(/^\//,''))); | ||
fields.push(get(doc, slugField.replace(/^\//, ''))); | ||
}); | ||
let oldSlug = get(doc, slug.path); | ||
if ( | ||
!(slug.unique || slug.unique_slug) && | ||
!(slug.unique || slug.uniqueSlug) && | ||
(!slug.uniqueGroupFields || !slug.uniqueGroupFields.length) | ||
@@ -546,7 +472,3 @@ ) { | ||
set(doc, slug.path, makeSlug(fields, options)); | ||
// console.log('slug set',slug.path,fields); | ||
} else { | ||
// console.log('slug not set',oldSlug,slug.permanent); | ||
} | ||
// console.log('not unique slug generated',slug.path,doc); | ||
return; | ||
@@ -557,10 +479,8 @@ } else { | ||
slug.uniqueGroupFields.forEach(function(fieldName) { | ||
fieldName = fieldName.replace(/^\//,''); | ||
query[fieldName] = get(doc,fieldName); | ||
fieldName = fieldName.replace(/^\//, ''); | ||
query[fieldName] = get(doc, fieldName); | ||
}); | ||
// console.log('group query', query); | ||
} | ||
if (!doc[slug.path] || !(slug.permanent && doc[slug.path])) { | ||
if (slug.isShortIdMode) { | ||
// console.log("shortid",slug); | ||
set( | ||
@@ -580,5 +500,3 @@ doc, | ||
); | ||
// console.log("shortid "+slug.path,get(doc,slug.path)); | ||
} else { | ||
// console.log('counter', slug); | ||
set( | ||
@@ -597,3 +515,2 @@ doc, | ||
); | ||
// console.log("counter "+slug.path,get(doc,slug.path)); | ||
} | ||
@@ -612,3 +529,3 @@ } | ||
} | ||
function extractCounter(value,separator) { | ||
function extractCounter(value, separator) { | ||
let count = 0, | ||
@@ -623,2 +540,3 @@ test = new RegExp(separator + '(\\d+)$'), | ||
} | ||
async function makeUniqueCounterSlug( | ||
@@ -639,3 +557,2 @@ doc, | ||
sort[field] = -1; | ||
// console.log("counter slug query before",query); | ||
if (doc._id) { | ||
@@ -648,17 +565,7 @@ query['_id'] = { | ||
// field = search and doc != doc | ||
let result = await findOne(query, sort); | ||
let result = await findOne(query, sort); | ||
// if(query["uniqueSlug"]){ | ||
// console.log("counter slug query after",query); | ||
// console.log("counter slug check", result); | ||
// } | ||
if (result) { | ||
count = extractCounter(result.get(field),options.separator)+1; | ||
slug += options.separator + pad(count, padding); | ||
// console.log("slug counter inc",slug); | ||
// if(result.n!==undefined && query["children.4.slugCounter"]){ | ||
// console.log(result.n+": "+field); | ||
// console.log(slug); | ||
// } | ||
count = extractCounter(result.get(field), options.separator) + 1; | ||
slug += options.separator + _.padStart(count, padding, '0'); | ||
} | ||
@@ -668,17 +575,2 @@ return slug; | ||
function pad(num, size) { | ||
var s = num + ''; | ||
while (s.length < size) s = '0' + s; | ||
return s; | ||
} | ||
/*** | ||
* Generates a unique slug. If the slug is already used, the generated slug has an appended random string, eg: my-slug-NJw9XvZ5l | ||
* | ||
* @param doc | ||
* @param field | ||
* @param values | ||
* @param options | ||
* @param query | ||
*/ | ||
async function makeUniqueShortIdSlug( | ||
@@ -707,3 +599,3 @@ doc, | ||
// console.log('doc already exists', result[field], doc[field],slug); | ||
let oldSlug = get(doc,field); | ||
let oldSlug = get(doc, field); | ||
if ( | ||
@@ -710,0 +602,0 @@ //reuse old slug if possible |
{ | ||
"name": "mongoose-slug-updater", | ||
"version": "2.5.4", | ||
"version": "2.6.0", | ||
"description": "Schema-based slug plugin for Mongoose - single/compound - unique over collection/group - nested docs/arrays - relative/abs paths - sync on change: create/save/update/updateOne/updateMany/findOneAndUpdate tracked - $set operator - counter/shortId", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -110,3 +110,3 @@ # mongoose-slug-updater | ||
If `unique` or `unique_slug` is set, the plugin searches in the mongo database, and if the slug already exists in the collection, it appends to the slug a separator (default: "-") and a random string (generated with the shortid module). <br> | ||
If `unique` or `uniqueSlug` is set, the plugin searches in the mongo database, and if the slug already exists in the collection, it appends to the slug a separator (default: "-") and a random string (generated with the shortid module). <br> | ||
MongoDB supports unique index for nested arrays elements, but he check for duplication conflict only on per-document basis, so inside document duplicate nested array's elements are still allowed. <br> | ||
@@ -133,3 +133,3 @@ Same logic implemented for unique slugs of nested arrays too. | ||
Alternatively you can modify this behaviour and instead of appending a random string, an incremental counter will be used. For that to happen, you must use the parameter `slug_padding_size` specifying the total length of the counter: | ||
Alternatively you can modify this behaviour and instead of appending a random string, an incremental counter will be used. For that to happen, you must use the parameter `slugPaddingSize` specifying the total length of the counter: | ||
@@ -145,3 +145,3 @@ #### example counter | ||
subtitle: String, | ||
slug: { type: String, slug: ["title", "subtitle"], slug_padding_size: 4, unique: true } | ||
slug: { type: String, slug: ["title", "subtitle"], slugPaddingSize: 4, unique: true } | ||
}); | ||
@@ -166,7 +166,8 @@ | ||
If you don't want to define your field as unique for some reasons, but still need slug to be unique,<br> | ||
you can use `unique_slug:true` option instead of `unique`.<br> | ||
you can use `uniqueSlug:true` option instead of `unique`.<br> | ||
This option will not cause index creation, but still will be considered by the plugin. | ||
`force_id` option will append shortId even if no duplicates were found.<br> | ||
`forceIdSlug` option will append shortId even if no duplicates were found.<br> | ||
This is useful for applications with high chance of concurrent modification of unique fields.<br> | ||
Check for conflict made by plugin is not atomic with subsequent insert/update operation,<br> | ||
@@ -177,7 +178,7 @@ so there is a possibility of external change of data in the moment between check and write.<br> | ||
You can just retry operation, so plugin will check collection again and regenerate correct unique slug.<br> | ||
Or you can set `force_id` option - this will solve the problem completely, but you will pay for this by less readabilty of your slugs, because they will *always* be appended with random string. | ||
Or you can set `forceIdSlug` option - this will solve the problem completely, but you will pay for this by less readabilty of your slugs, because they will *always* be appended with random string. | ||
In most cases write operations not so frequent to care about possible conflicts. | ||
note: `force_id` option will also overwite `unique` to the `true`, and `slug_padding_size` option will be ignored. | ||
note: `forceIdSlug` option will also overwite `unique` to the `true`, and `slugPaddingSize` option will be ignored. | ||
@@ -187,3 +188,3 @@ ### Unique slug within a group | ||
Sometimes you only want slugs to be unique within a specific group.<br> | ||
This is done with the `uniqueGroup` property which is an array of fields to group by: | ||
This is done with the `uniqueGroupSlug` property which is an array of fields to group by: | ||
@@ -199,4 +200,4 @@ **example unique per group (using the field named 'group')** | ||
type: String, | ||
uniqueGroup: ['group'], | ||
slug_padding_size: 4, | ||
uniqueGroupSlug: ['group'], | ||
slugPaddingSize: 4, | ||
slug: 'title', | ||
@@ -246,11 +247,11 @@ index: true, | ||
//by default all hooks are enabled | ||
//on:{ save: true, update: true, updateOne: true, updateMany: true, findOneAndUpdate: true } | ||
//slugOn:{ save: true, update: true, updateOne: true, updateMany: true, findOneAndUpdate: true } | ||
}, | ||
slugNoSave: { type: String, slug: 'title', on: { save: false } }, | ||
slugNoUpdate: { type: String, slug: 'title', on: { update: false } }, | ||
slugNoUpdateOne: { type: String, slug: 'title', on: { updateOne: false } }, | ||
slugNoSave: { type: String, slug: 'title', slugOn: { save: false } }, | ||
slugNoUpdate: { type: String, slug: 'title', slugOn: { update: false } }, | ||
slugNoUpdateOne: { type: String, slug: 'title', slugOn: { updateOne: false } }, | ||
slugNoUpdateMany: { | ||
type: String, | ||
slug: 'title', | ||
on: { updateMany: false }, | ||
slugOn: { updateMany: false }, | ||
}, | ||
@@ -260,3 +261,3 @@ slugNoFindOneAndUpdate: { | ||
slug: 'title', | ||
on: { findOneAndUpdate: false }, | ||
slugOn: { findOneAndUpdate: false }, | ||
}, | ||
@@ -292,3 +293,3 @@ }); | ||
permanent: true, //permanent option | ||
slug_padding_size: 4, | ||
slugPaddingSize: 4, | ||
}, | ||
@@ -500,3 +501,4 @@ }); | ||
lang: "en", | ||
truncate: 120 | ||
truncate: 120, | ||
backwardCompatible: true//suppor for the old options names used in the mongoose-slug-generator | ||
}, | ||
@@ -522,3 +524,3 @@ mongoose.plugin(slug, options), | ||
Merged and fixed `uniqueGroup` feature by [rickogden](https://github.com/rickogden). | ||
Merged and fixed `uniqueGroupSlug` feature by [rickogden](https://github.com/rickogden). | ||
@@ -525,0 +527,0 @@ `update`, `updateOne`, `updateMany` and `findOneAndUpdate` operations support implemented. |
@@ -8,3 +8,3 @@ 'use strict'; | ||
const { nIterations, slug_padding_size, Counter } = require('./model'); | ||
const { nIterations, slugPaddingSize, Counter } = require('./model'); | ||
@@ -11,0 +11,0 @@ const tellme = require('./tellme'); |
@@ -8,3 +8,3 @@ 'use strict'; | ||
const tellme = require('./../tellme'); | ||
const { options, slug_padding_size, nIterations } = require('./../options'); | ||
const { options, slugPaddingSize, nIterations } = require('./../options'); | ||
@@ -17,4 +17,4 @@ const ResourceGroupedUniqueCounter = new mongoose.Schema({ | ||
type: String, | ||
uniqueGroup: ['group'], | ||
slug_padding_size: slug_padding_size, | ||
uniqueGroupSlug: ['group'], | ||
slugPaddingSize: slugPaddingSize, | ||
slug: 'title', | ||
@@ -28,4 +28,4 @@ index: true, | ||
type: String, | ||
uniqueGroup: ['/group'], | ||
slug_padding_size, | ||
uniqueGroupSlug: ['/group'], | ||
slugPaddingSize, | ||
slug: 'title', | ||
@@ -45,3 +45,3 @@ index: true, | ||
type: String, | ||
uniqueGroup: ['group'], | ||
uniqueGroupSlug: ['group'], | ||
slug: 'title', | ||
@@ -55,3 +55,3 @@ index: true, | ||
type: String, | ||
uniqueGroup: ['/group'], | ||
uniqueGroupSlug: ['/group'], | ||
slug: 'title', | ||
@@ -58,0 +58,0 @@ index: true, |
'use strict'; | ||
const mongoose = require('mongoose'); | ||
const { options, slug_padding_size, nIterations } = require('./../options'); | ||
const { options, slugPaddingSize, nIterations } = require('./../options'); | ||
const slugGenerator = require('../../.'); | ||
@@ -45,3 +45,3 @@ mongoose.plugin(slugGenerator, options); | ||
uniqueSlug: { type: String, unique: true, slug: 'title' }, | ||
forcedSlug: { type: String, slug: ['subtitle'], force_id: true }, | ||
forcedSlug: { type: String, slug: ['subtitle'], forceIdSlug: true }, | ||
}); | ||
@@ -57,3 +57,3 @@ | ||
unique: true, | ||
slug_padding_size: slug_padding_size, | ||
slugPaddingSize: slugPaddingSize, | ||
slug: 'title', | ||
@@ -73,3 +73,3 @@ }, | ||
permanent: true, | ||
slug_padding_size: slug_padding_size, | ||
slugPaddingSize: slugPaddingSize, | ||
}, | ||
@@ -81,10 +81,10 @@ }); | ||
slug: { type: String, slug: 'title' }, | ||
slugNoSave: { type: String, slug: 'title', on: { save: false } }, | ||
slugNoUpdate: { type: String, slug: 'title', on: { update: false } }, | ||
slugNoUpdateOne: { type: String, slug: 'title', on: { updateOne: false } }, | ||
slugNoUpdateMany: { type: String, slug: 'title', on: { updateMany: false } }, | ||
slugNoSave: { type: String, slug: 'title', slugOn: { save: false } }, | ||
slugNoUpdate: { type: String, slug: 'title', slugOn: { update: false } }, | ||
slugNoUpdateOne: { type: String, slug: 'title', slugOn: { updateOne: false } }, | ||
slugNoUpdateMany: { type: String, slug: 'title', slugOn: { updateMany: false } }, | ||
slugNoFindOneAndUpdate: { | ||
type: String, | ||
slug: 'title', | ||
on: { findOneAndUpdate: false }, | ||
slugOn: { findOneAndUpdate: false }, | ||
}, | ||
@@ -91,0 +91,0 @@ }); |
@@ -8,3 +8,3 @@ 'use strict'; | ||
const tellme = require('./../tellme'); | ||
const { options, slug_padding_size, nIterations } = require('./../options'); | ||
const { options, slugPaddingSize, nIterations } = require('./../options'); | ||
@@ -18,3 +18,3 @@ const InlineSchema = new mongoose.Schema({ | ||
slugShort: { type: String, slug: 'title', unique: true }, | ||
slugCounter: { type: String, slug: 'title', unique: true, slug_padding_size }, | ||
slugCounter: { type: String, slug: 'title', unique: true, slugPaddingSize }, | ||
// root slug with absolute path to root title | ||
@@ -35,3 +35,3 @@ absoluteSlug: { type: String, slug: '/title' }, | ||
unique: true, | ||
slug_padding_size, | ||
slugPaddingSize, | ||
}, | ||
@@ -54,3 +54,3 @@ // root slug with relative path to child's subchild title | ||
unique: true, | ||
slug_padding_size, | ||
slugPaddingSize, | ||
}, | ||
@@ -79,3 +79,3 @@ // root slug with relative path to the title of 4th subChildren' element of first children array element | ||
unique: true, | ||
slug_padding_size, | ||
slugPaddingSize, | ||
}, | ||
@@ -137,3 +137,3 @@ child: { | ||
unique: true, | ||
slug_padding_size, | ||
slugPaddingSize, | ||
}, | ||
@@ -693,3 +693,3 @@ // two parents up is a root | ||
slugShort: { type: String, unique: true, slug: 'title' }, | ||
slugCounter: { type: String, slug: 'title', unique: true, slug_padding_size }, | ||
slugCounter: { type: String, slug: 'title', unique: true, slugPaddingSize }, | ||
child: { | ||
@@ -702,3 +702,3 @@ title: { type: String }, | ||
unique: true, | ||
slug_padding_size, | ||
slugPaddingSize, | ||
}, | ||
@@ -714,3 +714,3 @@ }, | ||
unique: true, | ||
slug_padding_size, | ||
slugPaddingSize, | ||
}, | ||
@@ -717,0 +717,0 @@ }, |
@@ -8,3 +8,3 @@ 'use strict'; | ||
const tellme = require('./../tellme'); | ||
const { options, slug_padding_size, nIterations } = require('./../options'); | ||
const { options, slugPaddingSize, nIterations } = require('./../options'); | ||
@@ -366,3 +366,3 @@ const SubChildSchema = new mongoose.Schema({ | ||
slugShort: { type: String, slug: 'title', unique:true }, | ||
slugCounter: { type: String, slug: 'title', unique:true, slug_padding_size }, | ||
slugCounter: { type: String, slug: 'title', unique:true, slugPaddingSize }, | ||
}); | ||
@@ -374,3 +374,3 @@ | ||
slugShort: { type: String, slug: 'title', unique:true }, | ||
slugCounter: { type: String, slug: 'title', unique:true, slug_padding_size }, | ||
slugCounter: { type: String, slug: 'title', unique:true, slugPaddingSize }, | ||
child: UniqueChildSchema, | ||
@@ -377,0 +377,0 @@ children: [UniqueChildSchema], |
@@ -9,3 +9,3 @@ 'use strict'; | ||
nIterations: 15, | ||
slug_padding_size: 4, | ||
slugPaddingSize: 4, | ||
}; |
'use strict'; | ||
const _ = require('lodash'); | ||
const { options, slug_padding_size } = require('./options'); | ||
const { options, slugPaddingSize } = require('./options'); | ||
const slugify = require('speakingurl'); | ||
@@ -34,3 +34,3 @@ | ||
return ( | ||
getSlug(index) + options.separator + _.padStart(n, slug_padding_size, '0') | ||
getSlug(index) + options.separator + _.padStart(n, slugPaddingSize, '0') | ||
); | ||
@@ -37,0 +37,0 @@ return getSlug(index); |
@@ -12,3 +12,3 @@ 'use strict'; | ||
nIterations, | ||
slug_padding_size, | ||
slugPaddingSize, | ||
GroupedUniqueCounter, | ||
@@ -15,0 +15,0 @@ GroupedUniqueShortId, |
526
175712
4353