В угловом приложении может ли TSLint принудительно импортировать модуль через сопоставление путей iso через относительные пути? - PullRequest
0 голосов
/ 18 января 2019

Скажем, у меня есть следующие настройки для углового проекта:

apps/my-app
libs/my-comp/my-lib

В коде my-app я использую код из my-lib. Я мог бы импортировать код my-lib с помощью импорта машинописного текста, например, import ../../libs/my-comp/my-lib, но это безобразно и подвержено ошибкам. Используя отображение пути , я могу смоделировать импорт модуля, например, import { MyLibModule} from @my-comp/my-lib. Много чище.

Но можем ли мы обеспечить это? Как мы можем запретить разработчикам импортировать код из другого модуля, используя относительные пути? Есть ли для этого правило TSLint? Должны ли мы написать собственный код TSLint? Кто-нибудь уже пытался это сделать:)?

1 Ответ

0 голосов
/ 18 января 2019

У нас аналогичная настройка, и мы внедрили 2 пользовательских правила lint:

  • импорт из my-lib с относительным импортом запрещен
  • импорт из @my-comp/my-lib внутри самой библиотеки запрещен

Возможно, лучшей настройкой будет использование nx-workspace (см. Раздел «Предварительно собранные ограничения»). Это идет с подобными правилами и добавляет больше:

  • Lib не может импортировать приложения.
  • Проект, загружающий библиотеку через loadChildren, также не может импортировать ее с помощью импорта ESM.
  • Круговые зависимости не допускаются.
  • Lib не могут быть импортированы с использованием относительного импорта.

Это наша реализация правила, запрещающего относительный импорт из библиотеки. Это работает, но может иметь некоторые серьезные проблемы, которые мы еще не обнаружили (например, замедление задержки:)

import * as ts from 'typescript';
import * as Lint from 'tslint';

export class Rule extends Lint.Rules.AbstractRule {
    static readonly FAILURE_STRING = `Import should be from '${Rule.SHARED_IMPORT}'`;
    static readonly SHARED_IMPORT = 'my-lib';

    public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
        return this.applyWithFunction(sourceFile, walk);
    }
}

function walk(ctx: Lint.WalkContext<void>) {
    return ts.forEachChild(ctx.sourceFile, cb);

    function cb(node: ts.Node): void {
        if (node.kind !== ts.SyntaxKind.ImportDeclaration) {
            return;
        }

        const importLocation = getImportLocation(node.getText());

        if (containsIncorrectImportFromSharedFolder(importLocation)) {
            const locationWidth = importLocation.length + 3;
            const fix = new Lint.Replacement(node.getEnd() - locationWidth, locationWidth, `'${Rule.SHARED_IMPORT}';`);
            return ctx.addFailureAtNode(node, Rule.FAILURE_STRING, fix);
        }

        return ts.forEachChild(node, cb);
    }

    function containsIncorrectImportFromSharedFolder(importLocation: String): boolean {
        return importLocation.indexOf(Rule.SHARED_IMPORT) > -1 && importLocation !== Rule.SHARED_IMPORT;
    }

    function getImportLocation(location: string): string {
        const importLocation = location.match(/'(.*?[^'])'/);
        return importLocation !== null ? importLocation[1] : '';
    }
}

Вы должны скомпилировать правило в js с помощью tsc:

node "node_modules/typescript/bin/tsc" tools/tslint-rules/myLibImportRule.ts

и вы должны добавить его к tslint.json:

"rulesDirectory": [
    ...
    "tools/tslint-rules",
    ...
],
"rules": {
    ...,
    "my-lib-import": true,
    ...
}

Имя правила - это имя файла myLibImportRule.js => my-lib-import.

...