Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ All notable changes to this project will be documented in this file.

### Fixed

- **devenv / ts:emit**: resolve project references with filesystem directory
checks so dotted directory names map to `tsconfig.json`, and treat an
all-`noEmit` reference graph as successful no-work instead of invoking the
compiler with an empty build root.
- **@overeng/utils**: restore the downstream `@effect/platform` patch
projection in the generated package manifest after vendoring
`effect-distributed-lock`.
Expand Down
41 changes: 40 additions & 1 deletion nix/devenv-modules/tasks/shared/tests/ts-task-smoke.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ mkdir -p \
"$workspace/node_modules/typescript" \
"$workspace/packages/no-emit" \
"$workspace/packages/emit" \
"$workspace/packages/dotted.name" \
"$tmpdir/bin"

cat > "$workspace/tsconfig.all.json" <<'EOF'
Expand All @@ -96,7 +97,8 @@ cat > "$workspace/tsconfig.all.json" <<'EOF'
"references": [
{ "path": "packages/no-emit/tsconfig.json" }, // explicit file path
// This mid-file comment used to break the old JSON.parse path.
{ "path": "packages/emit" }
{ "path": "packages/emit" },
{ "path": "packages/dotted.name" }
]
}
EOF
Expand All @@ -121,6 +123,15 @@ cat > "$workspace/packages/emit/tsconfig.json" <<'EOF'
}
EOF

cat > "$workspace/packages/dotted.name/tsconfig.json" <<'EOF'
{
"compilerOptions": {
"composite": true,
"declaration": true
}
}
EOF

cat > "$workspace/node_modules/typescript/package.json" <<'EOF'
{"name":"typescript","main":"./index.js"}
EOF
Expand Down Expand Up @@ -223,6 +234,9 @@ if (paths.includes('packages/no-emit/tsconfig.json')) {
if (!paths.includes('packages/emit')) {
throw new Error('emit project should remain in generated emit tsconfig')
}
if (!paths.includes('packages/dotted.name')) {
throw new Error('dotted directory reference should remain in generated emit tsconfig')
}

fs.copyFileSync(configPath, process.env.TEST_CAPTURED_TSCONFIG)
NODE
Expand Down Expand Up @@ -260,5 +274,30 @@ echo "Test 2: ts:emit status uses the same filtered graph"
test -f "$TEST_CAPTURED_TSCONFIG"
grep -q -- '--dry --noCheck --verbose --pretty false' "$TEST_TSC_LOG"

echo "Test 3: ts:emit succeeds without invoking tsc when every referenced project is noEmit"
cat > "$workspace/tsconfig.all.json" <<'EOF'
{
"files": [],
"references": [
{ "path": "packages/no-emit" }
]
}
EOF
(
cd "$workspace"
: > "$TEST_TSC_LOG"
rm -f "$TEST_CAPTURED_TSCONFIG"
bash "$tmpdir/ts-emit.exec.sh" > "$tmpdir/no-work.out"
grep -qF "ts:emit: no emit-capable referenced projects" "$tmpdir/no-work.out"
assert_eq "" "$(cat "$TEST_TSC_LOG")" "ts:emit exec should not invoke tsc for all-noEmit graph"

set +e
bash "$tmpdir/ts-emit.status.sh"
exit_code=$?
set -e
assert_exit_code 0 "$exit_code" "ts:emit status should succeed for all-noEmit graph"
assert_eq "" "$(cat "$TEST_TSC_LOG")" "ts:emit status should not invoke tsc for all-noEmit graph"
)

echo ""
echo "ts task smoke test passed"
24 changes: 23 additions & 1 deletion nix/devenv-modules/tasks/shared/ts.nix
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,15 @@ let

const resolveReferenceTsconfig = (referencePath) => {
const resolvedPath = path.resolve(baseDir, referencePath)
return path.extname(resolvedPath) ? resolvedPath : path.join(resolvedPath, 'tsconfig.json')
try {
return fs.statSync(resolvedPath).isDirectory()
? path.join(resolvedPath, 'tsconfig.json')
: resolvedPath
} catch {
return path.basename(resolvedPath).endsWith('.json')
? resolvedPath
: path.join(resolvedPath, 'tsconfig.json')
}
}

const rootConfig = readTsconfig(sourceTsconfig)
Expand All @@ -134,6 +142,13 @@ let
return refConfig.compilerOptions?.noEmit !== true
})

if (
rootConfig.references.length === 0 &&
(!Array.isArray(rootConfig.files) || rootConfig.files.length === 0)
) {
rootConfig.__effectUtilsTsEmitNoWork = true
}

fs.writeFileSync(targetTsconfig, JSON.stringify(rootConfig))
NODE
}
Expand Down Expand Up @@ -407,6 +422,10 @@ let
_emit_tsconfig="$(mktemp "$_emit_tmpdir/.ts-emit-XXXXXX.json")"
trap 'rm -f "$_emit_tsconfig"' EXIT
generate_emit_tsconfig "${tsconfigFile}" "$_emit_tsconfig"
if ${pkgs.nodejs}/bin/node -e 'const fs = require("node:fs"); process.exit(JSON.parse(fs.readFileSync(process.argv[1], "utf8")).__effectUtilsTsEmitNoWork === true ? 0 : 1)' "$_emit_tsconfig"; then
echo "ts:emit: no emit-capable referenced projects"
exit 0
fi
${tscWithDiagnostics "ts:emit" tscBin "--build \"$_emit_tsconfig\"" "--noCheck"}
'';
# trace-audit-allow: raw status - argument to trace.withStatus "ts:emit" above.
Expand All @@ -420,6 +439,9 @@ let
_emit_tsconfig="$(mktemp "$_emit_tmpdir/.ts-emit-XXXXXX.json")"
trap 'rm -f "$_emit_tsconfig"' EXIT
generate_emit_tsconfig "${tsconfigFile}" "$_emit_tsconfig"
if ${pkgs.nodejs}/bin/node -e 'const fs = require("node:fs"); process.exit(JSON.parse(fs.readFileSync(process.argv[1], "utf8")).__effectUtilsTsEmitNoWork === true ? 0 : 1)' "$_emit_tsconfig"; then
exit 0
fi
_out="$(${tscBin} --build "$_emit_tsconfig" --dry --noCheck --verbose --pretty false 2>&1)" || exit 1
# tsc --build --dry reports pending work as:
# - "A non-dry build would build project ..."
Expand Down
Loading