@napi-rs/cli 3.0.0-alpha.7 → 3.0.0-alpha.70

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.
Files changed (160) hide show
  1. package/cli.mjs +1 -1
  2. package/dist/api/artifacts.js +28 -7
  3. package/dist/api/artifacts.js.map +1 -1
  4. package/dist/api/build.js +243 -47
  5. package/dist/api/build.js.map +1 -1
  6. package/dist/api/create-npm-dirs.js +46 -9
  7. package/dist/api/create-npm-dirs.js.map +1 -1
  8. package/dist/api/new.js +57 -20
  9. package/dist/api/new.js.map +1 -1
  10. package/dist/api/pre-publish.js +9 -7
  11. package/dist/api/pre-publish.js.map +1 -1
  12. package/dist/api/rename.js +9 -1
  13. package/dist/api/rename.js.map +1 -1
  14. package/dist/api/templates/cargo.toml.js +1 -0
  15. package/dist/api/templates/cargo.toml.js.map +1 -1
  16. package/dist/api/templates/ci-template.d.ts +3 -1
  17. package/dist/api/templates/ci-template.js +144 -131
  18. package/dist/api/templates/ci-template.js.map +1 -1
  19. package/dist/api/templates/ci.yml.d.ts +3 -1
  20. package/dist/api/templates/ci.yml.js +21 -5
  21. package/dist/api/templates/ci.yml.js.map +1 -1
  22. package/dist/api/templates/js-binding.d.ts +1 -0
  23. package/dist/api/templates/js-binding.js +129 -221
  24. package/dist/api/templates/js-binding.js.map +1 -1
  25. package/dist/api/templates/lib.rs.js +1 -4
  26. package/dist/api/templates/lib.rs.js.map +1 -1
  27. package/dist/api/templates/load-wasi-template.d.ts +2 -0
  28. package/dist/api/templates/load-wasi-template.js +166 -0
  29. package/dist/api/templates/load-wasi-template.js.map +1 -0
  30. package/dist/api/templates/package.json.d.ts +9 -2
  31. package/dist/api/templates/package.json.js +26 -4
  32. package/dist/api/templates/package.json.js.map +1 -1
  33. package/dist/api/templates/wasi-worker-template.d.ts +2 -0
  34. package/dist/api/templates/wasi-worker-template.js +122 -0
  35. package/dist/api/templates/wasi-worker-template.js.map +1 -0
  36. package/dist/api/universalize.js +5 -5
  37. package/dist/api/universalize.js.map +1 -1
  38. package/dist/api/version.js +2 -2
  39. package/dist/api/version.js.map +1 -1
  40. package/dist/commands/artifacts.js +2 -2
  41. package/dist/commands/artifacts.js.map +1 -1
  42. package/dist/commands/build.js +1 -1
  43. package/dist/commands/build.js.map +1 -1
  44. package/dist/commands/new.js +34 -34
  45. package/dist/commands/new.js.map +1 -1
  46. package/dist/def/artifacts.d.ts +21 -1
  47. package/dist/def/artifacts.js +10 -2
  48. package/dist/def/artifacts.js.map +1 -1
  49. package/dist/def/build.d.ts +155 -4
  50. package/dist/def/build.js +30 -4
  51. package/dist/def/build.js.map +1 -1
  52. package/dist/def/create-npm-dirs.d.ts +10 -0
  53. package/dist/def/create-npm-dirs.js +4 -0
  54. package/dist/def/create-npm-dirs.js.map +1 -1
  55. package/dist/def/new.d.ts +25 -7
  56. package/dist/def/new.js +11 -1
  57. package/dist/def/new.js.map +1 -1
  58. package/dist/def/pre-publish.d.ts +12 -2
  59. package/dist/def/pre-publish.js +7 -3
  60. package/dist/def/pre-publish.js.map +1 -1
  61. package/dist/def/rename.d.ts +16 -6
  62. package/dist/def/rename.js +5 -1
  63. package/dist/def/rename.js.map +1 -1
  64. package/dist/def/universalize.d.ts +10 -0
  65. package/dist/def/universalize.js +4 -0
  66. package/dist/def/universalize.js.map +1 -1
  67. package/dist/def/version.d.ts +10 -0
  68. package/dist/def/version.js +4 -0
  69. package/dist/def/version.js.map +1 -1
  70. package/dist/index.cjs +8007 -14675
  71. package/dist/index.d.ts +1 -0
  72. package/dist/index.js +1 -0
  73. package/dist/index.js.map +1 -1
  74. package/dist/utils/__tests__/config.spec.d.ts +1 -0
  75. package/dist/utils/__tests__/config.spec.js +63 -0
  76. package/dist/utils/__tests__/config.spec.js.map +1 -0
  77. package/dist/utils/__tests__/typegen.spec.js +8 -4
  78. package/dist/utils/__tests__/typegen.spec.js.map +1 -1
  79. package/dist/utils/cargo.js +2 -2
  80. package/dist/utils/cargo.js.map +1 -1
  81. package/dist/utils/config.d.ts +48 -4
  82. package/dist/utils/config.js +37 -5
  83. package/dist/utils/config.js.map +1 -1
  84. package/dist/utils/index.d.ts +0 -1
  85. package/dist/utils/index.js +0 -1
  86. package/dist/utils/index.js.map +1 -1
  87. package/dist/utils/metadata.js +2 -2
  88. package/dist/utils/metadata.js.map +1 -1
  89. package/dist/utils/misc.d.ts +1 -2
  90. package/dist/utils/misc.js +3 -3
  91. package/dist/utils/misc.js.map +1 -1
  92. package/dist/utils/target.d.ts +7 -5
  93. package/dist/utils/target.js +17 -3
  94. package/dist/utils/target.js.map +1 -1
  95. package/dist/utils/typegen.d.ts +1 -1
  96. package/dist/utils/typegen.js +51 -17
  97. package/dist/utils/typegen.js.map +1 -1
  98. package/dist/utils/version.d.ts +2 -1
  99. package/dist/utils/version.js +10 -8
  100. package/dist/utils/version.js.map +1 -1
  101. package/package.json +27 -26
  102. package/src/api/artifacts.ts +81 -9
  103. package/src/api/build.ts +398 -66
  104. package/src/api/create-npm-dirs.ts +57 -9
  105. package/src/api/new.ts +89 -31
  106. package/src/api/pre-publish.ts +13 -7
  107. package/src/api/rename.ts +10 -1
  108. package/src/api/templates/cargo.toml.ts +1 -0
  109. package/src/api/templates/ci-template.ts +154 -131
  110. package/src/api/templates/ci.yml.ts +27 -6
  111. package/src/api/templates/js-binding.ts +135 -219
  112. package/src/api/templates/lib.rs.ts +1 -4
  113. package/src/api/templates/load-wasi-template.ts +180 -0
  114. package/src/api/templates/package.json.ts +47 -5
  115. package/src/api/templates/wasi-worker-template.ts +122 -0
  116. package/src/api/universalize.ts +13 -8
  117. package/src/api/version.ts +5 -2
  118. package/src/commands/artifacts.ts +2 -2
  119. package/src/commands/build.ts +1 -1
  120. package/src/commands/new.ts +46 -45
  121. package/src/def/artifacts.ts +22 -3
  122. package/src/def/build.ts +64 -8
  123. package/src/def/create-npm-dirs.ts +9 -0
  124. package/src/def/new.ts +28 -3
  125. package/src/def/pre-publish.ts +12 -3
  126. package/src/def/rename.ts +11 -2
  127. package/src/def/universalize.ts +9 -0
  128. package/src/def/version.ts +9 -0
  129. package/src/index.ts +2 -0
  130. package/src/utils/__tests__/__fixtures__/napi_type_def +130 -130
  131. package/src/utils/__tests__/__snapshots__/config.spec.ts.md +97 -0
  132. package/src/utils/__tests__/__snapshots__/config.spec.ts.snap +0 -0
  133. package/src/utils/__tests__/__snapshots__/target.spec.ts.md +28 -0
  134. package/src/utils/__tests__/__snapshots__/target.spec.ts.snap +0 -0
  135. package/src/utils/__tests__/__snapshots__/typegen.spec.ts.md +711 -158
  136. package/src/utils/__tests__/__snapshots__/typegen.spec.ts.snap +0 -0
  137. package/src/utils/__tests__/__snapshots__/version.spec.ts.md +8 -7
  138. package/src/utils/__tests__/__snapshots__/version.spec.ts.snap +0 -0
  139. package/src/utils/__tests__/config.spec.ts +81 -0
  140. package/src/utils/__tests__/typegen.spec.ts +18 -3
  141. package/src/utils/cargo.ts +2 -2
  142. package/src/utils/config.ts +112 -10
  143. package/src/utils/index.ts +0 -1
  144. package/src/utils/metadata.ts +2 -2
  145. package/src/utils/misc.ts +11 -3
  146. package/src/utils/target.ts +22 -4
  147. package/src/utils/typegen.ts +81 -36
  148. package/src/utils/version.ts +10 -8
  149. package/dist/api/load-wasi-template.d.ts +0 -1
  150. package/dist/api/load-wasi-template.js +0 -63
  151. package/dist/api/load-wasi-template.js.map +0 -1
  152. package/dist/api/wasi-worker-template.d.ts +0 -1
  153. package/dist/api/wasi-worker-template.js +0 -53
  154. package/dist/api/wasi-worker-template.js.map +0 -1
  155. package/dist/utils/ci.d.ts +0 -11
  156. package/dist/utils/ci.js +0 -96
  157. package/dist/utils/ci.js.map +0 -1
  158. package/src/api/load-wasi-template.ts +0 -65
  159. package/src/api/wasi-worker-template.ts +0 -52
  160. package/src/utils/ci.ts +0 -111
package/src/api/build.ts CHANGED
@@ -1,10 +1,12 @@
1
1
  import { spawn } from 'node:child_process'
2
2
  import { createHash } from 'node:crypto'
3
+ import { existsSync, mkdirSync, unlinkSync } from 'node:fs'
3
4
  import { createRequire } from 'node:module'
4
- import { tmpdir } from 'node:os'
5
+ import { tmpdir, homedir } from 'node:os'
5
6
  import { parse, join, resolve } from 'node:path'
6
7
 
7
8
  import * as colors from 'colorette'
9
+ import { include as setjmpInclude, lib as setjmpLib } from 'wasm-sjlj'
8
10
 
9
11
  import { BuildOptions as RawBuildOptions } from '../def/build.js'
10
12
  import {
@@ -30,9 +32,15 @@ import {
30
32
  writeFileAsync,
31
33
  } from '../utils/index.js'
32
34
 
33
- import { createWasiBinding } from './load-wasi-template.js'
34
- import { createCjsBinding } from './templates/index.js'
35
- import { WASI_WORKER_TEMPLATE } from './wasi-worker-template.js'
35
+ import { createCjsBinding, createEsmBinding } from './templates/index.js'
36
+ import {
37
+ createWasiBinding,
38
+ createWasiBrowserBinding,
39
+ } from './templates/load-wasi-template.js'
40
+ import {
41
+ createWasiBrowserWorkerBinding,
42
+ WASI_WORKER_TEMPLATE,
43
+ } from './templates/wasi-worker-template.js'
36
44
 
37
45
  const debug = debugFactory('build')
38
46
  const require = createRequire(import.meta.url)
@@ -81,15 +89,18 @@ export async function buildProject(options: BuildOptions) {
81
89
  options.target
82
90
  ? parseTriple(options.target)
83
91
  : process.env.CARGO_BUILD_TARGET
84
- ? parseTriple(process.env.CARGO_BUILD_TARGET)
85
- : getSystemDefaultTarget(),
92
+ ? parseTriple(process.env.CARGO_BUILD_TARGET)
93
+ : getSystemDefaultTarget(),
86
94
  crateDir,
87
95
  resolvePath(options.outputDir ?? crateDir),
88
96
  options.targetDir ??
89
97
  process.env.CARGO_BUILD_TARGET_DIR ??
90
98
  metadata.target_directory,
91
99
  await readNapiConfig(
92
- resolvePath(options.packageJsonPath ?? 'package.json'),
100
+ resolvePath(
101
+ options.configPath ?? options.packageJsonPath ?? 'package.json',
102
+ ),
103
+ options.configPath ? resolvePath(options.configPath) : undefined,
93
104
  ),
94
105
  )
95
106
 
@@ -143,11 +154,138 @@ class Builder {
143
154
  .setPackage()
144
155
  .setFeatures()
145
156
  .setTarget()
157
+ .pickCrossToolchain()
146
158
  .setEnvs()
147
159
  .setBypassArgs()
148
160
  .exec()
149
161
  }
150
162
 
163
+ private pickCrossToolchain() {
164
+ if (!this.options.useNapiCross) {
165
+ return this
166
+ }
167
+ if (this.options.useCross) {
168
+ debug.warn(
169
+ 'You are trying to use both `--cross` and `--use-napi-cross` options, `--use-cross` will be ignored.',
170
+ )
171
+ }
172
+
173
+ if (this.options.crossCompile) {
174
+ debug.warn(
175
+ 'You are trying to use both `--cross-compile` and `--use-napi-cross` options, `--cross-compile` will be ignored.',
176
+ )
177
+ }
178
+
179
+ try {
180
+ const { version, download } = require('@napi-rs/cross-toolchain')
181
+
182
+ const alias: Record<string, string> = {
183
+ 's390x-unknown-linux-gnu': 's390x-ibm-linux-gnu',
184
+ }
185
+
186
+ const toolchainPath = join(
187
+ homedir(),
188
+ '.napi-rs',
189
+ 'cross-toolchain',
190
+ version,
191
+ this.target.triple,
192
+ )
193
+ mkdirSync(toolchainPath, { recursive: true })
194
+ if (existsSync(join(toolchainPath, 'package.json'))) {
195
+ debug(`Toolchain ${toolchainPath} exists, skip extracting`)
196
+ } else {
197
+ const tarArchive = download(process.arch, this.target.triple)
198
+ tarArchive.unpack(toolchainPath)
199
+ }
200
+ const upperCaseTarget = targetToEnvVar(this.target.triple)
201
+ const crossTargetName = alias[this.target.triple] ?? this.target.triple
202
+ const linkerEnv = `CARGO_TARGET_${upperCaseTarget}_LINKER`
203
+ this.envs[linkerEnv] = join(
204
+ toolchainPath,
205
+ 'bin',
206
+ `${crossTargetName}-gcc`,
207
+ )
208
+ if (!process.env.TARGET_SYSROOT) {
209
+ this.envs[`TARGET_SYSROOT`] = join(
210
+ toolchainPath,
211
+ crossTargetName,
212
+ 'sysroot',
213
+ )
214
+ }
215
+ if (!process.env.TARGET_AR) {
216
+ this.envs[`TARGET_AR`] = join(
217
+ toolchainPath,
218
+ 'bin',
219
+ `${crossTargetName}-ar`,
220
+ )
221
+ }
222
+ if (!process.env.TARGET_RANLIB) {
223
+ this.envs[`TARGET_RANLIB`] = join(
224
+ toolchainPath,
225
+ 'bin',
226
+ `${crossTargetName}-ranlib`,
227
+ )
228
+ }
229
+ if (!process.env.TARGET_READELF) {
230
+ this.envs[`TARGET_READELF`] = join(
231
+ toolchainPath,
232
+ 'bin',
233
+ `${crossTargetName}-readelf`,
234
+ )
235
+ }
236
+ if (!process.env.TARGET_C_INCLUDE_PATH) {
237
+ this.envs[`TARGET_C_INCLUDE_PATH`] = join(
238
+ toolchainPath,
239
+ crossTargetName,
240
+ 'sysroot',
241
+ 'usr',
242
+ 'include/',
243
+ )
244
+ }
245
+ if (!process.env.CC && !process.env.TARGET_CC) {
246
+ this.envs[`CC`] = join(toolchainPath, 'bin', `${crossTargetName}-gcc`)
247
+ this.envs[`TARGET_CC`] = join(
248
+ toolchainPath,
249
+ 'bin',
250
+ `${crossTargetName}-gcc`,
251
+ )
252
+ }
253
+ if (!process.env.CXX && !process.env.TARGET_CXX) {
254
+ this.envs[`CXX`] = join(
255
+ toolchainPath,
256
+ 'bin',
257
+ `${this.target.triple}-g++`,
258
+ )
259
+ this.envs[`TARGET_CXX`] = join(
260
+ toolchainPath,
261
+ 'bin',
262
+ `${this.target.triple}-g++`,
263
+ )
264
+ }
265
+ if (
266
+ (process.env.CC === 'clang' &&
267
+ (process.env.TARGET_CC === 'clang' || !process.env.TARGET_CC)) ||
268
+ process.env.TARGET_CC === 'clang'
269
+ ) {
270
+ this.envs.CFLAGS = `--sysroot=${this.envs.TARGET_SYSROOT} --gcc-toolchain=${toolchainPath}`
271
+ }
272
+ if (
273
+ (process.env.CXX === 'clang++' &&
274
+ (process.env.TARGET_CXX === 'clang++' || !process.env.TARGET_CXX)) ||
275
+ process.env.TARGET_CXX === 'clang++'
276
+ ) {
277
+ this.envs.CXXFLAGS = `--sysroot=${this.envs.TARGET_SYSROOT} --gcc-toolchain=${toolchainPath}`
278
+ }
279
+ this.envs.PATH = this.envs.PATH
280
+ ? `${toolchainPath}/bin:${this.envs.PATH}:${process.env.PATH}`
281
+ : `${toolchainPath}/bin:${process.env.PATH}`
282
+ } catch (e) {
283
+ debug.warn('Pick cross toolchain failed', e as Error)
284
+ // ignore, do nothing
285
+ }
286
+ return this
287
+ }
288
+
151
289
  private exec() {
152
290
  debug(`Start building crate: ${this.crate.name}`)
153
291
  debug(' %i', `cargo ${this.args.join(' ')}`)
@@ -156,6 +294,11 @@ class Builder {
156
294
 
157
295
  const watch = this.options.watch
158
296
  const buildTask = new Promise<void>((resolve, reject) => {
297
+ if (this.options.useCross && this.options.crossCompile) {
298
+ throw new Error(
299
+ '`--use-cross` and `--cross-compile` can not be used together',
300
+ )
301
+ }
159
302
  const command =
160
303
  process.env.CARGO ?? (this.options.useCross ? 'cross' : 'cargo')
161
304
  const buildProcess = spawn(command, this.args, {
@@ -189,7 +332,7 @@ class Builder {
189
332
  buildProcess.stderr?.on('data', (data) => {
190
333
  const output = data.toString()
191
334
  console.error(output)
192
- if (/Finished\s(dev|release)/.test(output)) {
335
+ if (/Finished\s(`dev`|`release`)/.test(output)) {
193
336
  this.postBuild().catch(() => {})
194
337
  }
195
338
  })
@@ -352,7 +495,7 @@ class Builder {
352
495
  const linkerEnv = `CARGO_TARGET_${targetToEnvVar(
353
496
  this.target.triple,
354
497
  )}_LINKER`
355
- if (linker && !process.env[linkerEnv]) {
498
+ if (linker && !process.env[linkerEnv] && !this.envs[linkerEnv]) {
356
499
  this.envs[linkerEnv] = linker
357
500
  }
358
501
 
@@ -373,15 +516,15 @@ class Builder {
373
516
  process.platform === 'darwin'
374
517
  ? 'darwin'
375
518
  : process.platform === 'win32'
376
- ? 'windows'
377
- : 'linux'
519
+ ? 'windows'
520
+ : 'linux'
378
521
  Object.assign(this.envs, {
379
522
  CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-android24-clang`,
380
523
  CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-androideabi24-clang`,
381
- CC: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang`,
382
- CXX: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang++`,
383
- AR: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ar`,
384
- RANLIB: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ranlib`,
524
+ TARGET_CC: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang`,
525
+ TARGET_CXX: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang++`,
526
+ TARGET_AR: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ar`,
527
+ TARGET_RANLIB: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ranlib`,
385
528
  ANDROID_NDK: ANDROID_NDK_LATEST_HOME,
386
529
  PATH: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin:${process.env.PATH}`,
387
530
  })
@@ -396,6 +539,47 @@ class Builder {
396
539
  'wasm32-wasi-threads',
397
540
  )
398
541
  this.envs.EMNAPI_LINK_DIR = emnapi
542
+ this.envs.SETJMP_LINK_DIR = setjmpLib
543
+ const { WASI_SDK_PATH } = process.env
544
+
545
+ if (WASI_SDK_PATH && existsSync(WASI_SDK_PATH)) {
546
+ this.envs.CARGO_TARGET_WASM32_WASI_PREVIEW1_THREADS_LINKER = join(
547
+ WASI_SDK_PATH,
548
+ 'bin',
549
+ 'wasm-ld',
550
+ )
551
+ this.envs.CARGO_TARGET_WASM32_WASIP1_LINKER = join(
552
+ WASI_SDK_PATH,
553
+ 'bin',
554
+ 'wasm-ld',
555
+ )
556
+ this.envs.CARGO_TARGET_WASM32_WASIP1_THREADS_LINKER = join(
557
+ WASI_SDK_PATH,
558
+ 'bin',
559
+ 'wasm-ld',
560
+ )
561
+ this.envs.CARGO_TARGET_WASM32_WASIP2_LINKER = join(
562
+ WASI_SDK_PATH,
563
+ 'bin',
564
+ 'wasm-ld',
565
+ )
566
+ this.setEnvIfNotExists('CC', join(WASI_SDK_PATH, 'bin', 'clang'))
567
+ this.setEnvIfNotExists('CXX', join(WASI_SDK_PATH, 'bin', 'clang++'))
568
+ this.setEnvIfNotExists('AR', join(WASI_SDK_PATH, 'bin', 'ar'))
569
+ this.setEnvIfNotExists('RANLIB', join(WASI_SDK_PATH, 'bin', 'ranlib'))
570
+ this.setEnvIfNotExists(
571
+ 'CFLAGS',
572
+ `--target=wasm32-wasi-threads --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -pthread -mllvm -wasm-enable-sjlj -I${setjmpInclude}`,
573
+ )
574
+ this.setEnvIfNotExists(
575
+ 'CXXFLAGS',
576
+ `--target=wasm32-wasi-threads --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -pthread -mllvm -wasm-enable-sjlj -I${setjmpInclude}`,
577
+ )
578
+ this.setEnvIfNotExists(
579
+ `LDFLAGS`,
580
+ `-fuse-ld=${WASI_SDK_PATH}/bin/wasm-ld --target=wasm32-wasi-threads`,
581
+ )
582
+ }
399
583
  }
400
584
 
401
585
  debug('Set envs: ')
@@ -408,11 +592,17 @@ class Builder {
408
592
 
409
593
  private setFeatures() {
410
594
  const args = []
595
+ if (this.options.allFeatures && this.options.noDefaultFeatures) {
596
+ throw new Error(
597
+ 'Cannot specify --all-features and --no-default-features together',
598
+ )
599
+ }
411
600
  if (this.options.allFeatures) {
412
601
  args.push('--all-features')
413
602
  } else if (this.options.noDefaultFeatures) {
414
603
  args.push('--no-default-features')
415
- } else if (this.options.features) {
604
+ }
605
+ if (this.options.features) {
416
606
  args.push('--features', ...this.options.features)
417
607
  }
418
608
 
@@ -440,6 +630,10 @@ class Builder {
440
630
  this.args.push('--profile', this.options.profile)
441
631
  }
442
632
 
633
+ if (this.options.manifestPath) {
634
+ this.args.push('--manifest-path', this.options.manifestPath)
635
+ }
636
+
443
637
  if (this.options.cargoOptions?.length) {
444
638
  this.args.push(...this.options.cargoOptions)
445
639
  }
@@ -448,14 +642,21 @@ class Builder {
448
642
  }
449
643
 
450
644
  private getIntermediateTypeFile() {
451
- return join(
645
+ const dtsPath = join(
452
646
  tmpdir(),
453
647
  `${this.crate.name}-${createHash('sha256')
454
648
  .update(this.crate.manifest_path)
455
649
  .update(CLI_VERSION)
456
650
  .digest('hex')
457
- .substring(0, 8)}.napi_type_def.tmp`,
651
+ .substring(0, 8)}.napi_type_def`,
458
652
  )
653
+ if (!this.options.dtsCache) {
654
+ try {
655
+ unlinkSync(dtsPath)
656
+ } catch {}
657
+ return `${dtsPath}_${Date.now()}.tmp`
658
+ }
659
+ return `${dtsPath}.tmp`
459
660
  }
460
661
 
461
662
  private getIntermediateWasiRegisterFile() {
@@ -481,38 +682,48 @@ class Builder {
481
682
  })
482
683
  }
483
684
 
484
- const dest = await this.copyArtifact()
685
+ const wasmBinaryName = await this.copyArtifact()
485
686
 
486
687
  // only for cdylib
487
688
  if (this.cdyLibName) {
488
689
  const idents = await this.generateTypeDef()
489
690
  const intermediateWasiRegisterFile = this.envs.WASI_REGISTER_TMP_PATH
490
- const wasiRegisterFunctions =
491
- this.target.arch === 'wasm32'
492
- ? JSON.parse(
493
- await readFileAsync(intermediateWasiRegisterFile, 'utf8').catch(
494
- (err) => {
495
- console.warn(
496
- `Read ${colors.yellowBright(
497
- intermediateWasiRegisterFile,
498
- )} failed, reason: ${err.message}`,
499
- )
500
- return `[]`
501
- },
502
- ),
503
- )
504
- : []
691
+ const wasiRegisterFunctions = this.config.targets.some(
692
+ (t) => t.platform === 'wasi',
693
+ )
694
+ ? await (async function readIntermediateWasiRegisterFile() {
695
+ const fileContent = await readFileAsync(
696
+ intermediateWasiRegisterFile,
697
+ 'utf8',
698
+ ).catch((err) => {
699
+ console.warn(
700
+ `Read ${colors.yellowBright(
701
+ intermediateWasiRegisterFile,
702
+ )} failed, reason: ${err.message}`,
703
+ )
704
+ return ``
705
+ })
706
+ return fileContent
707
+ .split('\n')
708
+ .map((l) => l.trim())
709
+ .filter((l) => l.length)
710
+ .map((line) => {
711
+ const [_, fn] = line.split(':')
712
+ return fn.trim()
713
+ })
714
+ })()
715
+ : []
505
716
  const jsOutput = await this.writeJsBinding(idents)
506
- const wasmOutput = await this.writeWasiBinding(
717
+ const wasmBindingsOutput = await this.writeWasiBinding(
507
718
  wasiRegisterFunctions,
508
- dest ?? 'index.wasm',
719
+ wasmBinaryName ?? 'index.wasm',
509
720
  idents,
510
721
  )
511
722
  if (jsOutput) {
512
723
  this.outputs.push(jsOutput)
513
724
  }
514
- if (wasmOutput) {
515
- this.outputs.push(wasmOutput)
725
+ if (wasmBindingsOutput) {
726
+ this.outputs.push(...wasmBindingsOutput)
516
727
  }
517
728
  }
518
729
 
@@ -520,7 +731,7 @@ class Builder {
520
731
  }
521
732
 
522
733
  private async copyArtifact() {
523
- const [srcName, destName] = this.getArtifactNames()
734
+ const [srcName, destName, wasmBinaryName] = this.getArtifactNames()
524
735
  if (!srcName || !destName) {
525
736
  return
526
737
  }
@@ -530,6 +741,7 @@ class Builder {
530
741
  const src = join(this.targetDir, this.target.triple, profile, srcName)
531
742
  debug(`Copy artifact from: [${src}]`)
532
743
  const dest = join(this.outputDir, destName)
744
+ const isWasm = dest.endsWith('.wasm')
533
745
 
534
746
  try {
535
747
  if (await fileExists(dest)) {
@@ -538,12 +750,47 @@ class Builder {
538
750
  }
539
751
  debug('Copy artifact to:')
540
752
  debug(' %i', dest)
541
- await copyFileAsync(src, dest)
753
+ if (isWasm) {
754
+ const { ModuleConfig } = await import('@napi-rs/wasm-tools')
755
+ debug('Generate debug wasm module')
756
+ try {
757
+ const debugWasmModule = new ModuleConfig()
758
+ .generateDwarf(true)
759
+ .generateNameSection(true)
760
+ .generateProducersSection(true)
761
+ .preserveCodeTransform(true)
762
+ .strictValidate(false)
763
+ .parse(await readFileAsync(src))
764
+ const debugWasmBinary = debugWasmModule.emitWasm(true)
765
+ await writeFileAsync(
766
+ dest.replace('.wasm', '.debug.wasm'),
767
+ debugWasmBinary,
768
+ )
769
+ debug('Generate release wasm module')
770
+ const releaseWasmModule = new ModuleConfig()
771
+ .generateDwarf(false)
772
+ .generateNameSection(false)
773
+ .generateProducersSection(false)
774
+ .preserveCodeTransform(false)
775
+ .strictValidate(false)
776
+ .onlyStableFeatures(false)
777
+ .parse(debugWasmBinary)
778
+ const releaseWasmBinary = releaseWasmModule.emitWasm(false)
779
+ await writeFileAsync(dest, releaseWasmBinary)
780
+ } catch (e) {
781
+ debug.warn(
782
+ `Failed to generate debug wasm module: ${(e as any).message ?? e}`,
783
+ )
784
+ await copyFileAsync(src, dest)
785
+ }
786
+ } else {
787
+ await copyFileAsync(src, dest)
788
+ }
542
789
  this.outputs.push({
543
- kind: dest.endsWith('.node') ? 'node' : 'exe',
790
+ kind: dest.endsWith('.node') ? 'node' : isWasm ? 'wasm' : 'exe',
544
791
  path: dest,
545
792
  })
546
- return dest
793
+ return wasmBinaryName ? join(this.outputDir, wasmBinaryName) : null
547
794
  } catch (e) {
548
795
  throw new Error('Failed to copy artifact', {
549
796
  cause: e,
@@ -554,15 +801,16 @@ class Builder {
554
801
  private getArtifactNames() {
555
802
  if (this.cdyLibName) {
556
803
  const cdyLib = this.cdyLibName.replace(/-/g, '_')
804
+ const wasiTarget = this.config.targets.find((t) => t.platform === 'wasi')
557
805
 
558
806
  const srcName =
559
807
  this.target.platform === 'darwin'
560
808
  ? `lib${cdyLib}.dylib`
561
809
  : this.target.platform === 'win32'
562
- ? `${cdyLib}.dll`
563
- : this.target.platform === 'wasi' || this.target.platform === 'wasm'
564
- ? `${cdyLib}.wasm`
565
- : `lib${cdyLib}.so`
810
+ ? `${cdyLib}.dll`
811
+ : this.target.platform === 'wasi' || this.target.platform === 'wasm'
812
+ ? `${cdyLib}.wasm`
813
+ : `lib${cdyLib}.so`
566
814
 
567
815
  let destName = this.config.binaryName
568
816
  // add platform suffix to binary name
@@ -572,12 +820,18 @@ class Builder {
572
820
  destName += `.${this.target.platformArchABI}`
573
821
  }
574
822
  if (srcName.endsWith('.wasm')) {
575
- destName += '.wasi-wasm32.wasm'
823
+ destName += '.wasm'
576
824
  } else {
577
825
  destName += '.node'
578
826
  }
579
827
 
580
- return [srcName, destName]
828
+ return [
829
+ srcName,
830
+ destName,
831
+ wasiTarget
832
+ ? `${this.config.binaryName}.${wasiTarget.platformArchABI}.wasm`
833
+ : null,
834
+ ]
581
835
  } else if (this.binName) {
582
836
  const srcName =
583
837
  this.target.platform === 'win32' ? `${this.binName}.exe` : this.binName
@@ -597,8 +851,22 @@ class Builder {
597
851
 
598
852
  const { dts, exports } = await processTypeDef(
599
853
  this.envs.TYPE_DEF_TMP_PATH,
854
+ this.options.constEnum ?? this.config.constEnum ?? true,
600
855
  !this.options.noDtsHeader
601
- ? this.options.dtsHeader ?? DEFAULT_TYPE_DEF_HEADER
856
+ ? (this.options.dtsHeader ??
857
+ (this.config.dtsHeaderFile
858
+ ? await readFileAsync(
859
+ join(this.cwd, this.config.dtsHeaderFile),
860
+ 'utf-8',
861
+ ).catch(() => {
862
+ debug.warn(
863
+ `Failed to read dts header file ${this.config.dtsHeaderFile}`,
864
+ )
865
+ return null
866
+ })
867
+ : null) ??
868
+ this.config.dtsHeader ??
869
+ DEFAULT_TYPE_DEF_HEADER)
602
870
  : '',
603
871
  )
604
872
 
@@ -628,19 +896,20 @@ class Builder {
628
896
  return
629
897
  }
630
898
 
631
- const name = parse(this.options.jsBinding ?? 'index.js').name
899
+ const name = this.options.jsBinding ?? 'index.js'
632
900
 
633
- const cjs = createCjsBinding(
901
+ const createBinding = this.options.esm ? createEsmBinding : createCjsBinding
902
+ const binding = createBinding(
634
903
  this.config.binaryName,
635
904
  this.config.packageName,
636
905
  idents,
637
906
  )
638
907
 
639
908
  try {
640
- const dest = join(this.outputDir, `${name}.js`)
909
+ const dest = join(this.outputDir, name)
641
910
  debug('Writing js binding to:')
642
911
  debug(' %i', dest)
643
- await writeFileAsync(dest, cjs, 'utf-8')
912
+ await writeFileAsync(dest, binding, 'utf-8')
644
913
  return {
645
914
  kind: 'js',
646
915
  path: dest,
@@ -657,26 +926,89 @@ class Builder {
657
926
  ) {
658
927
  if (distFileName && wasiRegisterFunctions.length) {
659
928
  const { name, dir } = parse(distFileName)
660
- const newPath = join(dir, `${this.config.binaryName}.wasi.mjs`)
929
+ const bindingPath = join(dir, `${this.config.binaryName}.wasi.cjs`)
930
+ const browserBindingPath = join(
931
+ dir,
932
+ `${this.config.binaryName}.wasi-browser.js`,
933
+ )
661
934
  const workerPath = join(dir, 'wasi-worker.mjs')
662
- const declareCodes = `const { ${idents.join(', ')} } = binding\n`
663
- const exportsCode = `export {\n${idents
664
- .map((ident) => ` ${ident}`)
665
- .join(',\n')}\n}`
935
+ const browserWorkerPath = join(dir, 'wasi-worker-browser.mjs')
936
+ const browserEntryPath = join(dir, 'browser.js')
937
+ const exportsCode = idents
938
+ .map(
939
+ (ident) => `module.exports.${ident} = __napiModule.exports.${ident}`,
940
+ )
941
+ .join('\n')
666
942
  await writeFileAsync(
667
- newPath,
668
- createWasiBinding(name, wasiRegisterFunctions) +
669
- declareCodes +
943
+ bindingPath,
944
+ createWasiBinding(
945
+ name,
946
+ this.config.packageName,
947
+ wasiRegisterFunctions,
948
+ this.config.wasm?.initialMemory,
949
+ this.config.wasm?.maximumMemory,
950
+ ) +
670
951
  exportsCode +
671
952
  '\n',
672
953
  'utf8',
673
954
  )
955
+ await writeFileAsync(
956
+ browserBindingPath,
957
+ createWasiBrowserBinding(
958
+ name,
959
+ wasiRegisterFunctions,
960
+ this.config.wasm?.initialMemory,
961
+ this.config.wasm?.maximumMemory,
962
+ this.config.wasm?.browser?.fs,
963
+ ) +
964
+ idents
965
+ .map(
966
+ (ident) =>
967
+ `export const ${ident} = __napiModule.exports.${ident}`,
968
+ )
969
+ .join('\n') +
970
+ '\n',
971
+ 'utf8',
972
+ )
674
973
  await writeFileAsync(workerPath, WASI_WORKER_TEMPLATE, 'utf8')
675
- return {
676
- kind: 'wasm',
677
- path: newPath,
678
- } satisfies Output
974
+ await writeFileAsync(
975
+ browserWorkerPath,
976
+ createWasiBrowserWorkerBinding(this.config.wasm?.browser?.fs ?? false),
977
+ 'utf8',
978
+ )
979
+ await writeFileAsync(
980
+ browserEntryPath,
981
+ `export * from '${this.config.packageName}-wasm32-wasi'\n`,
982
+ )
983
+ return [
984
+ {
985
+ kind: 'js',
986
+ path: bindingPath,
987
+ },
988
+ {
989
+ kind: 'js',
990
+ path: browserBindingPath,
991
+ },
992
+ {
993
+ kind: 'js',
994
+ path: workerPath,
995
+ },
996
+ {
997
+ kind: 'js',
998
+ path: browserWorkerPath,
999
+ },
1000
+ {
1001
+ kind: 'js',
1002
+ path: browserEntryPath,
1003
+ },
1004
+ ] satisfies Output[]
1005
+ }
1006
+ return []
1007
+ }
1008
+
1009
+ private setEnvIfNotExists(env: string, value: string) {
1010
+ if (!process.env[env]) {
1011
+ this.envs[env] = value
679
1012
  }
680
- return null
681
1013
  }
682
1014
  }