feat: config files, readme

This commit is contained in:
2026-07-04 21:32:03 +02:00
parent d1620f7fdb
commit c3313223ef
13 changed files with 311 additions and 16 deletions
+18
View File
@@ -0,0 +1,18 @@
import * as esbuild from "esbuild";
const result = await esbuild.build({
entryPoints: ["src/index.ts", "src/config.ts"],
minify: true,
bundle: true,
outdir: "dist",
define: {
["import.meta.vitest"]: "undefined",
},
format: "esm",
platform: "node",
packages: "external",
});
if (result.errors.length !== 0) {
throw result;
}
+60
View File
@@ -0,0 +1,60 @@
# gen-doctests
Generate tests from your JSDoc documentation for whichever testing harness you prefer.
## Usage
> See `gen-doctests --help` for more detail.
Write a doctest alongside your source code:
````ts
// src/isEven.ts
/**
* Returns whether the specified number is divisible by 2
* @param x The number to check
* @example
* ```ts
* expect(isEven(5)).toBe(false);
* expect(isEven(4)).toBe(true);
* ```
*/
export function isEven(x: number) {
return x % 2 === 0;
}
````
And generate your doctests using either the library or the CLI:
```bash
$ gen-doctests src/**.ts --format vitest -o tests/generated
```
With the above produces the following test file:
```ts
// tests/generated/isEven.doc.test.ts
// Automatically generated tests for ../../src/isEven.ts
import { describe, expect, test, vi } from "vitest";
import { isEven } from "../../src/isEven";
test("isEven()", () => {
expect(isEven(5)).toBe(false);
expect(isEven(4)).toBe(true);
});
```
You can also define a `doctests.config.ts` file to skip the command arguments:
```ts
// doctests.config.ts
import { defineConfig } from "gen-doctests/config";
export default defineConfig({
include: ["src/**.{js,jsx,ts,tsx}"],
outDir: "dist/",
});
```
+6
View File
@@ -0,0 +1,6 @@
import { defineConfig } from "./dist/config";
export default defineConfig({
include: ["src/**.ts"],
templateHeader: ["console.log('hello, world!');"],
});
+9 -4
View File
@@ -1,17 +1,20 @@
{ {
"name": "gen-doctests", "name": "gen-doctests",
"private": false, "private": false,
"version": "0.1.0", "version": "0.2.0",
"type": "module", "type": "module",
"bin": "dist/index.js", "bin": "dist/index.js",
"scripts": { "scripts": {
"test": "vitest --run --reporter=tree", "test": "vitest --run --reporter=tree",
"build": "tsc -b && esbuild --minify --bundle src/index.ts --outdir=dist --define:import.meta.vitest=undefined --platform=node --format=esm --packages=external", "build": "tsc -b && node .config/build.js",
"prepublishOnly": "pnpm build", "prepublishOnly": "pnpm test && pnpm fmt && pnpm build",
"fmt": "prettier --write .", "fmt": "prettier --write .",
"lint": "eslint .", "lint": "eslint .",
"preview": "vite preview" "preview": "vite preview"
}, },
"exports": {
".": "./dist/index.js"
},
"devDependencies": { "devDependencies": {
"@eslint/js": "^10.0.1", "@eslint/js": "^10.0.1",
"@types/node": "^24.12.3", "@types/node": "^24.12.3",
@@ -19,13 +22,15 @@
"@typescript-eslint/types": "^8.61.1", "@typescript-eslint/types": "^8.61.1",
"esbuild": "^0.28.1", "esbuild": "^0.28.1",
"eslint": "^10.3.0", "eslint": "^10.3.0",
"jiti": "^2.7.0",
"prettier": "^3.8.4", "prettier": "^3.8.4",
"typescript-eslint": "^8.59.2", "typescript-eslint": "^8.59.2",
"vitest": "^4.1.9" "vitest": "^4.1.9"
}, },
"dependencies": { "dependencies": {
"arktype": "^2.2.2",
"citty": "^0.2.2", "citty": "^0.2.2",
"find-up": "^8.0.0",
"jiti": "^2.7.0",
"picomatch": "^4.0.5", "picomatch": "^4.0.5",
"typescript": "^6.0.3" "typescript": "^6.0.3"
} }
+82 -3
View File
@@ -8,9 +8,18 @@ importers:
.: .:
dependencies: dependencies:
arktype:
specifier: ^2.2.2
version: 2.2.2
citty: citty:
specifier: ^0.2.2 specifier: ^0.2.2
version: 0.2.2 version: 0.2.2
find-up:
specifier: ^8.0.0
version: 8.0.0
jiti:
specifier: ^2.7.0
version: 2.7.0
picomatch: picomatch:
specifier: ^4.0.5 specifier: ^4.0.5
version: 4.0.5 version: 4.0.5
@@ -36,9 +45,6 @@ importers:
eslint: eslint:
specifier: ^10.3.0 specifier: ^10.3.0
version: 10.5.0(jiti@2.7.0) version: 10.5.0(jiti@2.7.0)
jiti:
specifier: ^2.7.0
version: 2.7.0
prettier: prettier:
specifier: ^3.8.4 specifier: ^3.8.4
version: 3.8.4 version: 3.8.4
@@ -51,6 +57,12 @@ importers:
packages: packages:
'@ark/schema@0.56.1':
resolution: {integrity: sha512-1Cf2g9nKD8K/3JGRu+gCCfYw5d4qR8YLLjDs5W5kpmaButCYWAPFUJqSXyBATPjglzCd4tIkp398iPYVs8MjRA==}
'@ark/util@0.56.1':
resolution: {integrity: sha512-Tp1rTik3q5Z+jAeeDxr5JZpmVIw0miti1ykSEHyZv5Pw3TIJl2xbN6KTacOxITp0l3s9ytlrWd30Zvqcy5vzoQ==}
'@emnapi/core@1.10.0': '@emnapi/core@1.10.0':
resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==}
@@ -507,6 +519,12 @@ packages:
ajv@6.15.0: ajv@6.15.0:
resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==}
arkregex@0.0.7:
resolution: {integrity: sha512-O/Ltrn9EUSn3ui0KVzfyrWGDUsHlzKxDVBtpQxL/6JmLRMAZAebfSNf/A/J5Ny5S6QIwrXX+RfXsu888HMs35A==}
arktype@2.2.2:
resolution: {integrity: sha512-YYf1xhL2dh5aPZFlsY0RAsxv5HZqfLGLptH2ZP3JidTmsGRW8VOymhPjjMTkerL12vR2YtX0SK4c1mATtae8SA==}
assertion-error@2.0.1: assertion-error@2.0.1:
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -636,6 +654,10 @@ packages:
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
engines: {node: '>=10'} engines: {node: '>=10'}
find-up@8.0.0:
resolution: {integrity: sha512-JGG8pvDi2C+JxidYdIwQDyS/CgcrIdh18cvgxcBge3wSHRQOrooMD3GlFBcmMJAN9M42SAZjDp5zv1dglJjwww==}
engines: {node: '>=20'}
flat-cache@4.0.1: flat-cache@4.0.1:
resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
engines: {node: '>=16'} engines: {node: '>=16'}
@@ -769,6 +791,10 @@ packages:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'} engines: {node: '>=10'}
locate-path@8.0.0:
resolution: {integrity: sha512-XT9ewWAC43tiAV7xDAPflMkG0qOPn2QjHqlgX8FOqmWa/rxnyYDulF9T0F7tRy1u+TVTmK/M//6VIOye+2zDXg==}
engines: {node: '>=20'}
magic-string@0.30.21: magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
@@ -799,10 +825,18 @@ packages:
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
engines: {node: '>=10'} engines: {node: '>=10'}
p-limit@4.0.0:
resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
p-locate@5.0.0: p-locate@5.0.0:
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
engines: {node: '>=10'} engines: {node: '>=10'}
p-locate@6.0.0:
resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
path-exists@4.0.0: path-exists@4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -912,6 +946,10 @@ packages:
undici-types@7.18.2: undici-types@7.18.2:
resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==}
unicorn-magic@0.3.0:
resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==}
engines: {node: '>=18'}
uri-js@4.4.1: uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
@@ -1017,8 +1055,18 @@ packages:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'} engines: {node: '>=10'}
yocto-queue@1.2.2:
resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==}
engines: {node: '>=12.20'}
snapshots: snapshots:
'@ark/schema@0.56.1':
dependencies:
'@ark/util': 0.56.1
'@ark/util@0.56.1': {}
'@emnapi/core@1.10.0': '@emnapi/core@1.10.0':
dependencies: dependencies:
'@emnapi/wasi-threads': 1.2.1 '@emnapi/wasi-threads': 1.2.1
@@ -1396,6 +1444,16 @@ snapshots:
json-schema-traverse: 0.4.1 json-schema-traverse: 0.4.1
uri-js: 4.4.1 uri-js: 4.4.1
arkregex@0.0.7:
dependencies:
'@ark/util': 0.56.1
arktype@2.2.2:
dependencies:
'@ark/schema': 0.56.1
'@ark/util': 0.56.1
arkregex: 0.0.7
assertion-error@2.0.1: {} assertion-error@2.0.1: {}
balanced-match@4.0.4: {} balanced-match@4.0.4: {}
@@ -1548,6 +1606,11 @@ snapshots:
locate-path: 6.0.0 locate-path: 6.0.0
path-exists: 4.0.0 path-exists: 4.0.0
find-up@8.0.0:
dependencies:
locate-path: 8.0.0
unicorn-magic: 0.3.0
flat-cache@4.0.1: flat-cache@4.0.1:
dependencies: dependencies:
flatted: 3.4.2 flatted: 3.4.2
@@ -1646,6 +1709,10 @@ snapshots:
dependencies: dependencies:
p-locate: 5.0.0 p-locate: 5.0.0
locate-path@8.0.0:
dependencies:
p-locate: 6.0.0
magic-string@0.30.21: magic-string@0.30.21:
dependencies: dependencies:
'@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/sourcemap-codec': 1.5.5
@@ -1675,10 +1742,18 @@ snapshots:
dependencies: dependencies:
yocto-queue: 0.1.0 yocto-queue: 0.1.0
p-limit@4.0.0:
dependencies:
yocto-queue: 1.2.2
p-locate@5.0.0: p-locate@5.0.0:
dependencies: dependencies:
p-limit: 3.1.0 p-limit: 3.1.0
p-locate@6.0.0:
dependencies:
p-limit: 4.0.0
path-exists@4.0.0: {} path-exists@4.0.0: {}
path-key@3.1.1: {} path-key@3.1.1: {}
@@ -1775,6 +1850,8 @@ snapshots:
undici-types@7.18.2: {} undici-types@7.18.2: {}
unicorn-magic@0.3.0: {}
uri-js@4.4.1: uri-js@4.4.1:
dependencies: dependencies:
punycode: 2.3.1 punycode: 2.3.1
@@ -1831,3 +1908,5 @@ snapshots:
word-wrap@1.2.5: {} word-wrap@1.2.5: {}
yocto-queue@0.1.0: {} yocto-queue@0.1.0: {}
yocto-queue@1.2.2: {}
+1
View File
@@ -0,0 +1 @@
export { defineConfig, type Options } from "./options";
+2 -2
View File
@@ -111,6 +111,8 @@ export function createGenerator(options: Options) {
if (!isInclude(file.filePath) || isExclude(file.filePath)) if (!isInclude(file.filePath) || isExclude(file.filePath))
return; return;
if (file.tests.length === 0) return;
let source = ""; let source = "";
const regions: Region = {}; const regions: Region = {};
@@ -195,8 +197,6 @@ export function createGenerator(options: Options) {
const tests: string[] = []; const tests: string[] = [];
const regions: string[] = []; const regions: string[] = [];
console.log(region);
for (const key of Reflect.ownKeys(region)) { for (const key of Reflect.ownKeys(region)) {
const value = region[key]; const value = region[key];
if (typeof value === "string") { if (typeof value === "string") {
+71 -3
View File
@@ -1,12 +1,68 @@
#!/usr/bin/env node #!/usr/bin/env node
import { globSync } from "fs"; import { globSync, lstatSync, readFileSync } from "fs";
import { runCli } from "./cli"; import { runCli } from "./cli";
import { DEFAULT_OPTIONS } from "./options"; import { DEFAULT_OPTIONS, Options } from "./options";
import { parseFile } from "./parser"; import { parseFile } from "./parser";
import { createGenerator } from "./generator"; import { createGenerator } from "./generator";
import { createJiti } from "jiti";
import picomatch from "picomatch";
import { findUp } from "find-up";
import { basename } from "path";
import { pathToFileURL } from "url";
import { type } from "arktype";
async function main() { async function main() {
const configFilePath = await findUp([
"doctests.config.ts",
"doctest.config.ts",
"doctests.config.js",
"doctest.config.js",
]);
if (process.argv.length <= 2 && configFilePath !== undefined) {
const jit = createJiti(import.meta.url);
const config = readFileSync(configFilePath, {
encoding: "utf-8",
});
const configFile = basename(configFilePath);
const result = jit.evalModule(config, {
filename: pathToFileURL(configFile).toString(),
});
if (
typeof result === "object" &&
result !== null &&
"default" in result &&
typeof result.default === "object" &&
result.default !== null
) {
const config = Options(result.default);
if (config instanceof type.errors) {
console.error(
`error while reading ${configFile}: ${config.summary}`,
);
return;
}
parseWithOptions({
...DEFAULT_OPTIONS,
...config,
});
return;
} else {
console.error(
`error while reading ${configFile}: expected a default export with the config keys`,
);
console.info(
"see `defineConfig()` from `gen-doctests/config`",
);
}
return;
}
const result = await runCli(); const result = await runCli();
if (result === undefined) return; if (result === undefined) return;
@@ -21,6 +77,10 @@ async function main() {
options.include = include; options.include = include;
const { args } = result; const { args } = result;
options.exclude =
args.exclude !== undefined
? [args.exclude]
: DEFAULT_OPTIONS.exclude;
options.outDir = args["out-dir"] ?? DEFAULT_OPTIONS.outDir; options.outDir = args["out-dir"] ?? DEFAULT_OPTIONS.outDir;
options.fileExtension = args["test-extension"]; options.fileExtension = args["test-extension"];
options.testName = args["test-name"] ?? DEFAULT_OPTIONS.testName; options.testName = args["test-name"] ?? DEFAULT_OPTIONS.testName;
@@ -38,7 +98,15 @@ async function main() {
options.requireCodeBlock = args["must-codeblock"]; options.requireCodeBlock = args["must-codeblock"];
options.includePath = args.annotate; options.includePath = args.annotate;
const files = globSync(include); parseWithOptions(options);
}
function parseWithOptions(options: Options) {
const doctest = picomatch("**/*" + options.fileExtension + ".*");
const files = globSync(options.include)
.filter((v) => !doctest(v))
.filter((path) => !lstatSync(path).isDirectory());
const parsed = files const parsed = files
.map((path) => parseFile(path, options)) .map((path) => parseFile(path, options))
.filter((v) => v !== null); .filter((v) => v !== null);
+28
View File
@@ -1,3 +1,5 @@
import { type } from "arktype";
export interface Options { export interface Options {
/** /**
* Pattern matching files to include in parsing * Pattern matching files to include in parsing
@@ -66,6 +68,22 @@ export interface Options {
emitRegions: boolean; emitRegions: boolean;
} }
export const Options = type({
include: "string[]",
"exclude?": "string[]",
"outDir?": "string | null",
"fileExtension?": "string",
"testName?": "string | null",
"templateRoot?": "boolean",
"templateHeader?": "string[]",
"templateFooter?": "string[]",
"format?": '"jest" | "vitest" | "assert"',
"onlyGenerateTests?": "boolean",
"requireCodeBlock?": "boolean",
"includePath?": "boolean",
"emitRegions?": "boolean",
});
export const DEFAULT_OPTIONS: Required<Options> = { export const DEFAULT_OPTIONS: Required<Options> = {
include: [], include: [],
exclude: [], exclude: [],
@@ -81,3 +99,13 @@ export const DEFAULT_OPTIONS: Required<Options> = {
includePath: true, includePath: true,
emitRegions: true, emitRegions: true,
}; };
export function defineConfig(
opts: Partial<Omit<Options, "include">> &
Pick<Options, "include">,
): Options {
return {
...DEFAULT_OPTIONS,
...opts,
};
}
-2
View File
@@ -346,8 +346,6 @@ export function parseFile(
visit(node); visit(node);
console.log(tests);
return { return {
name: basename(filePath, extension), name: basename(filePath, extension),
extension: extension, extension: extension,
+7 -2
View File
@@ -11,13 +11,18 @@
"moduleResolution": "bundler", "moduleResolution": "bundler",
"allowImportingTsExtensions": true, "allowImportingTsExtensions": true,
"verbatimModuleSyntax": true, "verbatimModuleSyntax": true,
"emitDeclarationOnly": true,
"declaration": true,
"moduleDetection": "force", "moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx", "jsx": "react-jsx",
/* Linting */ /* Linting */
"noUnusedLocals": false, "noUnusedLocals": false,
"erasableSyntaxOnly": true, "erasableSyntaxOnly": true,
"outDir": "./dist",
"rootDir": "./src"
}, },
"include": ["src", "tests"] "include": ["src"],
"exclude": ["src/config.ts"]
} }
+26
View File
@@ -0,0 +1,26 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "es2023",
"lib": ["ES2023"],
"module": "esnext",
"types": ["vitest/importMeta", "node"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"verbatimModuleSyntax": true,
"moduleDetection": "force",
"emitDeclarationOnly": true,
"declaration": true,
"jsx": "react-jsx",
/* Linting */
"noUnusedLocals": false,
"erasableSyntaxOnly": true,
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/config.ts"]
}
+1
View File
@@ -2,6 +2,7 @@
"files": [], "files": [],
"references": [ "references": [
{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.config.json" },
{ "path": "./tsconfig.node.json" } { "path": "./tsconfig.node.json" }
] ]
} }