Skip to content

Commit 4bb12b6

Browse files
authored
Add npm package example (#169)
1 parent 8907200 commit 4bb12b6

20 files changed

Lines changed: 189 additions & 36 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
out/
22
bin/
33
obj/
4+
pkg/
45

56
*.suo
67
*.user

examples/Directory.Packages.props

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<Project>
2+
<PropertyGroup>
3+
<!-- False is the default, but this overrides the True value in the project root. -->
4+
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
5+
</PropertyGroup>
6+
</Project>

examples/aot-module/aot-module.csproj

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,15 @@
22

33
<PropertyGroup>
44
<TargetFramework>net8.0</TargetFramework>
5-
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
65
<GenerateDocumentationFile>true</GenerateDocumentationFile>
76
<PublishAot>true</PublishAot>
87
<PublishNodeModule>true</PublishNodeModule>
98
<PublishDir>bin</PublishDir>
109
</PropertyGroup>
1110

1211
<ItemGroup>
13-
<PackageReference Include="Microsoft.JavaScript.NodeApi" Version="0.2.*-*" PrivateAssets="none" />
14-
<PackageReference Include="Microsoft.JavaScript.NodeApi.Generator" Version="0.2.*-*" />
12+
<PackageReference Include="Microsoft.JavaScript.NodeApi" Version="0.4.*-*" PrivateAssets="none" />
13+
<PackageReference Include="Microsoft.JavaScript.NodeApi.Generator" Version="0.4.*-*" />
1514
</ItemGroup>
1615

1716
</Project>

examples/aot-npm-package/README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
2+
## Minimal Example .NET AOT NPM Package
3+
The `lib/Example.cs` class defines a Node.js add-on module that is AOT-compiled, so that it does not
4+
depend on the .NET runtime. The AOT module is then packaged as an npm package. The `app/example.js`
5+
script loads that _native_ module via its npm package and calls a method on it. The script has
6+
access to type definitions and doc-comments for the module's APIs via the auto-generated `.d.ts`
7+
file that was included in the npm package.
8+
9+
| Command | Explanation
10+
|-------------------------------|--------------------------------------------------
11+
| `dotnet pack ../..` | Build Node API .NET packages.
12+
| `cd lib`<br/>`dotnet publish` | Install Node API .NET packages into lib project; build lib project and compile to native binary; pack npm package.
13+
| `cd app`<br/> `npm install` | Install lib project npm package into app project.
14+
| `node example.js` | Run example JS code that calls the library API.
15+
16+
### Building multi-platform npm packages with platform-specific AOT binaries
17+
Native AOT binaries are platform-specific. The `dotnet publish` command above creates a package
18+
only for the current OS / CPU platform (aka .NET runtime-identifier). To create a multi-platform
19+
npm package with Native AOT binaries, run `dotnet publish` separately for each runtime-identifier,
20+
and only create the package on the last one:
21+
```
22+
dotnet publish -r:win-x64 -p:PackNpmPackage=false
23+
dotnet publish -r:win-arm64 -p:PackNpmPackage=true
24+
```
25+
26+
To create a fully cross-platform packatge, it will be necessary to compile on each targeted OS
27+
(Windows, Mac, Linux), then copy the outputs into a shared directory before creating the final
28+
npm package.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
const Example = require('aot-npm-package').Example;
5+
6+
// Call a method exported by the .NET module.
7+
const result = Example.hello('.NET AOT');
8+
9+
const assert = require('assert');
10+
assert.strictEqual(result, 'Hello .NET AOT!');
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "aot-npm-app",
3+
"private": true,
4+
"version": "0.1.0",
5+
"description": "Example Node.js app that references an npm-packaged C# Native AOT node module",
6+
"license": "MIT",
7+
"author": "Microsoft",
8+
"repository": "github:microsoft/node-api-dotnet",
9+
"main": "./example.js",
10+
"scripts": {
11+
},
12+
"dependencies": {
13+
"aot-npm-package": "file:../lib/pkg/aot-npm-package-0.1.6.tgz"
14+
}
15+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# When packaging, ignore everything except the .node binaries, scripts, and type definitions.
2+
# (Readme and license files are always included implictly.)
3+
*
4+
!/bin/**/*.node
5+
!/bin/*.js
6+
!/bin/*.d.ts
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
namespace Microsoft.JavaScript.NodeApi.Examples;
5+
6+
/// <summary>
7+
/// Example Node API module that exports a simple "hello" method.
8+
/// </summary>
9+
[JSExport]
10+
public static class Example
11+
{
12+
/// <summary>
13+
/// Gets a greeting string.
14+
/// </summary>
15+
/// <param name="greeter">Name of the greeter.</param>
16+
/// <returns>A greeting with the name.</returns>
17+
public static string Hello(string greeter)
18+
{
19+
System.Console.WriteLine($"Hello {greeter}!");
20+
return $"Hello {greeter}!";
21+
}
22+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
6+
<!-- The C# xmldoc file is converted to comments in the generated TS type definitions. -->
7+
<GenerateDocumentationFile>true</GenerateDocumentationFile>
8+
9+
<!-- `dotnet publish` will produce node module files in $(PublishDir), with
10+
.node native AOT binary files under $(RuntimeIdentifier) subdirectories. -->
11+
<PublishAot>true</PublishAot>
12+
<PublishNodeModule>true</PublishNodeModule>
13+
<PublishDir>bin</PublishDir>
14+
<PublishMultiPlatformNodeModule>true</PublishMultiPlatformNodeModule>
15+
16+
<!-- `dotnet publish` will produce an npm package in the $(PackageOutputPath) directory. -->
17+
<!-- `package.json` is required in the project directory; `.npmignore` is also recommended. -->
18+
<PackNpmPackage>true</PackNpmPackage>
19+
<PackageOutputPath>pkg</PackageOutputPath>
20+
</PropertyGroup>
21+
22+
<ItemGroup>
23+
<PackageReference Include="Microsoft.JavaScript.NodeApi" Version="0.4.*-*" PrivateAssets="none" />
24+
<PackageReference Include="Microsoft.JavaScript.NodeApi.Generator" Version="0.4.*-*" />
25+
</ItemGroup>
26+
27+
</Project>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "aot-npm-package",
3+
"private": true,
4+
"version": "0.1.6",
5+
"description": "Example npm-packaged C# Native AOT node module",
6+
"license": "MIT",
7+
"author": "Microsoft",
8+
"repository": "github:microsoft/node-api-dotnet",
9+
"main": "./bin/aot-npm-package",
10+
"scripts": {
11+
}
12+
}

0 commit comments

Comments
 (0)