@napi-rs/cli 3.0.0-alpha.94 → 3.0.0-alpha.96

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.
@@ -95,6 +95,10 @@ export interface CommonPackageJsonFields {
95
95
  author?: string;
96
96
  authors?: string[];
97
97
  license?: string;
98
+ cpu?: string[];
99
+ os?: string[];
100
+ libc?: string[];
101
+ files?: string[];
98
102
  repository?: any;
99
103
  homepage?: any;
100
104
  engines?: Record<string, string>;
@@ -1,4 +1,4 @@
1
- export type Platform = NodeJS.Platform | 'wasm' | 'wasi';
1
+ export type Platform = NodeJS.Platform | 'wasm' | 'wasi' | 'ohos';
2
2
  export declare const UNIVERSAL_TARGETS: {
3
3
  readonly 'universal-apple-darwin': readonly ["aarch64-apple-darwin", "x86_64-apple-darwin"];
4
4
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@napi-rs/cli",
3
- "version": "3.0.0-alpha.94",
3
+ "version": "3.0.0-alpha.96",
4
4
  "description": "Cli tools for napi-rs",
5
5
  "author": "LongYinan <lynweklm@gmail.com>",
6
6
  "homepage": "https://github.com/napi-rs/napi-rs",
@@ -132,5 +132,5 @@
132
132
  "e2e/**/*.spec.ts"
133
133
  ]
134
134
  },
135
- "gitHead": "08c364f5a76fa5f3b887b3050ffd175d33206a30"
135
+ "gitHead": "f2e838cf992f437a861cdd3108e32b3ab523e464"
136
136
  }
@@ -0,0 +1,210 @@
1
+ import { existsSync } from 'node:fs'
2
+ import { mkdir, readFile, rm, writeFile } from 'node:fs/promises'
3
+ import { tmpdir } from 'node:os'
4
+ import { join } from 'node:path'
5
+
6
+ import ava, { TestFn } from 'ava'
7
+
8
+ import { createNpmDirs } from '../create-npm-dirs.js'
9
+
10
+ const test = ava as TestFn<{
11
+ tmpDir: string
12
+ packageJsonPath: string
13
+ }>
14
+
15
+ test.beforeEach(async (t) => {
16
+ // Create a unique temp directory for tests
17
+ const timestamp = Date.now()
18
+ const random = Math.random().toString(36).substring(7)
19
+ const tmpDir = join(
20
+ tmpdir(),
21
+ 'napi-rs-test',
22
+ `create-npm-dirs-${timestamp}-${random}`,
23
+ )
24
+ const packageJsonPath = join(tmpDir, 'package.json')
25
+
26
+ // Create the directory
27
+ await mkdir(tmpDir, { recursive: true })
28
+
29
+ t.context = { tmpDir, packageJsonPath }
30
+ })
31
+
32
+ test.afterEach.always(async (t) => {
33
+ // Clean up any created directories
34
+ if (existsSync(t.context.tmpDir)) {
35
+ await rm(t.context.tmpDir, { recursive: true, force: true })
36
+ }
37
+ })
38
+
39
+ test('should omit exports fields from publishConfig in scoped packages', async (t) => {
40
+ const { tmpDir, packageJsonPath } = t.context
41
+
42
+ // Create a package.json with publishConfig that includes exports field
43
+ const packageJson = {
44
+ name: 'test-package',
45
+ version: '1.0.0',
46
+ publishConfig: {
47
+ registry: 'https://custom-registry.com',
48
+ access: 'public',
49
+ exports: {
50
+ '.': './dist/index.js',
51
+ './package.json': './package.json',
52
+ },
53
+ tag: 'beta',
54
+ },
55
+ napi: {
56
+ binaryName: 'test-package',
57
+ targets: ['x86_64-unknown-linux-gnu'],
58
+ },
59
+ }
60
+
61
+ await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2))
62
+
63
+ await createNpmDirs({
64
+ cwd: tmpDir,
65
+ packageJsonPath: 'package.json',
66
+ })
67
+
68
+ // Check that the scoped package directory was created
69
+ const scopedDir = join(tmpDir, 'npm', 'linux-x64-gnu')
70
+ t.true(existsSync(scopedDir))
71
+
72
+ // Read the generated package.json for the scoped package
73
+ const scopedPackageJsonPath = join(scopedDir, 'package.json')
74
+ t.true(existsSync(scopedPackageJsonPath))
75
+
76
+ const scopedPackageJson = JSON.parse(
77
+ await readFile(scopedPackageJsonPath, 'utf-8'),
78
+ )
79
+
80
+ // Verify that publishConfig only contains registry and access, not exports
81
+ t.truthy(scopedPackageJson.publishConfig)
82
+ t.is(scopedPackageJson.publishConfig.registry, 'https://custom-registry.com')
83
+ t.is(scopedPackageJson.publishConfig.access, 'public')
84
+ t.is(scopedPackageJson.publishConfig.exports, undefined)
85
+ t.is(scopedPackageJson.publishConfig.tag, undefined)
86
+ })
87
+
88
+ test('should handle package without publishConfig', async (t) => {
89
+ const { tmpDir, packageJsonPath } = t.context
90
+
91
+ // Create a package.json without publishConfig
92
+ const packageJson = {
93
+ name: 'test-package-no-config',
94
+ version: '1.0.0',
95
+ napi: {
96
+ binaryName: 'test-package-no-config',
97
+ targets: ['x86_64-unknown-linux-gnu'],
98
+ },
99
+ }
100
+
101
+ await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2))
102
+
103
+ await createNpmDirs({
104
+ cwd: tmpDir,
105
+ packageJsonPath: 'package.json',
106
+ })
107
+
108
+ // Check that the scoped package directory was created
109
+ const scopedDir = join(tmpDir, 'npm', 'linux-x64-gnu')
110
+ t.true(existsSync(scopedDir))
111
+
112
+ // Read the generated package.json for the scoped package
113
+ const scopedPackageJsonPath = join(scopedDir, 'package.json')
114
+ const scopedPackageJson = JSON.parse(
115
+ await readFile(scopedPackageJsonPath, 'utf-8'),
116
+ )
117
+
118
+ // Verify that publishConfig is not present when not in source
119
+ t.is(scopedPackageJson.publishConfig, undefined)
120
+ })
121
+
122
+ test('should preserve only registry and access in publishConfig', async (t) => {
123
+ const { tmpDir, packageJsonPath } = t.context
124
+
125
+ // Create a package.json with minimal publishConfig
126
+ const packageJson = {
127
+ name: 'test-package-minimal',
128
+ version: '1.0.0',
129
+ publishConfig: {
130
+ registry: 'https://npm.company.com',
131
+ access: 'restricted',
132
+ },
133
+ napi: {
134
+ binaryName: 'test-package-minimal',
135
+ targets: ['aarch64-apple-darwin'],
136
+ },
137
+ }
138
+
139
+ await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2))
140
+
141
+ await createNpmDirs({
142
+ cwd: tmpDir,
143
+ packageJsonPath: 'package.json',
144
+ })
145
+
146
+ // Check that the scoped package directory was created
147
+ const scopedDir = join(tmpDir, 'npm', 'darwin-arm64')
148
+ t.true(existsSync(scopedDir))
149
+
150
+ // Read the generated package.json for the scoped package
151
+ const scopedPackageJsonPath = join(scopedDir, 'package.json')
152
+ const scopedPackageJson = JSON.parse(
153
+ await readFile(scopedPackageJsonPath, 'utf-8'),
154
+ )
155
+
156
+ // Verify that publishConfig contains exactly registry and access
157
+ t.truthy(scopedPackageJson.publishConfig)
158
+ t.is(scopedPackageJson.publishConfig.registry, 'https://npm.company.com')
159
+ t.is(scopedPackageJson.publishConfig.access, 'restricted')
160
+ t.is(Object.keys(scopedPackageJson.publishConfig).length, 2)
161
+ })
162
+
163
+ test('should handle WASM targets correctly with publishConfig', async (t) => {
164
+ const { tmpDir, packageJsonPath } = t.context
165
+
166
+ // Create a package.json for WASM target
167
+ const packageJson = {
168
+ name: 'test-wasm-package',
169
+ version: '1.0.0',
170
+ publishConfig: {
171
+ registry: 'https://wasm-registry.com',
172
+ access: 'public',
173
+ exports: './wasm.js',
174
+ browser: './browser.js',
175
+ },
176
+ napi: {
177
+ binaryName: 'test-wasm-package',
178
+ targets: ['wasm32-wasi-preview1-threads'],
179
+ },
180
+ }
181
+
182
+ await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2))
183
+
184
+ await createNpmDirs({
185
+ cwd: tmpDir,
186
+ packageJsonPath: 'package.json',
187
+ })
188
+
189
+ // Check that the scoped package directory was created
190
+ const scopedDir = join(tmpDir, 'npm', 'wasm32-wasi')
191
+ t.true(existsSync(scopedDir))
192
+
193
+ // Read the generated package.json for the scoped package
194
+ const scopedPackageJsonPath = join(scopedDir, 'package.json')
195
+ const scopedPackageJson = JSON.parse(
196
+ await readFile(scopedPackageJsonPath, 'utf-8'),
197
+ )
198
+
199
+ // Verify that publishConfig is correctly filtered for WASM too
200
+ t.truthy(scopedPackageJson.publishConfig)
201
+ t.is(scopedPackageJson.publishConfig.registry, 'https://wasm-registry.com')
202
+ t.is(scopedPackageJson.publishConfig.access, 'public')
203
+ t.is(scopedPackageJson.publishConfig.exports, undefined)
204
+ t.is(scopedPackageJson.publishConfig.browser, undefined)
205
+
206
+ // Verify WASM-specific fields are set correctly
207
+ t.truthy(scopedPackageJson.main)
208
+ t.truthy(scopedPackageJson.browser)
209
+ t.truthy(scopedPackageJson.dependencies)
210
+ })
package/src/api/build.ts CHANGED
@@ -514,86 +514,15 @@ class Builder {
514
514
  }
515
515
 
516
516
  if (this.target.platform === 'android') {
517
- const { ANDROID_NDK_LATEST_HOME } = process.env
518
- if (!ANDROID_NDK_LATEST_HOME) {
519
- debug.warn(
520
- `${colors.red(
521
- 'ANDROID_NDK_LATEST_HOME',
522
- )} environment variable is missing`,
523
- )
524
- }
525
-
526
- const targetArch = this.target.arch === 'arm' ? 'armv7a' : 'aarch64'
527
- const targetPlatform =
528
- this.target.arch === 'arm' ? 'androideabi24' : 'android24'
529
- const hostPlatform =
530
- process.platform === 'darwin'
531
- ? 'darwin'
532
- : process.platform === 'win32'
533
- ? 'windows'
534
- : 'linux'
535
- Object.assign(this.envs, {
536
- CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-android24-clang`,
537
- CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-androideabi24-clang`,
538
- TARGET_CC: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang`,
539
- TARGET_CXX: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang++`,
540
- TARGET_AR: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ar`,
541
- TARGET_RANLIB: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ranlib`,
542
- ANDROID_NDK: ANDROID_NDK_LATEST_HOME,
543
- PATH: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin:${process.env.PATH}`,
544
- })
517
+ this.setAndroidEnv()
545
518
  }
546
- // END LINKER
547
519
 
548
520
  if (this.target.platform === 'wasi') {
549
- const emnapi = join(
550
- require.resolve('emnapi'),
551
- '..',
552
- 'lib',
553
- 'wasm32-wasi-threads',
554
- )
555
- this.envs.EMNAPI_LINK_DIR = emnapi
556
- this.envs.SETJMP_LINK_DIR = setjmpLib
557
- const { WASI_SDK_PATH } = process.env
521
+ this.setWasiEnv()
522
+ }
558
523
 
559
- if (WASI_SDK_PATH && existsSync(WASI_SDK_PATH)) {
560
- this.envs.CARGO_TARGET_WASM32_WASI_PREVIEW1_THREADS_LINKER = join(
561
- WASI_SDK_PATH,
562
- 'bin',
563
- 'wasm-ld',
564
- )
565
- this.envs.CARGO_TARGET_WASM32_WASIP1_LINKER = join(
566
- WASI_SDK_PATH,
567
- 'bin',
568
- 'wasm-ld',
569
- )
570
- this.envs.CARGO_TARGET_WASM32_WASIP1_THREADS_LINKER = join(
571
- WASI_SDK_PATH,
572
- 'bin',
573
- 'wasm-ld',
574
- )
575
- this.envs.CARGO_TARGET_WASM32_WASIP2_LINKER = join(
576
- WASI_SDK_PATH,
577
- 'bin',
578
- 'wasm-ld',
579
- )
580
- this.setEnvIfNotExists('CC', join(WASI_SDK_PATH, 'bin', 'clang'))
581
- this.setEnvIfNotExists('CXX', join(WASI_SDK_PATH, 'bin', 'clang++'))
582
- this.setEnvIfNotExists('AR', join(WASI_SDK_PATH, 'bin', 'ar'))
583
- this.setEnvIfNotExists('RANLIB', join(WASI_SDK_PATH, 'bin', 'ranlib'))
584
- this.setEnvIfNotExists(
585
- 'CFLAGS',
586
- `--target=wasm32-wasi-threads --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -pthread -mllvm -wasm-enable-sjlj -I${setjmpInclude}`,
587
- )
588
- this.setEnvIfNotExists(
589
- 'CXXFLAGS',
590
- `--target=wasm32-wasi-threads --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -pthread -mllvm -wasm-enable-sjlj -I${setjmpInclude}`,
591
- )
592
- this.setEnvIfNotExists(
593
- `LDFLAGS`,
594
- `-fuse-ld=${WASI_SDK_PATH}/bin/wasm-ld --target=wasm32-wasi-threads`,
595
- )
596
- }
524
+ if (this.target.abi === 'ohos') {
525
+ this.setOpenHarmonyEnv()
597
526
  }
598
527
 
599
528
  debug('Set envs: ')
@@ -618,6 +547,141 @@ class Builder {
618
547
  })
619
548
  }
620
549
 
550
+ private setAndroidEnv() {
551
+ const { ANDROID_NDK_LATEST_HOME } = process.env
552
+ if (!ANDROID_NDK_LATEST_HOME) {
553
+ debug.warn(
554
+ `${colors.red(
555
+ 'ANDROID_NDK_LATEST_HOME',
556
+ )} environment variable is missing`,
557
+ )
558
+ }
559
+
560
+ // skip cross compile setup if host is android
561
+ if (process.platform === 'android') {
562
+ return
563
+ }
564
+
565
+ const targetArch = this.target.arch === 'arm' ? 'armv7a' : 'aarch64'
566
+ const targetPlatform =
567
+ this.target.arch === 'arm' ? 'androideabi24' : 'android24'
568
+ const hostPlatform =
569
+ process.platform === 'darwin'
570
+ ? 'darwin'
571
+ : process.platform === 'win32'
572
+ ? 'windows'
573
+ : 'linux'
574
+ Object.assign(this.envs, {
575
+ CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-android24-clang`,
576
+ CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-androideabi24-clang`,
577
+ TARGET_CC: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang`,
578
+ TARGET_CXX: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/${targetArch}-linux-${targetPlatform}-clang++`,
579
+ TARGET_AR: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ar`,
580
+ TARGET_RANLIB: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin/llvm-ranlib`,
581
+ ANDROID_NDK: ANDROID_NDK_LATEST_HOME,
582
+ PATH: `${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${hostPlatform}-x86_64/bin${process.platform === 'win32' ? ';' : ':'}${process.env.PATH}`,
583
+ })
584
+ }
585
+
586
+ private setWasiEnv() {
587
+ const emnapi = join(
588
+ require.resolve('emnapi'),
589
+ '..',
590
+ 'lib',
591
+ 'wasm32-wasi-threads',
592
+ )
593
+ this.envs.EMNAPI_LINK_DIR = emnapi
594
+ this.envs.SETJMP_LINK_DIR = setjmpLib
595
+ const { WASI_SDK_PATH } = process.env
596
+
597
+ if (WASI_SDK_PATH && existsSync(WASI_SDK_PATH)) {
598
+ this.envs.CARGO_TARGET_WASM32_WASI_PREVIEW1_THREADS_LINKER = join(
599
+ WASI_SDK_PATH,
600
+ 'bin',
601
+ 'wasm-ld',
602
+ )
603
+ this.envs.CARGO_TARGET_WASM32_WASIP1_LINKER = join(
604
+ WASI_SDK_PATH,
605
+ 'bin',
606
+ 'wasm-ld',
607
+ )
608
+ this.envs.CARGO_TARGET_WASM32_WASIP1_THREADS_LINKER = join(
609
+ WASI_SDK_PATH,
610
+ 'bin',
611
+ 'wasm-ld',
612
+ )
613
+ this.envs.CARGO_TARGET_WASM32_WASIP2_LINKER = join(
614
+ WASI_SDK_PATH,
615
+ 'bin',
616
+ 'wasm-ld',
617
+ )
618
+ this.setEnvIfNotExists('TARGET_CC', join(WASI_SDK_PATH, 'bin', 'clang'))
619
+ this.setEnvIfNotExists(
620
+ 'TARGET_CXX',
621
+ join(WASI_SDK_PATH, 'bin', 'clang++'),
622
+ )
623
+ this.setEnvIfNotExists('TARGET_AR', join(WASI_SDK_PATH, 'bin', 'ar'))
624
+ this.setEnvIfNotExists(
625
+ 'TARGET_RANLIB',
626
+ join(WASI_SDK_PATH, 'bin', 'ranlib'),
627
+ )
628
+ this.setEnvIfNotExists(
629
+ 'TARGET_CFLAGS',
630
+ `--target=wasm32-wasi-threads --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -pthread -mllvm -wasm-enable-sjlj -I${setjmpInclude}`,
631
+ )
632
+ this.setEnvIfNotExists(
633
+ 'TARGET_CXXFLAGS',
634
+ `--target=wasm32-wasi-threads --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -pthread -mllvm -wasm-enable-sjlj -I${setjmpInclude}`,
635
+ )
636
+ this.setEnvIfNotExists(
637
+ `TARGET_LDFLAGS`,
638
+ `-fuse-ld=${WASI_SDK_PATH}/bin/wasm-ld --target=wasm32-wasi-threads`,
639
+ )
640
+ }
641
+ }
642
+
643
+ private setOpenHarmonyEnv() {
644
+ const { OHOS_SDK_PATH, OHOS_SDK_NATIVE } = process.env
645
+ const ndkPath = OHOS_SDK_PATH
646
+ ? `${OHOS_SDK_NATIVE}/native`
647
+ : OHOS_SDK_NATIVE
648
+ // @ts-expect-error
649
+ if (!ndkPath && process.platform !== 'openharmony') {
650
+ debug.warn(
651
+ `${colors.red('OHOS_SDK_PATH')} or ${colors.red('OHOS_SDK_NATIVE')} environment variable is missing`,
652
+ )
653
+ return
654
+ }
655
+ const linkerName = `CARGO_TARGET_${this.target.triple.toUpperCase().replace(/-/g, '_')}_LINKER`
656
+ const ranPath = `${ndkPath}/llvm/bin/llvm-ranlib`
657
+ const arPath = `${ndkPath}/llvm/bin/llvm-ar`
658
+ const ccPath = `${ndkPath}/llvm/bin/${this.target.triple}-clang`
659
+ const cxxPath = `${ndkPath}/llvm/bin/${this.target.triple}-clang++`
660
+ const asPath = `${ndkPath}/llvm/bin/llvm-as`
661
+ const ldPath = `${ndkPath}/llvm/bin/ld.lld`
662
+ const stripPath = `${ndkPath}/llvm/bin/llvm-strip`
663
+ const objDumpPath = `${ndkPath}/llvm/bin/llvm-objdump`
664
+ const objCopyPath = `${ndkPath}/llvm/bin/llvm-objcopy`
665
+ const nmPath = `${ndkPath}/llvm/bin/llvm-nm`
666
+ const binPath = `${ndkPath}/llvm/bin`
667
+ const libPath = `${ndkPath}/llvm/lib`
668
+
669
+ this.setEnvIfNotExists('LIBCLANG_PATH', libPath)
670
+ this.setEnvIfNotExists('DEP_ATOMIC', 'clang_rt.builtins')
671
+ this.setEnvIfNotExists(linkerName, ccPath)
672
+ this.setEnvIfNotExists('TARGET_CC', ccPath)
673
+ this.setEnvIfNotExists('TARGET_CXX', cxxPath)
674
+ this.setEnvIfNotExists('TARGET_AR', arPath)
675
+ this.setEnvIfNotExists('TARGET_RANLIB', ranPath)
676
+ this.setEnvIfNotExists('TARGET_AS', asPath)
677
+ this.setEnvIfNotExists('TARGET_LD', ldPath)
678
+ this.setEnvIfNotExists('TARGET_STRIP', stripPath)
679
+ this.setEnvIfNotExists('TARGET_OBJDUMP', objDumpPath)
680
+ this.setEnvIfNotExists('TARGET_OBJCOPY', objCopyPath)
681
+ this.setEnvIfNotExists('TARGET_NM', nmPath)
682
+ this.envs.PATH = `${binPath}${process.platform === 'win32' ? ';' : ':'}${process.env.PATH}`
683
+ }
684
+
621
685
  private setFeatures() {
622
686
  const args = []
623
687
  if (this.options.allFeatures && this.options.noDefaultFeatures) {
@@ -13,6 +13,7 @@ import {
13
13
  pick,
14
14
  writeFileAsync as rawWriteFileAsync,
15
15
  Target,
16
+ type CommonPackageJsonFields,
16
17
  } from '../utils/index.js'
17
18
 
18
19
  const debug = debugFactory('create-npm-dirs')
@@ -65,7 +66,7 @@ export async function createNpmDirs(userOptions: CreateNpmDirsOptions) {
65
66
  target.arch === 'wasm32'
66
67
  ? `${binaryName}.${target.platformArchABI}.wasm`
67
68
  : `${binaryName}.${target.platformArchABI}.node`
68
- const scopedPackageJson = {
69
+ const scopedPackageJson: CommonPackageJsonFields = {
69
70
  name: `${packageName}-${target.platformArchABI}`,
70
71
  version: packageJson.version,
71
72
  cpu: target.arch !== 'universal' ? [target.arch] : undefined,
@@ -80,22 +81,25 @@ export async function createNpmDirs(userOptions: CreateNpmDirsOptions) {
80
81
  'homepage',
81
82
  'license',
82
83
  'engines',
83
- 'publishConfig',
84
84
  'repository',
85
85
  'bugs',
86
86
  ),
87
87
  }
88
+ if (packageJson.publishConfig) {
89
+ scopedPackageJson.publishConfig = pick(
90
+ packageJson.publishConfig,
91
+ 'registry',
92
+ 'access',
93
+ )
94
+ }
88
95
  if (target.arch !== 'wasm32') {
89
- // @ts-expect-error
90
96
  scopedPackageJson.os = [target.platform]
91
97
  } else {
92
98
  const entry = `${binaryName}.wasi.cjs`
93
99
  scopedPackageJson.main = entry
94
- // @ts-expect-error
95
100
  scopedPackageJson.browser = `${binaryName}.wasi-browser.js`
96
- scopedPackageJson.files.push(
101
+ scopedPackageJson.files?.push(
97
102
  entry,
98
- // @ts-expect-error
99
103
  scopedPackageJson.browser,
100
104
  `wasi-worker.mjs`,
101
105
  `wasi-worker-browser.mjs`,
@@ -121,17 +125,14 @@ export async function createNpmDirs(userOptions: CreateNpmDirsOptions) {
121
125
  const wasmRuntime = await fetch(
122
126
  `https://registry.npmjs.org/@napi-rs/wasm-runtime`,
123
127
  ).then((res) => res.json() as Promise<PackageMeta>)
124
- // @ts-expect-error
125
128
  scopedPackageJson.dependencies = {
126
129
  '@napi-rs/wasm-runtime': `^${wasmRuntime['dist-tags'].latest}`,
127
130
  }
128
131
  }
129
132
 
130
133
  if (target.abi === 'gnu') {
131
- // @ts-expect-error
132
134
  scopedPackageJson.libc = ['glibc']
133
135
  } else if (target.abi === 'musl') {
134
- // @ts-expect-error
135
136
  scopedPackageJson.libc = ['musl']
136
137
  }
137
138
 
@@ -38,17 +38,19 @@ const bindingHeader = `// prettier-ignore
38
38
  `
39
39
 
40
40
  function createCommonBinding(localName: string, pkgName: string): string {
41
- function requireTuple(tuple: string) {
41
+ function requireTuple(tuple: string, identSize = 8) {
42
+ const identLow = ' '.repeat(identSize - 2)
43
+ const ident = ' '.repeat(identSize)
42
44
  return `try {
43
- return require('./${localName}.${tuple}.node')
44
- } catch (e) {
45
- loadErrors.push(e)
46
- }
47
- try {
48
- return require('${pkgName}-${tuple}')
49
- } catch (e) {
50
- loadErrors.push(e)
51
- }
45
+ ${ident}return require('./${localName}.${tuple}.node')
46
+ ${identLow}} catch (e) {
47
+ ${ident}loadErrors.push(e)
48
+ ${identLow}}
49
+ ${identLow}try {
50
+ ${ident}return require('${pkgName}-${tuple}')
51
+ ${identLow}} catch (e) {
52
+ ${ident}loadErrors.push(e)
53
+ ${identLow}}
52
54
  `
53
55
  }
54
56
 
@@ -70,6 +72,8 @@ const isMusl = () => {
70
72
  return musl
71
73
  }
72
74
 
75
+ const isOpenHarmony = process.platform === 'openharmony'
76
+
73
77
  const isFileMusl = (f) => f.includes('libc.musl-') || f.includes('ld-musl-')
74
78
 
75
79
  const isMuslFromFilesystem = () => {
@@ -135,7 +139,7 @@ function requireNative() {
135
139
  loadErrors.push(new Error(\`Unsupported architecture on Windows: \${process.arch}\`))
136
140
  }
137
141
  } else if (process.platform === 'darwin') {
138
- ${requireTuple('darwin-universal')}
142
+ ${requireTuple('darwin-universal', 6)}
139
143
  if (process.arch === 'x64') {
140
144
  ${requireTuple('darwin-x64')}
141
145
  } else if (process.arch === 'arm64') {
@@ -154,27 +158,33 @@ function requireNative() {
154
158
  } else if (process.platform === 'linux') {
155
159
  if (process.arch === 'x64') {
156
160
  if (isMusl()) {
157
- ${requireTuple('linux-x64-musl')}
161
+ ${requireTuple('linux-x64-musl', 8)}
162
+ } else if (isOpenHarmony) {
163
+ ${requireTuple('linux-x64-ohos', 8)}
158
164
  } else {
159
- ${requireTuple('linux-x64-gnu')}
165
+ ${requireTuple('linux-x64-gnu', 8)}
160
166
  }
161
167
  } else if (process.arch === 'arm64') {
162
168
  if (isMusl()) {
163
- ${requireTuple('linux-arm64-musl')}
169
+ ${requireTuple('linux-arm64-musl', 8)}
170
+ } else if (isOpenHarmony) {
171
+ ${requireTuple('linux-arm64-ohos', 8)}
164
172
  } else {
165
- ${requireTuple('linux-arm64-gnu')}
173
+ ${requireTuple('linux-arm64-gnu', 8)}
166
174
  }
167
175
  } else if (process.arch === 'arm') {
168
176
  if (isMusl()) {
169
- ${requireTuple('linux-arm-musleabihf')}
177
+ ${requireTuple('linux-arm-musleabihf', 8)}
178
+ } else if (isOpenHarmony) {
179
+ ${requireTuple('linux-arm-ohos', 8)}
170
180
  } else {
171
- ${requireTuple('linux-arm-gnueabihf')}
181
+ ${requireTuple('linux-arm-gnueabihf', 8)}
172
182
  }
173
183
  } else if (process.arch === 'riscv64') {
174
184
  if (isMusl()) {
175
- ${requireTuple('linux-riscv64-musl')}
185
+ ${requireTuple('linux-riscv64-musl', 8)}
176
186
  } else {
177
- ${requireTuple('linux-riscv64-gnu')}
187
+ ${requireTuple('linux-riscv64-gnu', 8)}
178
188
  }
179
189
  } else if (process.arch === 'ppc64') {
180
190
  ${requireTuple('linux-ppc64-gnu')}
@@ -115,6 +115,10 @@ export interface CommonPackageJsonFields {
115
115
  author?: string
116
116
  authors?: string[]
117
117
  license?: string
118
+ cpu?: string[]
119
+ os?: string[]
120
+ libc?: string[]
121
+ files?: string[]
118
122
  repository?: any
119
123
  homepage?: any
120
124
  engines?: Record<string, string>
@@ -1,6 +1,6 @@
1
1
  import { execSync } from 'node:child_process'
2
2
 
3
- export type Platform = NodeJS.Platform | 'wasm' | 'wasi'
3
+ export type Platform = NodeJS.Platform | 'wasm' | 'wasi' | 'ohos'
4
4
 
5
5
  export const UNIVERSAL_TARGETS = {
6
6
  'universal-apple-darwin': ['aarch64-apple-darwin', 'x86_64-apple-darwin'],