{
	"global Options": {
		"description": "basic setup for mongoose Model",
		"scope": "javascript,typescript",
		"prefix": "bread",
		"body": [
			"/* use in server|main|index.js */",
			"",
			"// set global mongoose-bread options",
			"const { mongooseBread } = require('mongoose-bread')",
			"mongooseBread.options = {",
			"\tdefaultPageSize: ${1:10}, // limits queries to return ${1:10} documents - default: 10",
			"\tmaxPageSize: ${2:100}, // limits queries to return ${2:100} documents max - default: 100",
			"\tparamsIdKey: '${3:id}', // expected request.params.${3:id} to identify a single Resource - default: id",
			"\t// i.e. https://test.org/books/6478d57784fabdbf127d0a2a",
			"\t// => router.get(books/:${3:id}, BookController.read)",
			"\t// => request.params.${3:id} = 6478d57784fabdbf127d0a2a",
			"",
			"\tbulkIdsKey: '${4:_ids}', // expected request.body.${4:_ids} - default: '_ids'",
			"\t// Used for bulk edit|add|destroy|softDelete|rehabilitate ",
			"",
			"\tbulkDocsKey: '${5:_docs}', // expected request.body.${5:_docs} with Array<any> - default: _docs",
			"\t// Used for bulk|edit|add",
			"\t// => request.body: { ${5:_docs}: [{name: 'newDoc#1'}, {name: 'newDoc#2'}] }",
			"",
			"\tallowDiskUse: ${6:false}, // allow MongoDB queries to use more than 100 MB - default: false",
			"\tcustomLabels: { // optional - set custom keys for results",
			"\t\tdocs: '${7:docs}', // default: 'docs'",
			"\t\tlimit: '${8:limit}', // default: 'limit'",
			"\t\tpage: '${9:page}', // default: 'page'",
			"\t\tpagingCounter: '${10:pagingCounter}', // default: 'pagingCounter'",
			"\t\thasNextPage: '${11:hasNextPage}', // default: 'hasNextPage'",
			"\t\thasPrevPage: '${12:hasPrevPage}', // default: 'hasPrevPage'",
			"\t\tnextPage: '${13:nextPage}', // default: 'nextPage'",
			"\t\tprevPage: '${14:prevPage}', // default: 'prevPage'",
			"\t\ttotalDocs: '${15:totalDocs}', // default: 'totalDocs'",
			"\t\ttotalPages: '${16:totalPages}', // default: 'totalPages'",
			"\t\tacknowledged: '${17:acknowledged}', // default: 'acknowledged'",
			"\t\tmodifiedCount: '${18:modifiedCount}', // default: 'modifiedCount'",
			"\t\tdeletedCount: '${19:deletedCount}', // default: 'deletedCount'",
			"\t\tcreatedCount: '${20:createdCount}', // default: 'createdCount'",
			"\t\treadCount: '${21:readCount}', // default: 'readCount'",
			"\t},",
			"}",
			"$0",
		]
	},
	"Model": {
		"description": "basic setup for mongoose Model",
		"scope": "javascript,typescript",
		"prefix": "bread",
		"body": [
			"const mongoose = require(\"mongoose\");",
			"const bread = require(\"mongoose-bread\");",
			"",
			"const ${1:resource}Schema = new mongoose.Schema({",
			"\tname: String,",
			"\t$0",
			"}, {",
			"\ttimestamps: true,",
			"});",
			"",
			"${1:resource}Schema.plugin(bread, {",
			"\t/* lean gets query results as plain js objects - can improve query speed  */",
			"\t// lean: false, // default: false",
			"\t// leanWithId: false, // default: false",
			"\t// leanWithout_id: false, // default: false",
			"",
			"\t/* if searchableFields is ommited search will be disabled for ${1/(.*)/${1:/capitalize}/} */",
			"\tsearchableFields: ['name'],",
			"",
			"\t/* exclude blacklistedFields from all query results */",
			"\tblacklistedFields: ['__v', 'createdAt', 'updatedAt'],",
			"})",
			"",
			"module.exports = mongoose.model('${1/(.*)/${1:/capitalize}/}', ${1:resource}Schema);",
		]
	},
	"softDelete Model": {
		"description": "basic setup for mongoose Model with softDelete enabled",
		"scope": "javascript,typescript",
		"prefix": "bread",
		"body": [
			"const mongoose = require(\"mongoose\");",
			"const bread = require(\"mongoose-bread\");",
			"",
			"const ${1:resource}Schema = new mongoose.Schema({",
			"\tname: String,",
			"\t$0",
			"}, {",
			"\ttimestamps: true,",
			"});",
			"",
			"${1:resource}Schema.plugin(bread, {",
			"\t/* lean gets query results as plain js objects - can improve query speed  */",
			"\t// lean: false, // default: false",
			"\t// leanWithId: false, // default: false",
			"\t// leanWithout_id: false, // default: false",
			"",
			"\t/* if searchableFields is ommited search will be disabled for ${1/(.*)/${1:/capitalize}/} */",
			"\tsearchableFields: ['name'],",
			"",
			"\t/* exclude blacklistedFields from all query results */",
			"\tblacklistedFields: ['__v', 'deleted', 'deletedAt', 'deletedBy', 'createdAt', 'updatedAt'],",
			"",
			"\t/* enables softDelete */",
			"\tsoftDelete: true,",
			"\tsoftDeleteOptions: {",
			"\t\tdeletedAt: true, // default: true",
			"\t\tdeletedBy: true, // default: false",
			"\t\trequestUserIdPath: 'auth.user.id' // default: ''",
			"\t}",
			"})",
			"",
			"module.exports = mongoose.model('${1/(.*)/${1:/capitalize}/}', ${1:resource}Schema);",
		]
	},
	"Controller": {
		"description": "basic setup for bread controller",
		"scope": "javascript,typescript",
		"prefix": "bread",
		"body": [
			"const ${1:Resource} = require(\"../Models/${1:Resource}\")",
			"",
			"function catchAsync(fn) { return (req, res, next) => { fn(req, res, next).catch(next) } }",
			"",
			"${0:/* use \"bread softDelete Controller\" snippet if pluginOptions.softDelete = true */}",
			"",
			"module.exports = {",
			"\tbrowse: catchAsync(async (req, res) => {",
			"\t\tconst options = ${1:Resource}.breadHelper().createBrowseOptions(req)",
			"\t\tconst result = await ${1:Resource}.browse(options)",
			"\t\tres.status(200).json({",
			"\t\t\tmessage: req.query.search ? 'search' : 'browse',",
			"\t\t\tresult,",
			"\t\t})",
			"\t}),",
			"\tread: catchAsync(async (req, res) => {",
			"\t\tconst options = ${1:Resource}.breadHelper().createReadOptions(req)",
			"\t\tconst result = await ${1:Resource}.read(options)",
			"\t\tres.status(200).json({ message: 'read', result })",
			"\t}),",
			"\tedit: catchAsync(async (req, res) => {",
			"\t\tconst options = ${1:Resource}.breadHelper().createEditOptions(req)",
			"\t\tconst result = await ${1:Resource}.edit(options)",
			"\t\tres.status(200).json({ message: 'edit', result })",
			"\t}),",
			"\tadd: catchAsync(async (req, res) => {",
			"\t\tconst options = ${1:Resource}.breadHelper().createAddOptions(req)",
			"\t\tconst result = await ${1:Resource}.add(options)",
			"\t\tres.status(200).json({ message: 'add', result })",
			"\t}),",
			"\tdestroy: catchAsync(async (req, res) => {",
			"\t\tconst options = ${1:Resource}.breadHelper().createDeleteOptions(req)",
			"\t\tconst result = await ${1:Resource}.destroy(options)",
			"\t\tres.status(200).json({ message: 'destroy', result })",
			"\t}),",
			"}",
		]
	},
	"softDelete Controller": {
		"description": "basic setup for bread controller",
		"scope": "javascript,typescript",
		"prefix": "bread",
		"body": [
			"const ${1:Resource} = require(\"../Models/${1:Resource}\")",
			"",
			"function catchAsync(fn) { return (req, res, next) => { fn(req, res, next).catch(next) } }",
			"",
			"${0:/* use \"bread Controller\" snippet if pluginOptions.softDelete = false */}",
			"",
			"module.exports = {",
			"\tbrowse: catchAsync(async (req, res) => {",
			"\t\tconst options = ${1:Resource}.breadHelper().createBrowseOptions(req)",
			"\t\tconst result = await ${1:Resource}.browse(options)",
			"\t\tres.status(200).json({",
			"\t\t\tmessage: req.query.search ? 'search' : 'browse',",
			"\t\t\tresult,",
			"\t\t})",
			"\t}),",
			"\tread: catchAsync(async (req, res) => {",
			"\t\tconst options = ${1:Resource}.breadHelper().createReadOptions(req)",
			"\t\tconst result = await ${1:Resource}.read(options)",
			"\t\tres.status(200).json({ message: 'read', result })",
			"\t}),",
			"\tedit: catchAsync(async (req, res) => {",
			"\t\tconst options = ${1:Resource}.breadHelper().createEditOptions(req)",
			"\t\tconst result = await ${1:Resource}.edit(options)",
			"\t\tres.status(200).json({ message: 'edit', result })",
			"\t}),",
			"\tadd: catchAsync(async (req, res) => {",
			"\t\tconst options = ${1:Resource}.breadHelper().createAddOptions(req)",
			"\t\tconst result = await ${1:Resource}.add(options)",
			"\t\tres.status(200).json({ message: 'add', result })",
			"\t}),",
			"\tdestroy: catchAsync(async (req, res) => {",
			"\t\tconst options = ${1:Resource}.breadHelper().createDeleteOptions(req)",
			"\t\tconst result = await ${1:Resource}.destroy(options)",
			"\t\tres.status(200).json({ message: 'destroy', result })",
			"\t}),",
			"",
			"\t/* softDelete methods */",
			"\tbrowseDeleted: catchAsync(async (req, res) => {",
			"\t\tconst options = ${1:Resource}.breadHelper().createBrowseDeletedOptions(req)",
			"\t\tconst result = await ${1:Resource}.browse(options)",
			"\t\tres.status(200).json({",
			"\t\t\tmessage: req.query.search ? 'searchDeleted' : 'browseDeleted',",
			"\t\t\tresult,",
			"\t\t})",
			"\t}),",
			"\treadDeleted: catchAsync(async (req, res) => {",
			"\t\tconst options = ${1:Resource}.breadHelper().createReadDeletedOptions(req)",
			"\t\tconst result = await ${1:Resource}.read(options)",
			"\t\tres.status(200).json({ message: 'readDeleted', result })",
			"\t}),",
			"\tsoftDelete: catchAsync(async (req, res) => {",
			"\t\tconst options = ${1:Resource}.breadHelper().createDeleteOptions(req)",
			"\t\tconst result = await ${1:Resource}.softDelete(options)",
			"\t\tres.status(200).json({ message: 'softDelete', result })",
			"\t}),",
			"\trehabilitate: catchAsync(async (req, res) => {",
			"\t\tconst options = ${1:Resource}.breadHelper().createRehabilitateOptions(req)",
			"\t\tconst result = await ${1:Resource}.rehabilitate(options)",
			"\t\tres.status(200).json({ message: 'rehabilitate', result })",
			"\t}),",
			"\t",
			"}",
		]
	},
	"Router": {
		"description": "basic setup for bread routes",
		"scope": "javascript,typescript",
		"prefix": "bread",
		"body": [
			"const express = require(\"express\");",
			"const ${1:ResourceController} = require(\"../Controller/${1:ResourceController}\");",
			"",
			"const router = express.Router()",
			"router.use(${2:auth-middleware})",
			"",
			"/* use \"bread softDelete Router\" snippet if pluginOptions.softDelete = true */",
			"",
			"router.get(   '/:id', ${3:middleware}, ${1:ResourceController}.read)",
			"router.patch( '/:id', ${3:middleware}, ${1:ResourceController}.edit)",
			"router.delete('/:id', ${3:middleware}, ${1:ResourceController}.destroy)",
			"router.get(   '/',    ${3:middleware}, ${1:ResourceController}.browse)",
			"router.patch( '/',    ${3:middleware}, ${1:ResourceController}.edit)",
			"router.delete('/',    ${3:middleware}, ${1:ResourceController}.destroy)",
			"router.post(  '/',    ${3:middleware}, ${1:ResourceController}.add)",
			"",
			"module.exports = router",
		]
	},
	"softDelete Router": {
		"description": "basic setup for bread routes with softDelete",
		"scope": "javascript,typescript",
		"prefix": "bread",
		"body": [
			"const express = require(\"express\");",
			"const ${1:ResourceController} = require(\"../Controller/${1:ResourceController}\");",
			"",
			"const router = express.Router()",
			"router.use(${2:auth-middleware})",
			"",
			"/* use \"bread Router\" snippet if pluginOptions.softDelete = false */",
			"",
			"router.get(   '/bin/:id', ${3:middleware}, ${1:ResourceController}.readDeleted)",
			"router.patch( '/bin/:id', ${3:middleware}, ${1:ResourceController}.rehabilitate)",
			"router.delete('/bin/:id', ${3:middleware}, ${1:ResourceController}.destroy)",
			"router.get(   '/bin',     ${3:middleware}, ${1:ResourceController}.browseDeleted)",
			"router.patch( '/bin',     ${3:middleware}, ${1:ResourceController}.rehabilitate)",
			"router.delete('/bin',     ${3:middleware}, ${1:ResourceController}.destroy)",
			"router.get(   '/:id',     ${3:middleware}, ${1:ResourceController}.read)",
			"router.patch( '/:id',     ${3:middleware}, ${1:ResourceController}.edit)",
			"router.delete('/:id',     ${3:middleware}, ${1:ResourceController}.softDelete)",
			"router.get(   '/',        ${3:middleware}, ${1:ResourceController}.browse)",
			"router.patch( '/',        ${3:middleware}, ${1:ResourceController}.edit)",
			"router.delete('/',        ${3:middleware}, ${1:ResourceController}.softDelete)",
			"router.post(  '/',        ${3:middleware}, ${1:ResourceController}.add)",
			"",
			"module.exports = router",
		]
	}
}