Зарегистрировать модуль узла вручную

Вопрос:

У меня есть проект на TypeScript, который использует несколько API, к которым у меня нет доступа на моем компьютере (они существуют в Интернете). Код отлично скомпилируется локально, поскольку у меня есть все API в foo.d.ts файлах, и поэтому система знает, что они где-то существуют.

Однако я хочу выполнить модульное тестирование частей кода с помощью приложения NodeJS. Я могу нормально импортировать код в узел, но всякий раз, когда я достигаю кода, который импортирует модуль из файла определения, я получаю следующую ошибку:

Error: Cannot find module 'messages'
    at Function.Module._resolveFilename (module.js:527:15)
    at Function.Module._load (module.js:476:23)
    at Module.require (module.js:568:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (~/dev/repos/sample_typescript_fail/App.js:3:18)
    at Module._compile (module.js:624:30)
    at Object.Module._extensions..js (module.js:635:10)
    at Module.load (module.js:545:32)
    at tryModuleLoad (module.js:508:12)
    at Function.Module._load (module.js:500:3)
...

Это имеет смысл, так как этот код просто определен локально и не существует.

Могу ли я вручную зарегистрировать модули в NodeJS, например

 Registry.register('messages', () => {...});

чтобы я мог компилировать и тестировать полифиллы?


Вот пример приложения

package.json

{
  "name": "sample_typescript_declare_issue",
  "version": "1.0.0",
  "description": "",
  "main": "index.ts",
  "scripts": {
    "start": "ts-node index.ts"
  },
  "author": "",
  "license": "MIT"
}

index.ts

import {App} from "./App";

console.log("Starting program");

// How do I fake "import {MessageSender} from "messages";"
// here so that I can run this node app as a test?

let app: App = new App();

console.log("Ending program");

App.ts

import {MessageSender} from "messages";

export class App {
    constructor() {
        let messageSender: MessageSender = new MessageSender();
        messageSender.sendMessage("foo!");
    }
}

node_modules/@types/messages/index.d.ts

export = Messages;
export as namespace Messages;

declare module Messages {

    class MessageSender {
        constructor();
        sendMessage(message: any): void;
    }

}

Запуск примера приложения

Запуск с npm start дает указанное выше сообщение об ошибке.

Запуск tsc *.tsc компилируется просто отлично.


Другие вещи, которые я пробовал

  1. Обновление package.json для включения корзины:

    {
      "name": "sample_typescript_declare_issue",
      "version": "1.0.0",
      "description": "",
      "main": "index.ts",
      "scripts": {
        "start": "ts-node index.ts"
      },
      "author": "",
      "license": "MIT",
      "bin": {
        "messages": "./polyfills/messages/index.ts"
      }
    }
    

person Jason    schedule 02.10.2017    source источник


Ответы (1)


Как вы упомянули, компиляция работает нормально - вопрос только в наличии .d.ts файлов.

Что вы хотите сделать, так это изменить импорт модуля во время выполнения, другими словами, изменить поведение функции nodejs require, поскольку

import {MessageSender} from "messages";

будет преобразован в javascript (ES6) во что-то вроде

const messages_1 = require("messages");
...
messages_1.MessageSender

Чтобы изменить это поведение, первое, что приходит на ум, — это использовать устаревший, но все еще доступный — require.extensions объект.

При локальном запуске вы должны сначала ввести что-то вроде

require.extensions['.js'] = (module, filename) => {
    if (filename === 'messages') {
        // then load mock module/polyfill using the passed module object
        // see (https://nodejs.org/api/modules.html#modules_the_module_object)
    }
};

В документе говорится, что есть лучшие альтернативы, но не упоминается ни одна из них.

Другая возможность — посмотреть на такие проекты, как sandboxed-module, которые должны помочь (у меня нет протестировал)

person Bruno Grieder    schedule 05.10.2017
comment
Я пробовал оба решения, но ни одно из них не работает. Расширения не позволяли мне вызывать super, а изолированный модуль никогда не работал у меня. Ничего не вводил. - person Jason; 11.10.2017