@napi-rs/cli 3.7.3 → 3.8.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/README.md +33 -0
- package/cli.mjs +9 -12
- package/dist/cli.js +9277 -1313
- package/dist/index.cjs +9266 -1302
- package/dist/index.d.cts +176 -158
- package/dist/index.d.ts +176 -158
- package/dist/index.js +9277 -1313
- package/docs/artifacts.md +33 -0
- package/docs/build.md +58 -0
- package/docs/create-npm-dirs.md +32 -0
- package/docs/new.md +39 -0
- package/docs/pre-publish.md +37 -0
- package/docs/rename.md +37 -0
- package/docs/universalize.md +31 -0
- package/docs/version.md +31 -0
- package/docs/wasi.md +161 -0
- package/package.json +11 -10
- package/src/api/__tests__/__snapshots__/templates.spec.ts.md +1019 -114
- package/src/api/__tests__/__snapshots__/templates.spec.ts.snap +0 -0
- package/src/api/__tests__/artifacts.spec.ts +17 -0
- package/src/api/__tests__/create-npm-dirs.spec.ts +14 -15
- package/src/api/__tests__/new.spec.ts +41 -5
- package/src/api/artifacts.ts +934 -108
- package/src/api/build.ts +1325 -194
- package/src/api/create-npm-dirs.ts +472 -101
- package/src/api/new.ts +354 -35
- package/src/api/pre-publish.ts +2845 -99
- package/src/api/rename.ts +1638 -124
- package/src/api/templates/js-binding.ts +216 -38
- package/src/api/templates/load-wasi-template.ts +1641 -111
- package/src/api/templates/wasi-worker-template.ts +32 -3
- package/src/commands/rename.ts +8 -3
- package/src/def/artifacts.ts +2 -2
- package/src/utils/__tests__/__fixtures__/optional-napi-derive/Cargo.toml +3 -0
- package/src/utils/__tests__/__fixtures__/optional-napi-derive/main-crate/Cargo.toml +8 -0
- package/src/utils/__tests__/__fixtures__/optional-napi-derive/main-crate/src/lib.rs +1 -0
- package/src/utils/__tests__/__fixtures__/optional-napi-derive/napi-derive/Cargo.toml +5 -0
- package/src/utils/__tests__/__fixtures__/optional-napi-derive/napi-derive/src/lib.rs +1 -0
- package/src/utils/__tests__/__fixtures__/optional-napi-derive/with-optional-derive/Cargo.toml +11 -0
- package/src/utils/__tests__/__fixtures__/optional-napi-derive/with-optional-derive/src/lib.rs +1 -0
- package/src/utils/__tests__/__snapshots__/target.spec.ts.md +2 -2
- package/src/utils/__tests__/__snapshots__/target.spec.ts.snap +0 -0
- package/src/utils/__tests__/metadata.spec.ts +43 -2
- package/src/utils/__tests__/misc.spec.ts +124 -3
- package/src/utils/__tests__/version.spec.ts +47 -1
- package/src/utils/config.ts +15 -2
- package/src/utils/metadata.ts +206 -7
- package/src/utils/misc.ts +6079 -0
- package/src/utils/target.ts +66 -8
- package/src/utils/typegen.ts +1223 -63
- package/src/utils/version.ts +96 -0
|
@@ -6,7 +6,13 @@ import { parentPort, Worker } from "node:worker_threads";
|
|
|
6
6
|
|
|
7
7
|
const require = createRequire(import.meta.url);
|
|
8
8
|
|
|
9
|
-
const {
|
|
9
|
+
const {
|
|
10
|
+
instantiateNapiModuleSync,
|
|
11
|
+
MessageHandler,
|
|
12
|
+
getDefaultContext,
|
|
13
|
+
emnapiAsyncWorkPlugin,
|
|
14
|
+
emnapiTSFNPlugin,
|
|
15
|
+
} = require("@napi-rs/wasm-runtime");
|
|
10
16
|
|
|
11
17
|
if (parentPort) {
|
|
12
18
|
parentPort.on("message", (data) => {
|
|
@@ -46,6 +52,11 @@ const handler = new MessageHandler({
|
|
|
46
52
|
childThread: true,
|
|
47
53
|
wasi,
|
|
48
54
|
context: emnapiContext,
|
|
55
|
+
// The wasm links a "basic" emnapi archive (no C async-work /
|
|
56
|
+
// threadsafe-function implementations), so every thread that
|
|
57
|
+
// instantiates it must provide the JavaScript implementations
|
|
58
|
+
// through the emnapi plugins.
|
|
59
|
+
plugins: [emnapiAsyncWorkPlugin, emnapiTSFNPlugin],
|
|
49
60
|
overwriteImports(importObject) {
|
|
50
61
|
importObject.env = {
|
|
51
62
|
...importObject.env,
|
|
@@ -68,11 +79,24 @@ export const createWasiBrowserWorkerBinding = (
|
|
|
68
79
|
errorEvent: boolean,
|
|
69
80
|
) => {
|
|
70
81
|
const fsImport = fs
|
|
71
|
-
? `import {
|
|
82
|
+
? `import {
|
|
83
|
+
instantiateNapiModuleSync,
|
|
84
|
+
MessageHandler,
|
|
85
|
+
WASI,
|
|
86
|
+
createFsProxy,
|
|
87
|
+
emnapiAsyncWorkPlugin,
|
|
88
|
+
emnapiTSFNPlugin,
|
|
89
|
+
} from '@napi-rs/wasm-runtime'
|
|
72
90
|
import { memfsExported as __memfsExported } from '@napi-rs/wasm-runtime/fs'
|
|
73
91
|
|
|
74
92
|
const fs = createFsProxy(__memfsExported)`
|
|
75
|
-
: `import {
|
|
93
|
+
: `import {
|
|
94
|
+
instantiateNapiModuleSync,
|
|
95
|
+
MessageHandler,
|
|
96
|
+
WASI,
|
|
97
|
+
emnapiAsyncWorkPlugin,
|
|
98
|
+
emnapiTSFNPlugin,
|
|
99
|
+
} from '@napi-rs/wasm-runtime'`
|
|
76
100
|
const errorOutputsAppend = errorEvent
|
|
77
101
|
? `\n errorOutputs.push([...arguments])`
|
|
78
102
|
: ''
|
|
@@ -118,6 +142,11 @@ const handler = new MessageHandler({
|
|
|
118
142
|
return instantiateNapiModuleSync(wasmModule, {
|
|
119
143
|
childThread: true,
|
|
120
144
|
wasi,
|
|
145
|
+
// The wasm links a "basic" emnapi archive (no C async-work /
|
|
146
|
+
// threadsafe-function implementations), so every thread that
|
|
147
|
+
// instantiates it must provide the JavaScript implementations
|
|
148
|
+
// through the emnapi plugins.
|
|
149
|
+
plugins: [emnapiAsyncWorkPlugin, emnapiTSFNPlugin],
|
|
121
150
|
overwriteImports(importObject) {
|
|
122
151
|
importObject.env = {
|
|
123
152
|
...importObject.env,
|
package/src/commands/rename.ts
CHANGED
|
@@ -6,14 +6,19 @@ import { BaseRenameCommand } from '../def/rename.js'
|
|
|
6
6
|
export class RenameCommand extends BaseRenameCommand {
|
|
7
7
|
async execute() {
|
|
8
8
|
const options = this.getOptions()
|
|
9
|
-
|
|
9
|
+
const hasExplicitRename = [
|
|
10
|
+
options.name,
|
|
11
|
+
options.binaryName,
|
|
12
|
+
options.packageName,
|
|
13
|
+
options.repository,
|
|
14
|
+
options.description,
|
|
15
|
+
].some((value) => value !== undefined)
|
|
16
|
+
if (!hasExplicitRename) {
|
|
10
17
|
const name = await input({
|
|
11
18
|
message: `Enter the new package name in the package.json`,
|
|
12
19
|
required: true,
|
|
13
20
|
})
|
|
14
21
|
options.name = name
|
|
15
|
-
}
|
|
16
|
-
if (!options.binaryName) {
|
|
17
22
|
const binaryName = await input({
|
|
18
23
|
message: `Enter the new binary name`,
|
|
19
24
|
required: true,
|
package/src/def/artifacts.ts
CHANGED
|
@@ -34,7 +34,7 @@ export abstract class BaseArtifactsCommand extends Command {
|
|
|
34
34
|
|
|
35
35
|
buildOutputDir?: string = Option.String('--build-output-dir', {
|
|
36
36
|
description:
|
|
37
|
-
'Path to the build output dir, only needed when targets
|
|
37
|
+
'Path to the build output dir, only needed when targets contain a WASI target',
|
|
38
38
|
})
|
|
39
39
|
|
|
40
40
|
getOptions() {
|
|
@@ -82,7 +82,7 @@ export interface ArtifactsOptions {
|
|
|
82
82
|
*/
|
|
83
83
|
npmDir?: string
|
|
84
84
|
/**
|
|
85
|
-
* Path to the build output dir, only needed when targets
|
|
85
|
+
* Path to the build output dir, only needed when targets contain a WASI target
|
|
86
86
|
*/
|
|
87
87
|
buildOutputDir?: string
|
|
88
88
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -167,8 +167,8 @@ Generated by [AVA](https://avajs.dev).
|
|
|
167
167
|
abi: 'wasi',
|
|
168
168
|
arch: 'wasm32',
|
|
169
169
|
platform: 'wasi',
|
|
170
|
-
platformArchABI: 'wasm32-
|
|
171
|
-
triple: 'wasm32-
|
|
170
|
+
platformArchABI: 'wasm32-wasip1',
|
|
171
|
+
triple: 'wasm32-wasip1',
|
|
172
172
|
},
|
|
173
173
|
{
|
|
174
174
|
abi: 'wasi',
|
|
Binary file
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { unlink, writeFile } from 'node:fs/promises'
|
|
2
2
|
import { tmpdir } from 'node:os'
|
|
3
|
-
import { join } from 'node:path'
|
|
3
|
+
import { dirname, join } from 'node:path'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
4
5
|
|
|
5
6
|
import test from 'ava'
|
|
6
7
|
|
|
7
|
-
import { parseMetadata } from '../metadata.js'
|
|
8
|
+
import { getNapiDeriveDependentCrates, parseMetadata } from '../metadata.js'
|
|
9
|
+
|
|
10
|
+
const FIXTURE_WORKSPACE = join(
|
|
11
|
+
dirname(fileURLToPath(import.meta.url)),
|
|
12
|
+
'__fixtures__',
|
|
13
|
+
'optional-napi-derive',
|
|
14
|
+
)
|
|
8
15
|
|
|
9
16
|
test('should surface child process startup errors', async (t) => {
|
|
10
17
|
const manifestPath = join(
|
|
@@ -26,3 +33,37 @@ test('should surface child process startup errors', async (t) => {
|
|
|
26
33
|
await unlink(manifestPath)
|
|
27
34
|
}
|
|
28
35
|
})
|
|
36
|
+
|
|
37
|
+
test('should exclude crates whose optional napi-derive dependency is disabled', async (t) => {
|
|
38
|
+
const metadata = await parseMetadata(
|
|
39
|
+
join(FIXTURE_WORKSPACE, 'main-crate', 'Cargo.toml'),
|
|
40
|
+
)
|
|
41
|
+
const dependentCrates = getNapiDeriveDependentCrates(metadata).map(
|
|
42
|
+
(crate) => crate.name,
|
|
43
|
+
)
|
|
44
|
+
t.deepEqual(dependentCrates, ['main-crate'])
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
test('should include crates whose optional napi-derive dependency is enabled via build features', async (t) => {
|
|
48
|
+
const metadata = await parseMetadata(
|
|
49
|
+
join(FIXTURE_WORKSPACE, 'with-optional-derive', 'Cargo.toml'),
|
|
50
|
+
{
|
|
51
|
+
features: ['node'],
|
|
52
|
+
},
|
|
53
|
+
)
|
|
54
|
+
const dependentCrates = getNapiDeriveDependentCrates(metadata).map(
|
|
55
|
+
(crate) => crate.name,
|
|
56
|
+
)
|
|
57
|
+
t.true(dependentCrates.includes('with-optional-derive'))
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('should fall back to declared dependencies when the resolve graph is unavailable', async (t) => {
|
|
61
|
+
const metadata = await parseMetadata(
|
|
62
|
+
join(FIXTURE_WORKSPACE, 'main-crate', 'Cargo.toml'),
|
|
63
|
+
)
|
|
64
|
+
metadata.resolve = null
|
|
65
|
+
const dependentCrates = getNapiDeriveDependentCrates(metadata)
|
|
66
|
+
.map((crate) => crate.name)
|
|
67
|
+
.sort()
|
|
68
|
+
t.deepEqual(dependentCrates, ['main-crate', 'with-optional-derive'])
|
|
69
|
+
})
|
|
@@ -1,11 +1,29 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs'
|
|
2
|
-
import {
|
|
1
|
+
import { existsSync, type BigIntStats } from 'node:fs'
|
|
2
|
+
import {
|
|
3
|
+
lstat,
|
|
4
|
+
mkdtemp,
|
|
5
|
+
readdir,
|
|
6
|
+
readFile,
|
|
7
|
+
rename,
|
|
8
|
+
rm,
|
|
9
|
+
writeFile,
|
|
10
|
+
} from 'node:fs/promises'
|
|
3
11
|
import { tmpdir } from 'node:os'
|
|
4
12
|
import { join } from 'node:path'
|
|
5
13
|
|
|
6
14
|
import ava, { type TestFn } from 'ava'
|
|
7
15
|
|
|
8
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
retireFailedSnapshotLeftover,
|
|
18
|
+
snapshotLeftoverIsTransactionOwned,
|
|
19
|
+
statIdentitiesMatch,
|
|
20
|
+
updatePackageJson,
|
|
21
|
+
} from '../misc.js'
|
|
22
|
+
|
|
23
|
+
async function fileIdentityStrings(path: string) {
|
|
24
|
+
const stats = await lstat(path, { bigint: true })
|
|
25
|
+
return { dev: String(stats.dev), ino: String(stats.ino) }
|
|
26
|
+
}
|
|
9
27
|
|
|
10
28
|
const test = ava as TestFn<{
|
|
11
29
|
tmpDir: string
|
|
@@ -54,3 +72,106 @@ test('updatePackageJson merges nested objects instead of overwriting them', asyn
|
|
|
54
72
|
'@napi-rs/fixture-darwin-arm64': '1.0.1',
|
|
55
73
|
})
|
|
56
74
|
})
|
|
75
|
+
|
|
76
|
+
test('statIdentitiesMatch distinguishes inodes that collide as lossy Numbers', (t) => {
|
|
77
|
+
const dev = 1n
|
|
78
|
+
const ino = 2n ** 53n
|
|
79
|
+
const owned = { dev, ino }
|
|
80
|
+
const successor = { dev, ino: ino + 1n }
|
|
81
|
+
|
|
82
|
+
// The defect being guarded against: past Number.MAX_SAFE_INTEGER two
|
|
83
|
+
// distinct 64-bit identifiers collapse onto the same JS double, so a
|
|
84
|
+
// numeric Stats.dev/ino comparison cannot tell these files apart.
|
|
85
|
+
t.is(Number(owned.ino), Number(successor.ino))
|
|
86
|
+
|
|
87
|
+
t.false(statIdentitiesMatch(owned, successor))
|
|
88
|
+
t.false(statIdentitiesMatch({ dev: dev + 1n, ino }, owned))
|
|
89
|
+
t.true(statIdentitiesMatch(owned, { dev, ino }))
|
|
90
|
+
t.false(statIdentitiesMatch(owned, undefined))
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
test('snapshotLeftoverIsTransactionOwned rejects Number-colliding successors', (t) => {
|
|
94
|
+
const identity = { dev: '1', ino: String(2n ** 53n) }
|
|
95
|
+
const ownedStats = {
|
|
96
|
+
isFile: () => true,
|
|
97
|
+
dev: 1n,
|
|
98
|
+
ino: 2n ** 53n,
|
|
99
|
+
} as unknown as BigIntStats
|
|
100
|
+
const successorStats = {
|
|
101
|
+
isFile: () => true,
|
|
102
|
+
dev: 1n,
|
|
103
|
+
ino: 2n ** 53n + 1n,
|
|
104
|
+
} as unknown as BigIntStats
|
|
105
|
+
|
|
106
|
+
t.true(snapshotLeftoverIsTransactionOwned(ownedStats, identity))
|
|
107
|
+
t.false(snapshotLeftoverIsTransactionOwned(successorStats, identity))
|
|
108
|
+
t.false(snapshotLeftoverIsTransactionOwned(undefined, identity))
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
test('retireFailedSnapshotLeftover removes the transaction-owned inode', async (t) => {
|
|
112
|
+
const destination = join(t.context.tmpDir, 'leftover.tmp')
|
|
113
|
+
await writeFile(destination, 'partial snapshot')
|
|
114
|
+
const identity = await fileIdentityStrings(destination)
|
|
115
|
+
|
|
116
|
+
const result = await retireFailedSnapshotLeftover(destination, identity)
|
|
117
|
+
|
|
118
|
+
t.deepEqual(result, { outcome: 'removed' })
|
|
119
|
+
t.false(existsSync(destination))
|
|
120
|
+
t.deepEqual(await readdir(t.context.tmpDir), [])
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
test('retireFailedSnapshotLeftover reports a missing leftover', async (t) => {
|
|
124
|
+
const destination = join(t.context.tmpDir, 'leftover.tmp')
|
|
125
|
+
await writeFile(destination, 'partial snapshot')
|
|
126
|
+
const identity = await fileIdentityStrings(destination)
|
|
127
|
+
await rm(destination)
|
|
128
|
+
|
|
129
|
+
const result = await retireFailedSnapshotLeftover(destination, identity)
|
|
130
|
+
|
|
131
|
+
t.deepEqual(result, { outcome: 'missing' })
|
|
132
|
+
t.deepEqual(await readdir(t.context.tmpDir), [])
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
test('retireFailedSnapshotLeftover keeps a pre-existing non-owned successor', async (t) => {
|
|
136
|
+
const destination = join(t.context.tmpDir, 'leftover.tmp')
|
|
137
|
+
await writeFile(destination, 'partial snapshot')
|
|
138
|
+
const identity = await fileIdentityStrings(destination)
|
|
139
|
+
|
|
140
|
+
// Replace the owned inode with a distinct one before cleanup runs. The
|
|
141
|
+
// successor is created as a sibling first so it deterministically has a
|
|
142
|
+
// different inode, then atomically renamed over the destination.
|
|
143
|
+
const successor = join(t.context.tmpDir, 'successor.tmp')
|
|
144
|
+
await writeFile(successor, 'successor content')
|
|
145
|
+
await rename(successor, destination)
|
|
146
|
+
|
|
147
|
+
const result = await retireFailedSnapshotLeftover(destination, identity)
|
|
148
|
+
|
|
149
|
+
t.deepEqual(result, { outcome: 'kept' })
|
|
150
|
+
t.is(await readFile(destination, 'utf8'), 'successor content')
|
|
151
|
+
t.deepEqual(await readdir(t.context.tmpDir), ['leftover.tmp'])
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
test('retireFailedSnapshotLeftover restores a successor swapped in during the race window', async (t) => {
|
|
155
|
+
const destination = join(t.context.tmpDir, 'leftover.tmp')
|
|
156
|
+
await writeFile(destination, 'partial snapshot')
|
|
157
|
+
const identity = await fileIdentityStrings(destination)
|
|
158
|
+
|
|
159
|
+
const successor = join(t.context.tmpDir, 'successor.tmp')
|
|
160
|
+
await writeFile(successor, 'successor content')
|
|
161
|
+
|
|
162
|
+
// Swap the successor onto the pathname after the ownership pre-check and
|
|
163
|
+
// before the retirement rename — the exact interval in which the previous
|
|
164
|
+
// lstat-then-unlink cleanup would have deleted a file the transaction never
|
|
165
|
+
// owned.
|
|
166
|
+
const result = await retireFailedSnapshotLeftover(
|
|
167
|
+
destination,
|
|
168
|
+
identity,
|
|
169
|
+
async () => {
|
|
170
|
+
await rename(successor, destination)
|
|
171
|
+
},
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
t.deepEqual(result, { outcome: 'kept' })
|
|
175
|
+
t.is(await readFile(destination, 'utf8'), 'successor content')
|
|
176
|
+
t.deepEqual(await readdir(t.context.tmpDir), ['leftover.tmp'])
|
|
177
|
+
})
|
|
@@ -1,7 +1,53 @@
|
|
|
1
1
|
import test from 'ava'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
MINIMUM_WASI_NODE_VERSION,
|
|
5
|
+
napiEngineRequirement,
|
|
6
|
+
restrictWasiNodeEngine,
|
|
7
|
+
SUPPORTED_NAPI_VERSIONS,
|
|
8
|
+
} from '../version.js'
|
|
4
9
|
|
|
5
10
|
test('should generate correct napi engine requirement', (t) => {
|
|
6
11
|
t.snapshot(SUPPORTED_NAPI_VERSIONS.map(napiEngineRequirement))
|
|
7
12
|
})
|
|
13
|
+
|
|
14
|
+
test('should keep node engine ranges inside the WASI floor', (t) => {
|
|
15
|
+
t.is(restrictWasiNodeEngine('^22.14.0'), '^22.14.0')
|
|
16
|
+
t.is(restrictWasiNodeEngine('>=24'), '>=24')
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
test('should return the WASI floor for superset node engine ranges', (t) => {
|
|
20
|
+
t.is(restrictWasiNodeEngine('>=18'), MINIMUM_WASI_NODE_VERSION)
|
|
21
|
+
t.is(restrictWasiNodeEngine('>=12 <14 || >=18'), MINIMUM_WASI_NODE_VERSION)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
test('should preserve partial intersections with the WASI floor', (t) => {
|
|
25
|
+
t.is(restrictWasiNodeEngine('>=22'), '>=22.13.0 <23.0.0-0 || >=23.5.0')
|
|
26
|
+
t.is(restrictWasiNodeEngine('<21'), '>=20.19.0 <21.0.0-0')
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('should reject node engine ranges disjoint from the WASI floor', (t) => {
|
|
30
|
+
for (const nodeRange of ['>=21 <22', '<20', '13.0.0', '21.0.0']) {
|
|
31
|
+
const error = t.throws(() => restrictWasiNodeEngine(nodeRange))
|
|
32
|
+
t.true(
|
|
33
|
+
error.message.includes(`"${nodeRange}"`),
|
|
34
|
+
`error should name the rejected range ${nodeRange}`,
|
|
35
|
+
)
|
|
36
|
+
t.true(
|
|
37
|
+
error.message.includes(`"${MINIMUM_WASI_NODE_VERSION}"`),
|
|
38
|
+
'error should name the supported WASI versions',
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
test('should fall back to the WASI floor for malformed node engine ranges', (t) => {
|
|
44
|
+
t.is(restrictWasiNodeEngine('not-a-range'), MINIMUM_WASI_NODE_VERSION)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
test('napi engine requirements always intersect the WASI floor', (t) => {
|
|
48
|
+
for (const napiVersion of SUPPORTED_NAPI_VERSIONS) {
|
|
49
|
+
t.notThrows(() =>
|
|
50
|
+
restrictWasiNodeEngine(napiEngineRequirement(napiVersion)),
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
})
|
package/src/utils/config.ts
CHANGED
|
@@ -64,7 +64,7 @@ export interface UserNapiConfig {
|
|
|
64
64
|
wasm?: {
|
|
65
65
|
/**
|
|
66
66
|
* https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/Memory
|
|
67
|
-
* @default 4000 pages (
|
|
67
|
+
* @default 4000 pages (250 MiB), or 1024 pages (64 MiB) for the deferred workerd loader
|
|
68
68
|
*/
|
|
69
69
|
initialMemory?: number
|
|
70
70
|
/**
|
|
@@ -151,6 +151,7 @@ export interface CommonPackageJsonFields {
|
|
|
151
151
|
|
|
152
152
|
dependencies?: Record<string, string>
|
|
153
153
|
devDependencies?: Record<string, string>
|
|
154
|
+
optionalDependencies?: Record<string, string>
|
|
154
155
|
|
|
155
156
|
ava?: {
|
|
156
157
|
timeout?: string
|
|
@@ -265,7 +266,19 @@ export async function readNapiConfig(
|
|
|
265
266
|
throw new Error(`Duplicate targets are not allowed: ${duplicateTarget}`)
|
|
266
267
|
}
|
|
267
268
|
|
|
268
|
-
|
|
269
|
+
const parsedTargets = targets.map(parseTriple)
|
|
270
|
+
const outputTargets = new Map<string, string>()
|
|
271
|
+
for (const [index, target] of parsedTargets.entries()) {
|
|
272
|
+
const previous = outputTargets.get(target.platformArchABI)
|
|
273
|
+
if (previous) {
|
|
274
|
+
throw new Error(
|
|
275
|
+
`Targets ${previous} and ${targets[index]} produce the same ${target.platformArchABI} artifact set. Choose one target spelling.`,
|
|
276
|
+
)
|
|
277
|
+
}
|
|
278
|
+
outputTargets.set(target.platformArchABI, targets[index])
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
napiConfig.targets = parsedTargets
|
|
269
282
|
|
|
270
283
|
return napiConfig
|
|
271
284
|
}
|