summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Erika <3019731+Princesseuh@users.noreply.github.com> 2022-10-12 15:11:25 -0300
committerGravatar GitHub <noreply@github.com> 2022-10-12 15:11:25 -0300
commit0ea6187f95f68d1a3ed98ef4d660e71206883bac (patch)
tree65e74ac43e8d70baa08d93850aa8ea0101154b4e
parenta5e3ecc8039c1e115ce5597362e18cd35d04e40b (diff)
downloadastro-0ea6187f95f68d1a3ed98ef4d660e71206883bac.tar.gz
astro-0ea6187f95f68d1a3ed98ef4d660e71206883bac.tar.zst
astro-0ea6187f95f68d1a3ed98ef4d660e71206883bac.zip
Added support for updating tsconfig.json when using astro add (#4959)
* Added support for updating tsconfig.json when using astro add * Refactor * Remove unneeded change * Fix build failling due to type difference * Extend changeset description
-rw-r--r--.changeset/giant-news-speak.md18
-rw-r--r--package.json3
-rw-r--r--packages/astro/package.json1
-rw-r--r--packages/astro/src/core/add/index.ts197
-rw-r--r--packages/astro/src/core/config/index.ts2
-rw-r--r--packages/astro/src/core/config/tsconfig.ts101
-rw-r--r--packages/astro/src/core/util.ts4
-rw-r--r--packages/astro/test/fixtures/tsconfig-handling/invalid/tsconfig.json3
-rw-r--r--packages/astro/test/fixtures/tsconfig-handling/jsconfig/jsconfig.json3
-rw-r--r--packages/astro/test/fixtures/tsconfig-handling/missing/.gitkeep0
-rw-r--r--packages/astro/test/fixtures/tsconfig-handling/nested-folder/.gitkeep0
-rw-r--r--packages/astro/test/fixtures/tsconfig-handling/tsconfig.json3
-rw-r--r--packages/astro/test/units/config/config-tsconfig.test.js68
-rw-r--r--packages/integrations/react/package.json3
-rw-r--r--pnpm-lock.yaml18
15 files changed, 388 insertions, 36 deletions
diff --git a/.changeset/giant-news-speak.md b/.changeset/giant-news-speak.md
new file mode 100644
index 000000000..f0fb38d64
--- /dev/null
+++ b/.changeset/giant-news-speak.md
@@ -0,0 +1,18 @@
+---
+'astro': minor
+---
+
+Added support for updating TypeScript settings automatically when using `astro add`
+
+The `astro add` command will now automatically update your `tsconfig.json` with the proper TypeScript settings needed for the chosen frameworks.
+
+For instance, typing `astro add solid` will update your `tsconfig.json` with the following settings, per [Solid's TypeScript guide](https://www.solidjs.com/guides/typescript):
+
+```json
+{
+ "compilerOptions": {
+ "jsx": "preserve",
+ "jsxImportSource": "solid-js"
+ }
+}
+```
diff --git a/package.json b/package.json
index e1d71d61c..cd298e1ff 100644
--- a/package.json
+++ b/package.json
@@ -53,6 +53,9 @@
}
}
},
+ "overrides": {
+ "tsconfig-resolver>type-fest": "3.0.0"
+ },
"peerDependencyRules": {
"ignoreMissing": [
"rollup",
diff --git a/packages/astro/package.json b/packages/astro/package.json
index 252a169f6..16a9a004d 100644
--- a/packages/astro/package.json
+++ b/packages/astro/package.json
@@ -116,6 +116,7 @@
"common-ancestor-path": "^1.0.1",
"cookie": "^0.5.0",
"debug": "^4.3.4",
+ "deepmerge-ts": "^4.2.2",
"diff": "^5.1.0",
"eol": "^0.9.1",
"es-module-lexer": "^0.10.5",
diff --git a/packages/astro/src/core/add/index.ts b/packages/astro/src/core/add/index.ts
index 0f4e387ed..396bf7eb9 100644
--- a/packages/astro/src/core/add/index.ts
+++ b/packages/astro/src/core/add/index.ts
@@ -3,14 +3,20 @@ import boxen from 'boxen';
import { diffWords } from 'diff';
import { execa } from 'execa';
import { existsSync, promises as fs } from 'fs';
-import { bold, cyan, dim, green, magenta, yellow } from 'kleur/colors';
+import { bold, cyan, dim, green, magenta, red, yellow } from 'kleur/colors';
import ora from 'ora';
import path from 'path';
import preferredPM from 'preferred-pm';
import prompts from 'prompts';
import { fileURLToPath, pathToFileURL } from 'url';
import type yargs from 'yargs-parser';
-import { resolveConfigPath } from '../config/index.js';
+import { loadTSConfig, resolveConfigPath } from '../config/index.js';
+import {
+ defaultTSConfig,
+ frameworkWithTSSettings,
+ presets,
+ updateTSConfigForFramework,
+} from '../config/tsconfig.js';
import { debug, info, LogOptions } from '../logger/core.js';
import * as msg from '../messages.js';
import { printHelp } from '../messages.js';
@@ -239,7 +245,7 @@ export default async function add(names: string[], { cwd, flags, logging, teleme
switch (configResult) {
case UpdateResult.cancelled: {
info(logging, null, msg.cancelled(`Your configuration has ${bold('NOT')} been updated.`));
- return;
+ break;
}
case UpdateResult.none: {
const pkgURL = new URL('./package.json', configURL);
@@ -253,12 +259,12 @@ export default async function add(names: string[], { cwd, flags, logging, teleme
);
if (missingDeps.length === 0) {
info(logging, null, msg.success(`Configuration up-to-date.`));
- return;
+ break;
}
}
info(logging, null, msg.success(`Configuration up-to-date.`));
- return;
+ break;
}
default: {
const list = integrations.map((integration) => ` - ${integration.packageName}`).join('\n');
@@ -273,6 +279,29 @@ export default async function add(names: string[], { cwd, flags, logging, teleme
);
}
}
+
+ const updateTSConfigResult = await updateTSConfig(cwd, logging, integrations, flags);
+
+ switch (updateTSConfigResult) {
+ case UpdateResult.none: {
+ break;
+ }
+ case UpdateResult.cancelled: {
+ info(
+ logging,
+ null,
+ msg.cancelled(`Your TypeScript configuration has ${bold('NOT')} been updated.`)
+ );
+ break;
+ }
+ case UpdateResult.failure: {
+ throw new Error(
+ `Unknown error parsing tsconfig.json or jsconfig.json. Could not update TypeScript settings.`
+ );
+ }
+ default:
+ info(logging, null, msg.success(`Successfully updated TypeScript settings`));
+ }
}
function isAdapter(
@@ -471,29 +500,13 @@ async function updateAstroConfig({
return UpdateResult.none;
}
- let changes = [];
- for (const change of diffWords(input, output)) {
- let lines = change.value.trim().split('\n').slice(0, change.count);
- if (lines.length === 0) continue;
- if (change.added) {
- if (!change.value.trim()) continue;
- changes.push(change.value);
- }
- }
- if (changes.length === 0) {
- return UpdateResult.none;
- }
+ const diff = getDiffContent(input, output);
- let diffed = output;
- for (let newContent of changes) {
- const coloredOutput = newContent
- .split('\n')
- .map((ln) => (ln ? green(ln) : ''))
- .join('\n');
- diffed = diffed.replace(newContent, coloredOutput);
+ if (!diff) {
+ return UpdateResult.none;
}
- const message = `\n${boxen(diffed, {
+ const message = `\n${boxen(diff, {
margin: 0.5,
padding: 0.5,
borderStyle: 'round',
@@ -533,6 +546,7 @@ interface InstallCommand {
flags: string[];
dependencies: string[];
}
+
async function getInstallIntegrationsCommand({
integrations,
cwd = process.cwd(),
@@ -727,6 +741,113 @@ export async function validateIntegrations(integrations: string[]): Promise<Inte
}
}
+async function updateTSConfig(
+ cwd = process.cwd(),
+ logging: LogOptions,
+ integrationsInfo: IntegrationInfo[],
+ flags: yargs.Arguments
+): Promise<UpdateResult> {
+ const integrations = integrationsInfo.map(
+ (integration) => integration.id as frameworkWithTSSettings
+ );
+ const firstIntegrationWithTSSettings = integrations.find((integration) =>
+ presets.has(integration)
+ );
+
+ if (!firstIntegrationWithTSSettings) {
+ return UpdateResult.none;
+ }
+
+ const inputConfig = loadTSConfig(cwd, false);
+ const configFileName = inputConfig.exists ? inputConfig.path.split('/').pop() : 'tsconfig.json';
+
+ if (inputConfig.reason === 'invalid-config') {
+ return UpdateResult.failure;
+ }
+
+ if (inputConfig.reason === 'not-found') {
+ debug('add', "Couldn't find tsconfig.json or jsconfig.json, generating one");
+ }
+
+ const outputConfig = updateTSConfigForFramework(
+ inputConfig.exists ? inputConfig.config : defaultTSConfig,
+ firstIntegrationWithTSSettings
+ );
+
+ const input = inputConfig.exists ? JSON.stringify(inputConfig.config, null, 2) : '';
+ const output = JSON.stringify(outputConfig, null, 2);
+ const diff = getDiffContent(input, output);
+
+ if (!diff) {
+ return UpdateResult.none;
+ }
+
+ const message = `\n${boxen(diff, {
+ margin: 0.5,
+ padding: 0.5,
+ borderStyle: 'round',
+ title: configFileName,
+ })}\n`;
+
+ info(
+ logging,
+ null,
+ `\n ${magenta(`Astro will make the following changes to your ${configFileName}:`)}\n${message}`
+ );
+
+ // Every major framework, apart from Vue and Svelte requires different `jsxImportSource`, as such it's impossible to config
+ // all of them in the same `tsconfig.json`. However, Vue only need `"jsx": "preserve"` for template intellisense which
+ // can be compatible with some frameworks (ex: Solid), though ultimately run into issues on the current version of Volar
+ const conflictingIntegrations = [...Object.keys(presets).filter((config) => config !== 'vue')];
+ const hasConflictingIntegrations =
+ integrations.filter((integration) => presets.has(integration)).length > 1 &&
+ integrations.filter((integration) => conflictingIntegrations.includes(integration)).length > 0;
+
+ if (hasConflictingIntegrations) {
+ info(
+ logging,
+ null,
+ red(
+ ` ${bold(
+ 'Caution:'
+ )} Selected UI frameworks require conflicting tsconfig.json settings, as such only settings for ${bold(
+ firstIntegrationWithTSSettings
+ )} were used.\n More information: https://docs.astro.build/en/guides/typescript/#errors-typing-multiple-jsx-frameworks-at-the-same-time\n`
+ )
+ );
+ }
+
+ // TODO: Remove this when Volar 1.0 ships, as it fixes the issue.
+ // Info: https://github.com/johnsoncodehk/volar/discussions/592#discussioncomment-3660903
+ if (
+ integrations.includes('vue') &&
+ hasConflictingIntegrations &&
+ ((outputConfig.compilerOptions?.jsx !== 'preserve' &&
+ outputConfig.compilerOptions?.jsxImportSource !== undefined) ||
+ integrations.includes('react')) // https://docs.astro.build/en/guides/typescript/#vue-components-are-mistakenly-typed-by-the-typesreact-package-when-installed
+ ) {
+ info(
+ logging,
+ null,
+ red(
+ ` ${bold(
+ 'Caution:'
+ )} Using Vue together with a JSX framework can lead to type checking issues inside Vue files.\n More information: https://docs.astro.build/en/guides/typescript/#vue-components-are-mistakenly-typed-by-the-typesreact-package-when-installed\n`
+ )
+ );
+ }
+
+ if (await askToContinue({ flags })) {
+ await fs.writeFile(inputConfig?.path ?? path.join(cwd, 'tsconfig.json'), output, {
+ encoding: 'utf-8',
+ });
+ debug('add', `Updated ${configFileName} file`);
+ return UpdateResult.updated;
+ } else {
+ return UpdateResult.cancelled;
+ }
+}
+
function parseIntegrationName(spec: string) {
const result = parseNpmName(spec);
if (!result) return;
@@ -755,3 +876,29 @@ async function askToContinue({ flags }: { flags: yargs.Arguments }): Promise<boo
return Boolean(response.askToContinue);
}
+
+function getDiffContent(input: string, output: string): string | null {
+ let changes = [];
+ for (const change of diffWords(input, output)) {
+ let lines = change.value.trim().split('\n').slice(0, change.count);
+ if (lines.length === 0) continue;
+ if (change.added) {
+ if (!change.value.trim()) continue;
+ changes.push(change.value);
+ }
+ }
+ if (changes.length === 0) {
+ return null;
+ }
+
+ let diffed = output;
+ for (let newContent of changes) {
+ const coloredOutput = newContent
+ .split('\n')
+ .map((ln) => (ln ? green(ln) : ''))
+ .join('\n');
+ diffed = diffed.replace(newContent, coloredOutput);
+ }
+
+ return diffed;
+}
diff --git a/packages/astro/src/core/config/index.ts b/packages/astro/src/core/config/index.ts
index 4984b3b91..195ab1430 100644
--- a/packages/astro/src/core/config/index.ts
+++ b/packages/astro/src/core/config/index.ts
@@ -7,4 +7,4 @@ export {
} from './config.js';
export type { AstroConfigSchema } from './schema';
export { createSettings } from './settings.js';
-export { loadTSConfig } from './tsconfig.js';
+export { loadTSConfig, updateTSConfigForFramework } from './tsconfig.js';
diff --git a/packages/astro/src/core/config/tsconfig.ts b/packages/astro/src/core/config/tsconfig.ts
index ddfa72300..e0ec7578b 100644
--- a/packages/astro/src/core/config/tsconfig.ts
+++ b/packages/astro/src/core/config/tsconfig.ts
@@ -1,11 +1,100 @@
+import { deepmerge } from 'deepmerge-ts';
import * as tsr from 'tsconfig-resolver';
+import { existsSync } from 'fs';
+import { join } from 'path';
-export function loadTSConfig(cwd: string | undefined): tsr.TsConfigResult | undefined {
- for (const searchName of ['tsconfig.json', 'jsconfig.json']) {
- const config = tsr.tsconfigResolverSync({ cwd, searchName });
- if (config.exists) {
- return config;
+export const defaultTSConfig: tsr.TsConfigJson = { extends: 'astro/tsconfigs/base' };
+
+export type frameworkWithTSSettings = 'vue' | 'react' | 'preact' | 'solid-js';
+// The following presets unfortunately cannot be inside the specific integrations, as we need
+// them even in cases where the integrations are not installed
+export const presets = new Map<frameworkWithTSSettings, tsr.TsConfigJson>([
+ [
+ 'vue', // Settings needed for template intellisense when using Volar
+ {
+ compilerOptions: {
+ jsx: 'preserve',
+ },
+ },
+ ],
+ [
+ 'react', // Default TypeScript settings, but we need to redefine them in case the users changed them previously
+ {
+ compilerOptions: {
+ jsx: 'react-jsx',
+ jsxImportSource: 'react',
+ },
+ },
+ ],
+ [
+ 'preact', // https://preactjs.com/guide/v10/typescript/#typescript-configuration
+ {
+ compilerOptions: {
+ jsx: 'react-jsx',
+ jsxImportSource: 'preact',
+ },
+ },
+ ],
+ [
+ 'solid-js', // https://www.solidjs.com/guides/typescript#configuring-typescript
+ {
+ compilerOptions: {
+ jsx: 'preserve',
+ jsxImportSource: 'solid-js',
+ },
+ },
+ ],
+]);
+
+/**
+ * Load a tsconfig.json or jsconfig.json is the former is not found
+ * @param cwd Directory to start from
+ * @param resolve Determine if the function should go up directories like TypeScript would
+ */
+export function loadTSConfig(cwd: string | undefined, resolve = true): tsr.TsConfigResult {
+ cwd = cwd ?? process.cwd();
+ let config = tsr.tsconfigResolverSync({
+ cwd,
+ filePath: resolve ? undefined : cwd,
+ });
+
+ // When a direct filepath is provided to `tsconfigResolver`, it'll instead return invalid-config even when
+ // the file does not exists. We'll manually handle this so we can provide better errors to users
+ if (!resolve && config.reason === 'invalid-config' && !existsSync(join(cwd, 'tsconfig.json'))) {
+ config = { reason: 'not-found', path: undefined, exists: false };
+ } else {
+ return config;
+ }
+
+ // If we couldn't find a tsconfig.json, try to load a jsconfig.json instead
+ if (config.reason === 'not-found') {
+ const jsconfig = tsr.tsconfigResolverSync({
+ cwd,
+ filePath: resolve ? undefined : cwd,
+ searchName: 'jsconfig.json',
+ });
+
+ if (
+ !resolve &&
+ jsconfig.reason === 'invalid-config' &&
+ !existsSync(join(cwd, 'jsconfig.json'))
+ ) {
+ return { reason: 'not-found', path: undefined, exists: false };
+ } else {
+ return jsconfig;
}
}
- return undefined;
+
+ return config;
+}
+
+export function updateTSConfigForFramework(
+ target: tsr.TsConfigJson,
+ framework: frameworkWithTSSettings
+): tsr.TsConfigJson {
+ if (!presets.has(framework)) {
+ return target;
+ }
+
+ return deepmerge(target, presets.get(framework)!);
}
diff --git a/packages/astro/src/core/util.ts b/packages/astro/src/core/util.ts
index 70cd7d2ac..ed049ff41 100644
--- a/packages/astro/src/core/util.ts
+++ b/packages/astro/src/core/util.ts
@@ -226,8 +226,8 @@ export function resolveJsToTs(filePath: string) {
}
export const AggregateError =
- typeof globalThis.AggregateError !== 'undefined'
- ? globalThis.AggregateError
+ typeof (globalThis as any).AggregateError !== 'undefined'
+ ? (globalThis as any).AggregateError
: class extends Error {
errors: Array<any> = [];
constructor(errors: Iterable<any>, message?: string | undefined) {
diff --git a/packages/astro/test/fixtures/tsconfig-handling/invalid/tsconfig.json b/packages/astro/test/fixtures/tsconfig-handling/invalid/tsconfig.json
new file mode 100644
index 000000000..0cad03048
--- /dev/null
+++ b/packages/astro/test/fixtures/tsconfig-handling/invalid/tsconfig.json
@@ -0,0 +1,3 @@
+{
+ "buildOptions":
+}
diff --git a/packages/astro/test/fixtures/tsconfig-handling/jsconfig/jsconfig.json b/packages/astro/test/fixtures/tsconfig-handling/jsconfig/jsconfig.json
new file mode 100644
index 000000000..ee8c7cd81
--- /dev/null
+++ b/packages/astro/test/fixtures/tsconfig-handling/jsconfig/jsconfig.json
@@ -0,0 +1,3 @@
+{
+ "files": ["im-a-test-js"]
+}
diff --git a/packages/astro/test/fixtures/tsconfig-handling/missing/.gitkeep b/packages/astro/test/fixtures/tsconfig-handling/missing/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/packages/astro/test/fixtures/tsconfig-handling/missing/.gitkeep
diff --git a/packages/astro/test/fixtures/tsconfig-handling/nested-folder/.gitkeep b/packages/astro/test/fixtures/tsconfig-handling/nested-folder/.gitkeep
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/packages/astro/test/fixtures/tsconfig-handling/nested-folder/.gitkeep
diff --git a/packages/astro/test/fixtures/tsconfig-handling/tsconfig.json b/packages/astro/test/fixtures/tsconfig-handling/tsconfig.json
new file mode 100644
index 000000000..c676c0234
--- /dev/null
+++ b/packages/astro/test/fixtures/tsconfig-handling/tsconfig.json
@@ -0,0 +1,3 @@
+{
+ "files": ["im-a-test"]
+}
diff --git a/packages/astro/test/units/config/config-tsconfig.test.js b/packages/astro/test/units/config/config-tsconfig.test.js
new file mode 100644
index 000000000..3e53278fa
--- /dev/null
+++ b/packages/astro/test/units/config/config-tsconfig.test.js
@@ -0,0 +1,68 @@
+import { expect } from 'chai';
+import { fileURLToPath } from 'url';
+import { loadTSConfig, updateTSConfigForFramework } from '../../../dist/core/config/index.js';
+import * as path from 'path';
+import * as tsr from 'tsconfig-resolver';
+
+const cwd = fileURLToPath(new URL('../../fixtures/tsconfig-handling/', import.meta.url));
+
+describe('TSConfig handling', () => {
+ beforeEach(() => {
+ // `tsconfig-resolver` has a weird internal cache that only vaguely respect its own rules when not resolving
+ // so we need to clear it before each test or we'll get false positives. This should only be relevant in tests.
+ tsr.clearCache();
+ });
+
+ describe('tsconfig / jsconfig loading', () => {
+ it('can load tsconfig.json', () => {
+ const config = loadTSConfig(cwd);
+
+ expect(config.exists).to.equal(true);
+ expect(config.config.files).to.deep.equal(['im-a-test']);
+ });
+
+ it('can resolve tsconfig.json up directories', () => {
+ const config = loadTSConfig(path.join(cwd, 'nested-folder'));
+
+ expect(config.exists).to.equal(true);
+ expect(config.path).to.equal(path.join(cwd, 'tsconfig.json'));
+ expect(config.config.files).to.deep.equal(['im-a-test']);
+ });
+
+ it('can fallback to jsconfig.json if tsconfig.json does not exists', () => {
+ const config = loadTSConfig(path.join(cwd, 'jsconfig'), false);
+
+ expect(config.exists).to.equal(true);
+ expect(config.path).to.equal(path.join(cwd, 'jsconfig', 'jsconfig.json'));
+ expect(config.config.files).to.deep.equal(['im-a-test-js']);
+ });
+
+ it('properly return errors when not resolving', () => {
+ const invalidConfig = loadTSConfig(path.join(cwd, 'invalid'), false);
+ const missingConfig = loadTSConfig(path.join(cwd, 'missing'), false);
+
+ expect(invalidConfig.exists).to.equal(false);
+ expect(invalidConfig.reason).to.equal('invalid-config');
+
+ expect(missingConfig.exists).to.equal(false);
+ expect(missingConfig.reason).to.equal('not-found');
+ });
+ });
+
+ describe('tsconfig / jsconfig updates', () => {
+ it('can update a tsconfig with a framework config', () => {
+ const config = loadTSConfig(cwd);
+ const updatedConfig = updateTSConfigForFramework(config.config, 'react');
+
+ expect(config.config).to.not.equal('react-jsx');
+ expect(updatedConfig.compilerOptions.jsx).to.equal('react-jsx');
+ });
+
+ it('produce no changes on invalid frameworks', () => {
+ const config = loadTSConfig(cwd);
+ const updatedConfig = updateTSConfigForFramework(config.config, 'doesnt-exist');
+
+ expect(config.config).to.deep.equal(updatedConfig);
+ });
+ });
+});
diff --git a/packages/integrations/react/package.json b/packages/integrations/react/package.json
index 7b7b7644f..980752eec 100644
--- a/packages/integrations/react/package.json
+++ b/packages/integrations/react/package.json
@@ -47,7 +47,8 @@
},
"peerDependencies": {
"react": "^17.0.2 || ^18.0.0",
- "react-dom": "^17.0.2 || ^18.0.0"
+ "react-dom": "^17.0.2 || ^18.0.0",
+ "@types/react": "^17.0.50 || ^18.0.21"
},
"engines": {
"node": "^14.18.0 || >=16.12.0"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 67501c838..b9258f1bb 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1,5 +1,8 @@
lockfileVersion: 5.4
+overrides:
+ tsconfig-resolver>type-fest: 3.0.0
+
packageExtensionsChecksum: 01871422d489547c532184effb134b35
patchedDependencies:
@@ -405,6 +408,7 @@ importers:
common-ancestor-path: ^1.0.1
cookie: ^0.5.0
debug: ^4.3.4
+ deepmerge-ts: ^4.2.2
diff: ^5.1.0
eol: ^0.9.1
es-module-lexer: ^0.10.5
@@ -475,6 +479,7 @@ importers:
common-ancestor-path: 1.0.1
cookie: 0.5.0
debug: 4.3.4
+ deepmerge-ts: 4.2.2
diff: 5.1.0
eol: 0.9.1
es-module-lexer: 0.10.5
@@ -11257,6 +11262,11 @@ packages:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
dev: true
+ /deepmerge-ts/4.2.2:
+ resolution: {integrity: sha512-Ka3Kb21tiWjvQvS9U+1Dx+aqFAHsdTnMdYptLTmC2VAmDFMugWMY1e15aTODstipmCun8iNuqeSfcx6rsUUk0Q==}
+ engines: {node: '>=12.4.0'}
+ dev: false
+
/deepmerge/4.2.2:
resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==}
engines: {node: '>=0.10.0'}
@@ -17177,7 +17187,8 @@ packages:
json5: 2.2.1
resolve: 1.22.1
strip-bom: 4.0.0
- type-fest: 0.13.1
+ type-fest: 3.0.0
+ dev: false
/tsconfig/7.0.0:
resolution: {integrity: sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==}
@@ -17402,6 +17413,11 @@ packages:
engines: {node: '>=12.20'}
dev: false
+ /type-fest/3.0.0:
+ resolution: {integrity: sha512-MINvUN5ug9u+0hJDzSZNSnuKXI8M4F5Yvb6SQZ2CYqe7SgKXKOosEcU5R7tRgo85I6eAVBbkVF7TCvB4AUK2xQ==}
+ engines: {node: '>=14.16'}
+ dev: false
+
/type-is/1.6.18:
resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==}
engines: {node: '>= 0.6'}