@napi-rs/cli 3.0.0-alpha.6 → 3.0.0-alpha.60

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 (155) hide show
  1. package/dist/api/artifacts.js +28 -7
  2. package/dist/api/artifacts.js.map +1 -1
  3. package/dist/api/build.js +220 -39
  4. package/dist/api/build.js.map +1 -1
  5. package/dist/api/create-npm-dirs.js +45 -8
  6. package/dist/api/create-npm-dirs.js.map +1 -1
  7. package/dist/api/new.js +57 -20
  8. package/dist/api/new.js.map +1 -1
  9. package/dist/api/pre-publish.js +9 -7
  10. package/dist/api/pre-publish.js.map +1 -1
  11. package/dist/api/rename.js +9 -1
  12. package/dist/api/rename.js.map +1 -1
  13. package/dist/api/templates/ci-template.d.ts +3 -1
  14. package/dist/api/templates/ci-template.js +124 -124
  15. package/dist/api/templates/ci-template.js.map +1 -1
  16. package/dist/api/templates/ci.yml.d.ts +3 -1
  17. package/dist/api/templates/ci.yml.js +21 -5
  18. package/dist/api/templates/ci.yml.js.map +1 -1
  19. package/dist/api/templates/js-binding.js +104 -214
  20. package/dist/api/templates/js-binding.js.map +1 -1
  21. package/dist/api/templates/lib.rs.js +1 -4
  22. package/dist/api/templates/lib.rs.js.map +1 -1
  23. package/dist/api/templates/load-wasi-template.d.ts +2 -0
  24. package/dist/api/templates/load-wasi-template.js +166 -0
  25. package/dist/api/templates/load-wasi-template.js.map +1 -0
  26. package/dist/api/templates/package.json.d.ts +9 -2
  27. package/dist/api/templates/package.json.js +26 -4
  28. package/dist/api/templates/package.json.js.map +1 -1
  29. package/dist/api/templates/wasi-worker-template.d.ts +2 -0
  30. package/dist/api/templates/wasi-worker-template.js +122 -0
  31. package/dist/api/templates/wasi-worker-template.js.map +1 -0
  32. package/dist/api/universalize.js +5 -5
  33. package/dist/api/universalize.js.map +1 -1
  34. package/dist/api/version.js +2 -2
  35. package/dist/api/version.js.map +1 -1
  36. package/dist/commands/artifacts.js +2 -2
  37. package/dist/commands/artifacts.js.map +1 -1
  38. package/dist/commands/build.js +1 -1
  39. package/dist/commands/build.js.map +1 -1
  40. package/dist/commands/new.js +30 -8
  41. package/dist/commands/new.js.map +1 -1
  42. package/dist/def/artifacts.d.ts +21 -1
  43. package/dist/def/artifacts.js +10 -2
  44. package/dist/def/artifacts.js.map +1 -1
  45. package/dist/def/build.d.ts +22 -4
  46. package/dist/def/build.js +16 -4
  47. package/dist/def/build.js.map +1 -1
  48. package/dist/def/create-npm-dirs.d.ts +10 -0
  49. package/dist/def/create-npm-dirs.js +4 -0
  50. package/dist/def/create-npm-dirs.js.map +1 -1
  51. package/dist/def/new.d.ts +25 -7
  52. package/dist/def/new.js +11 -1
  53. package/dist/def/new.js.map +1 -1
  54. package/dist/def/pre-publish.d.ts +12 -2
  55. package/dist/def/pre-publish.js +7 -3
  56. package/dist/def/pre-publish.js.map +1 -1
  57. package/dist/def/rename.d.ts +16 -6
  58. package/dist/def/rename.js +5 -1
  59. package/dist/def/rename.js.map +1 -1
  60. package/dist/def/universalize.d.ts +10 -0
  61. package/dist/def/universalize.js +4 -0
  62. package/dist/def/universalize.js.map +1 -1
  63. package/dist/def/version.d.ts +10 -0
  64. package/dist/def/version.js +4 -0
  65. package/dist/def/version.js.map +1 -1
  66. package/dist/index.cjs +8143 -14638
  67. package/dist/index.d.ts +1 -0
  68. package/dist/index.js +1 -0
  69. package/dist/index.js.map +1 -1
  70. package/dist/utils/__tests__/config.spec.d.ts +1 -0
  71. package/dist/utils/__tests__/config.spec.js +63 -0
  72. package/dist/utils/__tests__/config.spec.js.map +1 -0
  73. package/dist/utils/__tests__/typegen.spec.js +8 -4
  74. package/dist/utils/__tests__/typegen.spec.js.map +1 -1
  75. package/dist/utils/cargo.js +1 -1
  76. package/dist/utils/cargo.js.map +1 -1
  77. package/dist/utils/config.d.ts +49 -5
  78. package/dist/utils/config.js +38 -6
  79. package/dist/utils/config.js.map +1 -1
  80. package/dist/utils/index.d.ts +0 -1
  81. package/dist/utils/index.js +0 -1
  82. package/dist/utils/index.js.map +1 -1
  83. package/dist/utils/metadata.js +2 -2
  84. package/dist/utils/metadata.js.map +1 -1
  85. package/dist/utils/misc.d.ts +1 -2
  86. package/dist/utils/misc.js +3 -3
  87. package/dist/utils/misc.js.map +1 -1
  88. package/dist/utils/target.d.ts +7 -5
  89. package/dist/utils/target.js +17 -3
  90. package/dist/utils/target.js.map +1 -1
  91. package/dist/utils/typegen.d.ts +1 -1
  92. package/dist/utils/typegen.js +29 -9
  93. package/dist/utils/typegen.js.map +1 -1
  94. package/dist/utils/version.d.ts +2 -1
  95. package/dist/utils/version.js +10 -8
  96. package/dist/utils/version.js.map +1 -1
  97. package/package.json +25 -24
  98. package/src/api/artifacts.ts +81 -9
  99. package/src/api/build.ts +379 -58
  100. package/src/api/create-npm-dirs.ts +56 -8
  101. package/src/api/new.ts +89 -31
  102. package/src/api/pre-publish.ts +13 -7
  103. package/src/api/rename.ts +10 -1
  104. package/src/api/templates/ci-template.ts +134 -124
  105. package/src/api/templates/ci.yml.ts +27 -6
  106. package/src/api/templates/js-binding.ts +105 -214
  107. package/src/api/templates/lib.rs.ts +1 -4
  108. package/src/api/templates/load-wasi-template.ts +180 -0
  109. package/src/api/templates/package.json.ts +47 -5
  110. package/src/api/templates/wasi-worker-template.ts +122 -0
  111. package/src/api/universalize.ts +13 -8
  112. package/src/api/version.ts +5 -2
  113. package/src/commands/artifacts.ts +2 -2
  114. package/src/commands/build.ts +1 -1
  115. package/src/commands/new.ts +31 -8
  116. package/src/def/artifacts.ts +22 -3
  117. package/src/def/build.ts +36 -8
  118. package/src/def/create-npm-dirs.ts +9 -0
  119. package/src/def/new.ts +28 -3
  120. package/src/def/pre-publish.ts +12 -3
  121. package/src/def/rename.ts +11 -2
  122. package/src/def/universalize.ts +9 -0
  123. package/src/def/version.ts +9 -0
  124. package/src/index.ts +2 -0
  125. package/src/utils/__tests__/__fixtures__/napi_type_def +130 -130
  126. package/src/utils/__tests__/__snapshots__/config.spec.ts.md +97 -0
  127. package/src/utils/__tests__/__snapshots__/config.spec.ts.snap +0 -0
  128. package/src/utils/__tests__/__snapshots__/target.spec.ts.md +28 -0
  129. package/src/utils/__tests__/__snapshots__/target.spec.ts.snap +0 -0
  130. package/src/utils/__tests__/__snapshots__/typegen.spec.ts.md +713 -158
  131. package/src/utils/__tests__/__snapshots__/typegen.spec.ts.snap +0 -0
  132. package/src/utils/__tests__/__snapshots__/version.spec.ts.md +8 -7
  133. package/src/utils/__tests__/__snapshots__/version.spec.ts.snap +0 -0
  134. package/src/utils/__tests__/config.spec.ts +81 -0
  135. package/src/utils/__tests__/typegen.spec.ts +18 -3
  136. package/src/utils/cargo.ts +1 -1
  137. package/src/utils/config.ts +114 -12
  138. package/src/utils/index.ts +0 -1
  139. package/src/utils/metadata.ts +2 -2
  140. package/src/utils/misc.ts +11 -3
  141. package/src/utils/target.ts +22 -4
  142. package/src/utils/typegen.ts +37 -8
  143. package/src/utils/version.ts +10 -8
  144. package/dist/api/load-wasi-template.d.ts +0 -1
  145. package/dist/api/load-wasi-template.js +0 -63
  146. package/dist/api/load-wasi-template.js.map +0 -1
  147. package/dist/api/wasi-worker-template.d.ts +0 -1
  148. package/dist/api/wasi-worker-template.js +0 -53
  149. package/dist/api/wasi-worker-template.js.map +0 -1
  150. package/dist/utils/ci.d.ts +0 -11
  151. package/dist/utils/ci.js +0 -96
  152. package/dist/utils/ci.js.map +0 -1
  153. package/src/api/load-wasi-template.ts +0 -65
  154. package/src/api/wasi-worker-template.ts +0 -52
  155. 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 } 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
35
  import { createCjsBinding } from './templates/index.js'
35
- import { WASI_WORKER_TEMPLATE } from './wasi-worker-template.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,134 @@ 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 toolchainPath = join(
183
+ homedir(),
184
+ '.napi-rs',
185
+ 'cross-toolchain',
186
+ version,
187
+ this.target.triple,
188
+ )
189
+ mkdirSync(toolchainPath, { recursive: true })
190
+ if (existsSync(join(toolchainPath, 'package.json'))) {
191
+ debug(`Toolchain ${toolchainPath} exists, skip extracting`)
192
+ } else {
193
+ const tarArchive = download(process.arch, this.target.triple)
194
+ tarArchive.unpack(toolchainPath)
195
+ }
196
+ const upperCaseTarget = targetToEnvVar(this.target.triple)
197
+ const linkerEnv = `CARGO_TARGET_${upperCaseTarget}_LINKER`
198
+ this.envs[linkerEnv] = join(
199
+ toolchainPath,
200
+ 'bin',
201
+ `${this.target.triple}-gcc`,
202
+ )
203
+ if (!process.env.TARGET_SYSROOT) {
204
+ this.envs[`TARGET_SYSROOT`] = join(
205
+ toolchainPath,
206
+ this.target.triple,
207
+ 'sysroot',
208
+ )
209
+ }
210
+ if (!process.env.TARGET_AR) {
211
+ this.envs[`TARGET_AR`] = join(
212
+ toolchainPath,
213
+ 'bin',
214
+ `${this.target.triple}-ar`,
215
+ )
216
+ }
217
+ if (!process.env.TARGET_RANLIB) {
218
+ this.envs[`TARGET_RANLIB`] = join(
219
+ toolchainPath,
220
+ 'bin',
221
+ `${this.target.triple}-ranlib`,
222
+ )
223
+ }
224
+ if (!process.env.TARGET_READELF) {
225
+ this.envs[`TARGET_READELF`] = join(
226
+ toolchainPath,
227
+ 'bin',
228
+ `${this.target.triple}-readelf`,
229
+ )
230
+ }
231
+ if (!process.env.TARGET_C_INCLUDE_PATH) {
232
+ this.envs[`TARGET_C_INCLUDE_PATH`] = join(
233
+ toolchainPath,
234
+ this.target.triple,
235
+ 'sysroot',
236
+ 'usr',
237
+ 'include/',
238
+ )
239
+ }
240
+ if (!process.env.CC && !process.env.TARGET_CC) {
241
+ this.envs[`CC`] = join(
242
+ toolchainPath,
243
+ 'bin',
244
+ `${this.target.triple}-gcc`,
245
+ )
246
+ this.envs[`TARGET_CC`] = join(
247
+ toolchainPath,
248
+ 'bin',
249
+ `${this.target.triple}-gcc`,
250
+ )
251
+ }
252
+ if (!process.env.CXX && !process.env.TARGET_CXX) {
253
+ this.envs[`CXX`] = join(
254
+ toolchainPath,
255
+ 'bin',
256
+ `${this.target.triple}-g++`,
257
+ )
258
+ this.envs[`TARGET_CXX`] = join(
259
+ toolchainPath,
260
+ 'bin',
261
+ `${this.target.triple}-g++`,
262
+ )
263
+ }
264
+ if (
265
+ (process.env.CC === 'clang' &&
266
+ (process.env.TARGET_CC === 'clang' || !process.env.TARGET_CC)) ||
267
+ process.env.TARGET_CC === 'clang'
268
+ ) {
269
+ this.envs.CFLAGS = `--sysroot=${this.envs.TARGET_SYSROOT}`
270
+ }
271
+ if (
272
+ (process.env.CXX === 'clang++' &&
273
+ (process.env.TARGET_CXX === 'clang++' || !process.env.TARGET_CXX)) ||
274
+ process.env.TARGET_CXX === 'clang++'
275
+ ) {
276
+ this.envs.CXXFLAGS = `--sysroot=${this.envs.TARGET_SYSROOT}`
277
+ }
278
+ } catch (e) {
279
+ debug.warn('Pick cross toolchain failed', e as Error)
280
+ // ignore, do nothing
281
+ }
282
+ return this
283
+ }
284
+
151
285
  private exec() {
152
286
  debug(`Start building crate: ${this.crate.name}`)
153
287
  debug(' %i', `cargo ${this.args.join(' ')}`)
@@ -156,6 +290,11 @@ class Builder {
156
290
 
157
291
  const watch = this.options.watch
158
292
  const buildTask = new Promise<void>((resolve, reject) => {
293
+ if (this.options.useCross && this.options.crossCompile) {
294
+ throw new Error(
295
+ '`--use-cross` and `--cross-compile` can not be used together',
296
+ )
297
+ }
159
298
  const command =
160
299
  process.env.CARGO ?? (this.options.useCross ? 'cross' : 'cargo')
161
300
  const buildProcess = spawn(command, this.args, {
@@ -373,15 +512,15 @@ class Builder {
373
512
  process.platform === 'darwin'
374
513
  ? 'darwin'
375
514
  : process.platform === 'win32'
376
- ? 'windows'
377
- : 'linux'
515
+ ? 'windows'
516
+ : 'linux'
378
517
  Object.assign(this.envs, {
379
518
  CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-android24-clang`,
380
519
  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`,
520
+ TARGET_CC: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang`,
521
+ TARGET_CXX: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang++`,
522
+ TARGET_AR: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ar`,
523
+ TARGET_RANLIB: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ranlib`,
385
524
  ANDROID_NDK: ANDROID_NDK_LATEST_HOME,
386
525
  PATH: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin:${process.env.PATH}`,
387
526
  })
@@ -396,6 +535,47 @@ class Builder {
396
535
  'wasm32-wasi-threads',
397
536
  )
398
537
  this.envs.EMNAPI_LINK_DIR = emnapi
538
+ this.envs.SETJMP_LINK_DIR = setjmpLib
539
+ const { WASI_SDK_PATH } = process.env
540
+
541
+ if (WASI_SDK_PATH && existsSync(WASI_SDK_PATH)) {
542
+ this.envs.CARGO_TARGET_WASM32_WASI_PREVIEW1_THREADS_LINKER = join(
543
+ WASI_SDK_PATH,
544
+ 'bin',
545
+ 'wasm-ld',
546
+ )
547
+ this.envs.CARGO_TARGET_WASM32_WASIP1_LINKER = join(
548
+ WASI_SDK_PATH,
549
+ 'bin',
550
+ 'wasm-ld',
551
+ )
552
+ this.envs.CARGO_TARGET_WASM32_WASIP1_THREADS_LINKER = join(
553
+ WASI_SDK_PATH,
554
+ 'bin',
555
+ 'wasm-ld',
556
+ )
557
+ this.envs.CARGO_TARGET_WASM32_WASIP2_LINKER = join(
558
+ WASI_SDK_PATH,
559
+ 'bin',
560
+ 'wasm-ld',
561
+ )
562
+ this.setEnvIfNotExists('CC', join(WASI_SDK_PATH, 'bin', 'clang'))
563
+ this.setEnvIfNotExists('CXX', join(WASI_SDK_PATH, 'bin', 'clang++'))
564
+ this.setEnvIfNotExists('AR', join(WASI_SDK_PATH, 'bin', 'ar'))
565
+ this.setEnvIfNotExists('RANLIB', join(WASI_SDK_PATH, 'bin', 'ranlib'))
566
+ this.setEnvIfNotExists(
567
+ 'CFLAGS',
568
+ `--target=wasm32-wasi-threads --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -pthread -mllvm -wasm-enable-sjlj -I${setjmpInclude}`,
569
+ )
570
+ this.setEnvIfNotExists(
571
+ 'CXXFLAGS',
572
+ `--target=wasm32-wasi-threads --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -pthread -mllvm -wasm-enable-sjlj -I${setjmpInclude}`,
573
+ )
574
+ this.setEnvIfNotExists(
575
+ `LDFLAGS`,
576
+ `-fuse-ld=${WASI_SDK_PATH}/bin/wasm-ld --target=wasm32-wasi-threads`,
577
+ )
578
+ }
399
579
  }
400
580
 
401
581
  debug('Set envs: ')
@@ -408,11 +588,17 @@ class Builder {
408
588
 
409
589
  private setFeatures() {
410
590
  const args = []
591
+ if (this.options.allFeatures && this.options.allFeatures) {
592
+ throw new Error(
593
+ 'Cannot specify --all-features and --no-default-features together',
594
+ )
595
+ }
411
596
  if (this.options.allFeatures) {
412
597
  args.push('--all-features')
413
598
  } else if (this.options.noDefaultFeatures) {
414
599
  args.push('--no-default-features')
415
- } else if (this.options.features) {
600
+ }
601
+ if (this.options.features) {
416
602
  args.push('--features', ...this.options.features)
417
603
  }
418
604
 
@@ -440,6 +626,10 @@ class Builder {
440
626
  this.args.push('--profile', this.options.profile)
441
627
  }
442
628
 
629
+ if (this.options.manifestPath) {
630
+ this.args.push('--manifest-path', this.options.manifestPath)
631
+ }
632
+
443
633
  if (this.options.cargoOptions?.length) {
444
634
  this.args.push(...this.options.cargoOptions)
445
635
  }
@@ -481,38 +671,48 @@ class Builder {
481
671
  })
482
672
  }
483
673
 
484
- await this.copyArtifact()
674
+ const wasmBinaryName = await this.copyArtifact()
485
675
 
486
676
  // only for cdylib
487
677
  if (this.cdyLibName) {
488
678
  const idents = await this.generateTypeDef()
489
679
  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
- : []
680
+ const wasiRegisterFunctions = this.config.targets.some(
681
+ (t) => t.platform === 'wasi',
682
+ )
683
+ ? await (async function readIntermediateWasiRegisterFile() {
684
+ const fileContent = await readFileAsync(
685
+ intermediateWasiRegisterFile,
686
+ 'utf8',
687
+ ).catch((err) => {
688
+ console.warn(
689
+ `Read ${colors.yellowBright(
690
+ intermediateWasiRegisterFile,
691
+ )} failed, reason: ${err.message}`,
692
+ )
693
+ return ``
694
+ })
695
+ return fileContent
696
+ .split('\n')
697
+ .map((l) => l.trim())
698
+ .filter((l) => l.length)
699
+ .map((line) => {
700
+ const [_, fn] = line.split(':')
701
+ return fn.trim()
702
+ })
703
+ })()
704
+ : []
505
705
  const jsOutput = await this.writeJsBinding(idents)
506
- const wasmOutput = await this.writeWasiBinding(
706
+ const wasmBindingsOutput = await this.writeWasiBinding(
507
707
  wasiRegisterFunctions,
508
- jsOutput?.path ?? 'index',
708
+ wasmBinaryName ?? 'index.wasm',
509
709
  idents,
510
710
  )
511
711
  if (jsOutput) {
512
712
  this.outputs.push(jsOutput)
513
713
  }
514
- if (wasmOutput) {
515
- this.outputs.push(wasmOutput)
714
+ if (wasmBindingsOutput) {
715
+ this.outputs.push(...wasmBindingsOutput)
516
716
  }
517
717
  }
518
718
 
@@ -520,7 +720,7 @@ class Builder {
520
720
  }
521
721
 
522
722
  private async copyArtifact() {
523
- const [srcName, destName] = this.getArtifactNames()
723
+ const [srcName, destName, wasmBinaryName] = this.getArtifactNames()
524
724
  if (!srcName || !destName) {
525
725
  return
526
726
  }
@@ -530,6 +730,7 @@ class Builder {
530
730
  const src = join(this.targetDir, this.target.triple, profile, srcName)
531
731
  debug(`Copy artifact from: [${src}]`)
532
732
  const dest = join(this.outputDir, destName)
733
+ const isWasm = dest.endsWith('.wasm')
533
734
 
534
735
  try {
535
736
  if (await fileExists(dest)) {
@@ -538,11 +739,47 @@ class Builder {
538
739
  }
539
740
  debug('Copy artifact to:')
540
741
  debug(' %i', dest)
541
- await copyFileAsync(src, dest)
742
+ if (isWasm) {
743
+ const { ModuleConfig } = await import('@napi-rs/wasm-tools')
744
+ debug('Generate debug wasm module')
745
+ try {
746
+ const debugWasmModule = new ModuleConfig()
747
+ .generateDwarf(true)
748
+ .generateNameSection(true)
749
+ .generateProducersSection(true)
750
+ .preserveCodeTransform(true)
751
+ .strictValidate(false)
752
+ .parse(await readFileAsync(src))
753
+ const debugWasmBinary = debugWasmModule.emitWasm(true)
754
+ await writeFileAsync(
755
+ dest.replace('.wasm', '.debug.wasm'),
756
+ debugWasmBinary,
757
+ )
758
+ debug('Generate release wasm module')
759
+ const releaseWasmModule = new ModuleConfig()
760
+ .generateDwarf(false)
761
+ .generateNameSection(false)
762
+ .generateProducersSection(false)
763
+ .preserveCodeTransform(false)
764
+ .strictValidate(false)
765
+ .onlyStableFeatures(false)
766
+ .parse(debugWasmBinary)
767
+ const releaseWasmBinary = releaseWasmModule.emitWasm(false)
768
+ await writeFileAsync(dest, releaseWasmBinary)
769
+ } catch (e) {
770
+ debug.warn(
771
+ `Failed to generate debug wasm module: ${(e as any).message ?? e}`,
772
+ )
773
+ await copyFileAsync(src, dest)
774
+ }
775
+ } else {
776
+ await copyFileAsync(src, dest)
777
+ }
542
778
  this.outputs.push({
543
- kind: dest.endsWith('.node') ? 'node' : 'exe',
779
+ kind: dest.endsWith('.node') ? 'node' : isWasm ? 'wasm' : 'exe',
544
780
  path: dest,
545
781
  })
782
+ return wasmBinaryName ? join(this.outputDir, wasmBinaryName) : null
546
783
  } catch (e) {
547
784
  throw new Error('Failed to copy artifact', {
548
785
  cause: e,
@@ -553,15 +790,16 @@ class Builder {
553
790
  private getArtifactNames() {
554
791
  if (this.cdyLibName) {
555
792
  const cdyLib = this.cdyLibName.replace(/-/g, '_')
793
+ const wasiTarget = this.config.targets.find((t) => t.platform === 'wasi')
556
794
 
557
795
  const srcName =
558
796
  this.target.platform === 'darwin'
559
797
  ? `lib${cdyLib}.dylib`
560
798
  : this.target.platform === 'win32'
561
- ? `${cdyLib}.dll`
562
- : this.target.platform === 'wasi' || this.target.platform === 'wasm'
563
- ? `${cdyLib}.wasm`
564
- : `lib${cdyLib}.so`
799
+ ? `${cdyLib}.dll`
800
+ : this.target.platform === 'wasi' || this.target.platform === 'wasm'
801
+ ? `${cdyLib}.wasm`
802
+ : `lib${cdyLib}.so`
565
803
 
566
804
  let destName = this.config.binaryName
567
805
  // add platform suffix to binary name
@@ -571,12 +809,18 @@ class Builder {
571
809
  destName += `.${this.target.platformArchABI}`
572
810
  }
573
811
  if (srcName.endsWith('.wasm')) {
574
- destName += '.wasi-wasm32.wasm'
812
+ destName += '.wasm'
575
813
  } else {
576
814
  destName += '.node'
577
815
  }
578
816
 
579
- return [srcName, destName]
817
+ return [
818
+ srcName,
819
+ destName,
820
+ wasiTarget
821
+ ? `${this.config.binaryName}.${wasiTarget.platformArchABI}.wasm`
822
+ : null,
823
+ ]
580
824
  } else if (this.binName) {
581
825
  const srcName =
582
826
  this.target.platform === 'win32' ? `${this.binName}.exe` : this.binName
@@ -596,8 +840,22 @@ class Builder {
596
840
 
597
841
  const { dts, exports } = await processTypeDef(
598
842
  this.envs.TYPE_DEF_TMP_PATH,
843
+ this.options.constEnum ?? true,
599
844
  !this.options.noDtsHeader
600
- ? this.options.dtsHeader ?? DEFAULT_TYPE_DEF_HEADER
845
+ ? this.options.dtsHeader ??
846
+ (this.config.dtsHeaderFile
847
+ ? await readFileAsync(
848
+ join(this.cwd, this.config.dtsHeaderFile),
849
+ 'utf-8',
850
+ ).catch(() => {
851
+ debug.warn(
852
+ `Failed to read dts header file ${this.config.dtsHeaderFile}`,
853
+ )
854
+ return null
855
+ })
856
+ : null) ??
857
+ this.config.dtsHeader ??
858
+ DEFAULT_TYPE_DEF_HEADER
601
859
  : '',
602
860
  )
603
861
 
@@ -627,7 +885,7 @@ class Builder {
627
885
  return
628
886
  }
629
887
 
630
- const name = parse(this.options.jsBinding ?? 'index.js').name
888
+ const name = this.options.jsBinding ?? 'index.js'
631
889
 
632
890
  const cjs = createCjsBinding(
633
891
  this.config.binaryName,
@@ -636,7 +894,7 @@ class Builder {
636
894
  )
637
895
 
638
896
  try {
639
- const dest = join(this.outputDir, `${name}.js`)
897
+ const dest = join(this.outputDir, name)
640
898
  debug('Writing js binding to:')
641
899
  debug(' %i', dest)
642
900
  await writeFileAsync(dest, cjs, 'utf-8')
@@ -656,26 +914,89 @@ class Builder {
656
914
  ) {
657
915
  if (distFileName && wasiRegisterFunctions.length) {
658
916
  const { name, dir } = parse(distFileName)
659
- const newPath = join(dir, `${name}.wasi.mjs`)
917
+ const bindingPath = join(dir, `${this.config.binaryName}.wasi.cjs`)
918
+ const browserBindingPath = join(
919
+ dir,
920
+ `${this.config.binaryName}.wasi-browser.js`,
921
+ )
660
922
  const workerPath = join(dir, 'wasi-worker.mjs')
661
- const declareCodes = `const { ${idents.join(', ')} } = binding\n`
662
- const exportsCode = `export {\n${idents
663
- .map((ident) => ` ${ident}`)
664
- .join(',\n')}\n}`
923
+ const browserWorkerPath = join(dir, 'wasi-worker-browser.mjs')
924
+ const browserEntryPath = join(dir, 'browser.js')
925
+ const exportsCode = idents
926
+ .map(
927
+ (ident) => `module.exports.${ident} = __napiModule.exports.${ident}`,
928
+ )
929
+ .join('\n')
665
930
  await writeFileAsync(
666
- newPath,
667
- createWasiBinding(this.config.binaryName, wasiRegisterFunctions) +
668
- declareCodes +
931
+ bindingPath,
932
+ createWasiBinding(
933
+ name,
934
+ this.config.packageName,
935
+ wasiRegisterFunctions,
936
+ this.config.wasm?.initialMemory,
937
+ this.config.wasm?.maximumMemory,
938
+ ) +
669
939
  exportsCode +
670
940
  '\n',
671
941
  'utf8',
672
942
  )
943
+ await writeFileAsync(
944
+ browserBindingPath,
945
+ createWasiBrowserBinding(
946
+ name,
947
+ wasiRegisterFunctions,
948
+ this.config.wasm?.initialMemory,
949
+ this.config.wasm?.maximumMemory,
950
+ this.config.wasm?.browser?.fs,
951
+ ) +
952
+ idents
953
+ .map(
954
+ (ident) =>
955
+ `export const ${ident} = __napiModule.exports.${ident}`,
956
+ )
957
+ .join('\n') +
958
+ '\n',
959
+ 'utf8',
960
+ )
673
961
  await writeFileAsync(workerPath, WASI_WORKER_TEMPLATE, 'utf8')
674
- return {
675
- kind: 'wasm',
676
- path: newPath,
677
- } satisfies Output
962
+ await writeFileAsync(
963
+ browserWorkerPath,
964
+ createWasiBrowserWorkerBinding(this.config.wasm?.browser?.fs ?? false),
965
+ 'utf8',
966
+ )
967
+ await writeFileAsync(
968
+ browserEntryPath,
969
+ `export * from '${this.config.packageName}-wasm32-wasi'\n`,
970
+ )
971
+ return [
972
+ {
973
+ kind: 'js',
974
+ path: bindingPath,
975
+ },
976
+ {
977
+ kind: 'js',
978
+ path: browserBindingPath,
979
+ },
980
+ {
981
+ kind: 'js',
982
+ path: workerPath,
983
+ },
984
+ {
985
+ kind: 'js',
986
+ path: browserWorkerPath,
987
+ },
988
+ {
989
+ kind: 'js',
990
+ path: browserEntryPath,
991
+ },
992
+ ] satisfies Output[]
993
+ }
994
+ return []
995
+ }
996
+
997
+ private setEnvIfNotExists(env: string, value: string) {
998
+ if (!process.env[env]) {
999
+ this.envs[env] = value
678
1000
  }
679
- return null
680
1001
  }
681
1002
  }