Skip to content
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Node.js Test

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:
build:
runs-on: ubuntu-latest
environment: CI
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
registry-url: https://registry.npmjs.org/
- run: npm ci
- run: npm install
- run: npm test
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/node_modules/
/.parcel-cache/
*.DS_Store
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
save-exact = true
83 changes: 83 additions & 0 deletions buildHelper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import fs from 'node:fs/promises'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
import packageJson from './package.json' with { type: 'json' }
import { fork, spawn } from 'node:child_process'

type Opts = { type: string, tscArgs: string[], renameFileArgs: string[] }

const optionsMap: Record<string, Opts> = {
esm: {
type: 'module',
tscArgs: ['--project', 'tsconfig.json', '--declaration'],
renameFileArgs: ['esm']
},
cjs: {
type: 'commonjs',
tscArgs: ['--project', 'tsconfig.cjs.json', '--declaration'],
renameFileArgs: ['cjs']
}
}

const __dirname = dirname(fileURLToPath(import.meta.url))

const withTempTypeWrapper = async (newType: string, run: () => Promise<void> | void) => {
const suffix = crypto.randomUUID()
const tempFilePath = join(__dirname, `~$package.json.${suffix}`)
const packageJsonPath = join(__dirname, 'package.json')
await fs.copyFile(packageJsonPath, tempFilePath)
try {
const newContents = structuredClone(packageJson)
newContents.type = newType
await fs.writeFile(packageJsonPath, JSON.stringify(newContents, undefined, 2))
await run()
} finally {
await fs.copyFile(tempFilePath, packageJsonPath, fs.constants.COPYFILE_FICLONE)
await fs.unlink(tempFilePath)
}
}

const buildInternal = async (opts: Opts) => {
await new Promise<void>((resolve, reject) => {
const tsc = spawn('tsc', opts.tscArgs, {
env: {
...process.env,
PATH: [join(__dirname, 'node_modules', '.bin'), process.env.PATH].filter(Boolean).join(':')
},
stdio: 'inherit'
})
tsc.on('close', (code) => {
if (code !== 0) {
reject(new Error(`[tsc] code ${code}`))
} else {
resolve()
}
})
})
await new Promise<void>((resolve, reject) => {
const rename = fork(new URL('./renameFiles.mjs', import.meta.url), opts.renameFileArgs, { stdio: 'inherit' })
rename.on('close', (code) => {
if (code !== 0) {
reject(new Error(`[rename] code ${code}`))
} else {
resolve()
}
})
})
}

const build = async (opts: Opts) => {
if (packageJson.type !== opts.type) {
return withTempTypeWrapper(opts.type, () => buildInternal(opts))
} else {
return buildInternal(opts)
}
}

if (process.argv[2] === 'esm') {
await build(optionsMap.esm)
} else if (process.argv[2] === 'cjs') {
await build(optionsMap.cjs)
} else {
console.error('Invalid build type')
}
Loading