I'm writing a bazel rule in js for a mono repo. The idea behind this is services inside the mono repo(micro services) define there api spec in a open api schema files. In our case these schemas are in ts files since spec is broken as each route and final spec file import each route schema and integrate to the final object.
I want to write a bazel rule in a centralized location so each project can load the rule and call it with it's schema file(s)
generate_yaml_from_ts(
name = 'generate_yaml',
schema = "src/api/routes/openapi.schema.ts"
)
I'm not exactly sure whether all schema files ( openapi.schema.ts import other ts files) needed to made available to the rule.
In the rule I have a ts code where I want to refer to the passed schema files and generate yaml
file. (Something like follows, ya I know static imports will not work)
import fs from 'fs';
import YAML from 'yaml';
import openapiJson from './src/api/routes/openapi.schema';
fs.writeFileSync(process.argv[2], YAML.stringify(openapiJson));
I create a node executable to run from the code using ts-node
but the problem is input that we provide also are ts
files and hence needed to be compiled first.
I can think of two possible way to fix this but both I'm not sure exactly how to do.
- Compile the schema
ts
before passing to the rule from service. ( Use ats_library
and pass the out put to the rule ? ) - Create the ts executable at rule ( use
ts-node
in the bzl file ) passing source files concatenatinggenerateYml.ts
and schema files passed.
Simple project with bazel setup is available at github
I wrote a rule to take a json file from project and generate yaml build/rules/json2yaml
which works.
Effort to do the same with type script it in build/rules/ts-yaml
.
My questions are following
- Can I use
ts_library
and pass output the bazel rule? - Can I pass ts files from service and compile and execute logic from rule sile ( Better ) ?
I was able to find a way to get this done so I'm gonna try and explain it so if someone else has to do the same this might save his day.
First, problem with passing
ts
files as arguments is they need to be compiled before running. Usually when you create an executable withts-node
,ts_project
ornodejs_binary
the processing part which you already have is compiled but arguments are not.So what I needed is something that compile and execute typescript at runtime. Following was the solution I found.
Basically you can do following and import typescript at runtime.
So my yaml generator code can use this to import ts files passed as arguments.
First the BUILD.bazel for the rule
main.js
is the file that is going to do the processing. It needsyaml
library from the npm so is provided andts-node
to load the typescript files at runtime.Bazel rule is like following
executable(generator) is the
nodejs_binary
target from before. rule is expecting two arguments.schemas
which are the schema files in ts code. The reason that this is multiple files is schema is broken in to different objects and stored with each route for readability. So the main schema file import and append everything together. I needed another variable so the rule know which one is the main schema file. So the schema files made available to the executable by passing toinputs
and main ts file is passed as an argument.Following is the
main.js
file.Basically it import the passed typescript file and parse into
yaml
and save it to a file. There is a bit of a issue with the path ( hence../../../
) that I need to do more gracefully.Finally rule can be used in a package passing schemas as below.
Run the target and rule will generate the yaml file
Link to the gihub code of this example