From 19abd95e02db82322d5d3952cc3304a286d74c22 Mon Sep 17 00:00:00 2001 From: Victorien Elvinger Date: Thu, 26 Dec 2024 20:24:40 +0100 Subject: [PATCH] refactor: directly execute tests with NodeJS NodeJS introduced experimental flags to run TypeScript. This change uses this capability. This allows bypassing the build step for running tests. We have to change all imports of TypeScript files to use the `.ts` extension. Unfortuantely ESbuild is not able to rewrite the extensions. Fortunately, TSC 5.7 is capable of rewritting extensions. Thus this change switches to TSC for transpiling the sources. We still keep ESbuild for bundling CJS and the standalone executable. I took the opprotunity of replacing all tsconfigs with a global one. This allows easy referencing from test files to source files without involving TypeScript project references. Note that safety is preserved because we still use dedicated tsconfigs for building destination files: - `src/tsconfig.json` - `src/tsconfig.bin.json` This allows expressing restrictions. For instance our source files don't depend on NodeJS, while our test files do. --- .github/workflows/ci.yml | 6 +++- package.json | 7 +++-- scripts/build.sh | 9 ++---- ...sts-corpus.js => generate-tests-corpus.ts} | 5 ++-- scripts/test.sh | 12 -------- src/ast/bare-configure.ts | 4 +-- src/ast/bare-normalization.ts | 2 +- src/ast/bare-semantic-checker.ts | 8 +++--- src/bin/{cli.ts => bare.ts} | 2 +- src/generator/bare-ast-utils.ts | 4 +-- src/generator/bare-generator.ts | 4 +-- src/generator/js-generator.ts | 8 +++--- src/index.ts | 28 +++++++++---------- src/parser/bare-lexer.test.ts | 2 +- src/parser/bare-lexer.ts | 2 +- src/parser/bare-parser.ts | 10 +++---- src/tsconfig-test.json | 18 ------------ src/tsconfig.bin.json | 17 +++++++++++ src/tsconfig.json | 9 +++--- tests-corpus/{index.test.js => index.test.ts} | 2 +- tests-corpus/tsconfig.json | 6 ---- tsconfig-base.json => tsconfig.json | 7 +++-- 22 files changed, 78 insertions(+), 94 deletions(-) rename scripts/{generate-tests-corpus.js => generate-tests-corpus.ts} (93%) delete mode 100644 scripts/test.sh rename src/bin/{cli.ts => bare.ts} (99%) delete mode 100644 src/tsconfig-test.json create mode 100644 src/tsconfig.bin.json rename tests-corpus/{index.test.js => index.test.ts} (99%) delete mode 100644 tests-corpus/tsconfig.json rename tsconfig-base.json => tsconfig.json (86%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e43dd138..5d3cc8fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,13 +16,17 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: - node-version: "22.0.0" + node-version: "22.13.0" cache: npm - name: Build and test coverage run: | npm ci npm install c8 npm run coverage + - name: Print report + run: | + ls coverage + cat coverage/lcov.info - name: Coveralls uses: coverallsapp/github-action@master with: diff --git a/package.json b/package.json index cd9e53c9..edc7aecd 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ }, "type": "module", "bin": { - "bare": "dist/bin/cli.js" + "bare": "dist/bin/bare.js" }, "exports": { "./package.json": "./package.json", @@ -53,13 +53,14 @@ ], "scripts": { "build": "sh ./scripts/build.sh", + "check": "tsc --build && biome ci --error-on-warnings .", "clean": "rm -rf dist coverage", "coverage": "c8 --reporter=lcovonly npm test", "format": "biome format --write .", "lint": "biome lint .", "prepare": "validate-commit-msg", - "prepublishOnly": "npm run clean && npm test", - "test": "sh ./scripts/test.sh", + "prepublishOnly": "npm run clean && npm run build && npm test", + "test": "node --test --experimental-strip-types && npm run check", "version": "sh ./scripts/version.sh" }, "devDependencies": { diff --git a/scripts/build.sh b/scripts/build.sh index 1152abf1..f1c76524 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -5,16 +5,13 @@ set -eu # https://kangax.github.io/compat-table/es2016plus TARGET='node20.10.0' -# build .d.ts -tsc --build src/ +# build ESM and .d.ts +npx tsc --build src/tsconfig.bin.json cp -f dist/index.d.ts dist/index.d.cts -# build ESM -esbuild 'src/**/*.ts' --target=$TARGET --outdir=dist --log-level=warning - # build CommonJS (fallback) esbuild src/index.ts --bundle --target=$TARGET --platform=node > dist/index.cjs # build standalone cli program -esbuild dist/bin/cli.js --bundle --target=$TARGET --minify --keep-names --platform=node > dist/bin/bare +esbuild dist/bin/bare.js --bundle --target=$TARGET --minify --keep-names --platform=node > dist/bin/bare diff --git a/scripts/generate-tests-corpus.js b/scripts/generate-tests-corpus.ts similarity index 93% rename from scripts/generate-tests-corpus.js rename to scripts/generate-tests-corpus.ts index 997fa3bc..b3b136a5 100644 --- a/scripts/generate-tests-corpus.js +++ b/scripts/generate-tests-corpus.ts @@ -2,7 +2,7 @@ import * as fs from "node:fs" import * as path from "node:path" -import { Config, configure, parse, transform } from "@bare-ts/tools" +import { Config, configure, parse, transform } from "../src/index.ts" const CORPUS_DIR = "./tests-corpus" @@ -39,8 +39,7 @@ for (let category of fs.readdirSync(CORPUS_DIR)) { completedConfig, ) fs.writeFileSync(astPath, JSON.stringify(ast, null, 2)) - let out - out = transform(content, { ...config, schema, generator: "ts" }) + let out = transform(content, { ...config, schema, generator: "ts" }) fs.writeFileSync(tsPath, out) out = transform(content, { ...config, schema, generator: "js" }) fs.writeFileSync(jsPath, out) diff --git a/scripts/test.sh b/scripts/test.sh deleted file mode 100644 index 8e6fd98a..00000000 --- a/scripts/test.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -. scripts/build.sh - -# unit tests -node --test - -# lint -biome ci --error-on-warnings . - -# type check -tsc --build src/ src/tsconfig-test.json tests-corpus/ diff --git a/src/ast/bare-configure.ts b/src/ast/bare-configure.ts index d0e06f21..27e81a79 100644 --- a/src/ast/bare-configure.ts +++ b/src/ast/bare-configure.ts @@ -1,8 +1,8 @@ //! Copyright (c) 2022 Victorien Elvinger //! Licensed under the MIT License (https://mit-license.org/) -import type { Config } from "../core/config.js" -import * as ast from "./bare-ast.js" +import type { Config } from "../core/config.ts" +import * as ast from "./bare-ast.ts" export function configure(schema: ast.Ast, config: Config): ast.Ast { const c: Configurator = { diff --git a/src/ast/bare-normalization.ts b/src/ast/bare-normalization.ts index 873acae6..a56a2886 100644 --- a/src/ast/bare-normalization.ts +++ b/src/ast/bare-normalization.ts @@ -1,7 +1,7 @@ //! Copyright (c) 2022 Victorien Elvinger //! Licensed under the MIT License (https://mit-license.org/) -import * as ast from "./bare-ast.js" +import * as ast from "./bare-ast.ts" export function normalize(schema: ast.Ast): ast.Ast { const n: Context = { defs: [], dedup: new Map(), aliasCount: 0 } diff --git a/src/ast/bare-semantic-checker.ts b/src/ast/bare-semantic-checker.ts index 48ade740..a7cef458 100644 --- a/src/ast/bare-semantic-checker.ts +++ b/src/ast/bare-semantic-checker.ts @@ -1,14 +1,14 @@ //! Copyright (c) 2022 Victorien Elvinger //! Licensed under the MIT License (https://mit-license.org/) -import { CompilerError } from "../core/compiler-error.js" -import type { Config } from "../core/config.js" +import { CompilerError } from "../core/compiler-error.ts" +import type { Config } from "../core/config.ts" import { CAMEL_CASE_RE, CONSTANT_CASE_RE, PASCAL_CASE_RE, -} from "../utils/formatting.js" -import * as ast from "./bare-ast.js" +} from "../utils/formatting.ts" +import * as ast from "./bare-ast.ts" export function checkSemantic(schema: ast.Ast, config: Config): ast.Ast { if (schema.defs.length === 0) { diff --git a/src/bin/cli.ts b/src/bin/bare.ts similarity index 99% rename from src/bin/cli.ts rename to src/bin/bare.ts index 28112eb7..b66cd31d 100644 --- a/src/bin/cli.ts +++ b/src/bin/bare.ts @@ -7,7 +7,7 @@ import * as fs from "node:fs" import * as process from "node:process" import * as util from "node:util" import packageVersion from "../../VERSION.json" with { type: "json" } -import { CompilerError, Config, transform } from "../index.js" +import { CompilerError, Config, transform } from "../index.ts" const HELP_TEXT = ` Usage: bare [options] [schema] diff --git a/src/generator/bare-ast-utils.ts b/src/generator/bare-ast-utils.ts index 23196f63..c5e88f2e 100644 --- a/src/generator/bare-ast-utils.ts +++ b/src/generator/bare-ast-utils.ts @@ -1,8 +1,8 @@ //! Copyright (c) 2022 Victorien Elvinger //! Licensed under the MIT License (https://mit-license.org/) -import * as ast from "../ast/bare-ast.js" -import { CompilerError } from "../core/compiler-error.js" +import * as ast from "../ast/bare-ast.ts" +import { CompilerError } from "../core/compiler-error.ts" // This file is separated from ast folder because these utils are used for // facilitating code generation. diff --git a/src/generator/bare-generator.ts b/src/generator/bare-generator.ts index 12001f86..cad32459 100644 --- a/src/generator/bare-generator.ts +++ b/src/generator/bare-generator.ts @@ -1,8 +1,8 @@ //! Copyright (c) 2022 Victorien Elvinger //! Licensed under the MIT License (https://mit-license.org/) -import type * as ast from "../ast/bare-ast.js" -import { dent, toConstantCase } from "../utils/formatting.js" +import type * as ast from "../ast/bare-ast.ts" +import { dent, toConstantCase } from "../utils/formatting.ts" export function generateBare(schema: ast.Ast): string { let result = "" diff --git a/src/generator/js-generator.ts b/src/generator/js-generator.ts index 8aa12b9a..5a1e8dd8 100644 --- a/src/generator/js-generator.ts +++ b/src/generator/js-generator.ts @@ -1,16 +1,16 @@ //! Copyright (c) 2022 Victorien Elvinger //! Licensed under the MIT License (https://mit-license.org/) -import * as ast from "../ast/bare-ast.js" -import type { Config } from "../core/config.js" +import * as ast from "../ast/bare-ast.ts" +import type { Config } from "../core/config.ts" import { capitalize, dent, jsDoc, jsRpr, softSpace, -} from "../utils/formatting.js" -import * as utils from "./bare-ast-utils.js" +} from "../utils/formatting.ts" +import * as utils from "./bare-ast-utils.ts" export function generate(schema: ast.Ast, config: Config): string { const g: Gen = { config, symbols: ast.symbols(schema) } diff --git a/src/index.ts b/src/index.ts index ca5a713d..e0a44702 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,21 +1,21 @@ //! Copyright (c) 2022 Victorien Elvinger //! Licensed under the MIT License (https://mit-license.org/) -import { configure } from "./ast/bare-configure.js" -import { normalize } from "./ast/bare-normalization.js" -import { checkSemantic } from "./ast/bare-semantic-checker.js" -import { Config } from "./core/config.js" -import { generateBare } from "./generator/bare-generator.js" -import { generate } from "./generator/js-generator.js" -import { parse } from "./parser/bare-parser.js" +import { configure } from "./ast/bare-configure.ts" +import { normalize } from "./ast/bare-normalization.ts" +import { checkSemantic } from "./ast/bare-semantic-checker.ts" +import { Config } from "./core/config.ts" +import { generateBare } from "./generator/bare-generator.ts" +import { generate } from "./generator/js-generator.ts" +import { parse } from "./parser/bare-parser.ts" -export * from "./ast/bare-ast.js" -export * from "./ast/bare-configure.js" -export * from "./ast/bare-normalization.js" -export * from "./core/compiler-error.js" -export * from "./core/config.js" -export * from "./generator/js-generator.js" -export * from "./parser/bare-parser.js" +export * from "./ast/bare-ast.ts" +export * from "./ast/bare-configure.ts" +export * from "./ast/bare-normalization.ts" +export * from "./core/compiler-error.ts" +export * from "./core/config.ts" +export * from "./generator/js-generator.ts" +export * from "./parser/bare-parser.ts" /** * Turn the schema `content` into a target language, taking `conf` into account. diff --git a/src/parser/bare-lexer.test.ts b/src/parser/bare-lexer.test.ts index e45f73e3..24539c11 100644 --- a/src/parser/bare-lexer.test.ts +++ b/src/parser/bare-lexer.test.ts @@ -3,7 +3,7 @@ import * as assert from "node:assert/strict" import { test } from "node:test" -import * as lex from "./bare-lexer.js" +import * as lex from "./bare-lexer.ts" const SAMPLE = ` const C = { # struct diff --git a/src/parser/bare-lexer.ts b/src/parser/bare-lexer.ts index 3d06bd69..0064dbbf 100644 --- a/src/parser/bare-lexer.ts +++ b/src/parser/bare-lexer.ts @@ -1,7 +1,7 @@ //! Copyright (c) 2022 Victorien Elvinger //! Licensed under the MIT License (https://mit-license.org/) -import { CompilerError } from "../core/compiler-error.js" +import { CompilerError } from "../core/compiler-error.ts" const WHITE_SPACE_PATTERN = /\s/ const PUNCTUATION_PATTERN = /[{}[\]()<>=|:,;.!?~+\\/$@#-]/ diff --git a/src/parser/bare-parser.ts b/src/parser/bare-parser.ts index 88b79a69..353c9485 100644 --- a/src/parser/bare-parser.ts +++ b/src/parser/bare-parser.ts @@ -1,15 +1,15 @@ //! Copyright (c) 2022 Victorien Elvinger //! Licensed under the MIT License (https://mit-license.org/) -import * as ast from "../ast/bare-ast.js" -import { CompilerError } from "../core/compiler-error.js" -import type { Config } from "../core/config.js" +import * as ast from "../ast/bare-ast.ts" +import { CompilerError } from "../core/compiler-error.ts" +import type { Config } from "../core/config.ts" import { ALL_CASE_RE, CONSTANT_CASE_RE, toPascalCase, -} from "../utils/formatting.js" -import * as lexer from "./bare-lexer.js" +} from "../utils/formatting.ts" +import * as lexer from "./bare-lexer.ts" export function parse(content: string, config: Config): ast.Ast { const p: Parser = { config, lex: lexer.create(content) } diff --git a/src/tsconfig-test.json b/src/tsconfig-test.json deleted file mode 100644 index 64145759..00000000 --- a/src/tsconfig-test.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": "../tsconfig-base.json", - "compilerOptions": { - "types": [ - "node" - ], - "outDir": "../dist" - }, - "include": [ - "./bin/cli.ts", - "./**/*.test.ts" - ], - "references": [ - { - "path": "." - } - ] -} diff --git a/src/tsconfig.bin.json b/src/tsconfig.bin.json new file mode 100644 index 00000000..e4d04e09 --- /dev/null +++ b/src/tsconfig.bin.json @@ -0,0 +1,17 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "noEmit": false, + "rewriteRelativeImportExtensions": true, + "rootDir": ".", + "outDir": "../dist" + }, + "include": [ + "./bin/*.ts" + ], + "references": [ + { + "path": "." + } + ] +} diff --git a/src/tsconfig.json b/src/tsconfig.json index 1f7d3bdf..cf2641cb 100644 --- a/src/tsconfig.json +++ b/src/tsconfig.json @@ -1,15 +1,16 @@ { - "extends": "../tsconfig-base.json", + "extends": "../tsconfig.json", "compilerOptions": { "composite": true, - "checkJs": false, "isolatedDeclarations": true, - "emitDeclarationOnly": true, "noEmit": false, + "rewriteRelativeImportExtensions": true, + "types": [], + "rootDir": ".", "outDir": "../dist" }, "exclude": [ - "./bin/cli.ts", + "./bin/**", "./**/*.test.ts" ] } diff --git a/tests-corpus/index.test.js b/tests-corpus/index.test.ts similarity index 99% rename from tests-corpus/index.test.js rename to tests-corpus/index.test.ts index 67ce0c6f..e783d5c7 100644 --- a/tests-corpus/index.test.js +++ b/tests-corpus/index.test.ts @@ -11,7 +11,7 @@ import { configure, parse, transform, -} from "@bare-ts/tools" +} from "../src/index.ts" const CORPUS_DIR = "./tests-corpus" const INVALID_BARE_DIR = `${CORPUS_DIR}/invalid-bare-schema` diff --git a/tests-corpus/tsconfig.json b/tests-corpus/tsconfig.json deleted file mode 100644 index 85b4dede..00000000 --- a/tests-corpus/tsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": "../tsconfig-base.json", - "compilerOptions": { - "types": ["node"] - } -} diff --git a/tsconfig-base.json b/tsconfig.json similarity index 86% rename from tsconfig-base.json rename to tsconfig.json index 00727ede..7474f25d 100644 --- a/tsconfig-base.json +++ b/tsconfig.json @@ -6,11 +6,13 @@ ], "module": "NodeNext", "target": "ES2022", + "types": [ + "node" + ], "noEmit": true, - "types": [], - + "allowImportingTsExtensions": true, "esModuleInterop": true, "isolatedModules": true, "resolveJsonModule": true, @@ -18,7 +20,6 @@ "verbatimModuleSyntax": true, "allowUnreachableCode": false, - "checkJs": true, "noFallthroughCasesInSwitch": true, "noImplicitOverride": true, "noImplicitReturns": true,