@napi-rs/cli 3.0.0-alpha.1 → 3.0.0-alpha.100

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 (176) hide show
  1. package/cli.mjs +1 -1
  2. package/dist/api/__tests__/create-npm-dirs.spec.d.ts +1 -0
  3. package/dist/api/__tests__/new.spec.d.ts +1 -0
  4. package/dist/api/build.d.ts +2 -2
  5. package/dist/api/create-npm-dirs.d.ts +5 -0
  6. package/dist/api/templates/index.d.ts +0 -7
  7. package/dist/api/templates/js-binding.d.ts +2 -1
  8. package/dist/api/templates/load-wasi-template.d.ts +2 -0
  9. package/dist/api/templates/wasi-worker-template.d.ts +2 -0
  10. package/dist/cli.js +3961 -14
  11. package/dist/def/artifacts.d.ts +21 -1
  12. package/dist/def/build.d.ts +167 -4
  13. package/dist/def/create-npm-dirs.d.ts +10 -0
  14. package/dist/def/new.d.ts +25 -7
  15. package/dist/def/pre-publish.d.ts +21 -2
  16. package/dist/def/rename.d.ts +16 -6
  17. package/dist/def/universalize.d.ts +10 -0
  18. package/dist/def/version.d.ts +10 -0
  19. package/dist/index.cjs +10142 -20524
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.js +3711 -29
  22. package/dist/utils/__tests__/config.spec.d.ts +1 -0
  23. package/dist/utils/config.d.ts +70 -6
  24. package/dist/utils/index.d.ts +1 -1
  25. package/dist/utils/metadata.d.ts +13 -1
  26. package/dist/utils/misc.d.ts +3 -3
  27. package/dist/utils/read-config.d.ts +7 -0
  28. package/dist/utils/target.d.ts +9 -6
  29. package/dist/utils/typegen.d.ts +4 -1
  30. package/dist/utils/version.d.ts +2 -1
  31. package/package.json +60 -24
  32. package/src/api/__tests__/create-npm-dirs.spec.ts +210 -0
  33. package/src/api/__tests__/new.spec.ts +429 -0
  34. package/src/api/artifacts.ts +83 -8
  35. package/src/api/build.ts +682 -134
  36. package/src/api/create-npm-dirs.ts +64 -13
  37. package/src/api/new.ts +389 -125
  38. package/src/api/pre-publish.ts +27 -16
  39. package/src/api/rename.ts +103 -17
  40. package/src/api/templates/index.ts +0 -7
  41. package/src/api/templates/js-binding.ts +212 -107
  42. package/src/api/templates/load-wasi-template.ts +216 -0
  43. package/src/api/templates/wasi-worker-template.ts +122 -0
  44. package/src/api/universalize.ts +13 -8
  45. package/src/api/version.ts +5 -2
  46. package/src/commands/artifacts.ts +2 -2
  47. package/src/commands/build.ts +1 -1
  48. package/src/commands/new.ts +46 -49
  49. package/src/def/artifacts.ts +22 -3
  50. package/src/def/build.ts +83 -8
  51. package/src/def/create-npm-dirs.ts +9 -0
  52. package/src/def/new.ts +28 -3
  53. package/src/def/pre-publish.ts +24 -3
  54. package/src/def/rename.ts +11 -2
  55. package/src/def/universalize.ts +9 -0
  56. package/src/def/version.ts +9 -0
  57. package/src/index.ts +2 -0
  58. package/src/utils/__tests__/__fixtures__/napi_type_def +130 -130
  59. package/src/utils/__tests__/__snapshots__/config.spec.ts.md +97 -0
  60. package/src/utils/__tests__/__snapshots__/config.spec.ts.snap +0 -0
  61. package/src/utils/__tests__/__snapshots__/target.spec.ts.md +56 -0
  62. package/src/utils/__tests__/__snapshots__/target.spec.ts.snap +0 -0
  63. package/src/utils/__tests__/__snapshots__/typegen.spec.ts.md +703 -164
  64. package/src/utils/__tests__/__snapshots__/typegen.spec.ts.snap +0 -0
  65. package/src/utils/__tests__/__snapshots__/version.spec.ts.md +9 -8
  66. package/src/utils/__tests__/__snapshots__/version.spec.ts.snap +0 -0
  67. package/src/utils/__tests__/config.spec.ts +81 -0
  68. package/src/utils/__tests__/typegen.spec.ts +19 -4
  69. package/src/utils/cargo.ts +2 -2
  70. package/src/utils/config.ts +147 -13
  71. package/src/utils/index.ts +1 -1
  72. package/src/utils/log.ts +1 -1
  73. package/src/utils/metadata.ts +52 -14
  74. package/src/utils/misc.ts +21 -7
  75. package/src/utils/read-config.ts +20 -0
  76. package/src/utils/target.ts +53 -9
  77. package/src/utils/typegen.ts +100 -40
  78. package/src/utils/version.ts +11 -9
  79. package/dist/api/artifacts.js +0 -50
  80. package/dist/api/build.js +0 -404
  81. package/dist/api/create-npm-dirs.js +0 -63
  82. package/dist/api/new.js +0 -154
  83. package/dist/api/pre-publish.js +0 -157
  84. package/dist/api/rename.js +0 -28
  85. package/dist/api/templates/.gitignore.d.ts +0 -1
  86. package/dist/api/templates/.gitignore.js +0 -198
  87. package/dist/api/templates/.npmignore.d.ts +0 -1
  88. package/dist/api/templates/.npmignore.js +0 -14
  89. package/dist/api/templates/build.rs.d.ts +0 -1
  90. package/dist/api/templates/build.rs.js +0 -4
  91. package/dist/api/templates/cargo.toml.d.ts +0 -6
  92. package/dist/api/templates/cargo.toml.js +0 -25
  93. package/dist/api/templates/ci-template.d.ts +0 -1
  94. package/dist/api/templates/ci-template.js +0 -566
  95. package/dist/api/templates/ci.yml.d.ts +0 -1
  96. package/dist/api/templates/ci.yml.js +0 -92
  97. package/dist/api/templates/index.js +0 -8
  98. package/dist/api/templates/js-binding.js +0 -124
  99. package/dist/api/templates/lib.rs.d.ts +0 -1
  100. package/dist/api/templates/lib.rs.js +0 -10
  101. package/dist/api/templates/package.json.d.ts +0 -8
  102. package/dist/api/templates/package.json.js +0 -30
  103. package/dist/api/universalize.js +0 -38
  104. package/dist/api/version.js +0 -16
  105. package/dist/commands/artifacts.js +0 -19
  106. package/dist/commands/build.js +0 -34
  107. package/dist/commands/create-npm-dirs.js +0 -7
  108. package/dist/commands/help.js +0 -12
  109. package/dist/commands/new.js +0 -112
  110. package/dist/commands/pre-publish.js +0 -8
  111. package/dist/commands/rename.js +0 -7
  112. package/dist/commands/universalize.js +0 -7
  113. package/dist/commands/version.js +0 -7
  114. package/dist/def/artifacts.js +0 -38
  115. package/dist/def/build.js +0 -105
  116. package/dist/def/commands/artifacts.d.ts +0 -15
  117. package/dist/def/commands/artifacts.js +0 -29
  118. package/dist/def/commands/build.d.ts +0 -53
  119. package/dist/def/commands/build.js +0 -105
  120. package/dist/def/commands/create-npm-dirs.d.ts +0 -15
  121. package/dist/def/commands/create-npm-dirs.js +0 -29
  122. package/dist/def/commands/new.d.ts +0 -27
  123. package/dist/def/commands/new.js +0 -53
  124. package/dist/def/commands/pre-publish.d.ts +0 -23
  125. package/dist/def/commands/pre-publish.js +0 -45
  126. package/dist/def/commands/rename.d.ts +0 -25
  127. package/dist/def/commands/rename.js +0 -49
  128. package/dist/def/commands/universalize.d.ts +0 -13
  129. package/dist/def/commands/universalize.js +0 -25
  130. package/dist/def/commands/version.d.ts +0 -13
  131. package/dist/def/commands/version.js +0 -25
  132. package/dist/def/create-npm-dirs.js +0 -38
  133. package/dist/def/new.js +0 -66
  134. package/dist/def/options/artifacts.d.ts +0 -35
  135. package/dist/def/options/artifacts.js +0 -11
  136. package/dist/def/options/build.d.ts +0 -97
  137. package/dist/def/options/build.js +0 -3
  138. package/dist/def/options/create-npm-dirs.d.ts +0 -35
  139. package/dist/def/options/create-npm-dirs.js +0 -11
  140. package/dist/def/options/new.d.ts +0 -79
  141. package/dist/def/options/new.js +0 -15
  142. package/dist/def/options/pre-publish.d.ts +0 -65
  143. package/dist/def/options/pre-publish.js +0 -13
  144. package/dist/def/options/rename.d.ts +0 -75
  145. package/dist/def/options/rename.js +0 -11
  146. package/dist/def/options/universalize.d.ts +0 -28
  147. package/dist/def/options/universalize.js +0 -10
  148. package/dist/def/options/version.d.ts +0 -28
  149. package/dist/def/options/version.js +0 -10
  150. package/dist/def/pre-publish.js +0 -56
  151. package/dist/def/rename.js +0 -58
  152. package/dist/def/universalize.js +0 -33
  153. package/dist/def/version.js +0 -33
  154. package/dist/utils/__tests__/target.spec.js +0 -10
  155. package/dist/utils/__tests__/typegen.spec.js +0 -37
  156. package/dist/utils/__tests__/version.spec.js +0 -5
  157. package/dist/utils/cargo.js +0 -33
  158. package/dist/utils/ci.d.ts +0 -11
  159. package/dist/utils/ci.js +0 -86
  160. package/dist/utils/config.js +0 -42
  161. package/dist/utils/index.js +0 -9
  162. package/dist/utils/log.js +0 -14
  163. package/dist/utils/metadata.js +0 -19
  164. package/dist/utils/misc.js +0 -35
  165. package/dist/utils/target.js +0 -109
  166. package/dist/utils/typegen.js +0 -158
  167. package/dist/utils/version.js +0 -59
  168. package/src/api/templates/.gitignore.ts +0 -198
  169. package/src/api/templates/.npmignore.ts +0 -14
  170. package/src/api/templates/build.rs.ts +0 -4
  171. package/src/api/templates/cargo.toml.ts +0 -35
  172. package/src/api/templates/ci-template.ts +0 -566
  173. package/src/api/templates/ci.yml.ts +0 -116
  174. package/src/api/templates/lib.rs.ts +0 -10
  175. package/src/api/templates/package.json.ts +0 -44
  176. package/src/utils/ci.ts +0 -102
@@ -0,0 +1,216 @@
1
+ export const createWasiBrowserBinding = (
2
+ wasiFilename: string,
3
+ initialMemory = 4000,
4
+ maximumMemory = 65536,
5
+ fs = false,
6
+ asyncInit = false,
7
+ buffer = false,
8
+ ) => {
9
+ const fsImport = fs ? `import { memfs } from '@napi-rs/wasm-runtime/fs'` : ''
10
+ const bufferImport = buffer
11
+ ? fs
12
+ ? ``
13
+ : `import { Buffer } from 'buffer'`
14
+ : ''
15
+ const wasiCreation = fs
16
+ ? `
17
+ export const { fs: __fs, vol: __volume } = memfs()
18
+
19
+ const __wasi = new __WASI({
20
+ version: 'preview1',
21
+ fs: __fs,
22
+ preopens: {
23
+ '/': '/',
24
+ },
25
+ })`
26
+ : `
27
+ const __wasi = new __WASI({
28
+ version: 'preview1',
29
+ })`
30
+
31
+ const workerFsHandler = fs
32
+ ? ` worker.addEventListener('message', __wasmCreateOnMessageForFsProxy(__fs))\n`
33
+ : ''
34
+
35
+ const emnapiInjectBuffer = buffer
36
+ ? '__emnapiContext.feature.Buffer = Buffer'
37
+ : ''
38
+ const emnapiInstantiateImport = asyncInit
39
+ ? `instantiateNapiModule as __emnapiInstantiateNapiModule`
40
+ : `instantiateNapiModuleSync as __emnapiInstantiateNapiModuleSync`
41
+ const emnapiInstantiateCall = asyncInit
42
+ ? `await __emnapiInstantiateNapiModule`
43
+ : `__emnapiInstantiateNapiModuleSync`
44
+
45
+ return `import {
46
+ createOnMessage as __wasmCreateOnMessageForFsProxy,
47
+ getDefaultContext as __emnapiGetDefaultContext,
48
+ ${emnapiInstantiateImport},
49
+ WASI as __WASI,
50
+ } from '@napi-rs/wasm-runtime'
51
+ ${fsImport}
52
+ ${bufferImport}
53
+ ${wasiCreation}
54
+
55
+ const __wasmUrl = new URL('./${wasiFilename}.wasm', import.meta.url).href
56
+ const __emnapiContext = __emnapiGetDefaultContext()
57
+ ${emnapiInjectBuffer}
58
+
59
+ const __sharedMemory = new WebAssembly.Memory({
60
+ initial: ${initialMemory},
61
+ maximum: ${maximumMemory},
62
+ shared: true,
63
+ })
64
+
65
+ const __wasmFile = await fetch(__wasmUrl).then((res) => res.arrayBuffer())
66
+
67
+ const {
68
+ instance: __napiInstance,
69
+ module: __wasiModule,
70
+ napiModule: __napiModule,
71
+ } = ${emnapiInstantiateCall}(__wasmFile, {
72
+ context: __emnapiContext,
73
+ asyncWorkPoolSize: 4,
74
+ wasi: __wasi,
75
+ onCreateWorker() {
76
+ const worker = new Worker(new URL('./wasi-worker-browser.mjs', import.meta.url), {
77
+ type: 'module',
78
+ })
79
+ ${workerFsHandler}
80
+ return worker
81
+ },
82
+ overwriteImports(importObject) {
83
+ importObject.env = {
84
+ ...importObject.env,
85
+ ...importObject.napi,
86
+ ...importObject.emnapi,
87
+ memory: __sharedMemory,
88
+ }
89
+ return importObject
90
+ },
91
+ beforeInit({ instance }) {
92
+ for (const name of Object.keys(instance.exports)) {
93
+ if (name.startsWith('__napi_register__')) {
94
+ instance.exports[name]()
95
+ }
96
+ }
97
+ },
98
+ })
99
+ `
100
+ }
101
+
102
+ export const createWasiBinding = (
103
+ wasmFileName: string,
104
+ packageName: string,
105
+ initialMemory = 4000,
106
+ maximumMemory = 65536,
107
+ ) => `/* eslint-disable */
108
+ /* prettier-ignore */
109
+
110
+ /* auto-generated by NAPI-RS */
111
+
112
+ const __nodeFs = require('node:fs')
113
+ const __nodePath = require('node:path')
114
+ const { WASI: __nodeWASI } = require('node:wasi')
115
+ const { Worker } = require('node:worker_threads')
116
+
117
+ const {
118
+ createOnMessage: __wasmCreateOnMessageForFsProxy,
119
+ getDefaultContext: __emnapiGetDefaultContext,
120
+ instantiateNapiModuleSync: __emnapiInstantiateNapiModuleSync,
121
+ } = require('@napi-rs/wasm-runtime')
122
+
123
+ const __rootDir = __nodePath.parse(process.cwd()).root
124
+
125
+ const __wasi = new __nodeWASI({
126
+ version: 'preview1',
127
+ env: process.env,
128
+ preopens: {
129
+ [__rootDir]: __rootDir,
130
+ }
131
+ })
132
+
133
+ const __emnapiContext = __emnapiGetDefaultContext()
134
+
135
+ const __sharedMemory = new WebAssembly.Memory({
136
+ initial: ${initialMemory},
137
+ maximum: ${maximumMemory},
138
+ shared: true,
139
+ })
140
+
141
+ let __wasmFilePath = __nodePath.join(__dirname, '${wasmFileName}.wasm')
142
+ const __wasmDebugFilePath = __nodePath.join(__dirname, '${wasmFileName}.debug.wasm')
143
+
144
+ if (__nodeFs.existsSync(__wasmDebugFilePath)) {
145
+ __wasmFilePath = __wasmDebugFilePath
146
+ } else if (!__nodeFs.existsSync(__wasmFilePath)) {
147
+ try {
148
+ __wasmFilePath = __nodePath.resolve('${packageName}-wasm32-wasi')
149
+ } catch {
150
+ throw new Error('Cannot find ${wasmFileName}.wasm file, and ${packageName}-wasm32-wasi package is not installed.')
151
+ }
152
+ }
153
+
154
+ const { instance: __napiInstance, module: __wasiModule, napiModule: __napiModule } = __emnapiInstantiateNapiModuleSync(__nodeFs.readFileSync(__wasmFilePath), {
155
+ context: __emnapiContext,
156
+ asyncWorkPoolSize: (function() {
157
+ const threadsSizeFromEnv = Number(process.env.NAPI_RS_ASYNC_WORK_POOL_SIZE ?? process.env.UV_THREADPOOL_SIZE)
158
+ // NaN > 0 is false
159
+ if (threadsSizeFromEnv > 0) {
160
+ return threadsSizeFromEnv
161
+ } else {
162
+ return 4
163
+ }
164
+ })(),
165
+ reuseWorker: true,
166
+ wasi: __wasi,
167
+ onCreateWorker() {
168
+ const worker = new Worker(__nodePath.join(__dirname, 'wasi-worker.mjs'), {
169
+ env: process.env,
170
+ })
171
+ worker.onmessage = ({ data }) => {
172
+ __wasmCreateOnMessageForFsProxy(__nodeFs)(data)
173
+ }
174
+
175
+ // The main thread of Node.js waits for all the active handles before exiting.
176
+ // But Rust threads are never waited without \`thread::join\`.
177
+ // So here we hack the code of Node.js to prevent the workers from being referenced (active).
178
+ // According to https://github.com/nodejs/node/blob/19e0d472728c79d418b74bddff588bea70a403d0/lib/internal/worker.js#L415,
179
+ // a worker is consist of two handles: kPublicPort and kHandle.
180
+ {
181
+ const kPublicPort = Object.getOwnPropertySymbols(worker).find(s =>
182
+ s.toString().includes("kPublicPort")
183
+ );
184
+ if (kPublicPort) {
185
+ worker[kPublicPort].ref = () => {};
186
+ }
187
+
188
+ const kHandle = Object.getOwnPropertySymbols(worker).find(s =>
189
+ s.toString().includes("kHandle")
190
+ );
191
+ if (kHandle) {
192
+ worker[kHandle].ref = () => {};
193
+ }
194
+
195
+ worker.unref();
196
+ }
197
+ return worker
198
+ },
199
+ overwriteImports(importObject) {
200
+ importObject.env = {
201
+ ...importObject.env,
202
+ ...importObject.napi,
203
+ ...importObject.emnapi,
204
+ memory: __sharedMemory,
205
+ }
206
+ return importObject
207
+ },
208
+ beforeInit({ instance }) {
209
+ for (const name of Object.keys(instance.exports)) {
210
+ if (name.startsWith('__napi_register__')) {
211
+ instance.exports[name]()
212
+ }
213
+ }
214
+ },
215
+ })
216
+ `
@@ -0,0 +1,122 @@
1
+ export const WASI_WORKER_TEMPLATE = `import fs from "node:fs";
2
+ import { createRequire } from "node:module";
3
+ import { parse } from "node:path";
4
+ import { WASI } from "node:wasi";
5
+ import { parentPort, Worker } from "node:worker_threads";
6
+
7
+ const require = createRequire(import.meta.url);
8
+
9
+ const { instantiateNapiModuleSync, MessageHandler, getDefaultContext } = require("@napi-rs/wasm-runtime");
10
+
11
+ if (parentPort) {
12
+ parentPort.on("message", (data) => {
13
+ globalThis.onmessage({ data });
14
+ });
15
+ }
16
+
17
+ Object.assign(globalThis, {
18
+ self: globalThis,
19
+ require,
20
+ Worker,
21
+ importScripts: function (f) {
22
+ ;(0, eval)(fs.readFileSync(f, "utf8") + "//# sourceURL=" + f);
23
+ },
24
+ postMessage: function (msg) {
25
+ if (parentPort) {
26
+ parentPort.postMessage(msg);
27
+ }
28
+ },
29
+ });
30
+
31
+ const emnapiContext = getDefaultContext();
32
+
33
+ const __rootDir = parse(process.cwd()).root;
34
+
35
+ const handler = new MessageHandler({
36
+ onLoad({ wasmModule, wasmMemory }) {
37
+ const wasi = new WASI({
38
+ version: 'preview1',
39
+ env: process.env,
40
+ preopens: {
41
+ [__rootDir]: __rootDir,
42
+ },
43
+ });
44
+
45
+ return instantiateNapiModuleSync(wasmModule, {
46
+ childThread: true,
47
+ wasi,
48
+ context: emnapiContext,
49
+ overwriteImports(importObject) {
50
+ importObject.env = {
51
+ ...importObject.env,
52
+ ...importObject.napi,
53
+ ...importObject.emnapi,
54
+ memory: wasmMemory
55
+ };
56
+ },
57
+ });
58
+ },
59
+ });
60
+
61
+ globalThis.onmessage = function (e) {
62
+ handler.handle(e);
63
+ };
64
+ `
65
+
66
+ export const createWasiBrowserWorkerBinding = (fs: boolean) => {
67
+ const fsImport = fs
68
+ ? `import { instantiateNapiModuleSync, MessageHandler, WASI, createFsProxy } from '@napi-rs/wasm-runtime'
69
+ import { memfsExported as __memfsExported } from '@napi-rs/wasm-runtime/fs'
70
+
71
+ const fs = createFsProxy(__memfsExported)`
72
+ : `import { instantiateNapiModuleSync, MessageHandler, WASI } from '@napi-rs/wasm-runtime'`
73
+ const wasiCreation = fs
74
+ ? `const wasi = new WASI({
75
+ fs,
76
+ preopens: {
77
+ '/': '/',
78
+ },
79
+ print: function () {
80
+ // eslint-disable-next-line no-console
81
+ console.log.apply(console, arguments)
82
+ },
83
+ printErr: function() {
84
+ // eslint-disable-next-line no-console
85
+ console.error.apply(console, arguments)
86
+ },
87
+ })`
88
+ : `const wasi = new WASI({
89
+ print: function () {
90
+ // eslint-disable-next-line no-console
91
+ console.log.apply(console, arguments)
92
+ },
93
+ printErr: function() {
94
+ // eslint-disable-next-line no-console
95
+ console.error.apply(console, arguments)
96
+ },
97
+ })`
98
+ return `${fsImport}
99
+
100
+ const handler = new MessageHandler({
101
+ onLoad({ wasmModule, wasmMemory }) {
102
+ ${wasiCreation}
103
+ return instantiateNapiModuleSync(wasmModule, {
104
+ childThread: true,
105
+ wasi,
106
+ overwriteImports(importObject) {
107
+ importObject.env = {
108
+ ...importObject.env,
109
+ ...importObject.napi,
110
+ ...importObject.emnapi,
111
+ memory: wasmMemory,
112
+ }
113
+ },
114
+ })
115
+ },
116
+ })
117
+
118
+ globalThis.onmessage = function (e) {
119
+ handler.handle(e)
120
+ }
121
+ `
122
+ }
@@ -1,5 +1,5 @@
1
- import { spawnSync } from 'child_process'
2
- import { join, resolve } from 'path'
1
+ import { spawnSync } from 'node:child_process'
2
+ import { join, resolve } from 'node:path'
3
3
 
4
4
  import {
5
5
  applyDefaultUniversalizeOptions,
@@ -27,7 +27,10 @@ export async function universalizeBinaries(userOptions: UniversalizeOptions) {
27
27
 
28
28
  const packageJsonPath = join(options.cwd, options.packageJsonPath)
29
29
 
30
- const config = await readNapiConfig(packageJsonPath)
30
+ const config = await readNapiConfig(
31
+ packageJsonPath,
32
+ options.configPath ? resolve(options.cwd, options.configPath) : undefined,
33
+ )
31
34
 
32
35
  const target = config.targets.find(
33
36
  (t) => t.platform === process.platform && t.arch === 'universal',
@@ -39,8 +42,12 @@ export async function universalizeBinaries(userOptions: UniversalizeOptions) {
39
42
  )
40
43
  }
41
44
 
42
- const srcFiles = UniArchsByPlatform[process.platform]?.map(
43
- (arch) => `${config.binaryName}.${process.platform}-${arch}.node`,
45
+ const srcFiles = UniArchsByPlatform[process.platform]?.map((arch) =>
46
+ resolve(
47
+ options.cwd,
48
+ options.outputDir,
49
+ `${config.binaryName}.${process.platform}-${arch}.node`,
50
+ ),
44
51
  )
45
52
 
46
53
  if (!srcFiles || !universalizers[process.platform]) {
@@ -52,9 +59,7 @@ export async function universalizeBinaries(userOptions: UniversalizeOptions) {
52
59
  debug(`Looking up source binaries to combine: `)
53
60
  debug(' %O', srcFiles)
54
61
 
55
- const srcFileLookup = await Promise.all(
56
- srcFiles.map((f) => fileExists(resolve(options.cwd, options.outputDir, f))),
57
- )
62
+ const srcFileLookup = await Promise.all(srcFiles.map((f) => fileExists(f)))
58
63
 
59
64
  const notFoundFiles = srcFiles.filter((_, i) => !srcFileLookup[i])
60
65
 
@@ -1,4 +1,4 @@
1
- import { join, resolve } from 'path'
1
+ import { join, resolve } from 'node:path'
2
2
 
3
3
  import { applyDefaultVersionOptions, VersionOptions } from '../def/version.js'
4
4
  import {
@@ -13,7 +13,10 @@ export async function version(userOptions: VersionOptions) {
13
13
  const options = applyDefaultVersionOptions(userOptions)
14
14
  const packageJsonPath = resolve(options.cwd, options.packageJsonPath)
15
15
 
16
- const config = await readNapiConfig(packageJsonPath)
16
+ const config = await readNapiConfig(
17
+ packageJsonPath,
18
+ options.configPath ? resolve(options.cwd, options.configPath) : undefined,
19
+ )
17
20
 
18
21
  for (const target of config.targets) {
19
22
  const pkgDir = resolve(options.cwd, options.npmDir, target.platformArchABI)
@@ -8,9 +8,9 @@ export class ArtifactsCommand extends BaseArtifactsCommand {
8
8
  description: 'Copy artifacts from Github Actions into specified dir',
9
9
  examples: [
10
10
  [
11
- '$0 artifacts --dir . --dist ./npm',
11
+ '$0 artifacts --output-dir ./artifacts --dist ./npm',
12
12
  `Copy [binaryName].[platform].node under current dir(.) into packages under npm dir.
13
- e.g: index.linux-x64-gnu.node --> ./npm/linux-x64-gnu/index.node`,
13
+ e.g: index.linux-x64-gnu.node --> ./npm/linux-x64-gnu/index.linux-x64-gnu.node`,
14
14
  ],
15
15
  ],
16
16
  })
@@ -1,4 +1,4 @@
1
- import { execSync } from 'child_process'
1
+ import { execSync } from 'node:child_process'
2
2
 
3
3
  import { Option } from 'clipanion'
4
4
 
@@ -1,7 +1,7 @@
1
- import path from 'path'
1
+ import path from 'node:path'
2
2
 
3
+ import { input, select, checkbox, confirm } from '@inquirer/prompts'
3
4
  import { Option } from 'clipanion'
4
- import inquirer from 'inquirer'
5
5
 
6
6
  import { newProject } from '../api/new.js'
7
7
  import { BaseNewCommand } from '../def/new.js'
@@ -16,7 +16,7 @@ import { napiEngineRequirement } from '../utils/version.js'
16
16
  const debug = debugFactory('new')
17
17
 
18
18
  export class NewCommand extends BaseNewCommand {
19
- interactive = Option.Boolean('--interactive,-i', false, {
19
+ interactive = Option.Boolean('--interactive,-i', true, {
20
20
  description:
21
21
  'Ask project basic information interactively without just using the default.',
22
22
  })
@@ -37,9 +37,13 @@ export class NewCommand extends BaseNewCommand {
37
37
  const cmdOptions = super.getOptions()
38
38
 
39
39
  if (this.interactive) {
40
+ const targetPath: string = cmdOptions.path
41
+ ? cmdOptions.path
42
+ : await inquirerProjectPath()
43
+ cmdOptions.path = targetPath
40
44
  return {
41
45
  ...cmdOptions,
42
- name: await this.fetchName(path.parse(cmdOptions.path).base),
46
+ name: await this.fetchName(path.parse(targetPath).base),
43
47
  minNodeApiVersion: await this.fetchNapiVersion(),
44
48
  targets: await this.fetchTargets(),
45
49
  license: await this.fetchLicense(),
@@ -54,70 +58,54 @@ export class NewCommand extends BaseNewCommand {
54
58
  private async fetchName(defaultName: string): Promise<string> {
55
59
  return (
56
60
  this.$$name ??
57
- (await inquirer
58
- .prompt({
59
- type: 'input',
60
- name: 'name',
61
- message: 'Package name (the name field in your package.json file)',
62
- default: defaultName,
63
- })
64
- .then(({ name }) => name))
61
+ input({
62
+ message: 'Package name (the name field in your package.json file)',
63
+ default: defaultName,
64
+ })
65
65
  )
66
66
  }
67
67
 
68
68
  private async fetchLicense(): Promise<string> {
69
- return inquirer
70
- .prompt({
71
- type: 'input',
72
- name: 'license',
73
- message: 'License for open-sourced project',
74
- default: this.license,
75
- })
76
- .then(({ license }) => license)
69
+ return input({
70
+ message: 'License for open-sourced project',
71
+ default: this.license,
72
+ })
77
73
  }
78
74
 
79
75
  private async fetchNapiVersion(): Promise<number> {
80
- return inquirer
81
- .prompt({
82
- type: 'list',
83
- name: 'minNodeApiVersion',
84
- message: 'Minimum node-api version (with node version requirement)',
85
- loop: false,
86
- choices: new Array(8).fill(0).map((_, i) => ({
87
- name: `napi${i + 1} (${napiEngineRequirement(i + 1)})`,
88
- value: i + 1,
89
- })),
90
- // choice index
91
- default: this.minNodeApiVersion - 1,
92
- })
93
- .then(({ minNodeApiVersion }) => minNodeApiVersion)
76
+ return select({
77
+ message: 'Minimum node-api version (with node version requirement)',
78
+ loop: false,
79
+ choices: Array.from({ length: 8 }, (_, i) => ({
80
+ name: `napi${i + 1} (${napiEngineRequirement(i + 1)})`,
81
+ value: i + 1,
82
+ })),
83
+ // choice index
84
+ default: this.minNodeApiVersion - 1,
85
+ })
94
86
  }
95
87
 
96
88
  private async fetchTargets(): Promise<TargetTriple[]> {
97
- if (this.enableDefaultTargets) {
98
- return DEFAULT_TARGETS.concat()
99
- }
100
-
101
89
  if (this.enableAllTargets) {
102
90
  return AVAILABLE_TARGETS.concat()
103
91
  }
104
92
 
105
- const { targets } = await inquirer.prompt({
106
- name: 'targets',
107
- type: 'checkbox',
93
+ const targets = await checkbox({
108
94
  loop: false,
109
95
  message: 'Choose target(s) your crate will be compiled to',
110
- default: DEFAULT_TARGETS,
111
- choices: AVAILABLE_TARGETS,
96
+ choices: AVAILABLE_TARGETS.map((target) => ({
97
+ name: target,
98
+ value: target,
99
+ // @ts-expect-error
100
+ checked: DEFAULT_TARGETS.includes(target),
101
+ })),
112
102
  })
113
103
 
114
104
  return targets
115
105
  }
116
106
 
117
107
  private async fetchTypeDef(): Promise<boolean> {
118
- const { enableTypeDef } = await inquirer.prompt({
119
- name: 'enableTypeDef',
120
- type: 'confirm',
108
+ const enableTypeDef = await confirm({
121
109
  message: 'Enable type definition auto-generation',
122
110
  default: this.enableTypeDef,
123
111
  })
@@ -126,9 +114,7 @@ export class NewCommand extends BaseNewCommand {
126
114
  }
127
115
 
128
116
  private async fetchGithubActions(): Promise<boolean> {
129
- const { enableGithubActions } = await inquirer.prompt({
130
- name: 'enableGithubActions',
131
- type: 'confirm',
117
+ const enableGithubActions = await confirm({
132
118
  message: 'Enable Github Actions CI',
133
119
  default: this.enableGithubActions,
134
120
  })
@@ -136,3 +122,14 @@ export class NewCommand extends BaseNewCommand {
136
122
  return enableGithubActions
137
123
  }
138
124
  }
125
+
126
+ async function inquirerProjectPath(): Promise<string> {
127
+ return input({
128
+ message: 'Target path to create the project, relative to cwd.',
129
+ }).then((path) => {
130
+ if (!path) {
131
+ return inquirerProjectPath()
132
+ }
133
+ return path
134
+ })
135
+ }
@@ -15,11 +15,15 @@ export abstract class BaseArtifactsCommand extends Command {
15
15
  'The working directory of where napi command will be executed in, all other paths options are relative to this path',
16
16
  })
17
17
 
18
+ configPath?: string = Option.String('--config-path,-c', {
19
+ description: 'Path to `napi` config json file',
20
+ })
21
+
18
22
  packageJsonPath = Option.String('--package-json-path', 'package.json', {
19
23
  description: 'Path to `package.json`',
20
24
  })
21
25
 
22
- outputDir = Option.String('--output-dir,-o', './', {
26
+ outputDir = Option.String('--output-dir,-o,-d', './artifacts', {
23
27
  description:
24
28
  'Path to the folder where all built `.node` files put, same as `--output-dir` of build command',
25
29
  })
@@ -28,12 +32,19 @@ export abstract class BaseArtifactsCommand extends Command {
28
32
  description: 'Path to the folder where the npm packages put',
29
33
  })
30
34
 
35
+ buildOutputDir?: string = Option.String('--build-output-dir', {
36
+ description:
37
+ 'Path to the build output dir, only needed when targets contains `wasm32-wasi-*`',
38
+ })
39
+
31
40
  getOptions() {
32
41
  return {
33
42
  cwd: this.cwd,
43
+ configPath: this.configPath,
34
44
  packageJsonPath: this.packageJsonPath,
35
45
  outputDir: this.outputDir,
36
46
  npmDir: this.npmDir,
47
+ buildOutputDir: this.buildOutputDir,
37
48
  }
38
49
  }
39
50
  }
@@ -48,6 +59,10 @@ export interface ArtifactsOptions {
48
59
  * @default process.cwd()
49
60
  */
50
61
  cwd?: string
62
+ /**
63
+ * Path to `napi` config json file
64
+ */
65
+ configPath?: string
51
66
  /**
52
67
  * Path to `package.json`
53
68
  *
@@ -57,7 +72,7 @@ export interface ArtifactsOptions {
57
72
  /**
58
73
  * Path to the folder where all built `.node` files put, same as `--output-dir` of build command
59
74
  *
60
- * @default './'
75
+ * @default './artifacts'
61
76
  */
62
77
  outputDir?: string
63
78
  /**
@@ -66,13 +81,17 @@ export interface ArtifactsOptions {
66
81
  * @default 'npm'
67
82
  */
68
83
  npmDir?: string
84
+ /**
85
+ * Path to the build output dir, only needed when targets contains `wasm32-wasi-*`
86
+ */
87
+ buildOutputDir?: string
69
88
  }
70
89
 
71
90
  export function applyDefaultArtifactsOptions(options: ArtifactsOptions) {
72
91
  return {
73
92
  cwd: process.cwd(),
74
93
  packageJsonPath: 'package.json',
75
- outputDir: './',
94
+ outputDir: './artifacts',
76
95
  npmDir: 'npm',
77
96
  ...options,
78
97
  }