experiments

All kinds of coding experiments
Log | Files | Refs | Submodules

setupTypeScript.js (4040B)


      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 const fs = require("fs")
     17 const path = require("path")
     18 const { argv } = require("process")
     19 
     20 const projectRoot = argv[2] || path.join(__dirname, "..")
     21 
     22 // Add deps to pkg.json
     23 const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8"))
     24 packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, {
     25   "svelte-check": "^2.0.0",
     26   "svelte-preprocess": "^4.0.0",
     27   "@rollup/plugin-typescript": "^8.0.0",
     28   "typescript": "^4.0.0",
     29   "tslib": "^2.0.0",
     30   "@tsconfig/svelte": "^2.0.0"
     31 })
     32 
     33 // Add script for checking
     34 packageJSON.scripts = Object.assign(packageJSON.scripts, {
     35   "check": "svelte-check --tsconfig ./tsconfig.json"
     36 })
     37 
     38 // Write the package JSON
     39 fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, "  "))
     40 
     41 // mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too
     42 const beforeMainJSPath = path.join(projectRoot, "src", "main.js")
     43 const afterMainTSPath = path.join(projectRoot, "src", "main.ts")
     44 fs.renameSync(beforeMainJSPath, afterMainTSPath)
     45 
     46 // Switch the app.svelte file to use TS
     47 const appSveltePath = path.join(projectRoot, "src", "App.svelte")
     48 let appFile = fs.readFileSync(appSveltePath, "utf8")
     49 appFile = appFile.replace("<script>", '<script lang="ts">')
     50 appFile = appFile.replace("export let name;", 'export let name: string;')
     51 fs.writeFileSync(appSveltePath, appFile)
     52 
     53 // Edit rollup config
     54 const rollupConfigPath = path.join(projectRoot, "rollup.config.js")
     55 let rollupConfig = fs.readFileSync(rollupConfigPath, "utf8")
     56 
     57 // Edit imports
     58 rollupConfig = rollupConfig.replace(`'rollup-plugin-terser';`, `'rollup-plugin-terser';
     59 import sveltePreprocess from 'svelte-preprocess';
     60 import typescript from '@rollup/plugin-typescript';`)
     61 
     62 // Replace name of entry point
     63 rollupConfig = rollupConfig.replace(`'src/main.js'`, `'src/main.ts'`)
     64 
     65 // Add preprocessor
     66 rollupConfig = rollupConfig.replace(
     67   'compilerOptions:',
     68   'preprocess: sveltePreprocess({ sourceMap: !production }),\n\t\t\tcompilerOptions:'
     69 );
     70 
     71 // Add TypeScript
     72 rollupConfig = rollupConfig.replace(
     73   'commonjs(),',
     74   'commonjs(),\n\t\ttypescript({\n\t\t\tsourceMap: !production,\n\t\t\tinlineSources: !production\n\t\t}),'
     75 );
     76 fs.writeFileSync(rollupConfigPath, rollupConfig)
     77 
     78 // Add TSConfig
     79 const tsconfig = `{
     80   "extends": "@tsconfig/svelte/tsconfig.json",
     81 
     82   "include": ["src/**/*"],
     83   "exclude": ["node_modules/*", "__sapper__/*", "public/*"]
     84 }`
     85 const tsconfigPath =  path.join(projectRoot, "tsconfig.json")
     86 fs.writeFileSync(tsconfigPath, tsconfig)
     87 
     88 // Add global.d.ts
     89 const dtsPath =  path.join(projectRoot, "src", "global.d.ts")
     90 fs.writeFileSync(dtsPath, `/// <reference types="svelte" />`)
     91 
     92 // Delete this script, but not during testing
     93 if (!argv[2]) {
     94   // Remove the script
     95   fs.unlinkSync(path.join(__filename))
     96 
     97   // Check for Mac's DS_store file, and if it's the only one left remove it
     98   const remainingFiles = fs.readdirSync(path.join(__dirname))
     99   if (remainingFiles.length === 1 && remainingFiles[0] === '.DS_store') {
    100     fs.unlinkSync(path.join(__dirname, '.DS_store'))
    101   }
    102 
    103   // Check if the scripts folder is empty
    104   if (fs.readdirSync(path.join(__dirname)).length === 0) {
    105     // Remove the scripts folder
    106     fs.rmdirSync(path.join(__dirname))
    107   }
    108 }
    109 
    110 // Adds the extension recommendation
    111 fs.mkdirSync(path.join(projectRoot, ".vscode"), { recursive: true })
    112 fs.writeFileSync(path.join(projectRoot, ".vscode", "extensions.json"), `{
    113   "recommendations": ["svelte.svelte-vscode"]
    114 }
    115 `)
    116 
    117 console.log("Converted to TypeScript.")
    118 
    119 if (fs.existsSync(path.join(projectRoot, "node_modules"))) {
    120   console.log("\nYou will need to re-run your dependency manager to get started.")
    121 }