{"size": 4186, "ext": "js", "max_stars_repo_path": "lib/sequelize-sluggify.js", "max_stars_repo_name": "Cyberuben/sequelize-sluggify", "max_stars_repo_stars_event_min_datetime": null, "max_stars_repo_stars_event_max_datetime": null, "max_issues_repo_path": "lib/sequelize-sluggify.js", "max_issues_repo_name": "Cyberuben/sequelize-sluggify", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "lib/sequelize-sluggify.js", "max_forks_repo_name": "Cyberuben/sequelize-sluggify", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": null, "max_issues_count": null, "max_forks_count": null, "avg_line_length": 27.1818181818, "max_line_length": 106, "alphanum_fraction": 0.4672718586}
'use strict';

var slug = require("slug");

class SequelizeSluggify {
    sluggifyModel(Model, options) {
        if(!options) {
            options = {};
        }

        if(typeof options.column === "undefined") {
            options.column = "slug";
        }

        if(typeof options.source === "undefined") {
            throw new Error("options.source is required");
        }

        if(typeof options.source === "string") {
            options.source = [options.source];
        }

        if(!Array.isArray(options.source)) {
            throw new Error("options.source is not a string or array");
        }

        if(typeof options.overwrite === "undefined") {
            options.overwrite = true;
        }

        if(typeof options.suffixSource === "undefined") {
            options.suffixSources = [];
        }

        if(typeof options.reserved === "undefined") {
            options.reserved = [];
        }

        var composeSlug = (instance, fields) => {
            var parts = fields.map(field => instance[field] || " ");

            return slug(parts.join(" "), Object.assign({ lower: true }, options.slugOptions));
        }

        var isAvailable = (slug) => {
            if(options.reserved.indexOf(slug) != -1) {
                return Promise.resolve(false);
            }

            var query = {
                where: {}
            };

            query.where[options.column] = slug;

            return Model.find(query)
            .then((model) => {
                return Promise.resolve(model === null);
            });
        }

        var addFieldSuffix = (instance, count) => {
            if(!count) {
                count = 1;
            }

            if(!options.suffixSource || !Array.isArray(options.suffixSource)) {
                return Promise.resolve();
            }

            var slug = composeSlug(instance, options.source.concat(options.suffixSource.slice(0, count)));

            if(count > options.suffixSource.length) {
                return Promise.resolve(slug);
            }

            return isAvailable(slug)
            .then((available) => {
                if(available) {
                    return Promise.resolve(slug);
                }

                return addFieldSuffix(instance, count + 1);
            });
        };

        var addNumberSuffix = (slug, count) => {
            if(!count) {
                count = 1;
            }

            var suffixedSlug = slug + "-" + count;

            return isAvailable(suffixedSlug)
            .then((available) => {
                if(available) {
                    return Promise.resolve(suffixedSlug);
                }

                return addNumberSuffix(slug, count + 1);
            });
        };

        var handleSluggify = (instance, sequelizeOptions) => {
            var valuesChanged = options.source.some((field) => {
                return instance.changed(field);
            });

            var slug = instance[options.column];

            if(slug && !(options.overwrite && valuesChanged)) {
                return Promise.resolve();
            }

            slug = composeSlug(instance, options.source);

            return isAvailable(slug)
            .then((available) => {
                if(available) {
                    return Promise.resolve(slug);
                }

                return addFieldSuffix(instance);
            })
            .then((newSlug) => {
                if(!newSlug) {
                    return Promise.resolve();
                }

                slug = newSlug;

                return isAvailable(slug);
            })
            .then((available) => {
                if(available) {
                    return Promise.resolve(slug);
                }

                return addNumberSuffix(slug);
            })
            .then((slug) => {
                instance[options.column] = slug;

                return Promise.resolve();
            });
        };

        Model.addHook("beforeCreate", "generateSlug", handleSluggify);
        Model.addHook("beforeUpdate", "generateSlug", handleSluggify);
    }
}

module.exports = new SequelizeSluggify();
