I can't find the source of the nuget package https://www.nuget.org/packages/Microsoft.TypeScript.MSBuild and underlaying TypeScript.Tasks.dll.
Are they open sourced?
Microsoft.TypeScript.MSBuild
is a closed source library (at the time of writing this), despite the misleading link to microsoft/TypeScript mentioned in the comments above. However, it is not obfuscated and hence can be inspected with IlSpy or similar tools.
I've developed an open-source replacement BlazingTs (nothing to do with Blazor, targets netstandard2.0
), motivated by getting rid of some extra stuff Microsoft.TypeScript.MSBuild
does when scanning the solution for TS files, resulting in tsconfig.json
not being used correctly in hot starts sometimes.
The part with MSBuild step BlazingTs does is very similar to what Microsoft.TypeScript.MSBuild
is doing, if you don't feel like opening IlSpy, it's the closest to the source code of it I can link to.
The gist of it essentially:
YourProj.targets
; This will be picked by a convention.tsc.js
early in the process. There are multiple steps we could do that in, we've used BeforeBuild
(see the table of predefined steps)tsc.js
we need to invoke node
. We could either supply it or expect the host to have one already. Both BlazingTs and Microsoft.TypeScript.MSBuild do the latter.tsc.js
and friends. In YourProj.csproj
add a link to a folder we will ship our copy of the compiler in:Example:
<Content Include="tools\typescript\**\*">
<Pack>true</Pack>
<PackagePath>tools\typescript</PackagePath>
</Content>
tools\typescript
we copy whatever the result of npm i typescript
would add to packages
. The folder will include /bin
, /lib
, and a bunch of loose files. See here.tsc
we can use a simple shell script (tsc2.sh
, tsc2.cmd
in BlazingTs), this will be placed in the same folder:Example:
#!/bin/bash
# Get the directory where the script is located
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
LOG_FILE="$SCRIPT_DIR/typescript.log"
# Initialize log file
echo "[TypeScript] Starting compilation..." > "$LOG_FILE"
# Determine Node executable
if [ -f "$SCRIPT_DIR/node" ]; then
NODE_EXEC="$SCRIPT_DIR/node"
else
NODE_EXEC="node"
fi
echo "[TypeScript] Using Node from: $NODE_EXEC" >> "$LOG_FILE"
# Version check
VERSION_LINE=$("$NODE_EXEC" "$SCRIPT_DIR/bin/tsc" --version)
echo "[TypeScript] $VERSION_LINE" >> "$LOG_FILE"
# Transpilation
echo "[TypeScript] Running tsc with arguments: $@" >> "$LOG_FILE"
"$NODE_EXEC" "$SCRIPT_DIR/bin/tsc" "$@" >> "$LOG_FILE" 2>&1
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
echo "[TypeScript] Compilation completed successfully" >> "$LOG_FILE"
else
echo "[TypeScript] Compilation failed with error code $EXIT_CODE" >> "$LOG_FILE"
fi
exit $EXIT_CODE
For cross-platform compatibility, one would add an equivalent script for Windows or whatever other target.
Example:
<PropertyGroup>
<TypeScriptToolsPath>$([MSBuild]::NormalizePath('$(MSBuildThisFileDirectory)', '..', 'tools', 'typescript'))</TypeScriptToolsPath>
<TypeScriptLogFile>$([MSBuild]::NormalizePath('$(TypeScriptToolsPath)', 'typescript.log'))</TypeScriptLogFile>
<IsWindows Condition="'$(OS)' == 'Windows_NT'">true</IsWindows>
<IsWindows Condition="'$(OS)' != 'Windows_NT'">false</IsWindows>
<TypeScriptCompilerScript Condition="'$(IsWindows)' == 'true'">"$(TypeScriptToolsPath)\tsc2.cmd"</TypeScriptCompilerScript>
<TypeScriptCompilerScript Condition="'$(IsWindows)' != 'true'">$(TypeScriptToolsPath)/tsc2.sh</TypeScriptCompilerScript>
</PropertyGroup>
<UsingTask TaskName="ReadTypeScriptLog" TaskFactory="RoslynCodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
<LogFile ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Using Namespace="System.IO"/>
<Code Type="Fragment" Language="cs">
<![CDATA[
if (File.Exists(LogFile))
{
string content = File.ReadAllText(LogFile);
Log.LogMessage(MessageImportance.High, "TypeScript Build Log:");
Log.LogMessage(MessageImportance.High, "------------------------");
Log.LogMessage(MessageImportance.High, content);
Log.LogMessage(MessageImportance.High, "------------------------");
}
]]>
</Code>
</Task>
</UsingTask>
<Target Name="MakeTypeScriptShellScriptExecutable" BeforeTargets="CustomCompileTypeScript" Condition="'$(IsWindows)' != 'true'">
<Exec Command="chmod +x "$(TypeScriptCompilerScript)"" />
</Target>
<Target Name="CustomCompileTypeScript" BeforeTargets="BeforeBuild">
<Message Text="----- Starting TypeScript compilation via BlazingTs -----" Importance="high" />
<Delete Files="$(TypeScriptLogFile)" Condition="Exists('$(TypeScriptLogFile)')" />
<Exec
Command="$(TypeScriptCompilerScript) --project "$(ProjectDir)tsconfig.json""
WorkingDirectory="$(TypeScriptToolsPath)"
IgnoreExitCode="true"
/>
<ReadTypeScriptLog LogFile="$(TypeScriptLogFile)" />
<Message Text="----- Finished TypeScript compilation via BlazingTs -----" Importance="high" />
</Target>