144 lines
4.2 KiB
JavaScript
144 lines
4.2 KiB
JavaScript
|
// @ts-check
|
||
|
|
||
|
/** This script modifies the project to support TS code in .svelte files like:
|
||
|
|
||
|
<script lang="ts">
|
||
|
export let name: string;
|
||
|
</script>
|
||
|
|
||
|
As well as validating the code for CI.
|
||
|
*/
|
||
|
|
||
|
/** To work on this script:
|
||
|
rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template
|
||
|
*/
|
||
|
|
||
|
const fs = require("fs");
|
||
|
const path = require("path");
|
||
|
const { argv } = require("process");
|
||
|
|
||
|
const projectRoot = argv[2] || path.join(__dirname, "..");
|
||
|
|
||
|
// Add deps to pkg.json
|
||
|
const packageJSON = JSON.parse(
|
||
|
fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")
|
||
|
);
|
||
|
packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, {
|
||
|
"svelte-check": "^1.2.5",
|
||
|
"svelte-preprocess": "^4.6.9",
|
||
|
"@rollup/plugin-typescript": "^8.2.0",
|
||
|
typescript: "^4.2.3",
|
||
|
tslib: "^2.1.0",
|
||
|
"@tsconfig/svelte": "^1.0.10",
|
||
|
});
|
||
|
|
||
|
// Add script for checking
|
||
|
packageJSON.scripts = Object.assign(packageJSON.scripts, {
|
||
|
validate: "svelte-check",
|
||
|
});
|
||
|
|
||
|
// Write the package JSON
|
||
|
fs.writeFileSync(
|
||
|
path.join(projectRoot, "package.json"),
|
||
|
JSON.stringify(packageJSON, null, " ")
|
||
|
);
|
||
|
|
||
|
// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too
|
||
|
const beforeMainJSPath = path.join(projectRoot, "src", "main.js");
|
||
|
const afterMainTSPath = path.join(projectRoot, "src", "main.ts");
|
||
|
fs.renameSync(beforeMainJSPath, afterMainTSPath);
|
||
|
|
||
|
// Switch the app.svelte file to use TS
|
||
|
const appSveltePath = path.join(projectRoot, "src", "App.svelte");
|
||
|
let appFile = fs.readFileSync(appSveltePath, "utf8");
|
||
|
appFile = appFile.replace("<script>", '<script lang="ts">');
|
||
|
appFile = appFile.replace("export let name;", "export let name: string;");
|
||
|
fs.writeFileSync(appSveltePath, appFile);
|
||
|
|
||
|
// Edit rollup config
|
||
|
const rollupConfigPath = path.join(projectRoot, "rollup.config.js");
|
||
|
let rollupConfig = fs.readFileSync(rollupConfigPath, "utf8");
|
||
|
|
||
|
// Edit imports
|
||
|
rollupConfig = rollupConfig.replace(
|
||
|
`'rollup-plugin-terser';`,
|
||
|
`'rollup-plugin-terser';
|
||
|
import sveltePreprocess from 'svelte-preprocess';
|
||
|
import typescript from '@rollup/plugin-typescript';`
|
||
|
);
|
||
|
|
||
|
// Replace name of entry point
|
||
|
rollupConfig = rollupConfig.replace(`'src/main.js'`, `'src/main.ts'`);
|
||
|
|
||
|
// Add preprocess to the svelte config, this is tricky because there's no easy signifier.
|
||
|
// Instead we look for `css:` then the next `}` and add the preprocessor to that
|
||
|
let foundCSS = false;
|
||
|
let match;
|
||
|
|
||
|
// https://regex101.com/r/OtNjwo/1
|
||
|
const configEditor = new RegExp(/css:.|\n*}/gim);
|
||
|
while ((match = configEditor.exec(rollupConfig)) != null) {
|
||
|
if (foundCSS) {
|
||
|
const endOfCSSIndex = match.index + 1;
|
||
|
rollupConfig =
|
||
|
rollupConfig.slice(0, endOfCSSIndex) +
|
||
|
",\n preprocess: sveltePreprocess()," +
|
||
|
rollupConfig.slice(endOfCSSIndex);
|
||
|
break;
|
||
|
}
|
||
|
if (match[0].includes("css:")) foundCSS = true;
|
||
|
}
|
||
|
|
||
|
// Add TypeScript
|
||
|
rollupConfig = rollupConfig.replace(
|
||
|
"commonjs(),",
|
||
|
"commonjs(),\n\t\ttypescript({ sourceMap: !production }),"
|
||
|
);
|
||
|
fs.writeFileSync(rollupConfigPath, rollupConfig);
|
||
|
|
||
|
// Add TSConfig
|
||
|
const tsconfig = `{
|
||
|
"extends": "@tsconfig/svelte/tsconfig.json",
|
||
|
|
||
|
"include": ["src/**/*"],
|
||
|
"exclude": ["node_modules/*", "__sapper__/*", "public/*"],
|
||
|
}`;
|
||
|
const tsconfigPath = path.join(projectRoot, "tsconfig.json");
|
||
|
fs.writeFileSync(tsconfigPath, tsconfig);
|
||
|
|
||
|
// Delete this script, but not during testing
|
||
|
if (!argv[2]) {
|
||
|
// Remove the script
|
||
|
fs.unlinkSync(path.join(__filename));
|
||
|
|
||
|
// Check for Mac's DS_store file, and if it's the only one left remove it
|
||
|
const remainingFiles = fs.readdirSync(path.join(__dirname));
|
||
|
if (remainingFiles.length === 1 && remainingFiles[0] === ".DS_store") {
|
||
|
fs.unlinkSync(path.join(__dirname, ".DS_store"));
|
||
|
}
|
||
|
|
||
|
// Check if the scripts folder is empty
|
||
|
if (fs.readdirSync(path.join(__dirname)).length === 0) {
|
||
|
// Remove the scripts folder
|
||
|
fs.rmdirSync(path.join(__dirname));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Adds the extension recommendation
|
||
|
fs.mkdirSync(path.join(projectRoot, ".vscode"));
|
||
|
fs.writeFileSync(
|
||
|
path.join(projectRoot, ".vscode", "extensions.json"),
|
||
|
`{
|
||
|
"recommendations": ["svelte.svelte-vscode"]
|
||
|
}
|
||
|
`
|
||
|
);
|
||
|
|
||
|
console.log("Converted to TypeScript.");
|
||
|
|
||
|
if (fs.existsSync(path.join(projectRoot, "node_modules"))) {
|
||
|
console.log(
|
||
|
"\nYou will need to re-run your dependency manager to get started."
|
||
|
);
|
||
|
}
|