@napi-rs/cli 3.5.1 → 3.6.1
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/dist/cli.js +328 -324
- package/dist/index.cjs +356 -355
- package/dist/index.d.cts +20 -16
- package/dist/index.d.ts +20 -16
- package/dist/index.js +327 -322
- package/package.json +8 -7
- package/src/api/build.ts +23 -30
- package/src/api/create-npm-dirs.ts +56 -4
- package/src/api/new.ts +9 -18
- package/src/api/rename.ts +11 -3
- package/src/api/templates/load-wasi-template.ts +11 -0
- package/src/api/templates/wasi-worker-template.ts +18 -1
- package/src/commands/cli-version.ts +15 -0
- package/src/index.ts +2 -0
- package/src/utils/config.ts +4 -0
- package/src/utils/metadata.ts +5 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@napi-rs/cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.1",
|
|
4
4
|
"description": "Cli tools for napi-rs",
|
|
5
5
|
"author": "LongYinan <lynweklm@gmail.com>",
|
|
6
6
|
"homepage": "https://napi.rs/",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"@octokit/rest": "^22.0.1",
|
|
67
67
|
"clipanion": "^4.0.0-rc.4",
|
|
68
68
|
"colorette": "^2.0.20",
|
|
69
|
-
"emnapi": "^1.
|
|
69
|
+
"emnapi": "^1.9.1",
|
|
70
70
|
"es-toolkit": "^1.41.0",
|
|
71
71
|
"js-yaml": "^4.1.0",
|
|
72
72
|
"obug": "^2.0.0",
|
|
@@ -74,18 +74,19 @@
|
|
|
74
74
|
"typanion": "^3.14.0"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
|
-
"@emnapi/runtime": "^1.
|
|
78
|
-
"@oxc-node/core": "^0.0
|
|
77
|
+
"@emnapi/runtime": "^1.9.1",
|
|
78
|
+
"@oxc-node/core": "^0.1.0",
|
|
79
79
|
"@std/toml": "npm:@jsr/std__toml@^1.0.11",
|
|
80
80
|
"@types/inquirer": "^9.0.9",
|
|
81
81
|
"@types/js-yaml": "^4.0.9",
|
|
82
82
|
"@types/node": "^24.10.0",
|
|
83
83
|
"@types/semver": "^7.7.1",
|
|
84
|
-
"ava": "^
|
|
84
|
+
"ava": "^7.0.0",
|
|
85
85
|
"empathic": "^2.0.0",
|
|
86
|
-
"env-paths": "^
|
|
86
|
+
"env-paths": "^4.0.0",
|
|
87
|
+
"oxc-parser": "^0.124.0",
|
|
87
88
|
"prettier": "^3.6.2",
|
|
88
|
-
"tsdown": "^0.
|
|
89
|
+
"tsdown": "^0.21.0",
|
|
89
90
|
"tslib": "^2.8.1",
|
|
90
91
|
"typescript": "^5.9.3"
|
|
91
92
|
},
|
package/src/api/build.ts
CHANGED
|
@@ -381,35 +381,11 @@ class Builder {
|
|
|
381
381
|
set = true
|
|
382
382
|
}
|
|
383
383
|
} else {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
const glibcVersionRuntime =
|
|
390
|
-
// @ts-expect-error
|
|
391
|
-
process.report?.getReport()?.header?.glibcVersionRuntime
|
|
392
|
-
const libc = glibcVersionRuntime ? 'gnu' : 'musl'
|
|
393
|
-
return abi === libc
|
|
394
|
-
})(this.target.abi)
|
|
395
|
-
) {
|
|
396
|
-
debug.warn(
|
|
397
|
-
'You are trying to cross compile to linux target on linux platform which is unnecessary.',
|
|
398
|
-
)
|
|
399
|
-
} else if (
|
|
400
|
-
this.target.platform === 'darwin' &&
|
|
401
|
-
process.platform === 'darwin'
|
|
402
|
-
) {
|
|
403
|
-
debug.warn(
|
|
404
|
-
'You are trying to cross compile to darwin target on darwin platform which is unnecessary.',
|
|
405
|
-
)
|
|
406
|
-
} else {
|
|
407
|
-
// use cargo-zigbuild to cross compile to other platforms
|
|
408
|
-
debug('Use %i', 'cargo-zigbuild')
|
|
409
|
-
tryInstallCargoBinary('cargo-zigbuild', 'zigbuild')
|
|
410
|
-
this.args.push('zigbuild')
|
|
411
|
-
set = true
|
|
412
|
-
}
|
|
384
|
+
// use cargo-zigbuild to cross compile to other platforms
|
|
385
|
+
debug('Use %i', 'cargo-zigbuild')
|
|
386
|
+
tryInstallCargoBinary('cargo-zigbuild', 'zigbuild')
|
|
387
|
+
this.args.push('zigbuild')
|
|
388
|
+
set = true
|
|
413
389
|
}
|
|
414
390
|
}
|
|
415
391
|
|
|
@@ -569,6 +545,19 @@ class Builder {
|
|
|
569
545
|
'wasm32-wasi-threads',
|
|
570
546
|
)
|
|
571
547
|
this.envs.EMNAPI_LINK_DIR = emnapi
|
|
548
|
+
const emnapiVersion = require('emnapi/package.json').version
|
|
549
|
+
const projectRequire = createRequire(join(this.options.cwd, 'package.json'))
|
|
550
|
+
const emnapiCoreVersion = projectRequire('@emnapi/core').version
|
|
551
|
+
const emnapiRuntimeVersion = projectRequire('@emnapi/runtime').version
|
|
552
|
+
|
|
553
|
+
if (
|
|
554
|
+
emnapiVersion !== emnapiCoreVersion ||
|
|
555
|
+
emnapiVersion !== emnapiRuntimeVersion
|
|
556
|
+
) {
|
|
557
|
+
throw new Error(
|
|
558
|
+
`emnapi version mismatch: emnapi@${emnapiVersion}, @emnapi/core@${emnapiCoreVersion}, @emnapi/runtime@${emnapiRuntimeVersion}. Please ensure all emnapi packages are the same version.`,
|
|
559
|
+
)
|
|
560
|
+
}
|
|
572
561
|
const { WASI_SDK_PATH } = process.env
|
|
573
562
|
|
|
574
563
|
if (WASI_SDK_PATH && existsSync(WASI_SDK_PATH)) {
|
|
@@ -964,6 +953,7 @@ class Builder {
|
|
|
964
953
|
this.config.wasm?.browser?.fs,
|
|
965
954
|
this.config.wasm?.browser?.asyncInit,
|
|
966
955
|
this.config.wasm?.browser?.buffer,
|
|
956
|
+
this.config.wasm?.browser?.errorEvent,
|
|
967
957
|
) +
|
|
968
958
|
`export default __napiModule.exports\n` +
|
|
969
959
|
idents
|
|
@@ -978,7 +968,10 @@ class Builder {
|
|
|
978
968
|
await writeFileAsync(workerPath, WASI_WORKER_TEMPLATE, 'utf8')
|
|
979
969
|
await writeFileAsync(
|
|
980
970
|
browserWorkerPath,
|
|
981
|
-
createWasiBrowserWorkerBinding(
|
|
971
|
+
createWasiBrowserWorkerBinding(
|
|
972
|
+
this.config.wasm?.browser?.fs ?? false,
|
|
973
|
+
this.config.wasm?.browser?.errorEvent ?? false,
|
|
974
|
+
),
|
|
982
975
|
'utf8',
|
|
983
976
|
)
|
|
984
977
|
await writeFileAsync(
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'
|
|
1
2
|
import { join, resolve } from 'node:path'
|
|
2
3
|
|
|
3
4
|
import { parse } from 'semver'
|
|
4
5
|
|
|
6
|
+
const require = createRequire(import.meta.url)
|
|
7
|
+
|
|
5
8
|
import {
|
|
6
9
|
applyDefaultCreateNpmDirsOptions,
|
|
7
10
|
type CreateNpmDirsOptions,
|
|
@@ -22,6 +25,52 @@ export interface PackageMeta {
|
|
|
22
25
|
'dist-tags': { [index: string]: string }
|
|
23
26
|
}
|
|
24
27
|
|
|
28
|
+
const WASM_RUNTIME_PACKAGE_NAME = '@napi-rs/wasm-runtime'
|
|
29
|
+
|
|
30
|
+
async function getLatestWasmRuntimeVersion() {
|
|
31
|
+
const npmRegistryBase =
|
|
32
|
+
process.env.npm_config_registry?.replace(/\/?$/, '/') ??
|
|
33
|
+
'https://registry.npmjs.org/'
|
|
34
|
+
const packageMetadataUrl = `${npmRegistryBase}${WASM_RUNTIME_PACKAGE_NAME}`
|
|
35
|
+
let response: Response
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
response = await fetch(packageMetadataUrl)
|
|
39
|
+
} catch (error) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`Failed to fetch ${packageMetadataUrl} while resolving ${WASM_RUNTIME_PACKAGE_NAME}. Check your network connection and npm registry availability.`,
|
|
42
|
+
{ cause: error },
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
`Failed to fetch ${packageMetadataUrl} while resolving ${WASM_RUNTIME_PACKAGE_NAME}: npm registry responded with ${response.status} ${response.statusText || 'Unknown Status'}`,
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let packageMeta: PackageMeta
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
packageMeta = (await response.json()) as PackageMeta
|
|
56
|
+
} catch (error) {
|
|
57
|
+
throw new Error(
|
|
58
|
+
`Failed to parse npm registry metadata for ${WASM_RUNTIME_PACKAGE_NAME} from ${packageMetadataUrl}`,
|
|
59
|
+
{ cause: error },
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const latestVersion = packageMeta['dist-tags']?.latest
|
|
64
|
+
|
|
65
|
+
if (typeof latestVersion !== 'string' || latestVersion.trim().length === 0) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`npm registry metadata for ${WASM_RUNTIME_PACKAGE_NAME} from ${packageMetadataUrl} did not include a latest dist-tag`,
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return latestVersion.trim()
|
|
72
|
+
}
|
|
73
|
+
|
|
25
74
|
export async function createNpmDirs(userOptions: CreateNpmDirsOptions) {
|
|
26
75
|
const options = applyDefaultCreateNpmDirsOptions(userOptions)
|
|
27
76
|
|
|
@@ -57,6 +106,9 @@ export async function createNpmDirs(userOptions: CreateNpmDirsOptions) {
|
|
|
57
106
|
packageJsonPath,
|
|
58
107
|
options.configPath ? resolve(options.cwd, options.configPath) : undefined,
|
|
59
108
|
)
|
|
109
|
+
const wasmRuntimeVersion = targets.some((target) => target.arch === 'wasm32')
|
|
110
|
+
? await getLatestWasmRuntimeVersion()
|
|
111
|
+
: undefined
|
|
60
112
|
|
|
61
113
|
for (const target of targets) {
|
|
62
114
|
const targetDir = join(npmPath, `${target.platformArchABI}`)
|
|
@@ -122,11 +174,11 @@ export async function createNpmDirs(userOptions: CreateNpmDirsOptions) {
|
|
|
122
174
|
node: '>=14.0.0',
|
|
123
175
|
}
|
|
124
176
|
}
|
|
125
|
-
const
|
|
126
|
-
`https://registry.npmjs.org/@napi-rs/wasm-runtime`,
|
|
127
|
-
).then((res) => res.json() as Promise<PackageMeta>)
|
|
177
|
+
const emnapiVersion = require('emnapi/package.json').version
|
|
128
178
|
scopedPackageJson.dependencies = {
|
|
129
|
-
'@napi-rs/wasm-runtime': `^${
|
|
179
|
+
'@napi-rs/wasm-runtime': `^${wasmRuntimeVersion}`,
|
|
180
|
+
'@emnapi/core': emnapiVersion,
|
|
181
|
+
'@emnapi/runtime': emnapiVersion,
|
|
130
182
|
}
|
|
131
183
|
}
|
|
132
184
|
|
package/src/api/new.ts
CHANGED
|
@@ -34,24 +34,15 @@ const TEMPLATE_REPOS = {
|
|
|
34
34
|
} as const
|
|
35
35
|
|
|
36
36
|
async function checkGitCommand(): Promise<boolean> {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
resolve(false)
|
|
42
|
-
})
|
|
43
|
-
cp.on('exit', (code) => {
|
|
44
|
-
if (code === 0) {
|
|
45
|
-
resolve(true)
|
|
46
|
-
} else {
|
|
47
|
-
resolve(false)
|
|
48
|
-
}
|
|
49
|
-
})
|
|
37
|
+
return new Promise<boolean>((resolve) => {
|
|
38
|
+
const cp = exec('git --version')
|
|
39
|
+
cp.on('error', () => {
|
|
40
|
+
resolve(false)
|
|
50
41
|
})
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
42
|
+
cp.on('exit', (code) => {
|
|
43
|
+
resolve(code === 0)
|
|
44
|
+
})
|
|
45
|
+
})
|
|
55
46
|
}
|
|
56
47
|
|
|
57
48
|
async function ensureCacheDir(
|
|
@@ -132,7 +123,7 @@ async function copyDirectory(
|
|
|
132
123
|
!includeWasiBindings &&
|
|
133
124
|
(entry.name.endsWith('.wasi-browser.js') ||
|
|
134
125
|
entry.name.endsWith('.wasi.cjs') ||
|
|
135
|
-
entry.name.endsWith('wasi-worker
|
|
126
|
+
entry.name.endsWith('wasi-worker-browser.mjs') ||
|
|
136
127
|
entry.name.endsWith('wasi-worker.mjs') ||
|
|
137
128
|
entry.name.endsWith('browser.js'))
|
|
138
129
|
) {
|
package/src/api/rename.ts
CHANGED
|
@@ -45,8 +45,16 @@ export async function renameProject(userOptions: RenameOptions) {
|
|
|
45
45
|
const configPath = resolve(options.cwd, options.configPath)
|
|
46
46
|
const configContent = await readFileAsync(configPath, 'utf8')
|
|
47
47
|
const configData = JSON.parse(configContent)
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
merge(
|
|
49
|
+
configData,
|
|
50
|
+
omitBy(
|
|
51
|
+
{
|
|
52
|
+
binaryName: options.binaryName,
|
|
53
|
+
packageName: options.packageName,
|
|
54
|
+
},
|
|
55
|
+
isNil,
|
|
56
|
+
),
|
|
57
|
+
)
|
|
50
58
|
await writeFileAsync(configPath, JSON.stringify(configData, null, 2))
|
|
51
59
|
}
|
|
52
60
|
|
|
@@ -73,7 +81,7 @@ export async function renameProject(userOptions: RenameOptions) {
|
|
|
73
81
|
const updatedTomlContent = stringifyToml(cargoToml)
|
|
74
82
|
|
|
75
83
|
await writeFileAsync(cargoTomlPath, updatedTomlContent)
|
|
76
|
-
if (oldName !== options.binaryName) {
|
|
84
|
+
if (options.binaryName && oldName !== options.binaryName) {
|
|
77
85
|
const githubActionsPath = find.dir('.github', {
|
|
78
86
|
cwd: options.cwd,
|
|
79
87
|
})
|
|
@@ -5,6 +5,7 @@ export const createWasiBrowserBinding = (
|
|
|
5
5
|
fs = false,
|
|
6
6
|
asyncInit = false,
|
|
7
7
|
buffer = false,
|
|
8
|
+
errorEvent = false,
|
|
8
9
|
) => {
|
|
9
10
|
const fsImport = fs
|
|
10
11
|
? buffer
|
|
@@ -32,6 +33,15 @@ const __wasi = new __WASI({
|
|
|
32
33
|
? ` worker.addEventListener('message', __wasmCreateOnMessageForFsProxy(__fs))\n`
|
|
33
34
|
: ''
|
|
34
35
|
|
|
36
|
+
const workerErrorHandler = errorEvent
|
|
37
|
+
? ` worker.addEventListener('error', (event) => {
|
|
38
|
+
if (event.data && typeof event.data === 'object' && event.data.type === 'error') {
|
|
39
|
+
window.dispatchEvent(new CustomEvent('napi-rs-worker-error', { detail: event.data }))
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
`
|
|
43
|
+
: ''
|
|
44
|
+
|
|
35
45
|
const emnapiInjectBuffer = buffer
|
|
36
46
|
? '__emnapiContext.feature.Buffer = Buffer'
|
|
37
47
|
: ''
|
|
@@ -77,6 +87,7 @@ const {
|
|
|
77
87
|
type: 'module',
|
|
78
88
|
})
|
|
79
89
|
${workerFsHandler}
|
|
90
|
+
${workerErrorHandler}
|
|
80
91
|
return worker
|
|
81
92
|
},
|
|
82
93
|
overwriteImports(importObject) {
|
|
@@ -63,13 +63,19 @@ globalThis.onmessage = function (e) {
|
|
|
63
63
|
};
|
|
64
64
|
`
|
|
65
65
|
|
|
66
|
-
export const createWasiBrowserWorkerBinding = (
|
|
66
|
+
export const createWasiBrowserWorkerBinding = (
|
|
67
|
+
fs: boolean,
|
|
68
|
+
errorEvent: boolean,
|
|
69
|
+
) => {
|
|
67
70
|
const fsImport = fs
|
|
68
71
|
? `import { instantiateNapiModuleSync, MessageHandler, WASI, createFsProxy } from '@napi-rs/wasm-runtime'
|
|
69
72
|
import { memfsExported as __memfsExported } from '@napi-rs/wasm-runtime/fs'
|
|
70
73
|
|
|
71
74
|
const fs = createFsProxy(__memfsExported)`
|
|
72
75
|
: `import { instantiateNapiModuleSync, MessageHandler, WASI } from '@napi-rs/wasm-runtime'`
|
|
76
|
+
const errorOutputsAppend = errorEvent
|
|
77
|
+
? `\n errorOutputs.push([...arguments])`
|
|
78
|
+
: ''
|
|
73
79
|
const wasiCreation = fs
|
|
74
80
|
? `const wasi = new WASI({
|
|
75
81
|
fs,
|
|
@@ -83,6 +89,7 @@ const fs = createFsProxy(__memfsExported)`
|
|
|
83
89
|
printErr: function() {
|
|
84
90
|
// eslint-disable-next-line no-console
|
|
85
91
|
console.error.apply(console, arguments)
|
|
92
|
+
${errorOutputsAppend}
|
|
86
93
|
},
|
|
87
94
|
})`
|
|
88
95
|
: `const wasi = new WASI({
|
|
@@ -93,10 +100,19 @@ const fs = createFsProxy(__memfsExported)`
|
|
|
93
100
|
printErr: function() {
|
|
94
101
|
// eslint-disable-next-line no-console
|
|
95
102
|
console.error.apply(console, arguments)
|
|
103
|
+
${errorOutputsAppend}
|
|
96
104
|
},
|
|
97
105
|
})`
|
|
106
|
+
const errorHandler = errorEvent
|
|
107
|
+
? `onError(error) {
|
|
108
|
+
postMessage({ type: 'error', error, errorOutputs })
|
|
109
|
+
errorOutputs.length = 0
|
|
110
|
+
}`
|
|
111
|
+
: ''
|
|
98
112
|
return `${fsImport}
|
|
99
113
|
|
|
114
|
+
const errorOutputs = []
|
|
115
|
+
|
|
100
116
|
const handler = new MessageHandler({
|
|
101
117
|
onLoad({ wasmModule, wasmMemory }) {
|
|
102
118
|
${wasiCreation}
|
|
@@ -113,6 +129,7 @@ const handler = new MessageHandler({
|
|
|
113
129
|
},
|
|
114
130
|
})
|
|
115
131
|
},
|
|
132
|
+
${errorHandler}
|
|
116
133
|
})
|
|
117
134
|
|
|
118
135
|
globalThis.onmessage = function (e) {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Command } from 'clipanion'
|
|
2
|
+
|
|
3
|
+
import { CLI_VERSION } from '../utils/misc.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A command that prints the version of the CLI.
|
|
7
|
+
*
|
|
8
|
+
* Paths: `-v`, `--version`
|
|
9
|
+
*/
|
|
10
|
+
export class CliVersionCommand extends Command<any> {
|
|
11
|
+
static paths = [[`-v`], [`--version`]]
|
|
12
|
+
async execute() {
|
|
13
|
+
await this.context.stdout.write(`${CLI_VERSION}\n`)
|
|
14
|
+
}
|
|
15
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { universalizeBinaries } from './api/universalize.js'
|
|
|
10
10
|
import { version } from './api/version.js'
|
|
11
11
|
import { ArtifactsCommand } from './commands/artifacts.js'
|
|
12
12
|
import { BuildCommand } from './commands/build.js'
|
|
13
|
+
import { CliVersionCommand } from './commands/cli-version.js'
|
|
13
14
|
import { CreateNpmDirsCommand } from './commands/create-npm-dirs.js'
|
|
14
15
|
import { HelpCommand } from './commands/help.js'
|
|
15
16
|
import { NewCommand } from './commands/new.js'
|
|
@@ -33,6 +34,7 @@ cli.register(RenameCommand)
|
|
|
33
34
|
cli.register(PrePublishCommand)
|
|
34
35
|
cli.register(VersionCommand)
|
|
35
36
|
cli.register(HelpCommand)
|
|
37
|
+
cli.register(CliVersionCommand)
|
|
36
38
|
|
|
37
39
|
/**
|
|
38
40
|
*
|
package/src/utils/config.ts
CHANGED
package/src/utils/metadata.ts
CHANGED
|
@@ -62,7 +62,7 @@ export async function parseMetadata(manifestPath: string) {
|
|
|
62
62
|
let stdout = ''
|
|
63
63
|
let stderr = ''
|
|
64
64
|
let status = 0
|
|
65
|
-
let error = null
|
|
65
|
+
let error: Error | null = null
|
|
66
66
|
|
|
67
67
|
childProcess.stdout.on('data', (data) => {
|
|
68
68
|
stdout += data
|
|
@@ -72,6 +72,10 @@ export async function parseMetadata(manifestPath: string) {
|
|
|
72
72
|
stderr += data
|
|
73
73
|
})
|
|
74
74
|
|
|
75
|
+
childProcess.on('error', (err) => {
|
|
76
|
+
error = err
|
|
77
|
+
})
|
|
78
|
+
|
|
75
79
|
await new Promise<void>((resolve) => {
|
|
76
80
|
childProcess.on('close', (code) => {
|
|
77
81
|
status = code ?? 0
|