CoolFace
Apppublic

strong-tie/inbound-calls

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
pluginUtils.js168 linesDownload Raw Back to lib
1'use strict'2 3const semver = require('semver')4const assert = require('node:assert')5const kRegisteredPlugins = Symbol.for('registered-plugin')6const {7  kTestInternals8} = require('./symbols.js')9const { exist, existReply, existRequest } = require('./decorate')10const {11  FST_ERR_PLUGIN_VERSION_MISMATCH,12  FST_ERR_PLUGIN_NOT_PRESENT_IN_INSTANCE,13  FST_ERR_PLUGIN_INVALID_ASYNC_HANDLER14} = require('./errors')15 16function getMeta (fn) {17  return fn[Symbol.for('plugin-meta')]18}19 20function getPluginName (func) {21  const display = getDisplayName(func)22  if (display) {23    return display24  }25 26  // let's see if this is a file, and in that case use that27  // this is common for plugins28  const cache = require.cache29  // cache is undefined inside SEA30  if (cache) {31    const keys = Object.keys(cache)32 33    for (let i = 0; i < keys.length; i++) {34      const key = keys[i]35      if (cache[key].exports === func) {36        return key37      }38    }39  }40 41  // if not maybe it's a named function, so use that42  if (func.name) {43    return func.name44  }45 46  return null47}48 49function getFuncPreview (func) {50  // takes the first two lines of the function if nothing else works51  return func.toString().split('\n', 2).map(s => s.trim()).join(' -- ')52}53 54function getDisplayName (fn) {55  return fn[Symbol.for('fastify.display-name')]56}57 58function shouldSkipOverride (fn) {59  return !!fn[Symbol.for('skip-override')]60}61 62function checkDependencies (fn) {63  const meta = getMeta(fn)64  if (!meta) return65 66  const dependencies = meta.dependencies67  if (!dependencies) return68  assert(Array.isArray(dependencies), 'The dependencies should be an array of strings')69 70  dependencies.forEach(dependency => {71    assert(72      this[kRegisteredPlugins].indexOf(dependency) > -1,73      `The dependency '${dependency}' of plugin '${meta.name}' is not registered`74    )75  })76}77 78function checkDecorators (fn) {79  const meta = getMeta(fn)80  if (!meta) return81 82  const { decorators, name } = meta83  if (!decorators) return84 85  if (decorators.fastify) _checkDecorators(this, 'Fastify', decorators.fastify, name)86  if (decorators.reply) _checkDecorators(this, 'Reply', decorators.reply, name)87  if (decorators.request) _checkDecorators(this, 'Request', decorators.request, name)88}89 90const checks = {91  Fastify: exist,92  Request: existRequest,93  Reply: existReply94}95 96function _checkDecorators (that, instance, decorators, name) {97  assert(Array.isArray(decorators), 'The decorators should be an array of strings')98 99  decorators.forEach(decorator => {100    const withPluginName = typeof name === 'string' ? ` required by '${name}'` : ''101    if (!checks[instance].call(that, decorator)) {102      throw new FST_ERR_PLUGIN_NOT_PRESENT_IN_INSTANCE(decorator, withPluginName, instance)103    }104  })105}106 107function checkVersion (fn) {108  const meta = getMeta(fn)109  if (meta == null || meta?.fastify == null) return110 111  const requiredVersion = meta.fastify112 113  const fastifyRc = /-(?:rc|pre|alpha).+$/.test(this.version)114  if (fastifyRc === true && semver.gt(this.version, semver.coerce(requiredVersion)) === true) {115    // A Fastify release candidate phase is taking place. In order to reduce116    // the effort needed to test plugins with the RC, we allow plugins targeting117    // the prior Fastify release to be loaded.118    return119  }120  if (requiredVersion && semver.satisfies(this.version, requiredVersion, { includePrerelease: fastifyRc }) === false) {121    // We are not in a release candidate phase. Thus, we must honor the semver122    // ranges defined by the plugin's metadata. Which is to say, if the plugin123    // expects an older version of Fastify than the _current_ version, we will124    // throw an error.125    throw new FST_ERR_PLUGIN_VERSION_MISMATCH(meta.name, requiredVersion, this.version)126  }127}128 129function registerPluginName (fn) {130  const meta = getMeta(fn)131  if (!meta) return132 133  const name = meta.name134  if (!name) return135  this[kRegisteredPlugins].push(name)136  return name137}138 139function checkPluginHealthiness (fn, pluginName) {140  if (fn.constructor.name === 'AsyncFunction' && fn.length === 3) {141    throw new FST_ERR_PLUGIN_INVALID_ASYNC_HANDLER(pluginName)142  }143}144 145function registerPlugin (fn) {146  const pluginName = registerPluginName.call(this, fn) || getPluginName(fn)147  checkPluginHealthiness.call(this, fn, pluginName)148  checkVersion.call(this, fn)149  checkDecorators.call(this, fn)150  checkDependencies.call(this, fn)151  return shouldSkipOverride(fn)152}153 154module.exports = {155  getPluginName,156  getFuncPreview,157  kRegisteredPlugins,158  getDisplayName,159  registerPlugin160}161 162module.exports[kTestInternals] = {163  shouldSkipOverride,164  getMeta,165  checkDecorators,166  checkDependencies167}168