Skip to content

Commit 0b2f675

Browse files
authored
feat: node-patches\filesystem patcher. (#1332)
1 parent 9802e88 commit 0b2f675

26 files changed

Lines changed: 4399 additions & 1 deletion

WORKSPACE

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414

1515
workspace(
1616
name = "build_bazel_rules_nodejs",
17-
managed_directories = {"@npm": ["node_modules"]},
17+
managed_directories = {
18+
"@npm": ["node_modules"],
19+
"@npm_node_patches": ["packages/node-patches/node_modules"],
20+
},
1821
)
1922

2023
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
@@ -85,6 +88,12 @@ filegroup(
8588
yarn_lock = "//:yarn.lock",
8689
)
8790

91+
npm_install(
92+
name = "npm_node_patches",
93+
package_json = "//packages/node-patches:package.json",
94+
package_lock_json = "//packages/node-patches:package-lock.json",
95+
)
96+
8897
# Install all Bazel dependencies needed for npm packages that supply Bazel rules
8998
load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies")
9099

common.bazelrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
#
55
# The full list of Bazel options: https://docs.bazel.build/versions/master/command-line-reference.html
66

7+
# Cache action outputs on disk so they persist across output_base and bazel shutdown (eg. changing branches)
8+
build --disk_cache=~/.cache/bazel-disk-cache
9+
710
# Bazel will create symlinks from the workspace directory to output artifacts.
811
# Build results will be placed in a directory called "dist/bin"
912
# Other directories will be created like "dist/testlogs"

internal/node/bazel_require_script.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
// Adapt node programs to run under Bazel
22
// Meant to be run in a --require hook
33

4+
if(global.BAZEL_NODE_PATCHES) {
5+
return;
6+
}
7+
global.BAZEL_NODE_PATCHES = true;
8+
49
const fs = require('fs');
510
const path = require('path');
611
const orig = {};

packages/node-patches/.gitignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
coverage
2+
node_modules
3+
build
4+
.nyc_output
5+
src/*.js
6+
src/*.d.ts
7+
test/**/*.js
8+
test/**/*.d.ts
9+
register.js
10+
register.d.ts

packages/node-patches/.nycrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"include":["build/src/**","src/**"]}

packages/node-patches/BUILD.bazel

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Copyright 2017 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
load("@build_bazel_rules_nodejs//:tools/defaults.bzl", "npm_package")
16+
load("@npm_node_patches//mocha:index.bzl", "mocha_test")
17+
load("@npm_node_patches//typescript:index.bzl", "tsc")
18+
19+
package(default_visibility = ["//visibility:public"])
20+
21+
filegroup(
22+
name = "node-patches",
23+
srcs = [
24+
"package.json",
25+
":compile",
26+
],
27+
)
28+
29+
npm_package(
30+
name = "npm_package",
31+
srcs = [
32+
"README.md",
33+
],
34+
deps = [
35+
":node-patches",
36+
],
37+
)
38+
39+
sources = glob(
40+
[
41+
"src/*.ts",
42+
],
43+
exclude = ["src/*.d.ts"],
44+
) + ["register.ts"]
45+
46+
tests = glob(
47+
["test/**/*.ts"],
48+
exclude = ["test/**/*.d.ts"],
49+
)
50+
51+
tsc(
52+
name = "compile",
53+
# TODO: we ought to compile tests separately?
54+
outs = [s.replace(".ts", ext) for ext in [
55+
".js",
56+
".d.ts",
57+
] for s in sources + tests],
58+
args = [
59+
"-p",
60+
"$(location tsconfig-bazel.json)",
61+
"--outDir",
62+
"$@",
63+
],
64+
data = sources + tests + [
65+
"tsconfig-bazel.json",
66+
"@npm_node_patches//:node_modules",
67+
],
68+
)
69+
70+
test_js = [s.replace(".ts", ".js") for s in tests]
71+
72+
mocha_test(
73+
name = "unit_test",
74+
args = ["$(location %s)" % s for s in test_js],
75+
data = test_js + [s.replace(".ts", ".js") for s in sources] + [
76+
"@npm_node_patches//:node_modules",
77+
],
78+
tags = [
79+
"fix-windows",
80+
],
81+
)

packages/node-patches/README.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# @bazel/node-patches
2+
3+
Runtime modifications to nodejs internals to help node/npm distributed programs run in bazel
4+
5+
## fs
6+
7+
patch any `fs` like object such that symlinks that point outside a specified directory seem to be their targets instead of links
8+
9+
### example
10+
11+
```js
12+
const fs = require('fs')
13+
const path = require('path')
14+
const patcher = require('@bazel/node-patches')
15+
16+
patcher.fs(fs,'/my/files')
17+
18+
fs.symlinkSync(path.resolve('./node_modules'),'/my/files/node_modules')
19+
20+
// now try to stat.
21+
22+
const stat = fs.lstatSync('/my/files/node_modules')
23+
24+
console.log(stat.isSymbolicLink() === false)// true
25+
26+
console.log(stat.isDirectory() === true) //true
27+
28+
```
29+
30+
this should not change the behavior of any paths that are outside of the root.
31+
32+
### loader
33+
34+
you can use the register script to include it in a -r flag to preload the patch before user code.
35+
This depends on setting the environment variable BAZEL_PATCH_ROOT
36+
37+
```sh
38+
BAZEL_PATCH_ROOT=~/.cache/bazel node -r @bazel/node-patches/register <your app js>
39+
```
40+
41+
### api
42+
43+
`{fs} = require('@bazel/node-patches')`
44+
- fs(fsLikeObject: require('fs'), root:string)
45+
46+
## bazel
47+
48+
to use this package as a dependency in bazel depend on it's exposed file group rule.
49+
50+
`:node_patches`
51+
52+
this filegroup will always expose one or more files needed to run this package and will not depend on npm install etc.

0 commit comments

Comments
 (0)