All files / src/lib build-collection.js

13.51% Statements 5/37
0% Branches 0/10
0% Functions 0/14
14.29% Lines 5/35
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138                    1x                             1x                                           1x                             1x                                                                                               1x                                                      
import map from 'lodash/fp/map'
import pipe from 'lodash/fp/pipe'
 
/**
 * Router stack filter constructor
 *
 * @param {string} by The key that will be used to filter the routes
 * @param {string} value The value which to compare to
 * @returns {function(route:object)} The filterStack function
 */
const filterStack = (by, value) =>
	/**
	 * Router stack filter
	 *
	 * @param {object} route The route Layer
	 * @returns {Object[]} An array of routes
	 */
	route => route.stack.filter(route => route[by] === value)
 
/**
 * Checks if the endpoints group folder exists and if not create it
 *
 * @param {Object} collection The collection
 * @returns {Object} The collection
 */
const ensureFolderExists = collection =>
	/**
	 * Checks if the endpoints group folder exists and if not create it
	 *
	 * @param {object} route The route Layer
	 * @returns {*}
	 */
	route => {
		const id = getGroupId(route.regexp.source)
		if (!collection.item.has(id)) {
			collection.item.addFolder(id)
		}
 
		return route
	}
 
/**
 * Cleans a route regexp string to the the groupId
 *
 * @param {String} regex The regex string
 * @returns {string} The sanitized string
 */
const getGroupId = regex => {
	// @todo create better folder labels for first level routes instead of the route path cleaned from the regex
	const matches = regex.match(/\^(.*?)\?/g, '')
	if (matches.length) {
		return matches[0].replace(/[\\^$?]/g, '').slice(0, -1)
	}
	throw new Error(`Could not extract id from ${regex}`)
}
 
/**
 * Add route items to collection
 *
 * @param {object} collection The collection
 * @returns {*} The collection
 */
const addItems = collection =>
	/**
	 * Adds items to the collection
	 *
	 * @param {object} route The route Layer
	 * @returns {*}
	 */
	route => {
		const groupId = getGroupId(route.regexp.source)
		const stack = route.handle.stack
 
		if (!stack.length) {
			return collection
		}
		/**
		 * Recursive helper
		 *
		 * @param {number} index The current index
		 * @returns {*} The collection
		 */
		const r = index => {
			// @todo remove this function from here into a separate function
			const route = stack[index]
 
			if (!route.route) {
				return addItems(collection)(route)
			}
 
			createItemsFromMethods(collection, groupId, route.route)
 
			if (++index > stack.length - 1) {
				return collection
			}
 
			r(index)
		}
 
		return r(0)
	}
 
/**
 * Creates items based on the route methods
 *
 * @param {object} collection The collection
 * @param {string} groupId The group to add the new items to
 * @param {object} route A route layer
 * @returns {String[]} The method names that were added to the collection
 */
const createItemsFromMethods = (collection, groupId, route) => {
	return map(method => {
		collection.item.addToFolder(groupId, `${groupId}${route.path}`, method)
	})(Object.keys(route.methods))
}
 
/**
 * The collection builder
 *
 * @param {object} collection The collection
 * @param {object} router The app router object
 * @param {object} config The config object
 * @returns {Promise<Object>} A pronise that resolves with the built collection
 */
export default async (collection, router, config) => {
	pipe([
		filterStack('name', 'router'),
		routes =>
			map(route =>
				pipe([ensureFolderExists(collection), addItems(collection)])(
					route
				)
			)(routes)
	])(router)
 
	return collection
}