Skip to content

Mongoose plugin to automatically generate so called slugs (atomically)

License

Notifications You must be signed in to change notification settings

neol-co/mongoose-slugger

 
 

Repository files navigation

Slugger for Mongoose

Build Status codecov npm version

Automatically generates so called “slugs” for Mongoose documents. Slugs are typically used as human-readable parts of URLs instead of machine-readable identifiers (see e.g. here or here).

In case a slug is already taken by an existing document, the plugin automatically creates a new one (typically using a sequence number) and keeps trying until the document can be saved successfully.

When correctly configured, the plugin will do the following:

Model.create({ firstname: 'john', lastname: 'doe' }); // slug = 'john-doe'
Model.create({ firstname: 'jane', lastname: 'roe' }); // slug = 'jane-roe'
Model.create({ firstname: 'john', lastname: 'doe' }); // slug = 'john-doe-2'

There exist several similar Mongoose plugins already, however, none of them fit our requirements. These are:

  • We do not want to maintain a separate collection for storing any state.

  • Saving with a generated slug must work atomically. This means: First performing a query to check whether a slug is not yet taken and then saving a document is not acceptable!

  • We need the ability for “scoped” slugs. This means: Slugs can be unique with regards to other document properties (e.g. have unique person name slugs in regards to a place, …)

  • Must work with callbacks and promises.

  • It must be possible to specify the slug generation strategy.

Caveats

  1. For now, only one slugger instance per schema can be used.

  2. In the very worst case, this will perform a very high amount of attempts to insert. This is by design, as we assume that potential conflicts are relatively rare and, if they happen, can be circumvented by an acceptable amount of retries.

  3. Only works with MongoDB’s (default) “WiredTiger” storage engine. This is due to the fact that other engines product differently structured error types which do not contain the necessary index information.

Installation

$ yarn add mongoose-slugger-plugin

Usage

Note: A complete, working example is available in this repository.

const schema = new mongoose.Schema({
  firstname: String,
  lastname: String,
  city: String,
  slug: String
});

// create a unique index for slug generation;
// here, the slugs must be unique for each city
schema.index({ city: 1, slug: 1 }, { name: 'city_slug', unique: true });

// create the configuration
const sluggerOptions = new slugger.SluggerOptions({
  // the property path which stores the slug value
  slugPath: 'slug',
  // specify the properties which will be used for generating the slug
  generateFrom: [ 'firstname', 'lastname' ],
  // the unique index, see above
  index: 'city_slug'
});

// add the plugin
schema.plugin(slugger.plugin, sluggerOptions);

let Model = mongoose.model('MyModel', schema);

// make sure to wrap the Mongoose model
Model = slugger.wrap(Model);

Development

Install NPM dependencies with yarn.

To execute the tests, run the test task. It starts a new MongoDB instance using @shelf/jest-mongodb and then executes the test cases. The test coverage report can be found in coverage/index.html.

For the best development experience, make sure that your editor supports ESLint and EditorConfig.

Linting of code and commit message happens on commit via Husky.

Releasing to NPM

Commit all changes and run the following:

$ npm login
$ yarn version --<update_type>
$ npm publish

… where <update_type> is one of patch, minor, or major. This will update the package.json, and create a tagged Git commit with the version number.

Why yet Another Tool?

There’s a plethora of similar plugins, most of them old and abandoned though. Here’s a list, sorted by recent activity (first was updated recently when writing this):

Contributing

Pull requests are very welcome. Feel free to discuss bugs or new features by opening a new issue.


Copyright Philipp Katz, LineUpr GmbH, 2018 – 2021

About

Mongoose plugin to automatically generate so called slugs (atomically)

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 76.9%
  • JavaScript 23.1%