You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					141 lines
				
				3.4 KiB
			
		
		
			
		
	
	
					141 lines
				
				3.4 KiB
			| 
											3 years ago
										 | 'use strict' | ||
|  | 
 | ||
|  | const semver = require('semver') | ||
|  | const assert = require('assert') | ||
|  | const registeredPlugins = Symbol.for('registered-plugin') | ||
|  | const { | ||
|  |   kTestInternals | ||
|  | } = require('./symbols.js') | ||
|  | const { exist, existReply, existRequest } = require('./decorate') | ||
|  | const { FST_ERR_PLUGIN_VERSION_MISMATCH } = require('./errors') | ||
|  | 
 | ||
|  | function getMeta (fn) { | ||
|  |   return fn[Symbol.for('plugin-meta')] | ||
|  | } | ||
|  | 
 | ||
|  | function getPluginName (func) { | ||
|  |   const display = getDisplayName(func) | ||
|  |   if (display) { | ||
|  |     return display | ||
|  |   } | ||
|  | 
 | ||
|  |   // let's see if this is a file, and in that case use that
 | ||
|  |   // this is common for plugins
 | ||
|  |   const cache = require.cache | ||
|  |   const keys = Object.keys(cache) | ||
|  | 
 | ||
|  |   for (let i = 0; i < keys.length; i++) { | ||
|  |     const key = keys[i] | ||
|  |     if (cache[key].exports === func) { | ||
|  |       return key | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   // if not maybe it's a named function, so use that
 | ||
|  |   if (func.name) { | ||
|  |     return func.name | ||
|  |   } | ||
|  | 
 | ||
|  |   return null | ||
|  | } | ||
|  | 
 | ||
|  | function getFuncPreview (func) { | ||
|  |   // takes the first two lines of the function if nothing else works
 | ||
|  |   return func.toString().split('\n').slice(0, 2).map(s => s.trim()).join(' -- ') | ||
|  | } | ||
|  | 
 | ||
|  | function getDisplayName (fn) { | ||
|  |   return fn[Symbol.for('fastify.display-name')] | ||
|  | } | ||
|  | 
 | ||
|  | function shouldSkipOverride (fn) { | ||
|  |   return !!fn[Symbol.for('skip-override')] | ||
|  | } | ||
|  | 
 | ||
|  | function checkDependencies (fn) { | ||
|  |   const meta = getMeta(fn) | ||
|  |   if (!meta) return | ||
|  | 
 | ||
|  |   const dependencies = meta.dependencies | ||
|  |   if (!dependencies) return | ||
|  |   assert(Array.isArray(dependencies), 'The dependencies should be an array of strings') | ||
|  | 
 | ||
|  |   dependencies.forEach(dependency => { | ||
|  |     assert( | ||
|  |       this[registeredPlugins].indexOf(dependency) > -1, | ||
|  |       `The dependency '${dependency}' of plugin '${meta.name}' is not registered` | ||
|  |     ) | ||
|  |   }) | ||
|  | } | ||
|  | 
 | ||
|  | function checkDecorators (fn) { | ||
|  |   const meta = getMeta(fn) | ||
|  |   if (!meta) return | ||
|  | 
 | ||
|  |   const { decorators, name } = meta | ||
|  |   if (!decorators) return | ||
|  | 
 | ||
|  |   if (decorators.fastify) _checkDecorators(this, 'Fastify', decorators.fastify, name) | ||
|  |   if (decorators.reply) _checkDecorators(this, 'Reply', decorators.reply, name) | ||
|  |   if (decorators.request) _checkDecorators(this, 'Request', decorators.request, name) | ||
|  | } | ||
|  | 
 | ||
|  | const checks = { | ||
|  |   Fastify: exist, | ||
|  |   Request: existRequest, | ||
|  |   Reply: existReply | ||
|  | } | ||
|  | 
 | ||
|  | function _checkDecorators (that, instance, decorators, name) { | ||
|  |   assert(Array.isArray(decorators), 'The decorators should be an array of strings') | ||
|  | 
 | ||
|  |   decorators.forEach(decorator => { | ||
|  |     const withPluginName = typeof name === 'string' ? ` required by '${name}'` : '' | ||
|  |     if (!checks[instance].call(that, decorator)) { | ||
|  |       throw new Error(`The decorator '${decorator}'${withPluginName} is not present in ${instance}`) | ||
|  |     } | ||
|  |   }) | ||
|  | } | ||
|  | 
 | ||
|  | function checkVersion (fn) { | ||
|  |   const meta = getMeta(fn) | ||
|  |   if (!meta) return | ||
|  | 
 | ||
|  |   const requiredVersion = meta.fastify | ||
|  |   if (!requiredVersion) return | ||
|  | 
 | ||
|  |   if (!semver.satisfies(this.version, requiredVersion)) throw new FST_ERR_PLUGIN_VERSION_MISMATCH(meta.name, requiredVersion, this.version) | ||
|  | } | ||
|  | 
 | ||
|  | function registerPluginName (fn) { | ||
|  |   const meta = getMeta(fn) | ||
|  |   if (!meta) return | ||
|  | 
 | ||
|  |   const name = meta.name | ||
|  |   if (!name) return | ||
|  |   this[registeredPlugins].push(name) | ||
|  | } | ||
|  | 
 | ||
|  | function registerPlugin (fn) { | ||
|  |   registerPluginName.call(this, fn) | ||
|  |   checkVersion.call(this, fn) | ||
|  |   checkDecorators.call(this, fn) | ||
|  |   checkDependencies.call(this, fn) | ||
|  |   return shouldSkipOverride(fn) | ||
|  | } | ||
|  | 
 | ||
|  | module.exports = { | ||
|  |   getPluginName, | ||
|  |   getFuncPreview, | ||
|  |   registeredPlugins, | ||
|  |   getDisplayName, | ||
|  |   registerPlugin | ||
|  | } | ||
|  | 
 | ||
|  | module.exports[kTestInternals] = { | ||
|  |   shouldSkipOverride, | ||
|  |   getMeta, | ||
|  |   checkDecorators, | ||
|  |   checkDependencies | ||
|  | } |