Skip to content

Commit 24f8ba8

Browse files
committed
v4.2.0
1 parent fa3771a commit 24f8ba8

File tree

8 files changed

+178
-61
lines changed

8 files changed

+178
-61
lines changed

Directory.Packages.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project>
22
<PropertyGroup>
33
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
4-
<MotelyVersion>4.1.1</MotelyVersion>
4+
<MotelyVersion>4.2.0</MotelyVersion>
55
</PropertyGroup>
66
<ItemGroup>
77
<PackageVersion Include="Bootsharp" Version="0.7.0" />

Motely/build/stage-node.mjs

Lines changed: 100 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,115 @@
11
#!/usr/bin/env node
2-
import { copyFileSync, existsSync, mkdirSync } from 'fs';
2+
/**
3+
* Stage Native AOT Node module into `motely-node/` for npm.
4+
*
5+
* `dotnet publish Motely/Motely.csproj` with `-p:PublishAot=true` and a RID produces:
6+
* Motely.node, Motely.js, import.cjs, Motely.d.ts (from Microsoft.JavaScript.NodeApi.Generator)
7+
*
8+
* There is **no** `index.cjs` from the generator — CommonJS consumers expect a small loader that
9+
* `require()`s the native addon under `bin/<rid>/motely.node`.
10+
*/
11+
import { copyFileSync, existsSync, mkdirSync, readdirSync, statSync, writeFileSync } from 'fs';
312
import { dirname, join, resolve } from 'path';
413
import { fileURLToPath } from 'url';
514

615
const __dirname = dirname(fileURLToPath(import.meta.url));
716
const repoRoot = resolve(__dirname, '..', '..');
817
const pkgRoot = join(repoRoot, 'motely-node');
9-
const binDir = join(pkgRoot, 'bin', 'linux-x64');
1018

11-
const publishDir =
12-
process.env.MOTELY_NODE_PUBLISH_DIR ||
13-
join(repoRoot, 'Motely', 'bin', 'Release', 'net10.0', 'publish');
14-
// NativeAOT produces Motely.so on linux — rename to .node for Node.js
15-
const addonSrc = existsSync(join(publishDir, 'Motely.so'))
16-
? join(publishDir, 'Motely.so')
17-
: join(publishDir, 'motely.node');
19+
const ridFromEnv = process.env.MOTELY_NODE_RID;
20+
const CANDIDATE_PUBLISH_DIRS = [
21+
process.env.MOTELY_NODE_PUBLISH_DIR,
22+
ridFromEnv && join(repoRoot, 'Motely', 'bin', 'Release', 'net10.0', ridFromEnv, 'publish'),
23+
join(repoRoot, 'Motely', 'bin', 'Release', 'net10.0', 'linux-x64', 'publish'),
24+
join(repoRoot, 'Motely', 'bin', 'Release', 'net10.0', 'win-x64', 'publish'),
25+
join(repoRoot, 'Motely', 'bin', 'Release', 'net10.0', 'publish'),
26+
].filter(Boolean);
1827

19-
mkdirSync(binDir, { recursive: true });
28+
function findPublishDir() {
29+
for (const dir of CANDIDATE_PUBLISH_DIRS) {
30+
const nodeFile = join(dir, 'Motely.node');
31+
if (existsSync(nodeFile)) return dir;
32+
}
33+
return null;
34+
}
35+
36+
const publishDir = findPublishDir();
37+
if (!publishDir) {
38+
console.error('Native AOT publish output not found (expected Motely.node). Tried:');
39+
for (const dir of CANDIDATE_PUBLISH_DIRS) console.error(` - ${dir}`);
40+
console.error('Build first, e.g. docker + dotnet publish Motely/Motely.csproj -c Release -f net10.0 -r linux-x64 -p:PublishAot=true');
41+
console.error('On Windows after a local win-x64 AOT publish: MOTELY_NODE_RID=win-x64 node Motely/build/stage-node.mjs');
42+
process.exit(1);
43+
}
2044

21-
if (!existsSync(addonSrc)) {
22-
console.error(`Native addon not found at ${publishDir} (looked for Motely.so and motely.node)`);
23-
console.error('Build linux-x64 NativeAOT first: docker run ... dotnet publish -r linux-x64 -p:PublishAot=true');
24-
process.exit(1);
45+
function runtimeIdFromPath(dir) {
46+
if (dir.includes('linux-x64')) return 'linux-x64';
47+
if (dir.includes('win-x64')) return 'win-x64';
48+
if (dir.includes('osx-x64')) return 'osx-x64';
49+
if (dir.includes('osx-arm64')) return 'osx-arm64';
50+
return 'linux-x64';
2551
}
2652

53+
const rid = runtimeIdFromPath(publishDir);
54+
55+
const binDir = join(pkgRoot, 'bin', rid);
56+
mkdirSync(binDir, { recursive: true });
57+
58+
const addonSrc = join(publishDir, 'Motely.node');
2759
copyFileSync(addonSrc, join(binDir, 'motely.node'));
28-
console.log(`→ motely-node/bin/linux-x64/motely.node`);
60+
console.log(`→ motely-node/bin/${rid}/motely.node`);
61+
62+
const copyIfPresent = (name) => {
63+
const src = join(publishDir, name);
64+
if (existsSync(src) && statSync(src).isFile()) {
65+
copyFileSync(src, join(pkgRoot, name));
66+
console.log(`→ motely-node/${name}`);
67+
}
68+
};
69+
70+
for (const name of readdirSync(publishDir)) {
71+
if (name === 'Motely.node' || name === 'Motely.node.pdb') continue;
72+
const lower = name.toLowerCase();
73+
if (lower.endsWith('.dll') || lower.endsWith('.deps.json') || lower.endsWith('.pdb')) {
74+
copyIfPresent(name);
75+
continue;
76+
}
77+
if (name.endsWith('.js') || name.endsWith('.cjs') || name.endsWith('.mjs') || name.endsWith('.d.ts')) {
78+
copyIfPresent(name);
79+
}
80+
}
81+
82+
const indexCjs = `'use strict';
83+
const path = require('node:path');
84+
const addonPath = path.join(__dirname, 'bin', '${rid}', 'motely.node');
85+
const addon = require(addonPath);
86+
module.exports = addon;
87+
module.exports.default = addon;
88+
`;
89+
writeFileSync(join(pkgRoot, 'index.cjs'), indexCjs);
90+
console.log('→ motely-node/index.cjs (CommonJS loader → native addon)');
91+
92+
const schemaCandidates = [join(repoRoot, 'jaml.schema.json'), join(repoRoot, 'Motely', 'jaml.schema.json')];
93+
for (const p of schemaCandidates) {
94+
if (existsSync(p)) {
95+
copyFileSync(p, join(pkgRoot, 'jaml.schema.json'));
96+
console.log('→ motely-node/jaml.schema.json');
97+
break;
98+
}
99+
}
29100

30-
const schemaJson = join(repoRoot, 'Motely', 'jaml.schema.json');
31-
if (existsSync(schemaJson)) {
32-
copyFileSync(schemaJson, join(pkgRoot, 'jaml.schema.json'));
33-
console.log('→ motely-node/jaml.schema.json');
101+
/** Motely.d.ts imports these paths; publish output does not ship them — empty modules satisfy tsc. */
102+
const TYPEDEF_STUBS = [
103+
'System.Runtime',
104+
'System.Runtime.Intrinsics',
105+
'System.Text.Json',
106+
'System.Collections',
107+
'YamlDotNet',
108+
];
109+
for (const name of TYPEDEF_STUBS) {
110+
const stubPath = join(pkgRoot, `${name}.d.ts`);
111+
if (!existsSync(stubPath)) {
112+
writeFileSync(stubPath, 'export {};\n');
113+
console.log(`→ motely-node/${name}.d.ts (stub for Motely.d.ts imports)`);
114+
}
34115
}

Motely/build/stage-wasm.mjs

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,83 @@
11
#!/usr/bin/env node
2-
import { copyFileSync, cpSync, existsSync, mkdirSync, writeFileSync } from 'fs';
2+
/**
3+
* Stage Bootsharp browser output into `motely-wasm/dist/` for npm.
4+
*
5+
* `dotnet publish Motely.BrowserWasm` writes a **flat** ES module bundle under
6+
* `Motely.BrowserWasm/bin/<cfg>/net10.0-browser/browser-wasm/publish/` (not under `Motely/bin/...`).
7+
* Bootsharp may also mirror dotnet assets into `motely-wasm/dist/bootsharp` during publish; this script
8+
* replaces `dist/bootsharp` with the **full** publish tree so `./bootsharp/index.mjs` and relative
9+
* imports (`./dotnet.js`, etc.) resolve. Then writes `dist/index.mjs` (thin `boot()` wrapper).
10+
*/
11+
import { copyFileSync, cpSync, existsSync, mkdirSync, readdirSync, statSync, writeFileSync } from 'fs';
312
import { dirname, join, resolve } from 'path';
413
import { fileURLToPath } from 'url';
514

615
const __dirname = dirname(fileURLToPath(import.meta.url));
716
const repoRoot = resolve(__dirname, '..', '..');
8-
const pkgRoot = join(repoRoot, 'motely-wasm');
9-
const distRoot = join(pkgRoot, 'dist');
17+
const distRoot = join(repoRoot, 'motely-wasm', 'dist');
18+
const bootsharpDest = join(distRoot, 'bootsharp');
19+
const typesDest = join(distRoot, 'types');
1020

1121
const wasmPublish =
12-
process.env.MOTELY_WASM_PUBLISH_DIR ||
13-
join(repoRoot, 'Motely', 'bin', 'Release', 'net10.0-browser', 'publish');
14-
const bootsharpSrc = join(wasmPublish, 'bootsharp');
15-
16-
if (!existsSync(bootsharpSrc)) {
17-
console.error(`Bootsharp folder not found at ${bootsharpSrc}`);
18-
console.error('Publish net10.0-browser first (e.g. dotnet publish Motely -f net10.0-browser -c Release).');
19-
process.exit(1);
22+
process.env.MOTELY_WASM_PUBLISH_DIR ||
23+
join(
24+
repoRoot,
25+
'Motely.BrowserWasm',
26+
'bin',
27+
'Release',
28+
'net10.0-browser',
29+
'browser-wasm',
30+
'publish',
31+
);
32+
33+
const indexMjs = join(wasmPublish, 'index.mjs');
34+
if (!existsSync(indexMjs)) {
35+
console.error(`WASM publish output not found (expected index.mjs):\n ${wasmPublish}`);
36+
console.error('Publish first: dotnet publish Motely.BrowserWasm/Motely.BrowserWasm.csproj -c Release');
37+
process.exit(1);
2038
}
2139

22-
mkdirSync(join(distRoot, 'bootsharp'), { recursive: true });
23-
cpSync(bootsharpSrc, join(distRoot, 'bootsharp'), { recursive: true });
24-
console.log('→ motely-wasm/dist/bootsharp/');
40+
mkdirSync(bootsharpDest, { recursive: true });
41+
cpSync(wasmPublish, bootsharpDest, { recursive: true });
42+
console.log(`→ motely-wasm/dist/bootsharp/ (${wasmPublish})`);
2543

2644
const wasmEntry = `import bootsharp, { MotelyWasm, Event } from "./bootsharp/index.mjs";
2745
2846
let bootPromise = null;
2947
3048
export function boot() {
3149
if (!bootPromise) {
32-
const root = new URL("./bootsharp", import.meta.url).href;
50+
const root = new URL("./bootsharp/", import.meta.url).href;
3351
bootPromise = bootsharp.boot({ root });
3452
}
3553
return bootPromise;
3654
}
3755
3856
export { MotelyWasm, Event };
57+
58+
const defaultExport = { boot, MotelyWasm, Event };
59+
export default defaultExport;
3960
`;
4061
writeFileSync(join(distRoot, 'index.mjs'), wasmEntry);
4162
console.log('→ motely-wasm/dist/index.mjs');
4263

43-
const stubDts = `export function boot(): Promise<void>;
44-
export class MotelyWasm {}
45-
export class Event {}
46-
`;
47-
writeFileSync(join(distRoot, 'index.d.ts'), stubDts);
64+
mkdirSync(typesDest, { recursive: true });
65+
const dtsFiles = readdirSync(wasmPublish).filter((f) => f.endsWith('.d.ts'));
66+
for (const f of dtsFiles) {
67+
const src = join(wasmPublish, f);
68+
if (statSync(src).isFile()) {
69+
copyFileSync(src, join(typesDest, f));
70+
}
71+
}
72+
if (dtsFiles.length) {
73+
console.log(`→ motely-wasm/dist/types/*.d.ts (${dtsFiles.length} files)`);
74+
}
4875

49-
const schemaJson = join(repoRoot, 'Motely', 'jaml.schema.json');
50-
if (existsSync(schemaJson)) {
51-
copyFileSync(schemaJson, join(distRoot, 'jaml.schema.json'));
52-
console.log('→ motely-wasm/dist/jaml.schema.json');
76+
const schemaCandidates = [join(repoRoot, 'jaml.schema.json'), join(repoRoot, 'Motely', 'jaml.schema.json')];
77+
for (const p of schemaCandidates) {
78+
if (existsSync(p)) {
79+
copyFileSync(p, join(distRoot, 'jaml.schema.json'));
80+
console.log('→ motely-wasm/dist/jaml.schema.json');
81+
break;
82+
}
5383
}

Motely/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "motely",
3-
"version": "4.1.1",
3+
"version": "4.2.0",
44
"description": "MotelyJAML — Balatro seed search, analysis, and JAML filtering. Native Node.js module + Browser WASM.",
55
"type": "module",
66
"exports": {

build-and-pack.ps1

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,21 @@ if ($Node) {
3939
Write-Host "Building in Docker..." -ForegroundColor Yellow
4040
docker run --rm -v "${PWD}:/src" -w "//src" mcr.microsoft.com/dotnet/sdk:10.0 bash -c "apt-get update -qq && apt-get install -y -qq clang zlib1g-dev npm >/dev/null 2>&1 && dotnet publish Motely/Motely.csproj -c Release -f net10.0 -r linux-x64 -p:PublishAot=true"
4141
if ($LASTEXITCODE -ne 0) { throw "Node NativeAOT build failed" }
42-
Write-Host " Motely.node ready" -ForegroundColor Green
42+
node (Join-Path $PSScriptRoot "Motely/build/stage-node.mjs")
43+
if ($LASTEXITCODE -ne 0) { throw "stage-node.mjs failed" }
44+
Write-Host " motely-node/ staged (index.cjs + bin/linux-x64/motely.node + Motely.d.ts)" -ForegroundColor Green
4345
}
4446

4547
# Phase 2: Browser WASM (Bootsharp LLVM)
4648
if ($Wasm) {
4749
Write-Host "`n=== Browser WASM (Bootsharp LLVM) ===" -ForegroundColor Cyan
4850
dotnet publish Motely.BrowserWasm/Motely.BrowserWasm.csproj -c Release
4951
if ($LASTEXITCODE -ne 0) { throw "WASM build failed" }
50-
Write-Host " motely-wasm ready" -ForegroundColor Green
52+
node (Join-Path $PSScriptRoot "Motely/build/stage-wasm.mjs")
53+
if ($LASTEXITCODE -ne 0) { throw "stage-wasm.mjs failed" }
54+
Write-Host " motely-wasm/dist ready (dist/index.mjs + full dist/bootsharp/)" -ForegroundColor Green
5155
}
5256

5357
Write-Host "`n=== DONE ===" -ForegroundColor Cyan
54-
if ($Node) { Write-Host " Node: Motely/pkg/*.tgz" -ForegroundColor White }
55-
if ($Wasm) { Write-Host " WASM: motely-wasm/dist/" -ForegroundColor White }
58+
if ($Node) { Write-Host " Node: cd motely-node && npm pack" -ForegroundColor White }
59+
if ($Wasm) { Write-Host " WASM: cd motely-wasm && npm pack" -ForegroundColor White }

motely-node/index.d.ts

Lines changed: 0 additions & 6 deletions
This file was deleted.

motely-node/package.json

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
{
22
"name": "motely-node",
3-
"version": "4.1.1",
3+
"version": "4.2.0",
44
"description": "Motely native Node.js addon (linux-x64 only). No Windows binary.",
55
"main": "index.cjs",
6-
"types": "index.d.ts",
6+
"types": "Motely.d.ts",
77
"files": [
88
"index.cjs",
9-
"index.d.ts",
9+
"Motely.js",
10+
"Motely.d.ts",
11+
"import.cjs",
12+
"System.Runtime.d.ts",
13+
"System.Runtime.Intrinsics.d.ts",
14+
"System.Text.Json.d.ts",
15+
"System.Collections.d.ts",
16+
"YamlDotNet.d.ts",
1017
"bin/linux-x64/motely.node",
1118
"jaml.schema.json"
1219
],

motely-wasm/package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "motely-wasm",
3-
"version": "4.1.1",
3+
"version": "4.2.0",
44
"description": "Motely WebAssembly (Bootsharp) for browser.",
55
"type": "module",
66
"main": "dist/index.mjs",
@@ -9,7 +9,8 @@
99
".": {
1010
"types": "./dist/types/index.d.ts",
1111
"import": "./dist/index.mjs"
12-
}
12+
},
13+
"./jaml.schema.json": "./dist/jaml.schema.json"
1314
},
1415
"files": [
1516
"dist"
@@ -24,6 +25,6 @@
2425
},
2526
"license": "MIT",
2627
"scripts": {
27-
"build": "dotnet publish ../Motely.BrowserWasm/Motely.BrowserWasm.csproj -c Release"
28+
"build": "dotnet publish ../Motely.BrowserWasm/Motely.BrowserWasm.csproj -c Release && node ../Motely/build/stage-wasm.mjs"
2829
}
2930
}

0 commit comments

Comments
 (0)