diff --git a/build.config.ts b/build.config.ts index d99a4d3..53d3ba5 100644 --- a/build.config.ts +++ b/build.config.ts @@ -4,14 +4,38 @@ * @see https://github.com/flex-development/mkbuild */ -import { defineBuildConfig, type Config } from '@flex-development/mkbuild' -import { constant, define } from '@flex-development/tutils' +import { unassert } from '@flex-development/estree-util-unassert' +import { + defineBuildConfig, + type Config, + type OutputMetadata +} from '@flex-development/mkbuild' +import pathe from '@flex-development/pathe' +import { + DOT, + constant, + define, + entries, + get, + overwrite +} from '@flex-development/tutils' import { ok } from 'devlop' -import type { BuildResult, PluginBuild } from 'esbuild' +import { fromJs } from 'esast-util-from-js' +import type { BuildResult, Metafile, OutputFile, PluginBuild } from 'esbuild' +import type { Program } from 'estree' +import { attachComments } from 'estree-util-attach-comments' +import { toJs } from 'estree-util-to-js' +import { visit } from 'estree-util-visit' import util from 'node:util' import pkg from './package.json' assert { type: 'json' } import tsconfig from './tsconfig.build.json' assert { type: 'json' } +declare module 'estree' { + interface BaseNode { + position?: import('unist').Position | undefined + } +} + /** * Build configuration options. * @@ -23,23 +47,9 @@ const config: Config = defineBuildConfig({ { dts: 'only' }, - { - dts: 'only', - outdir: 'dist/dev' - }, { dts: false, - ignore: ['interfaces'], - outdir: 'dist/dev', - sourcemap: true, - sourcesContent: false - }, - { - dts: false, - ignore: ['interfaces'], - plugins: [], - sourcemap: true, - sourcesContent: false + ignore: ['interfaces', 'types'] } ], plugins: [ @@ -59,7 +69,7 @@ const config: Config = defineBuildConfig({ */ setup(build: PluginBuild): void { /** - * Regular expression used to fix module specifier. + * Regular expression used to fix module specifiers. * * @const {RegExp} regex */ @@ -80,6 +90,160 @@ const config: Config = defineBuildConfig({ } }) } + }, + { + /** + * Plugin name. + */ + name: unassert.name, + + /** + * Remove assertions. + * + * @this {void} + * + * @param {PluginBuild} build - esbuild plugin api + * @return {void} Nothing + */ + setup(build: PluginBuild): void { + const { + absWorkingDir: cwd = process.cwd(), + format, + outdir = DOT + } = build.initialOptions + + /** + * Directory to store development output files. + * + * @const {string} devdir + */ + const devdir: string = pathe.join(outdir, 'dev') + + return void build.onEnd((result: BuildResult): void => { + ok(result.metafile, 'expected metafile') + ok(result.outputFiles, 'expected output files') + + /** + * Output file filter. + * + * @const {RegExp} filter + */ + const filter: RegExp = /\.[cm]{0,1}js$/ + + /** + * Development output file metadata. + * + * @const {Metafile['outputs']} outputs + */ + const outputs: Metafile['outputs'] = {} + + /** + * Development output files. + * + * @const {OutputFile[]} outputs + */ + const outputFiles: OutputFile[] = [] + + // get development output file metadata + for (const [path, output] of entries(result.metafile.outputs)) { + if (filter.test(path)) { + define(outputs, path.replace(outdir, devdir), { value: output }) + } + } + + // handle output files + for (const output of result.outputFiles) { + if (filter.test(output.path)) { + /** + * JavaScript syntax tree. + * + * @const {Program} tree + */ + const tree: Program = fromJs(output.text, { + module: format !== 'iife' + }) + + // attach comments + visit(tree, node => void (node.loc = node.position)) + attachComments(tree, tree.comments) + delete tree.comments + + // remove assertions + unassert(tree) + + /** + * Relative path to output file. + * + * @const {string} outfile + */ + const outfile: string = output.path.replace(cwd + pathe.sep, '') + + /** + * Path to development output file. + * + * @const {string} devpath + */ + const devpath: string = pathe.resolve( + cwd, + devdir, + outfile.replace(outdir + pathe.sep, '') + ) + + /** + * Output file text. + * + * @const {string} text + */ + const text: string = toJs(tree).value + + /** + * Output file contents. + * + * @const {Uint8Array} contents + */ + const contents: Uint8Array = new util.TextEncoder().encode(text) + + /** + * Output file metadata. + * + * @const {OutputMetadata} metadata + */ + const metadata: OutputMetadata = get( + result.metafile.outputs, + outfile + ) + + // assert output file metadata + ok(metadata, 'expected output file metadata') + + // add development output file + outputFiles.push( + define({ contents: output.contents, path: devpath }, 'text', { + get: constant(output.text) + }) + ) + + // update output file + define(output, 'text', { get: constant(text) }) + output.contents = new util.TextEncoder().encode(output.text) + + // update output file metadata + define(result.metafile.outputs, outfile, { + value: overwrite(metadata, { + bytes: contents.byteLength, + imports: metadata.imports.filter(({ path }) => { + return !unassert.MODULES_REGEX.test(path) + }) + }) + }) + } + } + + // update output files and metadata + result.outputFiles = [...outputFiles, ...result.outputFiles] + result.metafile.outputs = { ...outputs, ...result.metafile.outputs } + }) + } } ], target: [ diff --git a/package.json b/package.json index f1ac077..4b7ea71 100644 --- a/package.json +++ b/package.json @@ -32,13 +32,12 @@ ], "exports": { ".": { + "types": "./dist/index.d.mts", "development": "./dist/dev/index.mjs", "default": "./dist/index.mjs" }, "./package.json": "./package.json" }, - "module": "./dist/index.mjs", - "types": "./dist/index.d.mts", "scripts": { "build": "node --loader=./loader.mjs --enable-source-maps ./build", "check:ci": "yarn dedupe --check && yarn check:format && yarn check:lint && yarn check:spelling && yarn typecheck && yarn test:cov && yarn pack && yarn check:types:build && attw package.tgz && yarn clean:pack", @@ -84,7 +83,7 @@ "unist-util-is": "6.0.0" }, "devDependencies": { - "@arethetypeswrong/cli": "0.14.1", + "@arethetypeswrong/cli": "0.15.0", "@commitlint/cli": "18.6.1", "@commitlint/types": "18.6.1", "@flex-development/commitlint-config": "1.0.1", diff --git a/src/unassert.ts b/src/unassert.ts index a4bade6..577ec19 100644 --- a/src/unassert.ts +++ b/src/unassert.ts @@ -47,4 +47,10 @@ function unassert(this: void, tree: Program, options?: Nilable): void { }) } +/** + * @property {RegExp} MODULES_REGEX - Default regular expression used to match + * assertion module ids + */ +unassert.MODULES_REGEX = MODULES_REGEX + export default unassert diff --git a/yarn.lock b/yarn.lock index 908cc32..e32ce6f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -29,11 +29,11 @@ __metadata: languageName: node linkType: hard -"@arethetypeswrong/cli@npm:0.14.1": - version: 0.14.1 - resolution: "@arethetypeswrong/cli@npm:0.14.1" +"@arethetypeswrong/cli@npm:0.15.0": + version: 0.15.0 + resolution: "@arethetypeswrong/cli@npm:0.15.0" dependencies: - "@arethetypeswrong/core": "npm:0.14.1" + "@arethetypeswrong/core": "npm:0.15.0" chalk: "npm:^4.1.2" cli-table3: "npm:^0.6.3" commander: "npm:^10.0.1" @@ -42,13 +42,13 @@ __metadata: semver: "npm:^7.5.4" bin: attw: dist/index.js - checksum: 10/958a6b21ccb4b1adc790dba98a6b1dc008d1ce768cd7d6d5a1c3ee18cc9f010287eb44af7820a7f67563bba71ca60d77fd4e69ec3eb29cf8604ea32f77bfacb8 + checksum: 10/699605a92ff95684269aca7cb769f21cca99e6f163df222e662d39eac59eec90ce64c448b2bfd660c359240c26a3050f2d7403f2bdd43a3deccea551cbd8a820 languageName: node linkType: hard -"@arethetypeswrong/core@npm:0.14.1": - version: 0.14.1 - resolution: "@arethetypeswrong/core@npm:0.14.1" +"@arethetypeswrong/core@npm:0.15.0": + version: 0.15.0 + resolution: "@arethetypeswrong/core@npm:0.15.0" dependencies: "@andrewbranch/untar.js": "npm:^1.0.3" fflate: "npm:^0.8.2" @@ -56,7 +56,7 @@ __metadata: ts-expose-internals-conditionally: "npm:1.0.0-empty.0" typescript: "npm:5.3.3" validate-npm-package-name: "npm:^5.0.0" - checksum: 10/44bb7d92933539d5a3413f44465e935ee67f5e28538f653a4271603c2e79bc27e81cfe08fecc2e6d803968530d8a8f8224c5ebf17e05940953f131cb2536e19a + checksum: 10/4aa5ed29d3d9f56aa890382e5d996afde65147d45fcf073cfbc8b0773ab5a8748f0a3b8060b5e68ad3373bcb6b418deb5eafc613be4eb72d854efd6ee291917d languageName: node linkType: hard @@ -1451,7 +1451,7 @@ __metadata: version: 0.0.0-use.local resolution: "@flex-development/estree-util-unassert@workspace:." dependencies: - "@arethetypeswrong/cli": "npm:0.14.1" + "@arethetypeswrong/cli": "npm:0.15.0" "@commitlint/cli": "npm:18.6.1" "@commitlint/types": "npm:18.6.1" "@flex-development/commitlint-config": "npm:1.0.1"