diff --git a/cli/codegen/commands.ts b/cli/codegen/commands.ts index 58d35d8a..a2bc8b27 100644 --- a/cli/codegen/commands.ts +++ b/cli/codegen/commands.ts @@ -328,6 +328,12 @@ const ARTIFACTS_OPTIONS: CommandSchema = { description: 'Path to the folder where the npm packages put', default: "'npm'", }, + { + name: 'buildOutputDir', + type: 'string', + description: + 'Path to the build output dir, only needed when targets contains `wasm32-wasi-*`', + }, ], } diff --git a/cli/codegen/index.ts b/cli/codegen/index.ts index 4e8102f0..f3d5b69d 100644 --- a/cli/codegen/index.ts +++ b/cli/codegen/index.ts @@ -1,7 +1,7 @@ -import { execSync } from 'child_process' -import fs from 'fs' -import path from 'path' -import { fileURLToPath } from 'url' +import { execSync } from 'node:child_process' +import fs from 'node:fs' +import path from 'node:path' +import { fileURLToPath } from 'node:url' import { kebabCase, startCase } from 'lodash-es' diff --git a/cli/docs/artifacts.md b/cli/docs/artifacts.md index 66d7f96a..491e8246 100644 --- a/cli/docs/artifacts.md +++ b/cli/docs/artifacts.md @@ -30,3 +30,4 @@ new NapiCli().artifacts({ | packageJsonPath | --package-json-path | string | false | 'package.json' | Path to `package.json` | | outputDir | --output-dir,-o,-d | string | false | './artifacts' | Path to the folder where all built `.node` files put, same as `--output-dir` of build command | | npmDir | --npm-dir | string | false | 'npm' | Path to the folder where the npm packages put | +| buildOutputDir | --build-output-dir | string | false | | Path to the build output dir, only needed when targets contains `wasm32-wasi-*` | diff --git a/cli/src/api/artifacts.ts b/cli/src/api/artifacts.ts index a0378947..ddfe356a 100644 --- a/cli/src/api/artifacts.ts +++ b/cli/src/api/artifacts.ts @@ -1,4 +1,4 @@ -import { join, parse, resolve } from 'node:path' +import { join, parse } from 'node:path' import * as colors from 'colorette' @@ -20,11 +20,11 @@ const debug = debugFactory('artifacts') export async function collectArtifacts(userOptions: ArtifactsOptions) { const options = applyDefaultArtifactsOptions(userOptions) - const packageJsonPath = resolve(options.cwd, options.packageJsonPath) + const packageJsonPath = join(options.cwd, options.packageJsonPath) const { targets, binaryName } = await readNapiConfig(packageJsonPath) const distDirs = targets.map((platform) => - resolve(options.cwd, options.npmDir, platform.platformArchABI), + join(options.cwd, options.npmDir, platform.platformArchABI), ) const universalSourceBins = new Set( @@ -36,7 +36,7 @@ export async function collectArtifacts(userOptions: ArtifactsOptions) { .filter(Boolean) as string[], ) - await collectNodeBinaries(resolve(options.cwd, options.outputDir)).then( + await collectNodeBinaries(join(options.cwd, options.outputDir)).then( (output) => Promise.all( output.map(async (filePath) => { @@ -80,6 +80,41 @@ export async function collectArtifacts(userOptions: ArtifactsOptions) { }), ), ) + + const wasiTarget = targets.find((t) => t.platform === 'wasi') + if (wasiTarget) { + const wasiDir = join( + options.cwd, + options.npmDir, + wasiTarget.platformArchABI, + ) + const cjsFile = join( + options.buildOutputDir ?? options.cwd, + `${binaryName}.wasi.cjs`, + ) + const workerFile = join( + options.buildOutputDir ?? options.cwd, + `wasi-worker.mjs`, + ) + debug.info( + `Move wasi cjs file [${colors.yellowBright( + cjsFile, + )}] to [${colors.yellowBright(wasiDir)}]`, + ) + await writeFileAsync( + join(wasiDir, `${binaryName}.wasi.cjs`), + await readFileAsync(cjsFile), + ) + debug.info( + `Move wasi worker file [${colors.yellowBright( + workerFile, + )}] to [${colors.yellowBright(wasiDir)}]`, + ) + await writeFileAsync( + join(wasiDir, `wasi-worker.mjs`), + await readFileAsync(workerFile), + ) + } } async function collectNodeBinaries(root: string) { diff --git a/cli/src/api/create-npm-dirs.ts b/cli/src/api/create-npm-dirs.ts index d535ea78..9cfa6706 100644 --- a/cli/src/api/create-npm-dirs.ts +++ b/cli/src/api/create-npm-dirs.ts @@ -13,6 +13,8 @@ import { Target, } from '../utils/index.js' +import type { PackageMeta } from './templates/package.json.js' + const debug = debugFactory('create-npm-dirs') export async function createNpmDirs(userOptions: CreateNpmDirsOptions) { @@ -82,6 +84,21 @@ export async function createNpmDirs(userOptions: CreateNpmDirsOptions) { if (target.arch !== 'wasm32') { // @ts-expect-error scopedPackageJson.os = [target.platform] + } else { + const entry = `${binaryName}.wasi.cjs` + scopedPackageJson.files.push(entry, `wasi-worker.mjs`) + scopedPackageJson.main = entry + const emnapiCore = await fetch( + `https://registry.npmjs.org/@emnapi/core`, + ).then((res) => res.json() as Promise) + const emnapiRuntime = await fetch( + `https://registry.npmjs.org/@emnapi/runtime`, + ).then((res) => res.json() as Promise) + // @ts-expect-error + scopedPackageJson.dependencies = { + '@emnapi/core': `^${emnapiCore['dist-tags'].latest}`, + '@emnapi/runtime': `^${emnapiRuntime['dist-tags'].latest}`, + } } if (target.abi === 'gnu') { diff --git a/cli/src/api/templates/package.json.ts b/cli/src/api/templates/package.json.ts index c67af55d..50f0570b 100644 --- a/cli/src/api/templates/package.json.ts +++ b/cli/src/api/templates/package.json.ts @@ -4,7 +4,7 @@ import type { } from '../../utils/config.js' import { UNIVERSAL_TARGETS } from '../../utils/target.js' -interface PackageMeta { +export interface PackageMeta { 'dist-tags': { [index: string]: string } } diff --git a/cli/src/def/artifacts.ts b/cli/src/def/artifacts.ts index 49bd17b0..80d0daa7 100644 --- a/cli/src/def/artifacts.ts +++ b/cli/src/def/artifacts.ts @@ -32,6 +32,11 @@ export abstract class BaseArtifactsCommand extends Command { description: 'Path to the folder where the npm packages put', }) + buildOutputDir?: string = Option.String('--build-output-dir', { + description: + 'Path to the build output dir, only needed when targets contains `wasm32-wasi-*`', + }) + getOptions() { return { cwd: this.cwd, @@ -39,6 +44,7 @@ export abstract class BaseArtifactsCommand extends Command { packageJsonPath: this.packageJsonPath, outputDir: this.outputDir, npmDir: this.npmDir, + buildOutputDir: this.buildOutputDir, } } } @@ -75,6 +81,10 @@ export interface ArtifactsOptions { * @default 'npm' */ npmDir?: string + /** + * Path to the build output dir, only needed when targets contains `wasm32-wasi-*` + */ + buildOutputDir?: string } export function applyDefaultArtifactsOptions(options: ArtifactsOptions) {