Проверка типов объектов пространства имен модуля в NodeJS в качестве встроенного, локального или внешнего модуля с поддержкой операторов require и import? - PullRequest
0 голосов
/ 01 августа 2020

Встроенный модуль util узла предлагает метод проверки того, является ли модуль допустимым Объект пространства имен модуля . Но его использование ограничено только модулями, загруженными с помощью операторов import и , имеющих принудительное имя модуля.

От узла util docs

/* The two lines below are assumed (Not in original docs) */
import util from 'util'        // load built-in module via import (works)
const util = require('util')   // load built-in module via require (CommonJS, also works)


import * as ns from './a.js';  // import module with "coerced" namespace

let checkType = util.types.isModuleNamespaceObject(ns);

console.log(checkType)         // Returns true

С .isModuleNamespaceObject(<module>), который является рабочим узлом API, предлагает.

Однако , следующие примеры НЕ работают

1. import модуль как экспорт в пространство имен из файла (локального)

// Assume util module is already imported/required

import { ns } from './a.js';  // Assumes "a.js" has an export "ns"

let checkType = util.types.isModuleNamespaceObject(ns);

console.log(checkType)        // Returns false

2. import модуль как экспорт по умолчанию из файла (локальный)

// Assume util module is already imported/required

import ns from './a.js';  // Assumes "a.js" has default export

let checkType = util.types.isModuleNamespaceObject(ns);

console.log(checkType)        // Returns false

3. require модуль как экспорт в пространство имен из файла (локального)

// Assume util module is already imported/required

const { ns } = require('./a.js');  // Assumes "a.js" exports "ns"

let checkType = util.types.isModuleNamespaceObject(ns);

console.log(checkType)        // Returns false

4. require модуль как экспорт по умолчанию из файла (локальный)

// Assume util module is already imported/required

const ns = require('./a.js');  // Assumes "a.js" provides default export using
                               // "module.exports", otherwise ".default" would
                               // need to be appended to the require statement
                               // had "a.js" provided default export using 
                               // "export default". 
                               // Also assumes no external module or config exists 
                               // that messes with Node's module resolution (i.e. esm)

let checkType = util.types.isModuleNamespaceObject(ns);

console.log(checkType)        // Returns false

Существует ли существующий способ ввода модулей проверки, который удовлетворяет каждому приведенному выше нерабочему примеру?

и (при условии, что на первый вопрос можно ответить «да» и как)

Существует ли способ указать модули проверки как встроенные, локальные или внешние?

Где:

встроенный относится к модулю, доступному во время выполнения узла (например, «os», «http», «net» и c.)

local относится к модулю, загруженному через файл (т.е. «./a.js")

external относится к модулю, в котором для загрузки сначала требуется удаленная загрузка через реестр (например, «loda sh», «bluebird», «moment» и т. Д. c .)

Где я сейчас пытаюсь понять это ...

Мне совсем не повезло с вопросом 1.

  • Собственный объект module узла ( также доступен как import/require) предлагает ключ id, но после загрузки модуля его значением является путь к файлу, из которого он был загружен. module.exports и module.children также не очень помогают.
  • Собственный объект узла require предлагает .cache, но это считается ненадежным, и метод .resolve, но он должен вызываться вместе с модуль require выписка. Тем не менее, возвращаемое значение - это путь к файлу, в который экспортируется модуль.
  • Собственный объект process узла предлагает отличный метод .binding(<module_name>), который будет работать, но для этого требуется <module_name> может быть задано как typeof <module_name> === 'string'.

На вопрос 2 нетрудно найти работоспособное решение.

  • встроено типы модулей могут быть проверены с использованием возвращаемого значения из process.builtIns, которое является array встроенными модулями в виде строк, доступных Node во время выполнения.
  • локальные типы модулей могут быть проверил их путь экспорта. Если он не находится в папке node_modules, не указан в package.json проекта как dep или devDep и находится непосредственно в кодовой базе проекта, то можно с уверенностью предположить, что это local .
  • внешние типы модулей могут быть проверены с использованием того же logi c, что и проверка локальных типов, очевидно, только обратное должно быть истинным.

Возможные решения:

Возможность анализировать строку, используемую в операторе require/import, а затем возвращать значение process.bind().

Где я Я застрял в попытке понять, есть ли способ go синтаксического анализа строки, используемой в операторе require, на который ссылается через переменную?

Итак:

const { magicParser } = require('magicParser') // import/require the parser

const foo = require('bar')    // require external module
const baz = require('./qux')  // require local module
const os = require('os')      // require built-in module

let externalName = magicParser(foo) // Returns 'bar' 
let localName = magicParser(baz)    // Returns './qux' 
let builtInName = magicParser(os)   // Returns 'os' 

// Then for solving the last bit, some psuedo logic like...
const pkg = require('path/to/project/root/package.json')

// External type...
for (let [k,v] of Object.entries(externalName)) {
  // code that checks key/prop values in pacakge.json for matching name....
}

// Local type...
require('fs').exist(`${process.cwd()}/${localName}) // true/false

// Built-in type...
process.builtIns.filter(name => name === builtInName) // true/false

...