@napi-rs/cli 3.7.4 → 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.
Files changed (43) hide show
  1. package/README.md +33 -0
  2. package/cli.mjs +9 -12
  3. package/dist/cli.js +9248 -1311
  4. package/dist/index.cjs +9268 -1331
  5. package/dist/index.d.cts +175 -157
  6. package/dist/index.d.ts +175 -157
  7. package/dist/index.js +9248 -1311
  8. package/docs/artifacts.md +33 -0
  9. package/docs/build.md +58 -0
  10. package/docs/create-npm-dirs.md +32 -0
  11. package/docs/new.md +39 -0
  12. package/docs/pre-publish.md +37 -0
  13. package/docs/rename.md +37 -0
  14. package/docs/universalize.md +31 -0
  15. package/docs/version.md +31 -0
  16. package/docs/wasi.md +161 -0
  17. package/package.json +11 -10
  18. package/src/api/__tests__/__snapshots__/templates.spec.ts.md +1019 -114
  19. package/src/api/__tests__/__snapshots__/templates.spec.ts.snap +0 -0
  20. package/src/api/__tests__/artifacts.spec.ts +17 -0
  21. package/src/api/__tests__/create-npm-dirs.spec.ts +14 -15
  22. package/src/api/__tests__/new.spec.ts +41 -5
  23. package/src/api/artifacts.ts +934 -108
  24. package/src/api/build.ts +1317 -188
  25. package/src/api/create-npm-dirs.ts +472 -101
  26. package/src/api/new.ts +354 -35
  27. package/src/api/pre-publish.ts +2845 -99
  28. package/src/api/rename.ts +1638 -124
  29. package/src/api/templates/js-binding.ts +216 -38
  30. package/src/api/templates/load-wasi-template.ts +1641 -111
  31. package/src/api/templates/wasi-worker-template.ts +32 -3
  32. package/src/commands/rename.ts +8 -3
  33. package/src/def/artifacts.ts +2 -2
  34. package/src/utils/__tests__/__snapshots__/target.spec.ts.md +2 -2
  35. package/src/utils/__tests__/__snapshots__/target.spec.ts.snap +0 -0
  36. package/src/utils/__tests__/misc.spec.ts +124 -3
  37. package/src/utils/__tests__/version.spec.ts +47 -1
  38. package/src/utils/config.ts +15 -2
  39. package/src/utils/metadata.ts +155 -47
  40. package/src/utils/misc.ts +6079 -0
  41. package/src/utils/target.ts +66 -8
  42. package/src/utils/typegen.ts +1223 -63
  43. package/src/utils/version.ts +96 -0
@@ -53,7 +53,15 @@ test('resolves a relative WASI build output directory from cwd', async (t) => {
53
53
  const browserEntry =
54
54
  "const worker = new URL('./wasi-worker-browser.mjs', import.meta.url)\n"
55
55
  await Promise.all([
56
+ writeFile(
57
+ join(tmpDir, 'artifacts', `${binaryName}.wasm32-wasi.wasm`),
58
+ 'wasm artifact',
59
+ ),
56
60
  writeFile(join(buildOutputDir, `${binaryName}.wasi.cjs`), 'node binding'),
61
+ writeFile(
62
+ join(buildOutputDir, `${binaryName}.wasi.d.cts`),
63
+ 'node binding types',
64
+ ),
57
65
  writeFile(join(buildOutputDir, 'wasi-worker.mjs'), 'node worker'),
58
66
  writeFile(
59
67
  join(buildOutputDir, `${binaryName}.wasi-browser.js`),
@@ -63,6 +71,8 @@ test('resolves a relative WASI build output directory from cwd', async (t) => {
63
71
  join(buildOutputDir, 'wasi-worker-browser.mjs'),
64
72
  'browser worker',
65
73
  ),
74
+ writeFile(join(buildOutputDir, 'browser.js'), 'root browser'),
75
+ writeFile(join(buildOutputDir, 'index.js'), 'root index'),
66
76
  ])
67
77
 
68
78
  await collectArtifacts({
@@ -70,6 +80,13 @@ test('resolves a relative WASI build output directory from cwd', async (t) => {
70
80
  buildOutputDir: 'build-output',
71
81
  })
72
82
 
83
+ t.is(
84
+ await readFile(
85
+ join(wasiPackageDir, `${binaryName}.wasm32-wasi.wasm`),
86
+ 'utf8',
87
+ ),
88
+ 'wasm artifact',
89
+ )
73
90
  t.is(
74
91
  await readFile(join(wasiPackageDir, `${binaryName}.wasi.cjs`), 'utf8'),
75
92
  'node binding',
@@ -8,6 +8,7 @@ import { join } from 'node:path'
8
8
  import ava, { type TestFn } from 'ava'
9
9
 
10
10
  import { createNpmDirs } from '../create-npm-dirs.js'
11
+ import { MINIMUM_WASI_NODE_VERSION } from '../../utils/index.js'
11
12
 
12
13
  const require = createRequire(import.meta.url)
13
14
 
@@ -281,7 +282,7 @@ test('should preserve stricter node engine ranges for WASM targets', async (t) =
281
282
  name: 'test-wasm-engines',
282
283
  version: '1.0.0',
283
284
  engines: {
284
- node: '>=18',
285
+ node: '>=24',
285
286
  },
286
287
  napi: {
287
288
  binaryName: 'test-wasm-engines',
@@ -300,7 +301,7 @@ test('should preserve stricter node engine ranges for WASM targets', async (t) =
300
301
  await readFile(join(tmpDir, 'npm', 'wasm32-wasi', 'package.json'), 'utf-8'),
301
302
  )
302
303
 
303
- t.is(scopedPackageJson.engines.node, '>=18')
304
+ t.is(scopedPackageJson.engines.node, '>=24')
304
305
  })
305
306
 
306
307
  test('should intersect mixed node engine ranges with the WASI minimum', async (t) => {
@@ -329,7 +330,7 @@ test('should intersect mixed node engine ranges with the WASI minimum', async (t
329
330
  await readFile(join(tmpDir, 'npm', 'wasm32-wasi', 'package.json'), 'utf-8'),
330
331
  )
331
332
 
332
- t.is(scopedPackageJson.engines.node, '>=18.0.0')
333
+ t.is(scopedPackageJson.engines.node, MINIMUM_WASI_NODE_VERSION)
333
334
  })
334
335
 
335
336
  test('should preserve sibling engine constraints when node is missing for WASM targets', async (t) => {
@@ -360,11 +361,11 @@ test('should preserve sibling engine constraints when node is missing for WASM t
360
361
 
361
362
  t.deepEqual(scopedPackageJson.engines, {
362
363
  npm: '>=10',
363
- node: '>=14.0.0',
364
+ node: MINIMUM_WASI_NODE_VERSION,
364
365
  })
365
366
  })
366
367
 
367
- test('should replace an exact node engine below the WASI minimum for WASM targets', async (t) => {
368
+ test('should reject an exact node engine below the WASI minimum for WASM targets', async (t) => {
368
369
  const { tmpDir, packageJsonPath } = t.context
369
370
 
370
371
  const packageJson = {
@@ -381,16 +382,14 @@ test('should replace an exact node engine below the WASI minimum for WASM target
381
382
 
382
383
  await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2))
383
384
 
384
- await createNpmDirs({
385
- cwd: tmpDir,
386
- packageJsonPath: 'package.json',
387
- })
388
-
389
- const scopedPackageJson = JSON.parse(
390
- await readFile(join(tmpDir, 'npm', 'wasm32-wasi', 'package.json'), 'utf-8'),
385
+ const error = await t.throwsAsync(() =>
386
+ createNpmDirs({
387
+ cwd: tmpDir,
388
+ packageJsonPath: 'package.json',
389
+ }),
391
390
  )
392
-
393
- t.is(scopedPackageJson.engines.node, '>=14.0.0')
391
+ t.true(error.message.includes('"13.0.0"'))
392
+ t.true(error.message.includes(`"${MINIMUM_WASI_NODE_VERSION}"`))
394
393
  })
395
394
 
396
395
  test('should drop exact node engine branches below the WASI minimum for WASM targets', async (t) => {
@@ -419,7 +418,7 @@ test('should drop exact node engine branches below the WASI minimum for WASM tar
419
418
  await readFile(join(tmpDir, 'npm', 'wasm32-wasi', 'package.json'), 'utf-8'),
420
419
  )
421
420
 
422
- t.is(scopedPackageJson.engines.node, '>=18.0.0')
421
+ t.is(scopedPackageJson.engines.node, MINIMUM_WASI_NODE_VERSION)
423
422
  })
424
423
 
425
424
  test('should set @emnapi/core and @emnapi/runtime versions to match emnapi for WASM targets', async (t) => {
@@ -9,7 +9,7 @@ import { parse as parseToml } from '@std/toml'
9
9
  import ava, { type TestFn } from 'ava'
10
10
  import { load as yamlLoad } from 'js-yaml'
11
11
 
12
- import { newProject } from '../new.js'
12
+ import { GENERATED_WASI_BINDING, newProject } from '../new.js'
13
13
 
14
14
  const test = ava as TestFn<{
15
15
  tmpDir: string
@@ -66,10 +66,10 @@ test('create a new project with default options', async (t) => {
66
66
  join(projectPath, '.gitattributes'),
67
67
  'utf-8',
68
68
  )
69
- t.truthy(gitAttributes.includes('default-project.wasi-browser.js'))
70
- t.truthy(gitAttributes.includes('default-project.wasi.cjs'))
71
- t.truthy(gitAttributes.includes('wasi-worker-browser.mjs'))
72
- t.truthy(gitAttributes.includes('wasi-worker.mjs'))
69
+ t.false(gitAttributes.includes('default-project.wasi-browser.js'))
70
+ t.false(gitAttributes.includes('default-project.wasi.cjs'))
71
+ t.false(gitAttributes.includes('wasi-worker-browser.mjs'))
72
+ t.false(gitAttributes.includes('wasi-worker.mjs'))
73
73
  const ciYaml = await readFile(
74
74
  join(projectPath, '.github', 'workflows', 'CI.yml'),
75
75
  'utf-8',
@@ -525,3 +525,39 @@ test('should fail when no targets are enabled', async (t) => {
525
525
  { message: /At least one target must be enabled/ },
526
526
  )
527
527
  })
528
+
529
+ test('generated WASI binding pattern matches every generated artifact name', (t) => {
530
+ // Mirrors the artifact names produced for the threaded (`wasi`) and
531
+ // non-threaded (`wasip1`) loader suffixes, including the `.d.cts` loader
532
+ // typings emitted alongside `.cjs` entries.
533
+ const generated = [
534
+ 'binary.wasi.cjs',
535
+ 'binary.wasi.d.cts',
536
+ 'binary.wasi-browser.js',
537
+ 'wasi-worker.mjs',
538
+ 'wasi-worker-browser.mjs',
539
+ 'binary.wasip1.cjs',
540
+ 'binary.wasip1.d.cts',
541
+ 'binary.wasip1-browser.js',
542
+ 'binary.wasip1-deferred.js',
543
+ 'binary.wasip1-deferred.d.ts',
544
+ ]
545
+ for (const file of generated) {
546
+ t.true(GENERATED_WASI_BINDING.test(file), `should match ${file}`)
547
+ t.true(
548
+ GENERATED_WASI_BINDING.test(`${file} linguist-detectable=false`),
549
+ `should match the .gitattributes line for ${file}`,
550
+ )
551
+ }
552
+
553
+ const notGenerated = [
554
+ 'index.js',
555
+ 'index.d.ts',
556
+ 'browser.js',
557
+ 'binary.wasm32-wasi.wasm.d.mts',
558
+ 'binary.node',
559
+ ]
560
+ for (const file of notGenerated) {
561
+ t.false(GENERATED_WASI_BINDING.test(file), `should not match ${file}`)
562
+ }
563
+ })