@napi-rs/cli 3.5.0 → 3.6.0
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 +299 -308
- package/dist/index.cjs +327 -339
- package/dist/index.d.cts +19 -15
- package/dist/index.d.ts +19 -15
- package/dist/index.js +298 -306
- package/package.json +8 -7
- package/src/api/build.ts +18 -1
- package/src/api/create-npm-dirs.ts +6 -0
- package/src/api/templates/js-binding.ts +6 -2
- package/src/api/templates/load-wasi-template.ts +12 -1
- 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 +6 -0
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@napi-rs/cli",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.0",
|
|
4
4
|
"description": "Cli tools for napi-rs",
|
|
5
5
|
"author": "LongYinan <lynweklm@gmail.com>",
|
|
6
|
-
"homepage": "https://
|
|
6
|
+
"homepage": "https://napi.rs/",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"engines": {
|
|
@@ -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.
|
|
77
|
+
"@emnapi/runtime": "^1.9.1",
|
|
78
78
|
"@oxc-node/core": "^0.0.35",
|
|
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.121.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
|
@@ -569,6 +569,19 @@ class Builder {
|
|
|
569
569
|
'wasm32-wasi-threads',
|
|
570
570
|
)
|
|
571
571
|
this.envs.EMNAPI_LINK_DIR = emnapi
|
|
572
|
+
const emnapiVersion = require('emnapi/package.json').version
|
|
573
|
+
const projectRequire = createRequire(join(this.options.cwd, 'package.json'))
|
|
574
|
+
const emnapiCoreVersion = projectRequire('@emnapi/core').version
|
|
575
|
+
const emnapiRuntimeVersion = projectRequire('@emnapi/runtime').version
|
|
576
|
+
|
|
577
|
+
if (
|
|
578
|
+
emnapiVersion !== emnapiCoreVersion ||
|
|
579
|
+
emnapiVersion !== emnapiRuntimeVersion
|
|
580
|
+
) {
|
|
581
|
+
throw new Error(
|
|
582
|
+
`emnapi version mismatch: emnapi@${emnapiVersion}, @emnapi/core@${emnapiCoreVersion}, @emnapi/runtime@${emnapiRuntimeVersion}. Please ensure all emnapi packages are the same version.`,
|
|
583
|
+
)
|
|
584
|
+
}
|
|
572
585
|
const { WASI_SDK_PATH } = process.env
|
|
573
586
|
|
|
574
587
|
if (WASI_SDK_PATH && existsSync(WASI_SDK_PATH)) {
|
|
@@ -964,6 +977,7 @@ class Builder {
|
|
|
964
977
|
this.config.wasm?.browser?.fs,
|
|
965
978
|
this.config.wasm?.browser?.asyncInit,
|
|
966
979
|
this.config.wasm?.browser?.buffer,
|
|
980
|
+
this.config.wasm?.browser?.errorEvent,
|
|
967
981
|
) +
|
|
968
982
|
`export default __napiModule.exports\n` +
|
|
969
983
|
idents
|
|
@@ -978,7 +992,10 @@ class Builder {
|
|
|
978
992
|
await writeFileAsync(workerPath, WASI_WORKER_TEMPLATE, 'utf8')
|
|
979
993
|
await writeFileAsync(
|
|
980
994
|
browserWorkerPath,
|
|
981
|
-
createWasiBrowserWorkerBinding(
|
|
995
|
+
createWasiBrowserWorkerBinding(
|
|
996
|
+
this.config.wasm?.browser?.fs ?? false,
|
|
997
|
+
this.config.wasm?.browser?.errorEvent ?? false,
|
|
998
|
+
),
|
|
982
999
|
'utf8',
|
|
983
1000
|
)
|
|
984
1001
|
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,
|
|
@@ -122,11 +125,14 @@ export async function createNpmDirs(userOptions: CreateNpmDirsOptions) {
|
|
|
122
125
|
node: '>=14.0.0',
|
|
123
126
|
}
|
|
124
127
|
}
|
|
128
|
+
const emnapiVersion = require('emnapi/package.json').version
|
|
125
129
|
const wasmRuntime = await fetch(
|
|
126
130
|
`https://registry.npmjs.org/@napi-rs/wasm-runtime`,
|
|
127
131
|
).then((res) => res.json() as Promise<PackageMeta>)
|
|
128
132
|
scopedPackageJson.dependencies = {
|
|
129
133
|
'@napi-rs/wasm-runtime': `^${wasmRuntime['dist-tags'].latest}`,
|
|
134
|
+
'@emnapi/core': emnapiVersion,
|
|
135
|
+
'@emnapi/runtime': emnapiVersion,
|
|
130
136
|
}
|
|
131
137
|
}
|
|
132
138
|
|
|
@@ -238,13 +238,17 @@ if (!nativeBinding || process.env.NAPI_RS_FORCE_WASI) {
|
|
|
238
238
|
wasiBindingError = err
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
|
-
if (!nativeBinding) {
|
|
241
|
+
if (!nativeBinding || process.env.NAPI_RS_FORCE_WASI) {
|
|
242
242
|
try {
|
|
243
243
|
wasiBinding = require('${pkgName}-wasm32-wasi')
|
|
244
244
|
nativeBinding = wasiBinding
|
|
245
245
|
} catch (err) {
|
|
246
246
|
if (process.env.NAPI_RS_FORCE_WASI) {
|
|
247
|
-
wasiBindingError
|
|
247
|
+
if (!wasiBindingError) {
|
|
248
|
+
wasiBindingError = err
|
|
249
|
+
} else {
|
|
250
|
+
wasiBindingError.cause = err
|
|
251
|
+
}
|
|
248
252
|
loadErrors.push(err)
|
|
249
253
|
}
|
|
250
254
|
}
|
|
@@ -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) {
|
|
@@ -145,7 +156,7 @@ if (__nodeFs.existsSync(__wasmDebugFilePath)) {
|
|
|
145
156
|
__wasmFilePath = __wasmDebugFilePath
|
|
146
157
|
} else if (!__nodeFs.existsSync(__wasmFilePath)) {
|
|
147
158
|
try {
|
|
148
|
-
__wasmFilePath =
|
|
159
|
+
__wasmFilePath = require.resolve('${packageName}-wasm32-wasi/${wasmFileName}.wasm')
|
|
149
160
|
} catch {
|
|
150
161
|
throw new Error('Cannot find ${wasmFileName}.wasm file, and ${packageName}-wasm32-wasi package is not installed.')
|
|
151
162
|
}
|
|
@@ -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
|
@@ -83,6 +83,10 @@ export interface UserNapiConfig {
|
|
|
83
83
|
* Whether to inject `buffer` to emnapi context
|
|
84
84
|
*/
|
|
85
85
|
buffer?: boolean
|
|
86
|
+
/**
|
|
87
|
+
* Whether to emit custom events for errors in worker
|
|
88
|
+
*/
|
|
89
|
+
errorEvent?: boolean
|
|
86
90
|
}
|
|
87
91
|
}
|
|
88
92
|
|
|
@@ -198,6 +202,8 @@ export async function readNapiConfig(
|
|
|
198
202
|
`Both napi field in ${pkgJsonPath} and [NAPI-RS config](${configPathUnderline}) file are found, the NAPI-RS config file will be used.`,
|
|
199
203
|
),
|
|
200
204
|
)
|
|
205
|
+
}
|
|
206
|
+
if (separatedConfig) {
|
|
201
207
|
Object.assign(userNapiConfig, separatedConfig)
|
|
202
208
|
}
|
|
203
209
|
const napiConfig: NapiConfig = merge(
|