setupTypeScript.js
1 // @ts-check 2 3 /** This script modifies the project to support TS code in .svelte files like: 4 5 <script lang="ts"> 6 export let name: string; 7 </script> 8 9 As well as validating the code for CI. 10 */ 11 12 /** To work on this script: 13 rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template 14 */ 15 16 import fs from "fs" 17 import path from "path" 18 import { argv } from "process" 19 import url from 'url'; 20 21 const __filename = url.fileURLToPath(import.meta.url); 22 const __dirname = url.fileURLToPath(new URL('.', import.meta.url)); 23 const projectRoot = argv[2] || path.join(__dirname, "..") 24 25 // Add deps to pkg.json 26 const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) 27 packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { 28 "svelte-check": "^3.0.0", 29 "svelte-preprocess": "^5.0.0", 30 "@rollup/plugin-typescript": "^11.0.0", 31 "typescript": "^4.9.0", 32 "tslib": "^2.5.0", 33 "@tsconfig/svelte": "^3.0.0" 34 }) 35 36 // Add script for checking 37 packageJSON.scripts = Object.assign(packageJSON.scripts, { 38 "check": "svelte-check" 39 }) 40 41 // Write the package JSON 42 fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) 43 44 // mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too 45 const beforeMainJSPath = path.join(projectRoot, "src", "main.js") 46 const afterMainTSPath = path.join(projectRoot, "src", "main.ts") 47 fs.renameSync(beforeMainJSPath, afterMainTSPath) 48 49 // Switch the app.svelte file to use TS 50 const appSveltePath = path.join(projectRoot, "src", "App.svelte") 51 let appFile = fs.readFileSync(appSveltePath, "utf8") 52 appFile = appFile.replace("<script>", '<script lang="ts">') 53 appFile = appFile.replace("export let name;", 'export let name: string;') 54 fs.writeFileSync(appSveltePath, appFile) 55 56 // Edit rollup config 57 const rollupConfigPath = path.join(projectRoot, "rollup.config.js") 58 let rollupConfig = fs.readFileSync(rollupConfigPath, "utf8") 59 60 // Edit imports 61 rollupConfig = rollupConfig.replace(`'rollup-plugin-css-only';`, `'rollup-plugin-css-only'; 62 import sveltePreprocess from 'svelte-preprocess'; 63 import typescript from '@rollup/plugin-typescript';`) 64 65 // Replace name of entry point 66 rollupConfig = rollupConfig.replace(`'src/main.js'`, `'src/main.ts'`) 67 68 // Add preprocessor 69 rollupConfig = rollupConfig.replace( 70 'compilerOptions:', 71 'preprocess: sveltePreprocess({ sourceMap: !production }),\n\t\t\tcompilerOptions:' 72 ); 73 74 // Add TypeScript 75 rollupConfig = rollupConfig.replace( 76 'commonjs(),', 77 'commonjs(),\n\t\ttypescript({\n\t\t\tsourceMap: !production,\n\t\t\tinlineSources: !production\n\t\t}),' 78 ); 79 fs.writeFileSync(rollupConfigPath, rollupConfig) 80 81 // Add svelte.config.js 82 const tsconfig = `{ 83 "extends": "@tsconfig/svelte/tsconfig.json", 84 85 "include": ["src/**/*"], 86 "exclude": ["node_modules/*", "__sapper__/*", "public/*"] 87 }` 88 const tsconfigPath = path.join(projectRoot, "tsconfig.json") 89 fs.writeFileSync(tsconfigPath, tsconfig) 90 91 // Add TSConfig 92 const svelteConfig = `import sveltePreprocess from 'svelte-preprocess'; 93 94 export default { 95 preprocess: sveltePreprocess() 96 }; 97 ` 98 const svelteConfigPath = path.join(projectRoot, "svelte.config.js") 99 fs.writeFileSync(svelteConfigPath, svelteConfig) 100 101 // Add global.d.ts 102 const dtsPath = path.join(projectRoot, "src", "global.d.ts") 103 fs.writeFileSync(dtsPath, `/// <reference types="svelte" />`) 104 105 // Delete this script, but not during testing 106 if (!argv[2]) { 107 // Remove the script 108 fs.unlinkSync(path.join(__filename)) 109 110 // Check for Mac's DS_store file, and if it's the only one left remove it 111 const remainingFiles = fs.readdirSync(path.join(__dirname)) 112 if (remainingFiles.length === 1 && remainingFiles[0] === '.DS_store') { 113 fs.unlinkSync(path.join(__dirname, '.DS_store')) 114 } 115 116 // Check if the scripts folder is empty 117 if (fs.readdirSync(path.join(__dirname)).length === 0) { 118 // Remove the scripts folder 119 fs.rmdirSync(path.join(__dirname)) 120 } 121 } 122 123 // Adds the extension recommendation 124 fs.mkdirSync(path.join(projectRoot, ".vscode"), { recursive: true }) 125 fs.writeFileSync(path.join(projectRoot, ".vscode", "extensions.json"), `{ 126 "recommendations": ["svelte.svelte-vscode"] 127 } 128 `) 129 130 console.log("Converted to TypeScript.") 131 132 if (fs.existsSync(path.join(projectRoot, "node_modules"))) { 133 console.log("\nYou will need to re-run your dependency manager to get started.") 134 }