UNPKG

@homer0/prettier-plugin-jsdoc

Version:
131 lines (127 loc) 4.01 kB
import path from 'node:path'; import { createRequire } from 'node:module'; /** * The actual dependency injection container. The keys will be the original functions, and * the values may be the same, or the overrides. * * @type {Map<Function, Function>} */ export const container = new Map(); /** * This secret exists so when {@link registerModule} gets called with a raw * `module.exports`, it can safely skip a provider, as providers created with * {@link createProvider} have this secret as a property. * * @type {symbol} */ const providerKey = Symbol('provider-secret'); /** * Adds a new function to the container. * * @param {Function} originalFn The reference for the original function. */ export const register = (originalFn) => { container.set(originalFn, originalFn); }; /** * Overrides a function on the container. * * @param {OG} originalFn The reference for the original function. * @param {OG} fn The override function. * @template OG */ export const override = (originalFn, fn) => { container.set(originalFn, fn); }; /** * Gets a function or a function override from the container. * * @param {OG} originalFn The reference for the original function. * @returns {OG} * @template OG */ export const get = (originalFn) => container.get(originalFn) || originalFn; /** * Registers a list or a dictionary of functions for a module. The idea of this function * is that it can be easily use to register a `module.exports`. Check the example. * * @param {string} id * The ID of the module; it will be added as the `moduleId` property of the functions. * @param {Function[] | Object.<string, Function>} fns * The list or dictionary of functions. * @example * * module.exports.myFn = myFn; * module.exports.myOtherFn = myOtherFn; * registerModule('my-mod', module.exports); * */ export const registerModule = (id, fns) => { const useFns = Array.isArray(fns) ? fns : Object.values(fns); useFns .filter((fn) => fn.providerKey !== providerKey) .forEach((fn) => { // eslint-disable-next-line no-param-reassign fn.moduleId = id; register(fn); }); }; /** * Creates a "module provider": a function that when called, it will execute * {@link registerModule}. * The idea of the providers is that they can be executed on runtime, or on a * "registration step". * * @param {string} id * The ID of the module. * @param {Function[] | Object.<string, Function>} fns * The list or dictionary of functions. * @returns {Function} */ export const createProvider = (id, fns) => { /** * The function that when executed will take care of registering the module. */ const fn = () => { registerModule(id, fns); }; fn.providerKey = providerKey; return fn; }; /** * Creates a "module provider": a function that when called, it will execute * {@link registerModule}. * The idea of the providers is that they can be executed on runtime, or on a * "registration step". * * @param {string} id * The ID of the module. * @param {Function[] | Object.<string, Function>} fns * The list or dictionary of functions. * @returns {Function} * @deprecated * Use `createProvider` instead. */ export const provider = createProvider; /** * Loads a list of files, takes their `provider` export (if present) and executes it. * * @param {string} directoryPath The path of where the `list` of files is located. * @param {string[]} list A list of files with a `provider` export that should * be executed. */ export const loadProviders = (directoryPath, list) => { const require = createRequire(import.meta.url); list .map((modName) => { // eslint-disable-next-line import-x/no-dynamic-require const { provider: modProvider } = require( path.join(directoryPath, `${modName}.js`), ); return modProvider; }) .filter((modProvider) => modProvider) .forEach((modProvider) => { modProvider(); }); };