@nyar/nyar 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -9
- package/bin/nyar.js +4 -52
- package/package.json +13 -8
- package/readme.md +21 -9
- package/src/cli/catalog.ts +18 -0
- package/src/cli/cli.ts +136 -0
- package/src/index.ts +23 -22
- package/src/native.ts +115 -0
- package/src/platform-triple.ts +25 -0
- package/src/platform.ts +5 -8
package/README.md
CHANGED
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
# @nyar/nyar
|
|
2
2
|
|
|
3
|
-
Cross-platform
|
|
3
|
+
Cross-platform Nyar host CLI and TypeScript facade. **CLI orchestration** uses [`@vmz/commander`](https://www.npmjs.com/package/@vmz/commander); **orthogonal native capabilities** are exported from `nyar-napi` via `src/native.ts`.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## CLI
|
|
6
6
|
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
```bash
|
|
8
|
+
nyar version
|
|
9
|
+
nyar host-info
|
|
10
|
+
nyar runtime list
|
|
11
|
+
nyar runtime prepare --family wasi --artifact ./app.wasm --entry main
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
## Programmatic native surface
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { getHostInfo, listRuntimeFamilies, prepareRuntimeCommand } from '@nyar/nyar';
|
|
18
|
+
|
|
19
|
+
const info = getHostInfo();
|
|
20
|
+
const families = listRuntimeFamilies();
|
|
21
|
+
const cmd = prepareRuntimeCommand({
|
|
22
|
+
family: 'wasi',
|
|
23
|
+
artifact: '/path/to/app.wasm',
|
|
24
|
+
entry: 'main',
|
|
25
|
+
});
|
|
26
|
+
```
|
|
15
27
|
|
|
16
|
-
|
|
28
|
+
Platform collects (`nyar-win32-x64`, `nyar-linux-x64`, `nyar-darwin-*`, `nyar-unknown-wasm32`) are resolved automatically when installed on a matching host.
|
|
17
29
|
|
|
18
30
|
## License
|
|
19
31
|
|
package/bin/nyar.js
CHANGED
|
@@ -1,53 +1,5 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import { createRequire } from 'node:module';
|
|
1
|
+
#!/usr/bin/env node --experimental-strip-types
|
|
2
|
+
import {runCli} from '../src/cli/cli.ts';
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const require = createRequire(import.meta.url);
|
|
8
|
-
const pkg = require('../package.json');
|
|
9
|
-
|
|
10
|
-
function printUsage() {
|
|
11
|
-
console.error(`@nyar/nyar ${pkg.version} (${hostPlatformKey()})`);
|
|
12
|
-
console.error('Usage: nyar <command> [args...]');
|
|
13
|
-
console.error('Commands:');
|
|
14
|
-
console.error(' host-info Print resolved platform collect metadata');
|
|
15
|
-
console.error(' version Print package version');
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function cmdHostInfo() {
|
|
19
|
-
const collect = resolveCollect();
|
|
20
|
-
console.log(JSON.stringify({ version: pkg.version, host: hostPlatformKey(), collect }, null, 2));
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function cmdVersion() {
|
|
24
|
-
console.log(pkg.version);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const [command, ...rest] = process.argv.slice(2);
|
|
28
|
-
|
|
29
|
-
if (!command || command === '--help' || command === '-h') {
|
|
30
|
-
printUsage();
|
|
31
|
-
process.exit(command ? 0 : 1);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (command === 'version' || command === '--version' || command === '-V') {
|
|
35
|
-
cmdVersion();
|
|
36
|
-
process.exit(0);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (command === 'host-info') {
|
|
40
|
-
cmdHostInfo();
|
|
41
|
-
process.exit(0);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Forward unknown commands to wasmtime when the wasm collect is present (maintainer / CI path).
|
|
45
|
-
const collect = resolveCollect();
|
|
46
|
-
if (collect.kind === 'wasm' && rest.length > 0) {
|
|
47
|
-
const result = spawnSync('wasmtime', [collect.entry, ...rest], { stdio: 'inherit', shell: false });
|
|
48
|
-
process.exit(result.status ?? 1);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
console.error(`nyar: unknown command '${command}'`);
|
|
52
|
-
printUsage();
|
|
53
|
-
process.exit(1);
|
|
4
|
+
const code = await runCli(process.argv.slice(2));
|
|
5
|
+
process.exit(code ?? 0);
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nyar/nyar",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Nyar VM
|
|
3
|
+
"version": "0.0.3",
|
|
4
|
+
"description": "Nyar VM host CLI (@vmz/commander) and orthogonal nyar-napi bindings.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"main": "src/index.ts",
|
|
8
8
|
"exports": {
|
|
9
|
-
".": "./src/index.ts"
|
|
9
|
+
".": "./src/index.ts",
|
|
10
|
+
"./cli": "./src/cli/cli.ts"
|
|
10
11
|
},
|
|
11
12
|
"bin": {
|
|
12
13
|
"nyar": "bin/nyar.js"
|
|
@@ -17,14 +18,18 @@
|
|
|
17
18
|
"readme.md",
|
|
18
19
|
"README.md"
|
|
19
20
|
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"test": "node --experimental-strip-types --test tests/**/*.test.ts"
|
|
23
|
+
},
|
|
20
24
|
"dependencies": {
|
|
21
|
-
"@
|
|
25
|
+
"@vmz/commander": "^0.3.2",
|
|
26
|
+
"@nyar/nyar-unknown-wasm32": "0.0.3"
|
|
22
27
|
},
|
|
23
28
|
"optionalDependencies": {
|
|
24
|
-
"@nyar/nyar-win32-x64": "0.0.
|
|
25
|
-
"@nyar/nyar-linux-x64": "0.0.
|
|
26
|
-
"@nyar/nyar-darwin-x64": "0.0.
|
|
27
|
-
"@nyar/nyar-darwin-arm64": "0.0.
|
|
29
|
+
"@nyar/nyar-win32-x64": "0.0.3",
|
|
30
|
+
"@nyar/nyar-linux-x64": "0.0.3",
|
|
31
|
+
"@nyar/nyar-darwin-x64": "0.0.3",
|
|
32
|
+
"@nyar/nyar-darwin-arm64": "0.0.3"
|
|
28
33
|
},
|
|
29
34
|
"engines": {
|
|
30
35
|
"node": ">=20"
|
package/readme.md
CHANGED
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
# @nyar/nyar
|
|
2
2
|
|
|
3
|
-
Cross-platform
|
|
3
|
+
Cross-platform Nyar host CLI and TypeScript facade. **CLI orchestration** uses [`@vmz/commander`](https://www.npmjs.com/package/@vmz/commander); **orthogonal native capabilities** are exported from `nyar-napi` via `src/native.ts`.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## CLI
|
|
6
6
|
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
```bash
|
|
8
|
+
nyar version
|
|
9
|
+
nyar host-info
|
|
10
|
+
nyar runtime list
|
|
11
|
+
nyar runtime prepare --family wasi --artifact ./app.wasm --entry main
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
## Programmatic native surface
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { getHostInfo, listRuntimeFamilies, prepareRuntimeCommand } from '@nyar/nyar';
|
|
18
|
+
|
|
19
|
+
const info = getHostInfo();
|
|
20
|
+
const families = listRuntimeFamilies();
|
|
21
|
+
const cmd = prepareRuntimeCommand({
|
|
22
|
+
family: 'wasi',
|
|
23
|
+
artifact: '/path/to/app.wasm',
|
|
24
|
+
entry: 'main',
|
|
25
|
+
});
|
|
26
|
+
```
|
|
15
27
|
|
|
16
|
-
|
|
28
|
+
Platform collects (`nyar-win32-x64`, `nyar-linux-x64`, `nyar-darwin-*`, `nyar-unknown-wasm32`) are resolved automatically when installed on a matching host.
|
|
17
29
|
|
|
18
30
|
## License
|
|
19
31
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type {LocaleCatalog} from '@vmz/commander';
|
|
2
|
+
|
|
3
|
+
/** Nyar CLI 英文 catalog(产品层;`commander.*` 由框架 fallback 提供)。 */
|
|
4
|
+
export const NYAR_CLI_CATALOG: LocaleCatalog = {
|
|
5
|
+
'cli.intro': 'Nyar VM host CLI — runtime dispatch and collect diagnostics',
|
|
6
|
+
'cli.cmd.version': 'Print package version and host protocol',
|
|
7
|
+
'cli.cmd.host-info': 'Print resolved platform collect and native host metadata',
|
|
8
|
+
'cli.cmd.runtime': 'Runtime family helpers',
|
|
9
|
+
'cli.cmd.runtime.list': 'List supported runtime families',
|
|
10
|
+
'cli.cmd.runtime.prepare': 'Expand a runtime template without executing',
|
|
11
|
+
'cli.cmd.runtime.run': 'Prepare and execute a runtime command',
|
|
12
|
+
'cli.opt.family': 'Runtime family id (clr, jvm, node, wasi, nyar-vm, …)',
|
|
13
|
+
'cli.opt.artifact': 'Artifact path (binary, jar, wasm module, …)',
|
|
14
|
+
'cli.opt.classpath': 'Classpath for JVM family',
|
|
15
|
+
'cli.opt.entry': 'Logical entry symbol',
|
|
16
|
+
'cli.opt.wasi-p3': 'Enable wasmtime -S p3 for WASI family',
|
|
17
|
+
'cli.opt.cwd': 'Working directory for runtime run',
|
|
18
|
+
};
|
package/src/cli/cli.ts
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import {spawnSync} from 'node:child_process';
|
|
2
|
+
import {readFileSync} from 'node:fs';
|
|
3
|
+
import {createRequire} from 'node:module';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
|
|
6
|
+
import type {Cli, Command, ParsedOptions} from '@vmz/commander';
|
|
7
|
+
import {createCli} from '@vmz/commander';
|
|
8
|
+
|
|
9
|
+
import {NYAR_CLI_CATALOG} from './catalog.ts';
|
|
10
|
+
import {getHostInfo, listRuntimeFamilies, prepareRuntimeCommand, runPreparedCommand} from '../native.ts';
|
|
11
|
+
import {hostPlatformKey, resolveCollect} from '../platform.ts';
|
|
12
|
+
|
|
13
|
+
const require = createRequire(import.meta.url);
|
|
14
|
+
const pkg = require('../../package.json') as { version: string };
|
|
15
|
+
|
|
16
|
+
function buildCli(): Cli {
|
|
17
|
+
const cli = createCli('nyar').catalog(() => NYAR_CLI_CATALOG).intro('cli.intro');
|
|
18
|
+
|
|
19
|
+
cli.command('version', 'cli.cmd.version').action(() => {
|
|
20
|
+
const info = getHostInfo();
|
|
21
|
+
console.log(`@nyar/nyar ${pkg.version}`);
|
|
22
|
+
console.log(`host ${info.hostProtocol} (${info.binding})`);
|
|
23
|
+
return 0;
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
cli.command('host-info', 'cli.cmd.host-info').action(() => {
|
|
27
|
+
const collect = resolveCollect();
|
|
28
|
+
const info = getHostInfo();
|
|
29
|
+
console.log(
|
|
30
|
+
JSON.stringify(
|
|
31
|
+
{
|
|
32
|
+
version: pkg.version,
|
|
33
|
+
host: hostPlatformKey(),
|
|
34
|
+
hostProtocol: info.hostProtocol,
|
|
35
|
+
binding: info.binding,
|
|
36
|
+
collect,
|
|
37
|
+
},
|
|
38
|
+
null,
|
|
39
|
+
2,
|
|
40
|
+
),
|
|
41
|
+
);
|
|
42
|
+
return 0;
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const runtime = cli.command('runtime', 'cli.cmd.runtime');
|
|
46
|
+
|
|
47
|
+
runtime.command('list', 'cli.cmd.runtime.list').action(() => {
|
|
48
|
+
for (const family of listRuntimeFamilies()) {
|
|
49
|
+
console.log(family);
|
|
50
|
+
}
|
|
51
|
+
return 0;
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const runtimeOpts = (cmd: Command) =>
|
|
55
|
+
cmd
|
|
56
|
+
.option('--family <id>', 'cli.opt.family')
|
|
57
|
+
.option('--artifact <path>', 'cli.opt.artifact')
|
|
58
|
+
.option('--classpath <path>', 'cli.opt.classpath')
|
|
59
|
+
.option('--entry <name>', 'cli.opt.entry')
|
|
60
|
+
.option('--wasi-p3', 'cli.opt.wasi-p3');
|
|
61
|
+
|
|
62
|
+
runtimeOpts(runtime.command('prepare', 'cli.cmd.runtime.prepare')).action((options: ParsedOptions) => {
|
|
63
|
+
const family = requireString(options, 'family');
|
|
64
|
+
const artifact = requireString(options, 'artifact');
|
|
65
|
+
const entry = requireString(options, 'entry');
|
|
66
|
+
const prepared = prepareRuntimeCommand({
|
|
67
|
+
family,
|
|
68
|
+
artifact: path.resolve(artifact),
|
|
69
|
+
classpath: typeof options.classpath === 'string' ? options.classpath : undefined,
|
|
70
|
+
entry,
|
|
71
|
+
wasiP3: Boolean(options['wasi-p3']),
|
|
72
|
+
});
|
|
73
|
+
console.log(JSON.stringify(prepared, null, 2));
|
|
74
|
+
return 0;
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
runtimeOpts(runtime.command('run', 'cli.cmd.runtime.run'))
|
|
78
|
+
.option('--cwd <dir>', 'cli.opt.cwd')
|
|
79
|
+
.action((options: ParsedOptions) => {
|
|
80
|
+
const family = requireString(options, 'family');
|
|
81
|
+
const artifact = requireString(options, 'artifact');
|
|
82
|
+
const entry = requireString(options, 'entry');
|
|
83
|
+
const prepared = prepareRuntimeCommand({
|
|
84
|
+
family,
|
|
85
|
+
artifact: path.resolve(artifact),
|
|
86
|
+
classpath: typeof options.classpath === 'string' ? options.classpath : undefined,
|
|
87
|
+
entry,
|
|
88
|
+
wasiP3: Boolean(options['wasi-p3']),
|
|
89
|
+
});
|
|
90
|
+
const cwd = typeof options.cwd === 'string' ? path.resolve(options.cwd) : process.cwd();
|
|
91
|
+
const code = runPreparedCommand(prepared, cwd);
|
|
92
|
+
return code;
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
return cli;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function requireString(options: ParsedOptions, key: string): string {
|
|
99
|
+
const value = options[key];
|
|
100
|
+
if (typeof value !== 'string' || !value) {
|
|
101
|
+
throw new Error(`missing required --${key}`);
|
|
102
|
+
}
|
|
103
|
+
return value;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** 解析 argv 并执行 Nyar CLI(@vmz/commander 编排;能力调用走 nyar-napi)。 */
|
|
107
|
+
export async function runCli(argv: string[] = process.argv.slice(2)): Promise<number> {
|
|
108
|
+
const [cmd] = argv;
|
|
109
|
+
if (cmd === 'wasm' && resolveCollect().kind === 'wasm') {
|
|
110
|
+
return forwardWasm(argv.slice(1));
|
|
111
|
+
}
|
|
112
|
+
return buildCli().parse(argv);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function forwardWasm(rest: string[]): number {
|
|
116
|
+
const collect = resolveCollect();
|
|
117
|
+
if (collect.kind !== 'wasm') {
|
|
118
|
+
console.error('nyar: wasm forward requires wasm collect');
|
|
119
|
+
return 1;
|
|
120
|
+
}
|
|
121
|
+
if (!existsArtifact(collect.entry)) {
|
|
122
|
+
console.error(`nyar: missing wasm collect at ${collect.entry}`);
|
|
123
|
+
return 1;
|
|
124
|
+
}
|
|
125
|
+
const result = spawnSync('wasmtime', [collect.entry, ...rest], {stdio: 'inherit', shell: false});
|
|
126
|
+
return result.status ?? 1;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function existsArtifact(filePath: string): boolean {
|
|
130
|
+
try {
|
|
131
|
+
readFileSync(filePath);
|
|
132
|
+
return true;
|
|
133
|
+
} catch {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,38 +1,39 @@
|
|
|
1
|
-
import { readFile } from 'node:fs/promises';
|
|
2
|
-
|
|
3
1
|
import { type NyarCollect, resolveCollect } from './platform.ts';
|
|
4
2
|
|
|
5
3
|
export { hostPlatformKey, type NyarCollect, resolveCollect } from './platform.ts';
|
|
4
|
+
export { nativeBinaryName, platformShort, platformTriple } from './platform-triple.ts';
|
|
5
|
+
export {
|
|
6
|
+
HOST_PROTOCOL,
|
|
7
|
+
getHostInfo,
|
|
8
|
+
listRuntimeFamilies,
|
|
9
|
+
loadNative,
|
|
10
|
+
prepareRuntimeCommand,
|
|
11
|
+
runPreparedCommand,
|
|
12
|
+
type HostInfo,
|
|
13
|
+
type PrepareRuntimeOptions,
|
|
14
|
+
type PreparedRuntimeCommand,
|
|
15
|
+
} from './native.ts';
|
|
16
|
+
export { runCli } from './cli/cli.ts';
|
|
6
17
|
|
|
7
18
|
export type NyarHost = {
|
|
8
19
|
/** Resolved platform collect metadata for diagnostics and tooling. */
|
|
9
20
|
collect: NyarCollect;
|
|
10
|
-
/**
|
|
11
|
-
|
|
21
|
+
/** Host protocol from nyar-napi. */
|
|
22
|
+
hostProtocol: string;
|
|
12
23
|
};
|
|
13
24
|
|
|
14
25
|
/**
|
|
15
|
-
* Create a Nyar host for the current platform.
|
|
26
|
+
* Create a Nyar host handle for the current platform.
|
|
16
27
|
*
|
|
17
28
|
* Native collects are preferred when the matching optional dependency is installed;
|
|
18
|
-
* otherwise the Wasm
|
|
29
|
+
* otherwise the Wasm collect from `@nyar/nyar-unknown-wasm32` is used.
|
|
19
30
|
*/
|
|
20
31
|
export async function createNyarHost(): Promise<NyarHost> {
|
|
21
32
|
const collect = resolveCollect();
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
// 0.0.0 ships collect layout only; bytecode execution is wired in the next host export drop.
|
|
29
|
-
await readFile(collect.entry);
|
|
30
|
-
throw new Error(
|
|
31
|
-
`nyar host collect resolved (${collect.kind} via ${collect.packageName}) but bytecode execution is not wired in 0.0.0`,
|
|
32
|
-
);
|
|
33
|
-
},
|
|
34
|
-
};
|
|
33
|
+
if (collect.kind === 'native') {
|
|
34
|
+
const { getHostInfo } = await import('./native.ts');
|
|
35
|
+
const info = getHostInfo();
|
|
36
|
+
return { collect, hostProtocol: info.hostProtocol };
|
|
37
|
+
}
|
|
38
|
+
return { collect, hostProtocol: 'nyar-host/0' };
|
|
35
39
|
}
|
|
36
|
-
|
|
37
|
-
/** @deprecated Use {@link createNyarHost}. */
|
|
38
|
-
export const NYAR_CLI_PLACEHOLDER = 'nyar';
|
package/src/native.ts
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import {createRequire} from 'node:module';
|
|
2
|
+
import {existsSync} from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import {fileURLToPath} from 'node:url';
|
|
5
|
+
|
|
6
|
+
import {hostPlatformKey} from './platform.ts';
|
|
7
|
+
import {nativeBinaryName, platformShort, platformTriple} from './platform-triple.ts';
|
|
8
|
+
|
|
9
|
+
/** Node 宿主协议 id(与 nyar-napi `HOST_PROTOCOL` 对齐)。 */
|
|
10
|
+
export const HOST_PROTOCOL = 'nyar-host/0';
|
|
11
|
+
|
|
12
|
+
export type HostInfo = {
|
|
13
|
+
hostProtocol: string;
|
|
14
|
+
binding: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type PrepareRuntimeOptions = {
|
|
18
|
+
family: string;
|
|
19
|
+
artifact: string;
|
|
20
|
+
classpath?: string;
|
|
21
|
+
entry: string;
|
|
22
|
+
wasiP3?: boolean;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type PreparedRuntimeCommand = {
|
|
26
|
+
family: string;
|
|
27
|
+
command: string;
|
|
28
|
+
args: string[];
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
type NyarNativeAddon = {
|
|
32
|
+
getHostInfo(): HostInfo;
|
|
33
|
+
listRuntimeFamilies(): string[];
|
|
34
|
+
parseRuntimeFamily(value: string): string;
|
|
35
|
+
prepareRuntimeCommand(options: {
|
|
36
|
+
family: string;
|
|
37
|
+
artifact: string;
|
|
38
|
+
classpath?: string;
|
|
39
|
+
entry: string;
|
|
40
|
+
wasiP3?: boolean;
|
|
41
|
+
}): PreparedRuntimeCommand;
|
|
42
|
+
runPreparedCommand(prepared: PreparedRuntimeCommand, cwd?: string): number;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const pkgRoot = path.dirname(fileURLToPath(import.meta.url));
|
|
46
|
+
const require = createRequire(import.meta.url);
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Resolve native `.node` via the platform optionalDependency (`@nyar/nyar-<short>`).
|
|
50
|
+
*/
|
|
51
|
+
export function resolveNativePath(): string {
|
|
52
|
+
const triple = platformTriple();
|
|
53
|
+
const short = platformShort(triple);
|
|
54
|
+
const packageName = `@nyar/nyar-${short}`;
|
|
55
|
+
const binary = nativeBinaryName(triple);
|
|
56
|
+
const candidates: string[] = [];
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const pkgJson = require.resolve(`${packageName}/package.json`);
|
|
60
|
+
const pkgDir = path.dirname(pkgJson);
|
|
61
|
+
candidates.push(path.join(pkgDir, 'lib', binary));
|
|
62
|
+
candidates.push(path.join(pkgDir, binary));
|
|
63
|
+
} catch {
|
|
64
|
+
/* optional dep not installed */
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
candidates.push(path.join(pkgRoot, '..', '..', `nyar-${short}`, 'lib', binary));
|
|
68
|
+
candidates.push(path.join(pkgRoot, '..', '..', `nyar-${short}`, binary));
|
|
69
|
+
candidates.push(path.join(pkgRoot, 'node_modules', packageName, 'lib', binary));
|
|
70
|
+
|
|
71
|
+
for (const candidate of candidates) {
|
|
72
|
+
if (existsSync(candidate)) return candidate;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
throw new Error(
|
|
76
|
+
`nyar native addon not found for ${packageName}. Run: node scripts/build.mjs napi\n` +
|
|
77
|
+
`Looked in:\n${candidates.map((c) => ` - ${c}`).join('\n')}\n` +
|
|
78
|
+
`(host ${hostPlatformKey()})`,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let nativeAddon: NyarNativeAddon | undefined;
|
|
83
|
+
|
|
84
|
+
/** 加载当前平台的 nyar-napi 绑定(正交能力面,不含 CLI)。 */
|
|
85
|
+
export function loadNative(): NyarNativeAddon {
|
|
86
|
+
if (nativeAddon) return nativeAddon;
|
|
87
|
+
const triple = platformTriple();
|
|
88
|
+
const short = platformShort(triple);
|
|
89
|
+
const packageName = `@nyar/nyar-${short}`;
|
|
90
|
+
nativeAddon = require(resolveNativePath()) as NyarNativeAddon;
|
|
91
|
+
return nativeAddon;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function getHostInfo(): HostInfo {
|
|
95
|
+
return loadNative().getHostInfo();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function listRuntimeFamilies(): string[] {
|
|
99
|
+
return loadNative().listRuntimeFamilies();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function prepareRuntimeCommand(options: PrepareRuntimeOptions): PreparedRuntimeCommand {
|
|
103
|
+
const native = loadNative();
|
|
104
|
+
return native.prepareRuntimeCommand({
|
|
105
|
+
family: options.family,
|
|
106
|
+
artifact: options.artifact,
|
|
107
|
+
classpath: options.classpath,
|
|
108
|
+
entry: options.entry,
|
|
109
|
+
wasiP3: options.wasiP3,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function runPreparedCommand(prepared: PreparedRuntimeCommand, cwd?: string): number {
|
|
114
|
+
return loadNative().runPreparedCommand(prepared, cwd);
|
|
115
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {arch, platform} from 'node:os';
|
|
2
|
+
|
|
3
|
+
/** npm platform short id (`win32-x64`, …) from host OS. */
|
|
4
|
+
export function platformShort(triple?: string): string {
|
|
5
|
+
const t = triple ?? platformTriple();
|
|
6
|
+
if (t.startsWith('win32-')) return 'win32-x64';
|
|
7
|
+
if (t.startsWith('linux-')) return 'linux-x64';
|
|
8
|
+
if (t === 'darwin-arm64') return 'darwin-arm64';
|
|
9
|
+
if (t === 'darwin-x64') return 'darwin-x64';
|
|
10
|
+
return t;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Host triple used for platform-named native binaries (`nyar.<triple>.node`). */
|
|
14
|
+
export function platformTriple(): string {
|
|
15
|
+
const {platform: os, arch: cpu} = {platform: platform(), arch: arch()};
|
|
16
|
+
if (os === 'win32' && cpu === 'x64') return 'win32-x64-msvc';
|
|
17
|
+
if (os === 'linux' && cpu === 'x64') return 'linux-x64-gnu';
|
|
18
|
+
if (os === 'darwin' && cpu === 'arm64') return 'darwin-arm64';
|
|
19
|
+
if (os === 'darwin' && cpu === 'x64') return 'darwin-x64';
|
|
20
|
+
return `${os}-${cpu}`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function nativeBinaryName(triple?: string): string {
|
|
24
|
+
return `nyar.${triple ?? platformTriple()}.node`;
|
|
25
|
+
}
|
package/src/platform.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import {createRequire} from 'node:module';
|
|
2
|
+
import {arch, platform} from 'node:os';
|
|
3
|
+
import {fileURLToPath} from 'node:url';
|
|
4
4
|
|
|
5
5
|
const HOST_KEY = `${platform()}-${arch()}`;
|
|
6
6
|
|
|
@@ -48,11 +48,8 @@ export function resolveCollect(): NyarCollect {
|
|
|
48
48
|
if (nativePackage) {
|
|
49
49
|
const req = requireOptional(nativePackage);
|
|
50
50
|
if (req) {
|
|
51
|
-
const entry =
|
|
52
|
-
|
|
53
|
-
? req.resolve('./nyar_napi.dll')
|
|
54
|
-
: req.resolve(`./libnyar_napi.${HOST_KEY.startsWith('darwin') ? 'dylib' : 'so'}`);
|
|
55
|
-
return { kind: 'native', packageName: nativePackage, entry };
|
|
51
|
+
const entry = req.resolve('./index.mjs');
|
|
52
|
+
return {kind: 'native', packageName: nativePackage, entry};
|
|
56
53
|
}
|
|
57
54
|
}
|
|
58
55
|
|