mirror of
				https://github.com/strapi/strapi.git
				synced 2025-10-31 01:47:13 +00:00 
			
		
		
		
	
		
			
	
	
		
			186 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			186 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|   | 'use strict'; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Module dependencies | ||
|  |  */ | ||
|  | 
 | ||
|  | // Public node modules.
 | ||
|  | const _ = require('lodash'); | ||
|  | const includeAll = require('include-all'); | ||
|  | 
 | ||
|  | /** | ||
|  |  * dictionary | ||
|  |  * | ||
|  |  * Go through each object, include the code, and determine its identity. | ||
|  |  * Tolerates non-existent files/directories by ignoring them. | ||
|  |  * | ||
|  |  * | ||
|  |  * Options: | ||
|  |  * | ||
|  |  *   - `dirname`: The path to the source directory. | ||
|  |  * | ||
|  |  *   - `identity`: If disabled, (explicitly set to false) don't inject an identity | ||
|  |  *      into the module. Also don't try to use the bundled `identity` property in | ||
|  |  *      the module to determine the keyname in the result object. | ||
|  |  *      Defaults to: `true` | ||
|  |  * | ||
|  |  *   - `optional`: If enabled, fail silently and return `{}` when source directory | ||
|  |  *      does not exist or cannot be read (otherwise, exit with an error). | ||
|  |  *      Defaults to: `false` | ||
|  |  * | ||
|  |  *   - `depth`: The level of recursion where modules will be included. | ||
|  |  * | ||
|  |  *   - `filter`: Only include modules whose `filename` matches this regex. | ||
|  |  *      Defaults to: `undefined` | ||
|  |  * | ||
|  |  *   - `pathFilter: Only include modules whose full relative path matches this regex
 | ||
|  |  *     (relative from the entry point directory). | ||
|  |  *      Defaults to: `undefined` | ||
|  |  * | ||
|  |  *   - `replaceExpr`: In identity: use this regex to remove substrings like 'Controller' or | ||
|  |  *     'Service' and replace them with the value of `replaceVal`. | ||
|  |  * | ||
|  |  *   - `dontLoad`: If `dontLoad` is set to `true`, don't run the module with V8 or load it | ||
|  |  *      into memory. Instead, return a tree representing the directory structure | ||
|  |  *      (all extant file leaves are included as keys, with their value = `true`). | ||
|  |  * | ||
|  |  *   - `useGlobalIdForKeyName: If set to true, don't lowercase the identity to get
 | ||
|  |  *      the keyname-- just use the globalId. | ||
|  |  */ | ||
|  | 
 | ||
|  | module.exports = dictionary; | ||
|  | 
 | ||
|  | function dictionary(options, cb) { | ||
|  | 
 | ||
|  |   // Defaults.
 | ||
|  |   options.replaceVal = options.replaceVal || ''; | ||
|  | 
 | ||
|  |   // Deliberately exclude source control directories.
 | ||
|  |   if (!options.excludeDirs) { | ||
|  |     options.excludeDirs = /^\.(git|svn)$/; | ||
|  |   } | ||
|  | 
 | ||
|  |   const files = includeAll(options); | ||
|  | 
 | ||
|  |   // Start building the module dictionary.
 | ||
|  |   let dictionary = {}; | ||
|  | 
 | ||
|  |   // Iterate through each module in the set.
 | ||
|  |   _.forEach(files, function (module, filename) { | ||
|  | 
 | ||
|  |     // Build the result object by merging all of the target modules
 | ||
|  |     // NOTE: Each module must export an object in order for this to work
 | ||
|  |     // (e.g. for building a configuration object from a set of config files)
 | ||
|  |     if (options.aggregate) { | ||
|  | 
 | ||
|  |       // Check that source module is a valid object.
 | ||
|  |       if (!_.isPlainObject(module)) { | ||
|  |         return cb(new Error('Invalid module:' + module)); | ||
|  |       } | ||
|  | 
 | ||
|  |       // Merge module into dictionary.
 | ||
|  |       _.merge(dictionary, module); | ||
|  | 
 | ||
|  |       return; | ||
|  |     } | ||
|  | 
 | ||
|  |     // Keyname is how the module will be identified in the returned module tree.
 | ||
|  |     let keyName = filename; | ||
|  | 
 | ||
|  |     // If a module is found but marked as `undefined`,
 | ||
|  |     // don't actually include it (since it's probably unusable).
 | ||
|  |     if (typeof module === 'undefined') { | ||
|  |       return; | ||
|  |     } | ||
|  | 
 | ||
|  |     // Unless the `identity` option is explicitly disabled,
 | ||
|  |     // (or `dontLoad` is set).
 | ||
|  |     if (!options.dontLoad && options.identity !== false) { | ||
|  | 
 | ||
|  |       // If no `identity` property is specified in module, infer it from the filename.
 | ||
|  |       if (!module.identity) { | ||
|  |         if (options.replaceExpr) { | ||
|  |           module.identity = filename.replace(options.replaceExpr, options.replaceVal); | ||
|  |         } else { | ||
|  |           module.identity = filename; | ||
|  |         } | ||
|  |       } | ||
|  | 
 | ||
|  |       // `globalId` is the name of the variable for this module
 | ||
|  |       // that will be exposed globally in Strapi unless configured otherwise
 | ||
|  |       // Generate `globalId` using the original value of `module.identity`.
 | ||
|  |       if (!module.globalId) { | ||
|  |         module.globalId = module.identity; | ||
|  |       } | ||
|  | 
 | ||
|  |       // `identity` is the all-lowercase version
 | ||
|  |       module.identity = module.identity.toLowerCase(); | ||
|  | 
 | ||
|  |       // Use the identity for the key name.
 | ||
|  |       keyName = options.useGlobalIdForKeyName ? module.globalId : module.identity; | ||
|  |     } | ||
|  | 
 | ||
|  |     // Save the module's contents in our dictionary object
 | ||
|  |     // (this will actually just be `true` if the `dontLoad` option is set).
 | ||
|  |     dictionary[keyName] = module; | ||
|  |   }); | ||
|  | 
 | ||
|  |   // Always return at least an empty object.
 | ||
|  |   dictionary = dictionary || {}; | ||
|  | 
 | ||
|  |   return cb(null, dictionary); | ||
|  | } | ||
|  | 
 | ||
|  | /** | ||
|  |  * Build a dictionary of named modules | ||
|  |  * (responds with an error if the container cannot be loaded). | ||
|  |  * | ||
|  |  * @param {Object} options | ||
|  |  * @param {Function} cb | ||
|  |  */ | ||
|  | 
 | ||
|  | module.exports.required = function (options, cb) { | ||
|  |   return dictionary(options, cb); | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Build a dictionary of named modules | ||
|  |  * (fails silently, returns {} if the container cannot be loaded). | ||
|  |  * | ||
|  |  * @param {Object} options | ||
|  |  * @param {Function} cb | ||
|  |  */ | ||
|  | 
 | ||
|  | module.exports.optional = function (options, cb) { | ||
|  |   options.optional = true; | ||
|  |   return dictionary(options, cb); | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Build a dictionary indicating whether the matched modules exist | ||
|  |  * (fails silently, returns {} if the container cannot be loaded). | ||
|  |  * | ||
|  |  * @param {Object} options | ||
|  |  * @param {Function} cb | ||
|  |  */ | ||
|  | 
 | ||
|  | module.exports.exists = function (options, cb) { | ||
|  |   options.optional = true; | ||
|  |   options.dontLoad = false; | ||
|  |   return dictionary(options, cb); | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Build a single module object by extending {} with the contents of each module | ||
|  |  * (fail silently, returns {} if the container cannot be loaded). | ||
|  |  * | ||
|  |  * @param {Object} options | ||
|  |  * @param {Function} cb | ||
|  |  */ | ||
|  | 
 | ||
|  | module.exports.aggregate = function (options, cb) { | ||
|  |   options.aggregate = true; | ||
|  |   options.optional = true; | ||
|  |   return dictionary(options, cb); | ||
|  | }; |