Skip to content

Commit

Permalink
chore(tools): add trext and @vercel/ncc to build workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
unicornware committed Oct 11, 2021
1 parent d7901d4 commit 9a7b3bd
Show file tree
Hide file tree
Showing 2 changed files with 835 additions and 55 deletions.
108 changes: 75 additions & 33 deletions tools/cli/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@

import logger from '@flex-development/grease/utils/logger.util'
import LogLevel from '@flex-development/log/enums/log-level.enum'
import convertExtension from 'convert-extension'
import type { PackageJson } from 'read-pkg'
import type { TrextOptions } from '@flex-development/trext'
import { trext } from '@flex-development/trext'
// @ts-expect-error ts(7016)
import ncc from '@vercel/ncc'
import fs from 'fs-extra'
import path from 'path'
import replace from 'replace-in-file'
import sh from 'shelljs'
import type { Argv } from 'yargs'
import yargs from 'yargs'
import { hideBin } from 'yargs/helpers'
import exec from '../helpers/exec'
import fixNodeModulePaths from '../helpers/fix-node-module-paths'
import pkg, { $WORKSPACE } from '../helpers/pkg'
import { $PACKAGE, $WORKSPACE, $WORKSPACE_NO_SCOPE } from '../helpers/pkg'
// @ts-expect-error ts(2307)
import useDualExports from '../helpers/use-dual-exports.mjs'

Expand Down Expand Up @@ -94,15 +99,21 @@ export type BuildOptions = {
/** @property {string[]} BUILD_FORMATS - Module build formats */
const BUILD_FORMATS: BuildOptions['formats'] = ['cjs', 'esm', 'types']

/** @property {string[]} BUNDLE_NAMES - Partial bundle names */
const BUNDLE_NAMES: string[] = [
$WORKSPACE_NO_SCOPE,
`${$WORKSPACE_NO_SCOPE}.min`
]

/** @property {string} COMMAND_PACK - Base pack command */
const COMMAND_PACK: string = 'yarn pack'

/** @property {string} CWD - Current working directory */
const CWD: string = process.cwd()

/** @property {string[]} ENV_CHOICES - Build environment options */
const ENV_CHOICES: BuildOptions['env'][] = ['production', 'test', 'development']

/** @property {PackageJson} PACKAGE - package.json data */
const PACKAGE: PackageJson = pkg()

/** @property {Argv<BuildOptions>} args - CLI arguments parser */
const args = yargs(hideBin(process.argv))
.usage('$0 [options]')
Expand Down Expand Up @@ -180,37 +191,71 @@ async function build(): Promise<void> {
exec(`node ./tools/cli/loadenv.cjs -c ${argv.env}`, argv.dryRun)
logger(argv, `set ${argv.env} environment variables`)

// Build project with ttypescript - https://github.com/cevek/ttypescript
// Build project, convert output extensions, create bundles
for (const format of argv.formats ?? []) {
// Get tsconfig config file and path
// Get tsconfig config file
const tsconfig: string = `tsconfig.prod.${format}.json`

// Remove stale directory
exec(`rimraf ./${format}`, argv.dryRun)
exec(`rimraf ${format}`, argv.dryRun)
logger(argv, `remove stale ${format} directory`)

// Run build command
if (exec(`ttsc -p ${tsconfig}`, argv.dryRun) || argv.dryRun) {
// ! Add ESM-compatible export statement to `exports.default` statements
if (format === 'cjs') useDualExports(`./${format}/**`)
if (format === 'cjs') useDualExports([`./${format}/**`] as never[])
logger(argv, `build ${format}`)
}

// Convert TypeScript output to .cjs or .mjs
// See: https://github.com/peterjwest/convert-extension
if (format !== 'types') {
// Get output extension
const ext = `${format === 'cjs' ? 'c' : 'm'}js`
// Fix node module import paths
fixNodeModulePaths()

// Convert extensions
!argv.dryRun && (await convertExtension(`${format}/`, 'js', ext))
logger(argv, `use .${ext} extensions`)
if (format !== 'types') {
// Get extension transformation options
const topts: TrextOptions<'js', 'cjs' | 'mjs'> = {
babel: { sourceMaps: 'inline' as const },
from: 'js',
pattern: /.js$/,
to: `${format === 'cjs' ? 'c' : 'm'}js`
}
// Convert TypeScript output to .cjs or .mjs
!argv.dryRun && (await trext<'js' | 'cjs' | 'mjs'>(`${format}/`, topts))
logger(argv, `use .${topts.to} extensions`)

// Create bundles
const BUNDLES = BUNDLE_NAMES.map(async name => {
const bundle = `${format}/${name}.${topts.to}`
const filename = 'src/index.ts'
const minify = path.extname(name) === '.min'

if (!argv.dryRun) {
const { code } = await ncc(`${CWD}/${filename}`, {
esm: format === 'esm',
externals: Object.keys($PACKAGE?.peerDependencies ?? {}),
filename,
minify: minify,
production: argv.env === 'production',
quiet: true,
target: format === 'cjs' ? 'es5' : 'es2020'
})

await fs.writeFile(bundle, code, { flag: 'wx+' })
await fs.copyFile(`${format}/index.d.ts`, `${format}/${name}.d.ts`)
await replace.replaceInFile({
files: bundle,
from: ';// CONCATENATED MODULE: ./src/',
to: ';// CONCATENATED MODULE: ../src/'
})
}

return bundle
})

// Complete bundle promises
logger(argv, `bundle ${format}`, await Promise.all(BUNDLES))
}
}

// Fix node module import paths
fixNodeModulePaths()

// Pack project
if (argv.tarball) {
const { dryRun, out: outFile, install, prepack } = argv
Expand All @@ -223,16 +268,15 @@ async function build(): Promise<void> {
]

// Check if package has postinstall and prepack scripts
const postinstall_script =
typeof PACKAGE.scripts?.postinstall === 'string'
const prepack_script = typeof PACKAGE.scripts?.prepack === 'string'
const has_postinstall = typeof $PACKAGE.scripts?.postinstall === 'string'
const has_prepack = typeof $PACKAGE.scripts?.prepack === 'string'

// Check if prepack script should be disabled
const disable_prepack = prepack_script && !prepack
const disable_prepack = has_prepack && !prepack

// Disable postinstall script
postinstall_script && exec('toggle-scripts -postinstall', dryRun)
postinstall_script && logger(argv, 'disable postinstall script')
has_postinstall && exec('toggle-scripts -postinstall', dryRun)
has_postinstall && logger(argv, 'disable postinstall script')

// Disable prepack script
disable_prepack && exec('toggle-scripts -prepack', dryRun)
Expand All @@ -243,18 +287,16 @@ async function build(): Promise<void> {
logger(argv, 'create tarball')

// Renable postinstall script
postinstall_script && exec('toggle-scripts +postinstall', dryRun)
postinstall_script && logger(argv, 'renable postinstall script')
has_postinstall && exec('toggle-scripts +postinstall', dryRun)
has_postinstall && logger(argv, 'renable postinstall script')

// Renable prepack script
disable_prepack && exec('toggle-scripts +prepack', dryRun)
disable_prepack && logger(argv, 'renable prepack script')
}
} catch (error) {
const exception = error as Error

logger(argv, exception.message, [], LogLevel.ERROR)
sh.exit((exception as any).code || 1)
logger(argv, (error as Error).message, [], LogLevel.ERROR)
sh.exit((error as any).code || 1)
}

// Log workflow end
Expand Down
Loading

0 comments on commit 9a7b3bd

Please sign in to comment.