aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/frontend
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2024-04-07 01:59:09 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2024-04-07 01:59:09 +0200
commit1d2b5c85a177b4be0cc270b8e6e54488e23da5a1 (patch)
treec8b87c875faa7e6048e5ba41b5a9e4449263fc6a /subprojects/frontend
parentchore(deps): upgrade to frontend-jdk17 8.0.0 (diff)
downloadrefinery-1d2b5c85a177b4be0cc270b8e6e54488e23da5a1.tar.gz
refinery-1d2b5c85a177b4be0cc270b8e6e54488e23da5a1.tar.zst
refinery-1d2b5c85a177b4be0cc270b8e6e54488e23da5a1.zip
build: move Javascript config to top level
We need this to support multiple Javascript subprojects (e.g., a frontend and a documentation website).
Diffstat (limited to 'subprojects/frontend')
-rw-r--r--subprojects/frontend/.eslintrc.cjs129
-rw-r--r--subprojects/frontend/build.gradle.kts7
-rw-r--r--subprojects/frontend/config/eslintReport.cjs58
-rw-r--r--subprojects/frontend/package.json24
-rw-r--r--subprojects/frontend/package.json.orig121
-rw-r--r--subprojects/frontend/prettier.config.cjs11
-rw-r--r--subprojects/frontend/tsconfig.base.json41
-rw-r--r--subprojects/frontend/tsconfig.json2
-rw-r--r--subprojects/frontend/tsconfig.node.json2
-rw-r--r--subprojects/frontend/tsconfig.shared.json2
10 files changed, 10 insertions, 387 deletions
diff --git a/subprojects/frontend/.eslintrc.cjs b/subprojects/frontend/.eslintrc.cjs
deleted file mode 100644
index 25b86a83..00000000
--- a/subprojects/frontend/.eslintrc.cjs
+++ /dev/null
@@ -1,129 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6
7const path = require('node:path');
8
9// Allow the Codium ESLint plugin to find `tsconfig.json` from the repository root.
10const project = [
11 path.join(__dirname, 'tsconfig.json'),
12 path.join(__dirname, 'tsconfig.node.json'),
13 path.join(__dirname, 'tsconfig.shared.json'),
14];
15
16/** @type {import('eslint').Linter.Config} */
17module.exports = {
18 plugins: ['@typescript-eslint', 'mobx'],
19 extends: [
20 'airbnb',
21 'airbnb-typescript',
22 'airbnb/hooks',
23 'plugin:@typescript-eslint/recommended',
24 'plugin:@typescript-eslint/recommended-requiring-type-checking',
25 'plugin:mobx/recommended',
26 'plugin:prettier/recommended',
27 ],
28 parserOptions: {
29 project,
30 sourceType: 'module',
31 },
32 parser: '@typescript-eslint/parser',
33 settings: {
34 'import/parsers': {
35 '@typescript-eslint/parser': ['.ts', '.tsx'],
36 },
37 'import/resolver': {
38 typescript: {
39 alwaysTryTypes: true,
40 project,
41 },
42 },
43 },
44 env: {
45 browser: true,
46 },
47 ignorePatterns: ['build/**/*', 'dev-dist/**/*', 'src/**/*.typegen.ts'],
48 rules: {
49 // In typescript, some class methods implementing an inderface do not use `this`:
50 // https://github.com/typescript-eslint/typescript-eslint/issues/1103
51 'class-methods-use-this': 'off',
52 // Disable rules with a high performance cost.
53 // See https://typescript-eslint.io/linting/troubleshooting/performance-troubleshooting/
54 'import/default': 'off',
55 'import/extensions': 'off',
56 'import/named': 'off',
57 'import/namespace': 'off',
58 'import/no-named-as-default': 'off',
59 'import/no-named-as-default-member': 'off',
60 '@typescript-eslint/indent': 'off',
61 // Make sure every import can be resolved by `eslint-import-resolver-typescript`.
62 'import/no-unresolved': 'error',
63 // Organize imports automatically.
64 'import/order': [
65 'error',
66 {
67 alphabetize: {
68 order: 'asc',
69 },
70 'newlines-between': 'always',
71 },
72 ],
73 // Not all components depend on observable state.
74 'mobx/missing-observer': 'off',
75 // A dangling underscore, while not neccessary for all private fields,
76 // is useful for backing fields of properties that should be read-only from outside the class.
77 'no-underscore-dangle': [
78 'error',
79 {
80 allowAfterThis: true,
81 allowFunctionParams: true,
82 },
83 ],
84 // Use prop spreading to conditionally add props with `exactOptionalPropertyTypes`.
85 'react/jsx-props-no-spreading': 'off',
86 // We use the `react-jsx` runtime, so there is no need to import `React`.
87 'react/react-in-jsx-scope': 'off',
88 },
89 overrides: [
90 {
91 files: ['types/**/*.d.ts'],
92 rules: {
93 // We don't have control over exports of external modules.
94 'import/prefer-default-export': 'off',
95 },
96 },
97 {
98 files: ['*.cjs'],
99 rules: {
100 // https://github.com/typescript-eslint/typescript-eslint/issues/1724
101 '@typescript-eslint/no-var-requires': 'off',
102 },
103 },
104 {
105 files: [
106 '.eslintrc.cjs',
107 'config/*.ts',
108 'config/*.cjs',
109 'prettier.config.cjs',
110 'vite.config.ts',
111 ],
112 env: {
113 browser: false,
114 node: true,
115 },
116 rules: {
117 // Allow devDependencies in configuration files.
118 'import/no-extraneous-dependencies': [
119 'error',
120 { devDependencies: true },
121 ],
122 // Allow writing to the console in ad-hoc scripts.
123 'no-console': 'off',
124 // Access to the environment in configuration files.
125 'no-process-env': 'off',
126 },
127 },
128 ],
129};
diff --git a/subprojects/frontend/build.gradle.kts b/subprojects/frontend/build.gradle.kts
index 40e31517..ac2c1817 100644
--- a/subprojects/frontend/build.gradle.kts
+++ b/subprojects/frontend/build.gradle.kts
@@ -32,8 +32,8 @@ val sourcesWithoutTypes = fileTree("src") {
32val sourcesWithTypes: FileCollection = fileTree("src") + fileTree("types") 32val sourcesWithTypes: FileCollection = fileTree("src") + fileTree("types")
33 33
34val buildScripts: FileCollection = fileTree("config") + files( 34val buildScripts: FileCollection = fileTree("config") + files(
35 ".eslintrc.cjs", 35 rootProject.file(".eslintrc.cjs"),
36 "prettier.config.cjs", 36 rootProject.file("prettier.config.cjs"),
37 "vite.config.ts", 37 "vite.config.ts",
38) 38)
39 39
@@ -44,8 +44,8 @@ val installationState = files(
44) 44)
45 45
46val sharedConfigFiles: FileCollection = installationState + files( 46val sharedConfigFiles: FileCollection = installationState + files(
47 rootProject.file("tsconfig.base.json"),
47 "tsconfig.json", 48 "tsconfig.json",
48 "tsconfig.base.json",
49 "tsconfig.node.json", 49 "tsconfig.node.json",
50 "tsconfig.shared.json", 50 "tsconfig.shared.json",
51) 51)
@@ -76,7 +76,6 @@ tasks {
76 outputs.dir(productionResources) 76 outputs.dir(productionResources)
77 } 77 }
78 78
79
80 val typeCheckFrontend by registering(RunYarn::class) { 79 val typeCheckFrontend by registering(RunYarn::class) {
81 dependsOn(installFrontend) 80 dependsOn(installFrontend)
82 dependsOn(generateXStateTypes) 81 dependsOn(generateXStateTypes)
diff --git a/subprojects/frontend/config/eslintReport.cjs b/subprojects/frontend/config/eslintReport.cjs
deleted file mode 100644
index 7c4b7bd6..00000000
--- a/subprojects/frontend/config/eslintReport.cjs
+++ /dev/null
@@ -1,58 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6
7const { writeFile } = require('node:fs/promises');
8const path = require('node:path');
9const { Readable } = require('node:stream');
10const { pipeline } = require('node:stream/promises');
11
12const { ESLint } = require('eslint');
13
14const rootDir = path.join(__dirname, '..');
15
16/**
17 * Write ESLint report to console.
18 *
19 * @param cli {import('eslint').ESLint} The ESLint CLI.
20 * @param report {import('eslint').ESLint.LintResult[]} The ESLint report.
21 * @return {Promise<void>} A promise that resolves when the report is finished.
22 */
23async function reportToConsole(cli, report) {
24 const stylishFormatter = await cli.loadFormatter('stylish');
25 const output = new Readable();
26 output.push(await stylishFormatter.format(report));
27 output.push(null);
28 return pipeline(output, process.stdout);
29}
30
31/**
32 * Write ESLint report to the <code>build</code> directory.
33 *
34 * @param cli {import('eslint').ESLint} The ESLint CLI.
35 * @param report {import('eslint').ESLint.LintResult[]} The ESLint report.
36 * @return {Promise<void>} A promise that resolves when the report is finished.
37 */
38async function reportToJson(cli, report) {
39 const jsonFormatter = await cli.loadFormatter('json');
40 const json = await jsonFormatter.format(report);
41 const reportPath = path.join(rootDir, 'build', 'eslint.json');
42 return writeFile(reportPath, json, 'utf-8');
43}
44
45async function createReport() {
46 const cli = new ESLint({
47 useEslintrc: true,
48 cwd: rootDir,
49 });
50 const report = await cli.lintFiles('.');
51 await Promise.all([reportToConsole(cli, report), reportToJson(cli, report)]);
52
53 if (report.some((entry) => entry.errorCount > 0)) {
54 process.exitCode = 1;
55 }
56}
57
58createReport().catch(console.error);
diff --git a/subprojects/frontend/package.json b/subprojects/frontend/package.json
index f7f6e8f8..c53d515f 100644
--- a/subprojects/frontend/package.json
+++ b/subprojects/frontend/package.json
@@ -10,11 +10,11 @@
10 "type": "module", 10 "type": "module",
11 "private": true, 11 "private": true,
12 "scripts": { 12 "scripts": {
13 "build": "cross-env MODE=production vite build", 13 "build": "MODE=production vite build",
14 "serve": "cross-env MODE=development vite serve", 14 "serve": "MODE=development vite serve",
15 "typegen": "xstate typegen \"src/**/*.ts?(x)\"", 15 "typegen": "xstate typegen \"src/**/*.ts?(x)\"",
16 "typecheck": "tsc -p tsconfig.shared.json && tsc -p tsconfig.node.json && tsc -p tsconfig.json", 16 "typecheck": "yarn run g:tsc -p subprojects/frontend/tsconfig.shared.json && yarn run g:tsc -p subprojects/frontend/tsconfig.node.json && yarn run g:tsc -p subprojects/frontend/tsconfig.json",
17 "lint": "node config/eslintReport.cjs", 17 "lint": "yarn run g:lint subprojects/frontend",
18 "lint:fix": "yarn run lint --fix" 18 "lint:fix": "yarn run lint --fix"
19 }, 19 },
20 "repository": { 20 "repository": {
@@ -83,7 +83,6 @@
83 "@types/d3-graphviz": "^2.6.10", 83 "@types/d3-graphviz": "^2.6.10",
84 "@types/d3-selection": "^3.0.10", 84 "@types/d3-selection": "^3.0.10",
85 "@types/d3-zoom": "^3.0.8", 85 "@types/d3-zoom": "^3.0.8",
86 "@types/eslint": "^8.56.7",
87 "@types/html-minifier-terser": "^7.0.2", 86 "@types/html-minifier-terser": "^7.0.2",
88 "@types/jspdf": "^2.0.0", 87 "@types/jspdf": "^2.0.0",
89 "@types/lodash-es": "^4.17.12", 88 "@types/lodash-es": "^4.17.12",
@@ -93,26 +92,11 @@
93 "@types/pnpapi": "^0.0.5", 92 "@types/pnpapi": "^0.0.5",
94 "@types/react": "^18.2.74", 93 "@types/react": "^18.2.74",
95 "@types/react-dom": "^18.2.23", 94 "@types/react-dom": "^18.2.23",
96 "@typescript-eslint/eslint-plugin": "^7.5.0",
97 "@typescript-eslint/parser": "^7.5.0",
98 "@vitejs/plugin-react-swc": "^3.6.0", 95 "@vitejs/plugin-react-swc": "^3.6.0",
99 "@xstate/cli": "^0.5.17", 96 "@xstate/cli": "^0.5.17",
100 "cross-env": "^7.0.3",
101 "eslint": "^8.57.0",
102 "eslint-config-airbnb": "^19.0.4",
103 "eslint-config-airbnb-typescript": "^18.0.0",
104 "eslint-config-prettier": "^9.1.0",
105 "eslint-import-resolver-typescript": "^3.6.1",
106 "eslint-plugin-import": "^2.29.1",
107 "eslint-plugin-jsx-a11y": "^6.8.0",
108 "eslint-plugin-mobx": "^0.0.9",
109 "eslint-plugin-prettier": "^5.1.3",
110 "eslint-plugin-react": "^7.34.1",
111 "eslint-plugin-react-hooks": "^4.6.0",
112 "html-minifier-terser": "^7.2.0", 97 "html-minifier-terser": "^7.2.0",
113 "micromatch": "^4.0.5", 98 "micromatch": "^4.0.5",
114 "pnpapi": "^0.0.0", 99 "pnpapi": "^0.0.0",
115 "prettier": "^3.2.5",
116 "typescript": "5.4.3", 100 "typescript": "5.4.3",
117 "vite": "^5.2.8", 101 "vite": "^5.2.8",
118 "vite-plugin-pwa": "^0.19.7", 102 "vite-plugin-pwa": "^0.19.7",
diff --git a/subprojects/frontend/package.json.orig b/subprojects/frontend/package.json.orig
deleted file mode 100644
index 34bbd6d2..00000000
--- a/subprojects/frontend/package.json.orig
+++ /dev/null
@@ -1,121 +0,0 @@
1{
2 "//": [
3 "SPDX-FileCopyrightText: 2021-2024 The Refinery Authors <https://refinery.tools/>",
4 "",
5 "SPDX-License-Identifier: EPL-2.0"
6 ],
7 "name": "@refinery/frontend",
8 "version": "0.0.0",
9 "description": "Web frontend for Refinery",
10 "type": "module",
11 "private": true,
12 "scripts": {
13 "build": "cross-env MODE=production vite build",
14 "serve": "cross-env MODE=development vite serve",
15 "typegen": "xstate typegen \"src/**/*.ts?(x)\"",
16 "typecheck": "tsc -p tsconfig.shared.json && tsc -p tsconfig.node.json && tsc -p tsconfig.json",
17 "lint": "node config/eslintReport.cjs",
18 "lint:fix": "yarn run lint --fix"
19 },
20 "repository": {
21 "type": "git",
22 "url": "git+https://github.com/graphs4value/refinery.git"
23 },
24 "author": "The Refinery Authors <https://refinery.tools/>",
25 "license": "EPL-2.0",
26 "bugs": {
27 "url": "https://github.com/graphs4value/refinery/issues"
28 },
29 "homepage": "https://refinery.tools",
30 "dependencies": {
31 "@codemirror/autocomplete": "^6.15.0",
32 "@codemirror/commands": "^6.3.3",
33 "@codemirror/language": "^6.10.1",
34 "@codemirror/lint": "^6.5.0",
35 "@codemirror/search": "^6.5.6",
36 "@codemirror/state": "^6.4.1",
37 "@codemirror/view": "^6.26.0",
38 "@emotion/cache": "^11.11.0",
39 "@emotion/react": "11.11.3",
40 "@emotion/serialize": "^1.1.3",
41 "@emotion/styled": "^11.11.0",
42 "@emotion/utils": "^1.2.1",
43 "@fontsource-variable/jetbrains-mono": "^5.0.20",
44 "@fontsource-variable/open-sans": "^5.0.28",
45 "@fontsource/open-sans": "^5.0.27",
46 "@hpcc-js/wasm": "^2.16.0",
47 "@lezer/common": "^1.2.1",
48 "@lezer/highlight": "^1.2.0",
49 "@lezer/lr": "^1.4.0",
50 "@material-icons/svg": "^1.0.33",
51 "@mui/icons-material": "5.15.11",
52 "@mui/material": "5.15.11",
53 "@mui/system": "5.15.11",
54 "@mui/x-data-grid": "6.19.5",
55 "ansi-styles": "^6.2.1",
56 "csstype": "^3.1.3",
57 "d3": "^7.9.0",
58 "d3-color": "^3.1.0",
59 "d3-graphviz": "patch:d3-graphviz@npm%3A5.3.0#~/.yarn/patches/d3-graphviz-npm-5.3.0-e0eace978a.patch",
60 "d3-selection": "^3.0.0",
61 "d3-zoom": "patch:d3-zoom@npm%3A3.0.0#~/.yarn/patches/d3-zoom-npm-3.0.0-18f706a421.patch",
62 "escape-string-regexp": "^5.0.0",
63 "jspdf": "^2.5.1",
64 "lodash-es": "^4.17.21",
65 "loglevel": "^1.9.1",
66 "loglevel-plugin-prefix": "^0.8.4",
67 "mobx": "^6.12.1",
68 "mobx-react-lite": "^4.0.6",
69 "ms": "^2.1.3",
70 "nanoid": "^5.0.6",
71 "notistack": "^3.0.1",
72 "react": "^18.2.0",
73 "react-dom": "^18.2.0",
74 "react-resize-detector": "^10.0.1",
75 "svg2pdf.js": "^2.2.3",
76 "xstate": "^4.38.3",
77 "zod": "^3.22.4"
78 },
79 "devDependencies": {
80 "@lezer/generator": "^1.7.0",
81 "@types/d3": "^7.4.3",
82 "@types/d3-color": "^3.1.3",
83 "@types/d3-graphviz": "^2.6.10",
84 "@types/d3-selection": "^3.0.10",
85 "@types/d3-zoom": "^3.0.8",
86 "@types/eslint": "^8.56.6",
87 "@types/html-minifier-terser": "^7.0.2",
88 "@types/jspdf": "^2.0.0",
89 "@types/lodash-es": "^4.17.12",
90 "@types/micromatch": "^4.0.6",
91 "@types/ms": "^0.7.34",
92 "@types/node": "^20.11.30",
93 "@types/pnpapi": "^0.0.5",
94 "@types/react": "^18.2.71",
95 "@types/react-dom": "^18.2.22",
96 "@typescript-eslint/eslint-plugin": "^7.4.0",
97 "@typescript-eslint/parser": "^7.4.0",
98 "@vitejs/plugin-react-swc": "^3.6.0",
99 "@xstate/cli": "^0.5.17",
100 "cross-env": "^7.0.3",
101 "eslint": "^8.57.0",
102 "eslint-config-airbnb": "^19.0.4",
103 "eslint-config-airbnb-typescript": "^18.0.0",
104 "eslint-config-prettier": "^9.1.0",
105 "eslint-import-resolver-typescript": "^3.6.1",
106 "eslint-plugin-import": "^2.29.1",
107 "eslint-plugin-jsx-a11y": "^6.8.0",
108 "eslint-plugin-mobx": "^0.0.9",
109 "eslint-plugin-prettier": "^5.1.3",
110 "eslint-plugin-react": "^7.34.1",
111 "eslint-plugin-react-hooks": "^4.6.0",
112 "html-minifier-terser": "^7.2.0",
113 "micromatch": "^4.0.5",
114 "pnpapi": "^0.0.0",
115 "prettier": "^3.2.5",
116 "typescript": "5.4.3",
117 "vite": "5.1.4",
118 "vite-plugin-pwa": "0.19.0",
119 "workbox-window": "^7.0.0"
120 }
121}
diff --git a/subprojects/frontend/prettier.config.cjs b/subprojects/frontend/prettier.config.cjs
deleted file mode 100644
index 6f9ff7ad..00000000
--- a/subprojects/frontend/prettier.config.cjs
+++ /dev/null
@@ -1,11 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6
7/** @type {import('prettier').Config} */
8module.exports = {
9 singleQuote: true,
10 trailingComma: 'all',
11};
diff --git a/subprojects/frontend/tsconfig.base.json b/subprojects/frontend/tsconfig.base.json
deleted file mode 100644
index 545eca35..00000000
--- a/subprojects/frontend/tsconfig.base.json
+++ /dev/null
@@ -1,41 +0,0 @@
1/*
2 * Copyright (c) Microsoft Corporation.
3 * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/>
4 *
5 * SPDX-License-Identifier: MIT
6 *
7 * This file is based on
8 * https://github.com/tsconfig/bases/blob/7db25a41bc5a9c0f66d91f6f3aa28438afcb2f18/bases/strictest.json
9 * but we moved it inside the project for better tooling support.
10 */
11{
12 "compilerOptions": {
13 "strict": true,
14 "allowUnusedLabels": false,
15 "allowUnreachableCode": false,
16 "exactOptionalPropertyTypes": true,
17 "noFallthroughCasesInSwitch": true,
18 "noImplicitOverride": true,
19 "noImplicitReturns": true,
20 "noPropertyAccessFromIndexSignature": true,
21 "noUncheckedIndexedAccess": true,
22 "noUnusedLocals": true,
23 "noUnusedParameters": true,
24 // "verbatimModuleSyntax" is incompatible with `import` syntax in modules
25 // with CommonJS import resolution, so we use "isolatedModules" only.
26 // "verbatimModuleSyntax": false,
27 "isolatedModules": true,
28 "checkJs": true,
29 "esModuleInterop": true,
30 "skipLibCheck": true,
31 "forceConsistentCasingInFileNames": true,
32 "useDefineForClassFields": true,
33 // Project-specific configuration below.
34 "module": "es2022",
35 "moduleResolution": "node",
36 "incremental": true,
37 "declaration": true,
38 "emitDeclarationOnly": true,
39 "outDir": "build/typescript"
40 }
41}
diff --git a/subprojects/frontend/tsconfig.json b/subprojects/frontend/tsconfig.json
index 06f6d8fe..3b20bc83 100644
--- a/subprojects/frontend/tsconfig.json
+++ b/subprojects/frontend/tsconfig.json
@@ -4,7 +4,7 @@
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6{ 6{
7 "extends": "./tsconfig.base.json", 7 "extends": "../../tsconfig.base.json",
8 "compilerOptions": { 8 "compilerOptions": {
9 "jsx": "react-jsx", 9 "jsx": "react-jsx",
10 "lib": ["DOM", "DOM.Iterable", "ES2022"], 10 "lib": ["DOM", "DOM.Iterable", "ES2022"],
diff --git a/subprojects/frontend/tsconfig.node.json b/subprojects/frontend/tsconfig.node.json
index 47feaf97..99e4eaca 100644
--- a/subprojects/frontend/tsconfig.node.json
+++ b/subprojects/frontend/tsconfig.node.json
@@ -4,7 +4,7 @@
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6{ 6{
7 "extends": "./tsconfig.base.json", 7 "extends": "../../tsconfig.base.json",
8 "compilerOptions": { 8 "compilerOptions": {
9 "composite": true, 9 "composite": true,
10 "lib": ["ES2022"], 10 "lib": ["ES2022"],
diff --git a/subprojects/frontend/tsconfig.shared.json b/subprojects/frontend/tsconfig.shared.json
index 154fe122..fe4e78e7 100644
--- a/subprojects/frontend/tsconfig.shared.json
+++ b/subprojects/frontend/tsconfig.shared.json
@@ -4,7 +4,7 @@
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6{ 6{
7 "extends": "./tsconfig.base.json", 7 "extends": "../../tsconfig.base.json",
8 "compilerOptions": { 8 "compilerOptions": {
9 "composite": true, 9 "composite": true,
10 "lib": ["ES2022"], 10 "lib": ["ES2022"],