импортировать файлы машинописного текста из правила базеля

Я пишу правило bazel на js для моно-репо. Идея заключается в том, что службы внутри монорепозитория (микросервисы) определяют спецификацию API в открытых файлах схемы API. В нашем случае эти схемы находятся в файлах ts, поскольку спецификация нарушается, поскольку каждый маршрут и окончательный файл спецификации импортируют каждую схему маршрута и интегрируются в конечный объект.

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

      generate_yaml_from_ts(
    name = 'generate_yaml',
    schema = "src/api/routes/openapi.schema.ts"
)

Я не совсем уверен, все ли файлы схемы (openapi.schema.ts импортируют другие файлы ts) должны быть доступны для правила.

В правиле у меня есть ts-код, в котором я хочу обратиться к переданным файлам схемы и сгенерировать файл. (Что-то вроде следующего, я знаю, что статический импорт не будет работать)

      import fs from 'fs';

import YAML from 'yaml';

import openapiJson from './src/api/routes/openapi.schema';

fs.writeFileSync(process.argv[2], YAML.stringify(openapiJson));

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

Я могу придумать два возможных способа исправить это, но я не совсем уверен, как это сделать.

  1. Скомпилируйте схему перед переходом к правилу из службы. (Используйте a и передайте выход правилу?)
  2. Создайте исполняемый файл ts в правиле (используйте в файле bzl) передача исходных файлов конкатенации и файлы схемы переданы.

Простой проект с настройкой bazel доступен на github

Я написал правило, чтобы взять файл json из проекта и сгенерировать yaml который работает.

Попытайтесь сделать то же самое с напечатайте скрипт в .

Мои вопросы следующие

  • Могу ли я использовать и передать вывод правила базеля?
  • Могу ли я передать ts-файлы из службы, а также скомпилировать и выполнить логику из правил молчания (лучше)?

1 ответ

Я смог найти способ сделать это, поэтому я попытаюсь объяснить это, так что, если кому-то еще придется сделать то же самое, это может спасти ему день.

Во-первых, проблема с прохождением tsфайлы в качестве аргументов - их необходимо скомпилировать перед запуском. Обычно, когда вы создаете исполняемый файл с помощью, ts_project или часть обработки, которая у вас уже есть, скомпилирована, а аргументы - нет.

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

Вы можете потребовать ts-node и зарегистрировать загрузчик на будущее, используя require ('ts-node'). Register ({/ * options * /}). Вы также можете использовать ярлыки файлов - node -r ts-node / register или node -r ts-node / register / transpile-only - в зависимости от ваших предпочтений. Документация здесь

В основном вы можете выполнять следующие действия и импортировать машинописный текст во время выполнения.

          require('ts-node').register({/* options */})
    
    const something = require('some-ts-file`);

Таким образом, мой код генератора yaml может использовать это для импорта файлов ts, переданных в качестве аргументов.

Сначала BUILD.bazel для правила

      load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary")

nodejs_binary(
    name = "ys-2-yaml",
    data = [
        "main.js",
        "@npm//yaml",
        "@npm//openapi-core",
        "@npm//ts-node"
    ],
    entry_point = "main.js",
    visibility = ["//visibility:public"],
)

это файл, который будет обрабатывать. Ему нужна библиотека из npm, поэтому предоставляется и ts-node для загрузки файлов машинописного текста во время выполнения.

Правило Базеля похоже на следующее

      """Generate the openapi yml file from the JSON version."""
def _generateYaml(ctx):
    inputs = [] +   ctx.files.schemas
    inputs.extend(ctx.attr.generator[DefaultInfo].data_runfiles.files.to_list())

    ctx.actions.run(
        inputs = inputs,
        outputs = [ctx.outputs.yaml],
        arguments = [ctx.outputs.yaml.path, ctx.file.main_file.path],
        executable = ctx.executable.generator,
    )

ts_2_yaml = rule(
    implementation = _generateYaml,
    attrs = {
        "generator": attr.label(
            default = "//build/rules/tsnoderegister:ys-2-yaml",
            cfg = "target",
            executable = True,
        ),
        "schemas": attr.label_list(default = [], allow_files = True),
        "main_file": attr.label(
            allow_single_file = True,
            mandatory = True,
        ),
    },
    outputs = {
        "yaml": "openapi.yaml",
    },
)
    

исполняемый файл (генератор) - это nodejs_binaryцель из ранее. Правило ожидает двух аргументов. schemasкоторые являются файлами схемы в коде TS. Причина того, что это несколько файлов, заключается в том, что схема разбита на разные объекты и хранится с каждым маршрутом для удобства чтения. Итак, основной файл схемы импортируется и складывается вместе. Мне нужна была еще одна переменная, чтобы правило знало, какая из них является основным файлом схемы. Таким образом, файлы схемы становятся доступными для исполняемого файла путем перехода к inputs и основной файл ts передается в качестве аргумента.

Ниже приводится main.js файл.

      const fs = require("fs");
const yaml = require("yaml");

require("ts-node").register({
  transpileOnly: true,
  // insert other options with a boolean flag here
});

const schemaFile = require("../../../" + process.argv[3]);

fs.writeFileSync(process.argv[2], yaml.stringify(schemaFile));

В основном он импортирует переданный файл машинописного текста и анализирует его в yamlи сохраните его в файл. Есть небольшая проблема с путем (следовательно, ../../../ ), что мне нужно сделать более изящно.

Наконец, правило можно использовать в схемах передачи пакетов, как показано ниже.

      load("//build/rules/tsnoderegister:runtimets.bzl", "ts_2_yaml")

ts_2_yaml(
    name = "generate_yaml",
    schemas = glob(["src/**/*schema.ts"]),
    main_file = "src/api/routes/openapi.schema.ts"
)

Запустите цель, и правило сгенерирует файл yaml

      bazel build //services/my-sample-service:generate_yaml
      bazel build //services/my-sample-service:generate_yaml
INFO: Analyzed target //services/my-sample-service:generate_yaml (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //services/my-sample-service:generate_yaml up-to-date:
  bazel-bin/services/my-sample-service/openapi.yaml
INFO: Elapsed time: 0.053s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action

Ссылка на код gihub этого примера

Удачного кодирования ...!!!

Другие вопросы по тегам