импортировать файлы машинописного текста из правила базеля
Я пишу правило 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));
Я создаю исполняемый файл узла для запуска из кода, но проблема заключается в том, что вводимые данные, которые мы предоставляем, также являются файлами и, следовательно, должны быть скомпилированы в первую очередь.
Я могу придумать два возможных способа исправить это, но я не совсем уверен, как это сделать.
- Скомпилируйте схему
перед переходом к правилу из службы. (Используйте a и передайте выход правилу?) - Создайте исполняемый файл 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 этого примера
Удачного кодирования ...!!!