我能够找到一种方法来完成这项工作,因此我将尝试解释它,以便如果其他人必须这样做,这可能会节省他的时间。
首先,将ts 文件作为参数传递的问题是它们需要在运行之前进行编译。通常,当您使用ts-node、ts_project 或nodejs_binary 创建可执行文件时,您已经拥有的处理部分会被编译,但参数不会。
所以我需要的是在运行时编译和执行 typescript 的东西。以下是我找到的解决方案。
您可以要求 ts-node 并注册加载程序以备将来需要
使用 require('ts-node').register({ /* options */ })。你也可以使用
文件快捷方式 - node -r ts-node/register 或 node -r
ts-node/register/transpile-only - 取决于您的偏好。
文档here
基本上你可以在运行时执行以下操作并导入打字稿。
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"],
)
main.js 是要进行处理的文件。它需要来自 npm 的 yaml 库,因此提供了 ts-node 以在运行时加载打字稿文件。
Bazel 规则如下
"""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",
},
)
executable(generator) 是之前的 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 code