Skip to content

Commit bd82af8

Browse files
committed
Support package.json in a monorepo setup with lockfile in parent directory
1 parent 433b36d commit bd82af8

6 files changed

Lines changed: 74 additions & 20 deletions

File tree

projectdo

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,20 @@ execute_command() {
5757
exit 0
5858
}
5959

60+
# Navigate up one directory. The command is successful if this is possible
61+
# without leaving the current project, entering the home directory, or entering
62+
# the root directory.
63+
go_up() {
64+
if [ "$PWD" = "$PROJECT_ROOT" ]; then
65+
return 1
66+
fi
67+
cd ..
68+
if [ "$PWD" = "$HOME" ] || [ "$PWD" = / ]; then
69+
return 1
70+
fi
71+
return 0
72+
}
73+
6074
# Every supported tool requires a function `try_tool` where `tool` is a name
6175
# indicating what tool the function tries to detect. The function should:
6276
#
@@ -70,19 +84,39 @@ execute_command() {
7084

7185
# JavaScript + NodeJS
7286

87+
# After a `package.json` has been found this detects the tool to use based on
88+
# any present lock file. In monorepo setups the lockfile might be in a parent
89+
# directory and not right next to the `package.json` file. This is handled by
90+
# looking up the directory hierarchy.
91+
detect_nodejs_tool() {
92+
while :
93+
do
94+
# echo looking for nodejs tool
95+
if [ -f package-lock.json ]; then
96+
echo yarn
97+
return
98+
elif [ -f bun.lock ] || [ -f bun.lockb ]; then
99+
echo bun
100+
return
101+
elif [ -f yarn.lock ]; then
102+
echo yarn
103+
return
104+
elif [ -f pnpm-lock.yaml ]; then
105+
echo pnpm
106+
return
107+
fi
108+
if ! go_up; then
109+
echo npm
110+
return
111+
fi
112+
done
113+
}
114+
73115
try_nodejs() {
74116
if [ ! -f package.json ]; then
75117
return 1
76118
fi
77-
if [ -f bun.lock ] || [ -f bun.lockb ]; then
78-
tool=bun
79-
elif [ -f yarn.lock ]; then
80-
tool=yarn
81-
elif [ -f pnpm-lock.yaml ]; then
82-
tool=pnpm
83-
else
84-
tool=npm
85-
fi
119+
tool=$(detect_nodejs_tool)
86120
if ! has_command $tool; then
87121
echo "Found a package.json file but '$tool' is not installed."
88122
exit 1
@@ -507,15 +541,9 @@ set_project_root
507541

508542
while :
509543
do
510-
# We don't want to do anything if we are in the home or root directory
511-
if [ "$PWD" = "$HOME" ] || [ "$PWD" = / ]; then
512-
nothing_found
513-
fi
514544
detect_and_run
515545
# If we didn't detect a tool to run in this directory we go up one directory
516-
# while ensuring that we don't leave the project root
517-
if [ "$PWD" = "$PROJECT_ROOT" ]; then
546+
if ! go_up; then
518547
nothing_found
519548
fi
520-
cd ..
521549
done

run-tests.sh

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,22 +55,22 @@ assertEqual() {
5555
RUN_EXIT=0
5656

5757
do_build_in() {
58-
RUN_RESULT=$(cd tests/"$1" && ../../projectdo -n build)
58+
RUN_RESULT=$(cd tests/"$1" && "$script_directory"/projectdo -n build)
5959
RUN_EXIT=$?
6060
}
6161

6262
do_run_in() {
63-
RUN_RESULT=$(cd tests/"$1" && ../../projectdo -n run)
63+
RUN_RESULT=$(cd tests/"$1" && "$script_directory"/projectdo -n run)
6464
RUN_EXIT=$?
6565
}
6666

6767
do_test_in() {
68-
RUN_RESULT=$(cd tests/"$1" && ../../projectdo -n test)
68+
RUN_RESULT=$(cd tests/"$1" && "$script_directory"/projectdo -n test)
6969
RUN_EXIT=$?
7070
}
7171

7272
do_print_tool_in() {
73-
RUN_RESULT=$(cd tests/"$1" && ../../projectdo -n tool)
73+
RUN_RESULT=$(cd tests/"$1" && "$script_directory"/projectdo -n tool)
7474
RUN_EXIT=$?
7575
}
7676

@@ -183,6 +183,12 @@ if describe "npm / yarn / pnpm / bun"; then
183183
do_print_tool_in "bun"; assert
184184
assertEqual "$RUN_RESULT" "bun"
185185
fi
186+
if it "detects yarn in workspace setup"; then
187+
do_print_tool_in "yarn-workspace/workspace-a"; assert
188+
assertEqual "$RUN_RESULT" "yarn"
189+
do_print_tool_in "yarn-workspace/workspace-b"; assert
190+
assertEqual "$RUN_RESULT" "yarn"
191+
fi
186192
fi
187193

188194
if describe "just"; then

tests/yarn-workspace/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"private": true,
3+
"workspaces": ["workspace-a", "workspace-b"]
4+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name": "workspace-a",
3+
"version": "1.0.0",
4+
"dependencies": {}
5+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "workspace-b",
3+
"version": "1.0.0",
4+
"dependencies": {
5+
"workspace-a": "1.0.0"
6+
}
7+
}

tests/yarn-workspace/yarn.lock

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2+
# yarn lockfile v1
3+
4+

0 commit comments

Comments
 (0)