Skip to content

Commit

Permalink
feat(cli): support wasi target test & release workflow (#1867)
Browse files Browse the repository at this point in the history
  • Loading branch information
Brooooooklyn committed Dec 26, 2023
1 parent bac8ea0 commit c42f00f
Show file tree
Hide file tree
Showing 26 changed files with 346 additions and 179 deletions.
22 changes: 14 additions & 8 deletions cli/codegen/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const NEW_OPTIONS: CommandSchema = {
name: 'path',
type: 'string',
description: 'The path where the NAPI-RS project will be created.',
required: true,
required: false,
},
],
options: [
Expand All @@ -53,13 +53,12 @@ const NEW_OPTIONS: CommandSchema = {
short: ['v'],
long: 'min-node-api',
},
// will support it later
// {
// name: 'packageManager',
// type: 'string',
// description: 'The package manager to use',
// default: "'yarn'",
// },
{
name: 'packageManager',
type: 'string',
description: 'The package manager to use. Only support yarn 4.x for now.',
default: "'yarn'",
},
{
name: 'license',
type: 'string',
Expand Down Expand Up @@ -99,6 +98,13 @@ const NEW_OPTIONS: CommandSchema = {
description: 'Whether generate preconfigured GitHub Actions workflow',
default: true,
},
{
name: 'testFramework',
type: 'string',
description:
'The JavaScript test framework to use, only support `ava` for now',
default: "'ava'",
},
{
name: 'dryRun',
type: 'boolean',
Expand Down
4 changes: 3 additions & 1 deletion cli/docs/new.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ new NapiCli().new({
| Options | CLI Options | type | required | default | description |
| -------------------- | ------------------------ | -------- | -------- | ------- | -------------------------------------------------------------------------------- |
| | --help,-h | | | | get help |
| path | <path> | true | string | | The path where the NAPI-RS project will be created. |
| path | <path> | false | string | | The path where the NAPI-RS project will be created. |
| name | --name,-n | string | false | | The name of the project, default to the name of the directory if not provided |
| minNodeApiVersion | --min-node-api,-v | number | false | 4 | The minimum Node-API version to support |
| packageManager | --package-manager | string | false | 'yarn' | The package manager to use. Only support yarn 4.x for now. |
| license | --license,-l | string | false | 'MIT' | License for open-sourced project |
| targets | --targets,-t | string[] | false | [] | All targets the crate will be compiled for. |
| enableDefaultTargets | --enable-default-targets | boolean | false | true | Whether enable default targets |
| enableAllTargets | --enable-all-targets | boolean | false | false | Whether enable all targets |
| enableTypeDef | --enable-type-def | boolean | false | true | Whether enable the `type-def` feature for typescript definitions auto-generation |
| enableGithubActions | --enable-github-actions | boolean | false | true | Whether generate preconfigured GitHub Actions workflow |
| testFramework | --test-framework | string | false | 'ava' | The JavaScript test framework to use, only support `ava` for now |
| dryRun | --dry-run | boolean | false | false | Whether to run the command in dry-run mode |
6 changes: 3 additions & 3 deletions cli/src/api/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ import {
writeFileAsync,
} from '../utils/index.js'

import { createWasiBinding } from './load-wasi-template.js'
import { createCjsBinding } from './templates/index.js'
import { WASI_WORKER_TEMPLATE } from './wasi-worker-template.js'
import { createWasiBinding } from './templates/load-wasi-template.js'
import { WASI_WORKER_TEMPLATE } from './templates/wasi-worker-template.js'

const debug = debugFactory('build')
const require = createRequire(import.meta.url)
Expand Down Expand Up @@ -704,7 +704,7 @@ class Builder {
destName += `.${this.target.platformArchABI}`
}
if (srcName.endsWith('.wasm')) {
destName += '.wasi-wasm32.wasm'
destName += '.wasm'
} else {
destName += '.node'
}
Expand Down
14 changes: 9 additions & 5 deletions cli/src/api/create-npm-dirs.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { join, resolve } from 'path'
import { join, resolve } from 'node:path'

import {
applyDefaultCreateNpmDirsOptions,
Expand Down Expand Up @@ -55,11 +55,13 @@ export async function createNpmDirs(userOptions: CreateNpmDirsOptions) {
const targetDir = join(npmPath, `${target.platformArchABI}`)
await mkdirAsync(targetDir)

const binaryFileName = `${binaryName}.${target.platformArchABI}.node`
const binaryFileName =
target.arch === 'wasm32'
? `${binaryName}.${target.platformArchABI}.wasm`
: `${binaryName}.${target.platformArchABI}.node`
const scopedPackageJson = {
name: `${packageName}-${target.platformArchABI}`,
version: packageJson.version,
os: [target.platform],
cpu: target.arch !== 'universal' ? [target.arch] : undefined,
main: binaryFileName,
files: [binaryFileName],
Expand All @@ -77,9 +79,11 @@ export async function createNpmDirs(userOptions: CreateNpmDirsOptions) {
'bugs',
),
}
if (target.arch !== 'wasm32') {
// @ts-expect-error
scopedPackageJson.os = [target.platform]
}

// Only works with yarn 3.1+
// https://github.com/yarnpkg/berry/pull/3981
if (target.abi === 'gnu') {
// @ts-expect-error
scopedPackageJson.libc = ['glibc']
Expand Down
55 changes: 34 additions & 21 deletions cli/src/api/new.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import path from 'path'
import path from 'node:path'

import {
applyDefaultNewOptions,
Expand All @@ -12,7 +12,9 @@ import {
mkdirAsync,
readdirAsync,
statAsync,
type SupportedTestFramework,
writeFileAsync,
SupportedPackageManager,
} from '../utils/index.js'
import { napiEngineRequirement } from '../utils/version.js'

Expand All @@ -37,6 +39,9 @@ type NewOptions = Required<RawNewOptions>

function processOptions(options: RawNewOptions) {
debug('Processing options...')
if (!options.path) {
throw new Error('Please provide the path as the argument')
}
options.path = path.resolve(process.cwd(), options.path)
debug(`Resolved target path to: ${options.path}`)

Expand Down Expand Up @@ -69,7 +74,7 @@ export async function newProject(userOptions: RawNewOptions) {
debug('Targets to be enabled:')
debug(options.targets)

const outputs = generateFiles(options)
const outputs = await generateFiles(options)

await ensurePath(options.path, options.dryRun)

Expand Down Expand Up @@ -110,30 +115,34 @@ async function ensurePath(path: string, dryRun = false) {
}
}

function generateFiles(options: NewOptions): Output[] {
async function generateFiles(options: NewOptions): Promise<Output[]> {
const packageJson = await generatePackageJson(options)
return [
generateCargoToml,
generateLibRs,
generateBuildRs,
generatePackageJson,
generateGithubWorkflow,
generateIgnoreFiles,
].flatMap((generator) => {
const output = generator(options)
]
.flatMap((generator) => {
const output = generator(options)

if (!output) {
return []
}
if (!output) {
return []
}

if (Array.isArray(output)) {
return output.map((o) => ({
...o,
target: path.join(options.path, o.target),
}))
} else {
return [{ ...output, target: path.join(options.path, output.target) }]
}
})
if (Array.isArray(output)) {
return output.map((o) => ({
...o,
target: path.join(options.path, o.target),
}))
} else {
return [{ ...output, target: path.join(options.path, output.target) }]
}
})
.concat([
{ ...packageJson, target: path.join(options.path, packageJson.target) },
])
}

function generateCargoToml(options: NewOptions): Output {
Expand Down Expand Up @@ -162,16 +171,17 @@ function generateBuildRs(_options: NewOptions): Output {
}
}

function generatePackageJson(options: NewOptions): Output {
async function generatePackageJson(options: NewOptions): Promise<Output> {
return {
target: './package.json',
content: createPackageJson({
content: await createPackageJson({
name: options.name,
binaryName: getBinaryName(options.name),
targets: options.targets,
license: options.license,
engineRequirement: napiEngineRequirement(options.minNodeApiVersion),
cliVersion: CLI_VERSION,
testFramework: options.testFramework as SupportedTestFramework,
}),
}
}
Expand All @@ -183,7 +193,10 @@ function generateGithubWorkflow(options: NewOptions): Output | null {

return {
target: './.github/workflows/ci.yml',
content: createGithubActionsCIYml(options.targets),
content: createGithubActionsCIYml(
options.targets,
options.packageManager as SupportedPackageManager,
),
}
}

Expand Down
10 changes: 6 additions & 4 deletions cli/src/api/pre-publish.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { execSync } from 'child_process'
import { existsSync, statSync } from 'fs'
import { join, resolve } from 'path'
import { execSync } from 'node:child_process'
import { existsSync, statSync } from 'node:fs'
import { join, resolve } from 'node:path'

import { Octokit } from '@octokit/rest'

Expand Down Expand Up @@ -153,7 +153,9 @@ export async function prePublish(userOptions: PrePublishOptions) {
options.npmDir,
`${target.platformArchABI}`,
)
const filename = `${binaryName}.${target.platformArchABI}.node`
const ext =
target.platform === 'wasi' || target.platform === 'wasm' ? 'wasm' : 'node'
const filename = `${binaryName}.${target.platformArchABI}.${ext}`
const dstPath = join(pkgDir, filename)

if (!options.dryRun) {
Expand Down
2 changes: 1 addition & 1 deletion cli/src/api/rename.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { resolve } from 'path'
import { resolve } from 'node:path'

import { isNil, merge, omitBy, pick } from 'lodash-es'

Expand Down
Loading

0 comments on commit c42f00f

Please sign in to comment.