Skip to content

Commit 70f143f

Browse files
generated tsconfig.json (#4118)
* generated tsconfig.json * eval user config * Update packages/kit/src/core/tsconfig.js Co-authored-by: Ben McCann <[email protected]> * use kleur instead of magic ansi codes * use base-relative URLs * paths should be relative to baseURL * include/exclude are NOT relative to baseURL * tidy up * tidy up, relativise paths consistently * move validation into separate function Co-authored-by: Ben McCann <[email protected]>
1 parent 353d94e commit 70f143f

File tree

6 files changed

+130
-42
lines changed

6 files changed

+130
-42
lines changed

Diff for: .changeset/silver-horses-check.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'create-svelte': patch
3+
'@sveltejs/kit': patch
4+
---
5+
6+
Extend user tsconfig from generated .svelte-kit/tsconfig.json
+1-34
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,3 @@
11
{
2-
"compilerOptions": {
3-
"moduleResolution": "node",
4-
"module": "es2020",
5-
"lib": ["es2020", "DOM"],
6-
"target": "es2020",
7-
/**
8-
svelte-preprocess cannot figure out whether you have a value or a type, so tell TypeScript
9-
to enforce using \`import type\` instead of \`import\` for Types.
10-
*/
11-
"importsNotUsedAsValues": "error",
12-
/**
13-
TypeScript doesn't know about import usages in the template because it only sees the
14-
script of a Svelte file. Therefore preserve all value imports. Requires TS 4.5 or higher.
15-
*/
16-
"preserveValueImports": true,
17-
"isolatedModules": true,
18-
"resolveJsonModule": true,
19-
/**
20-
To have warnings/errors of the Svelte compiler at the correct position,
21-
enable source maps by default.
22-
*/
23-
"sourceMap": true,
24-
"esModuleInterop": true,
25-
"skipLibCheck": true,
26-
"forceConsistentCasingInFileNames": true,
27-
"baseUrl": ".",
28-
"allowJs": true,
29-
"checkJs": true,
30-
"paths": {
31-
"$lib": ["src/lib"],
32-
"$lib/*": ["src/lib/*"]
33-
}
34-
},
35-
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts", "src/**/*.svelte"]
2+
"extends": "./.svelte-kit/tsconfig.json"
363
}
+1-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,3 @@
11
{
2-
"compilerOptions": {
3-
"baseUrl": ".",
4-
"paths": {
5-
"$lib": ["src/lib"],
6-
"$lib/*": ["src/lib/*"]
7-
}
8-
},
9-
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"]
2+
"extends": "./.svelte-kit/tsconfig.json"
103
}

Diff for: packages/kit/src/core/build/index.js

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { generate_manifest } from '../generate_manifest/index.js';
88
import { build_service_worker } from './build_service_worker.js';
99
import { build_client } from './build_client.js';
1010
import { build_server } from './build_server.js';
11+
import { generate_tsconfig } from '../tsconfig.js';
1112

1213
/**
1314
* @param {import('types').ValidatedConfig} config
@@ -24,6 +25,8 @@ export async function build(config) {
2425
rimraf(output_dir);
2526
mkdirp(output_dir);
2627

28+
generate_tsconfig(config);
29+
2730
const options = {
2831
cwd,
2932
config,

Diff for: packages/kit/src/core/dev/index.js

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { print_config_conflicts } from '../config/index.js';
66
import { SVELTE_KIT } from '../constants.js';
77
import { copy_assets, get_aliases, runtime } from '../utils.js';
88
import { create_plugin } from './plugin.js';
9+
import { generate_tsconfig } from '../tsconfig.js';
910

1011
/**
1112
* @typedef {{
@@ -22,6 +23,8 @@ import { create_plugin } from './plugin.js';
2223
export async function dev({ cwd, port, host, https, config }) {
2324
copy_assets(`${SVELTE_KIT}/runtime`);
2425

26+
generate_tsconfig(config);
27+
2528
const [vite_config] = deep_merge(
2629
{
2730
server: {

Diff for: packages/kit/src/core/tsconfig.js

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import fs from 'fs';
2+
import path from 'path';
3+
import colors from 'kleur';
4+
import { mkdirp } from '../utils/filesystem.js';
5+
import { SVELTE_KIT } from './constants.js';
6+
7+
/** @param {string} file */
8+
const exists = (file) => fs.existsSync(file) && file;
9+
10+
/** @param {import('types').ValidatedConfig} config */
11+
export function generate_tsconfig(config) {
12+
const out = path.resolve(SVELTE_KIT, 'tsconfig.json');
13+
const user_file = exists('tsconfig.json') || exists('jsconfig.json');
14+
15+
if (user_file) validate(config, out, user_file);
16+
17+
mkdirp(SVELTE_KIT);
18+
19+
/** @param {string} file */
20+
const project_relative = (file) => path.relative('.', file);
21+
22+
/** @param {string} file */
23+
const config_relative = (file) => path.relative(SVELTE_KIT, file);
24+
25+
fs.writeFileSync(
26+
`${SVELTE_KIT}/tsconfig.json`,
27+
JSON.stringify(
28+
{
29+
compilerOptions: {
30+
moduleResolution: 'node',
31+
module: 'es2020',
32+
lib: ['es2020', 'DOM'],
33+
target: 'es2020',
34+
// svelte-preprocess cannot figure out whether you have a value or a type, so tell TypeScript
35+
// to enforce using \`import type\` instead of \`import\` for Types.
36+
importsNotUsedAsValues: 'error',
37+
// TypeScript doesn't know about import usages in the template because it only sees the
38+
// script of a Svelte file. Therefore preserve all value imports. Requires TS 4.5 or higher.
39+
preserveValueImports: true,
40+
isolatedModules: true,
41+
resolveJsonModule: true,
42+
// To have warnings/errors of the Svelte compiler at the correct position,
43+
// enable source maps by default.
44+
sourceMap: true,
45+
esModuleInterop: true,
46+
skipLibCheck: true,
47+
forceConsistentCasingInFileNames: true,
48+
baseUrl: config_relative('.'),
49+
allowJs: true,
50+
checkJs: true,
51+
paths: {
52+
$lib: [project_relative(config.kit.files.lib)],
53+
'$lib/*': [project_relative(config.kit.files.lib + '/*')]
54+
}
55+
},
56+
include: ['**/*.d.ts', '**/*.js', '**/*.ts', '**/*.svelte'].map(config_relative),
57+
exclude: ['node_modules/**'].map(config_relative)
58+
},
59+
null,
60+
'\t'
61+
)
62+
);
63+
}
64+
65+
/**
66+
* @param {import('types').ValidatedConfig} config
67+
* @param {string} out
68+
* @param {string} user_file
69+
*/
70+
function validate(config, out, user_file) {
71+
// we have to eval the file, since it's not parseable as JSON (contains comments)
72+
const user_tsconfig_json = fs.readFileSync(user_file, 'utf-8');
73+
const user_tsconfig = (0, eval)(`(${user_tsconfig_json})`);
74+
75+
// we need to check that the user's tsconfig extends the framework config
76+
const extend = user_tsconfig.extends;
77+
const extends_framework_config = extend && path.resolve('.', extend) === out;
78+
79+
if (extends_framework_config) {
80+
const { paths: user_paths } = user_tsconfig.compilerOptions || {};
81+
82+
if (user_paths) {
83+
const lib = user_paths['$lib'] || [];
84+
const lib_ = user_paths['$lib/*'] || [];
85+
86+
const missing_lib_paths =
87+
!lib.some(
88+
(/** @type {string} */ relative) => path.resolve('.', relative) === config.kit.files.lib
89+
) ||
90+
!lib_.some(
91+
(/** @type {string} */ relative) =>
92+
path.resolve('.', relative) === config.kit.files.lib + '/*'
93+
);
94+
95+
if (missing_lib_paths) {
96+
console.warn(
97+
colors
98+
.bold()
99+
.yellow(`Your compilerOptions.paths in ${user_file} should include the following:`)
100+
);
101+
const relative = path.relative('.', config.kit.files.lib);
102+
console.warn(`{\n "$lib":["${relative}"],\n "$lib/*":["${relative}/*"]\n}`);
103+
}
104+
}
105+
} else {
106+
let relative = path.relative('.', out);
107+
if (relative.startsWith(SVELTE_KIT)) relative = './' + relative;
108+
109+
console.warn(
110+
colors
111+
.bold()
112+
.yellow(`Your ${user_file} should extend the configuration generated by SvelteKit:`)
113+
);
114+
console.warn(`{\n "extends": "${relative}"\n}`);
115+
}
116+
}

0 commit comments

Comments
 (0)