@napi-rs/cli 3.1.5 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.mjs +3 -3
- package/dist/cli.js +976 -1070
- package/dist/index.cjs +1114 -873
- package/dist/index.d.cts +32 -3
- package/dist/index.d.ts +31 -4
- package/dist/index.js +1065 -866
- package/package.json +21 -22
- package/src/api/artifacts.ts +8 -5
- package/src/api/build.ts +176 -111
- package/src/api/create-npm-dirs.ts +2 -2
- package/src/api/new.ts +5 -3
- package/src/api/pre-publish.ts +1 -1
- package/src/api/rename.ts +3 -4
- package/src/api/templates/js-binding.ts +31 -6
- package/src/api/universalize.ts +1 -1
- package/src/api/version.ts +4 -1
- package/src/cli.ts +1 -27
- package/src/commands/new.ts +2 -1
- package/src/index.ts +33 -0
- package/src/utils/config.ts +1 -1
- package/src/utils/misc.ts +15 -15
- package/src/utils/read-config.ts +1 -3
- package/src/utils/target.ts +7 -0
- package/src/api/__tests__/create-npm-dirs.spec.ts +0 -210
- package/src/api/__tests__/new.spec.ts +0 -429
- package/src/utils/__tests__/__fixtures__/napi_type_def +0 -201
- package/src/utils/__tests__/__snapshots__/config.spec.ts.md +0 -97
- package/src/utils/__tests__/__snapshots__/config.spec.ts.snap +0 -0
- package/src/utils/__tests__/__snapshots__/target.spec.ts.md +0 -166
- package/src/utils/__tests__/__snapshots__/target.spec.ts.snap +0 -0
- package/src/utils/__tests__/__snapshots__/typegen.spec.ts.md +0 -1157
- package/src/utils/__tests__/__snapshots__/typegen.spec.ts.snap +0 -0
- package/src/utils/__tests__/__snapshots__/version.spec.ts.md +0 -21
- package/src/utils/__tests__/__snapshots__/version.spec.ts.snap +0 -0
- package/src/utils/__tests__/config.spec.ts +0 -81
- package/src/utils/__tests__/target.spec.ts +0 -19
- package/src/utils/__tests__/typegen.spec.ts +0 -64
- package/src/utils/__tests__/version.spec.ts +0 -13
package/src/commands/new.ts
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
AVAILABLE_TARGETS,
|
|
10
10
|
debugFactory,
|
|
11
11
|
DEFAULT_TARGETS,
|
|
12
|
-
TargetTriple,
|
|
12
|
+
type TargetTriple,
|
|
13
13
|
} from '../utils/index.js'
|
|
14
14
|
import { napiEngineRequirement } from '../utils/version.js'
|
|
15
15
|
|
|
@@ -76,6 +76,7 @@ export class NewCommand extends BaseNewCommand {
|
|
|
76
76
|
return select({
|
|
77
77
|
message: 'Minimum node-api version (with node version requirement)',
|
|
78
78
|
loop: false,
|
|
79
|
+
pageSize: 10,
|
|
79
80
|
choices: Array.from({ length: 8 }, (_, i) => ({
|
|
80
81
|
name: `napi${i + 1} (${napiEngineRequirement(i + 1)})`,
|
|
81
82
|
value: i + 1,
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Cli } from 'clipanion'
|
|
2
|
+
|
|
1
3
|
import { collectArtifacts } from './api/artifacts.js'
|
|
2
4
|
import { buildProject } from './api/build.js'
|
|
3
5
|
import { createNpmDirs } from './api/create-npm-dirs.js'
|
|
@@ -6,6 +8,31 @@ import { prePublish } from './api/pre-publish.js'
|
|
|
6
8
|
import { renameProject } from './api/rename.js'
|
|
7
9
|
import { universalizeBinaries } from './api/universalize.js'
|
|
8
10
|
import { version } from './api/version.js'
|
|
11
|
+
import { ArtifactsCommand } from './commands/artifacts.js'
|
|
12
|
+
import { BuildCommand } from './commands/build.js'
|
|
13
|
+
import { CreateNpmDirsCommand } from './commands/create-npm-dirs.js'
|
|
14
|
+
import { HelpCommand } from './commands/help.js'
|
|
15
|
+
import { NewCommand } from './commands/new.js'
|
|
16
|
+
import { PrePublishCommand } from './commands/pre-publish.js'
|
|
17
|
+
import { RenameCommand } from './commands/rename.js'
|
|
18
|
+
import { UniversalizeCommand } from './commands/universalize.js'
|
|
19
|
+
import { VersionCommand } from './commands/version.js'
|
|
20
|
+
import { CLI_VERSION } from './utils/misc.js'
|
|
21
|
+
|
|
22
|
+
export const cli = new Cli({
|
|
23
|
+
binaryName: 'napi',
|
|
24
|
+
binaryVersion: CLI_VERSION,
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
cli.register(NewCommand)
|
|
28
|
+
cli.register(BuildCommand)
|
|
29
|
+
cli.register(CreateNpmDirsCommand)
|
|
30
|
+
cli.register(ArtifactsCommand)
|
|
31
|
+
cli.register(UniversalizeCommand)
|
|
32
|
+
cli.register(RenameCommand)
|
|
33
|
+
cli.register(PrePublishCommand)
|
|
34
|
+
cli.register(VersionCommand)
|
|
35
|
+
cli.register(HelpCommand)
|
|
9
36
|
|
|
10
37
|
/**
|
|
11
38
|
*
|
|
@@ -31,3 +58,9 @@ export class NapiCli {
|
|
|
31
58
|
}
|
|
32
59
|
|
|
33
60
|
export { parseTriple } from './utils/target.js'
|
|
61
|
+
export {
|
|
62
|
+
type GenerateTypeDefOptions,
|
|
63
|
+
type WriteJsBindingOptions,
|
|
64
|
+
writeJsBinding,
|
|
65
|
+
generateTypeDef,
|
|
66
|
+
} from './api/build.js'
|
package/src/utils/config.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { underline, yellow } from 'colorette'
|
|
|
2
2
|
import { merge, omit } from 'es-toolkit'
|
|
3
3
|
|
|
4
4
|
import { fileExists, readFileAsync } from './misc.js'
|
|
5
|
-
import { DEFAULT_TARGETS, parseTriple, Target } from './target.js'
|
|
5
|
+
import { DEFAULT_TARGETS, parseTriple, type Target } from './target.js'
|
|
6
6
|
|
|
7
7
|
export type ValueOfConstArray<T> = T[Exclude<keyof T, keyof Array<any>>]
|
|
8
8
|
|
package/src/utils/misc.ts
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
import {
|
|
2
2
|
readFile,
|
|
3
3
|
writeFile,
|
|
4
|
+
unlink,
|
|
4
5
|
copyFile,
|
|
5
6
|
mkdir,
|
|
6
|
-
unlink,
|
|
7
7
|
stat,
|
|
8
8
|
readdir,
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
access,
|
|
10
|
+
} from 'node:fs/promises'
|
|
11
11
|
|
|
12
12
|
import pkgJson from '../../package.json' with { type: 'json' }
|
|
13
13
|
import { debug } from './log.js'
|
|
14
14
|
|
|
15
|
-
export const readFileAsync =
|
|
16
|
-
export const writeFileAsync =
|
|
17
|
-
export const unlinkAsync =
|
|
18
|
-
export const copyFileAsync =
|
|
19
|
-
export const mkdirAsync =
|
|
20
|
-
export const statAsync =
|
|
21
|
-
export const readdirAsync =
|
|
15
|
+
export const readFileAsync = readFile
|
|
16
|
+
export const writeFileAsync = writeFile
|
|
17
|
+
export const unlinkAsync = unlink
|
|
18
|
+
export const copyFileAsync = copyFile
|
|
19
|
+
export const mkdirAsync = mkdir
|
|
20
|
+
export const statAsync = stat
|
|
21
|
+
export const readdirAsync = readdir
|
|
22
22
|
|
|
23
|
-
export
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
export function fileExists(path: string): Promise<boolean> {
|
|
24
|
+
return access(path).then(
|
|
25
|
+
() => true,
|
|
26
|
+
() => false,
|
|
27
|
+
)
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
export async function dirExistsAsync(path: string) {
|
package/src/utils/read-config.ts
CHANGED
|
@@ -11,9 +11,7 @@ interface MinimalNapiOptions {
|
|
|
11
11
|
export async function readConfig(options: MinimalNapiOptions) {
|
|
12
12
|
const resolvePath = (...paths: string[]) => resolve(options.cwd, ...paths)
|
|
13
13
|
const config = await readNapiConfig(
|
|
14
|
-
resolvePath(
|
|
15
|
-
options.configPath ?? options.packageJsonPath ?? 'package.json',
|
|
16
|
-
),
|
|
14
|
+
resolvePath(options.packageJsonPath ?? 'package.json'),
|
|
17
15
|
options.configPath ? resolvePath(options.configPath) : undefined,
|
|
18
16
|
)
|
|
19
17
|
return config
|
package/src/utils/target.ts
CHANGED
|
@@ -17,6 +17,7 @@ export const AVAILABLE_TARGETS = [
|
|
|
17
17
|
'aarch64-pc-windows-msvc',
|
|
18
18
|
'x86_64-apple-darwin',
|
|
19
19
|
'x86_64-pc-windows-msvc',
|
|
20
|
+
'x86_64-pc-windows-gnu',
|
|
20
21
|
'x86_64-unknown-linux-gnu',
|
|
21
22
|
'x86_64-unknown-linux-musl',
|
|
22
23
|
'x86_64-unknown-linux-ohos',
|
|
@@ -26,6 +27,7 @@ export const AVAILABLE_TARGETS = [
|
|
|
26
27
|
'armv7-unknown-linux-musleabihf',
|
|
27
28
|
'armv7-linux-androideabi',
|
|
28
29
|
'universal-apple-darwin',
|
|
30
|
+
'loongarch64-unknown-linux-gnu',
|
|
29
31
|
'riscv64gc-unknown-linux-gnu',
|
|
30
32
|
'powerpc64le-unknown-linux-gnu',
|
|
31
33
|
's390x-unknown-linux-gnu',
|
|
@@ -44,6 +46,8 @@ export const DEFAULT_TARGETS = [
|
|
|
44
46
|
|
|
45
47
|
export const TARGET_LINKER: Record<string, string> = {
|
|
46
48
|
'aarch64-unknown-linux-musl': 'aarch64-linux-musl-gcc',
|
|
49
|
+
// TODO: Switch to loongarch64-linux-gnu-gcc when available
|
|
50
|
+
'loongarch64-unknown-linux-gnu': 'loongarch64-linux-gnu-gcc-13',
|
|
47
51
|
'riscv64gc-unknown-linux-gnu': 'riscv64-linux-gnu-gcc',
|
|
48
52
|
'powerpc64le-unknown-linux-gnu': 'powerpc64le-linux-gnu-gcc',
|
|
49
53
|
's390x-unknown-linux-gnu': 's390x-linux-gnu-gcc',
|
|
@@ -54,6 +58,7 @@ type NodeJSArch =
|
|
|
54
58
|
| 'arm'
|
|
55
59
|
| 'arm64'
|
|
56
60
|
| 'ia32'
|
|
61
|
+
| 'loong64'
|
|
57
62
|
| 'mips'
|
|
58
63
|
| 'mipsel'
|
|
59
64
|
| 'ppc'
|
|
@@ -71,6 +76,7 @@ const CpuToNodeArch: Record<string, NodeJSArch> = {
|
|
|
71
76
|
aarch64: 'arm64',
|
|
72
77
|
i686: 'ia32',
|
|
73
78
|
armv7: 'arm',
|
|
79
|
+
loongarch64: 'loong64',
|
|
74
80
|
riscv64gc: 'riscv64',
|
|
75
81
|
powerpc64le: 'ppc64',
|
|
76
82
|
}
|
|
@@ -80,6 +86,7 @@ export const NodeArchToCpu: Record<string, string> = {
|
|
|
80
86
|
arm64: 'aarch64',
|
|
81
87
|
ia32: 'i686',
|
|
82
88
|
arm: 'armv7',
|
|
89
|
+
loong64: 'loongarch64',
|
|
83
90
|
riscv64: 'riscv64gc',
|
|
84
91
|
ppc64: 'powerpc64le',
|
|
85
92
|
}
|
|
@@ -1,210 +0,0 @@
|
|
|
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
|
-
})
|