From 5fbc4755a85899e6b521158179ec524b57519a6c Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 19 Oct 2020 23:42:48 -0400 Subject: [PATCH 1/5] add TypeScript support at project init --- .changeset/soft-bats-build.md | 5 ++++ packages/create-svelte/cli/index.js | 16 ++++++++++++ .../cli/modifications/add_typescript.js | 25 +++++++++++++++++++ packages/create-svelte/template/package.json | 3 ++- .../template/src/components/Counter.svelte | 2 +- .../create-svelte/template/svelte.config.js | 8 +++++- 6 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 .changeset/soft-bats-build.md create mode 100644 packages/create-svelte/cli/modifications/add_typescript.js diff --git a/.changeset/soft-bats-build.md b/.changeset/soft-bats-build.md new file mode 100644 index 000000000000..89087b5db80e --- /dev/null +++ b/.changeset/soft-bats-build.md @@ -0,0 +1,5 @@ +--- +'create-svelte': patch +--- + +Add TypeScript support at project init diff --git a/packages/create-svelte/cli/index.js b/packages/create-svelte/cli/index.js index c3adca318c5c..8dc55e82d969 100644 --- a/packages/create-svelte/cli/index.js +++ b/packages/create-svelte/cli/index.js @@ -6,6 +6,7 @@ import { mkdirp } from '@sveltejs/app-utils'; import gitignore_contents from '../template/.gitignore'; import prompts from 'prompts/lib/index'; import glob from 'tiny-glob/sync'; +import add_typescript from './modifications/add_typescript.js'; async function main() { const target = process.argv[2] || '.'; @@ -52,6 +53,21 @@ async function main() { fs.writeFileSync(pkg_file, pkg_json.replace(/workspace:/g, '').replace('~TODO~', name)); console.log(bold(green(`✔ Copied project files`))); + + // modifications + const modifications = [['Use TypeScript in components?', false, add_typescript]]; + + for (const [message, initial, fn] of modifications) { + const response = await prompts({ + type: 'confirm', + name: 'value', + message, + initial + }); + + await fn(target, response.value); + } + console.log(`\nNext steps:`); let i = 1; diff --git a/packages/create-svelte/cli/modifications/add_typescript.js b/packages/create-svelte/cli/modifications/add_typescript.js new file mode 100644 index 000000000000..e2ee129f4fb0 --- /dev/null +++ b/packages/create-svelte/cli/modifications/add_typescript.js @@ -0,0 +1,25 @@ +import fs from 'fs'; +import path from 'path'; +import { bold, cyan, green } from 'kleur/colors'; + +export default async function add_typescript(cwd, yes) { + if (yes) { + // update package.json + const pkg_file = path.join(cwd, 'package.json'); + const pkg_json = fs.readFileSync(pkg_file, 'utf-8'); + const pkg = JSON.parse(pkg_json); + + pkg.devDependencies['typescript'] = '^4.0.0'; + + fs.writeFileSync(pkg_file, JSON.stringify(pkg, null, '\t')); + + // update example component + const file = path.join(cwd, 'src/components/Counter.svelte'); + const code = fs.readFileSync(file, 'utf-8'); + fs.writeFileSync(file, code.replace(' + + \`\`\` + */ +declare module "*.gif" { + const value: string; + export = value; +} + +declare module "*.jpg" { + const value: string; + export = value; +} + +declare module "*.jpeg" { + const value: string; + export = value; +} + +declare module "*.png" { + const value: string; + export = value; +} + +declare module "*.svg" { + const value: string; + export = value; +} + +declare module "*.webp" { + const value: string; + export = value; +} +//#endregion +` + ); +} diff --git a/packages/create-svelte/cli/modifications/utils.js b/packages/create-svelte/cli/modifications/utils.js new file mode 100644 index 000000000000..90fa8b1d3307 --- /dev/null +++ b/packages/create-svelte/cli/modifications/utils.js @@ -0,0 +1,84 @@ +import fs from 'fs'; +import path from 'path'; + +/** + * Updates package.json with given devDependencies + */ +export function update_package_json(cwd, newDevDeps) { + const pkg_file = path.join(cwd, 'package.json'); + const pkg_json = fs.readFileSync(pkg_file, 'utf-8'); + const pkg = JSON.parse(pkg_json); + + pkg.devDependencies = sortObj({ + ...pkg.devDependencies, + ...newDevDeps + }); + + fs.writeFileSync(pkg_file, JSON.stringify(pkg, null, '\t')); +} + +/** + * Updates a Svelte component, doing all given replacements. + */ +export function update_component(cwd, filepath, replacements) { + const file = path.join(cwd, filepath); + + let code = fs.readFileSync(file, 'utf-8'); + replacements.forEach(replacement => (code = code.replace(replacement[0], replacement[1]))); + + fs.writeFileSync(file, code); +} + +/** + * Adds `svelte-preprocess` to `svelte.config.js`, if there's no preprocessor already. + */ +export function add_svelte_prepocess_to_config(cwd) { + const file = path.join(cwd, 'svelte.config.js'); + let config = fs.readFileSync(file, 'utf-8'); + + if (config.includes('preprocess:')) { + return; + } + + config = `const sveltePreprocess = require('svelte-preprocess');\n${config}`; + config = config.replace( + 'module.exports = {', + `module.exports = { + // Consult https://github.com/sveltejs/svelte-preprocess + // for more information about preprocessors + preprocess: sveltePreprocess(),` + ); + + fs.writeFileSync(file, config); +} + +/** + * Adds plugin to snowpack config file, if not already present. + */ +export function add_snowpack_plugin_to_config(cwd, pluginname) { + const file = path.join(cwd, 'snowpack.config.js'); + let config = fs.readFileSync(file, 'utf-8'); + + if (config.includes(pluginname)) { + return; + } + + if (config.includes('plugins: [')) { + config = config.replace('plugins: [', `plugins: ['${pluginname}', `); + } else { + config = config.replace( + `extends: '@sveltejs/snowpack-config'`, + `extends: '@sveltejs/snowpack-config', + plugins: ['${pluginname}']` + ); + } + + fs.writeFileSync(file, config); +} + +function sortObj(obj) { + return Object.keys(obj).reduce((newObj, key) => { + newObj[key] = obj[key]; + return newObj; + }, {}); +} diff --git a/packages/create-svelte/template/svelte.config.js b/packages/create-svelte/template/svelte.config.js index 450edb5c2d04..41f9bfa92743 100644 --- a/packages/create-svelte/template/svelte.config.js +++ b/packages/create-svelte/template/svelte.config.js @@ -1,12 +1,6 @@ -const preprocess = require('svelte-preprocess'); - module.exports = { // By default, `npm run build` will create a standard Node app. // You can create optimized builds for different platforms by // specifying a different adapter - adapter: '@sveltejs/adapter-node', - - // Consult https://github.com/sveltejs/svelte-preprocess - // for more information about preprocessors - preprocess: preprocess() -}; \ No newline at end of file + adapter: '@sveltejs/adapter-node' +}; From 42cef82d4de5d922d8450a7e12d2cff8dc2a86c5 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Sat, 24 Oct 2020 12:30:24 +0200 Subject: [PATCH 3/5] remove workspace references from template package.json --- packages/create-svelte/template/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/create-svelte/template/package.json b/packages/create-svelte/template/package.json index 18021d2d4e2b..1cfd426b65fe 100644 --- a/packages/create-svelte/template/package.json +++ b/packages/create-svelte/template/package.json @@ -6,9 +6,9 @@ "build": "svelte build" }, "devDependencies": { - "@sveltejs/adapter-node": "workspace:*", - "@sveltejs/kit": "workspace:*", - "@sveltejs/snowpack-config": "workspace:*", + "@sveltejs/adapter-node": "^0.0.1", + "@sveltejs/kit": "^0.0.1", + "@sveltejs/snowpack-config": "^0.0.1", "svelte": "^3.29.0" } } From 9535db80b9dd410776624399d50b545665612f92 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 27 Oct 2020 19:31:12 -0400 Subject: [PATCH 4/5] use workspace:* versions --- packages/create-svelte/.gitignore | 3 ++- packages/create-svelte/cli/index.js | 7 ++--- packages/create-svelte/package.json | 2 +- .../create-svelte/scripts/update-versions.js | 26 +++++++++++++++++++ packages/create-svelte/template/package.json | 6 ++--- 5 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 packages/create-svelte/scripts/update-versions.js diff --git a/packages/create-svelte/.gitignore b/packages/create-svelte/.gitignore index c5e82d74585d..05818c5a0181 100644 --- a/packages/create-svelte/.gitignore +++ b/packages/create-svelte/.gitignore @@ -1 +1,2 @@ -bin \ No newline at end of file +/bin +/cli/versions.js \ No newline at end of file diff --git a/packages/create-svelte/cli/index.js b/packages/create-svelte/cli/index.js index b11b66c0703f..a15eb423cf11 100644 --- a/packages/create-svelte/cli/index.js +++ b/packages/create-svelte/cli/index.js @@ -7,6 +7,7 @@ import prompts from 'prompts/lib/index'; import glob from 'tiny-glob/sync'; import gitignore_contents from '../template/.gitignore'; import add_typescript from './modifications/add_typescript.js'; +import versions from './versions.js'; const disclaimer = ` █████████ ███████████ ███████ ███████████ ███ @@ -14,10 +15,10 @@ const disclaimer = ` ░███ ░░░ ░ ░███ ░ ███ ░░███ ░███ ░███░███ ░░█████████ ░███ ░███ ░███ ░██████████ ░███ ░░░░░░░░███ ░███ ░███ ░███ ░███░░░░░░ ░███ -███ ░███ ░███ ░░███ ███ ░███ ░░░ +███ ░███ ░███ ░░███ ███ ░███ ░░░ ░░█████████ █████ ░░░███████░ █████ ███ -░░░░░░░░░ ░░░░░ ░░░░░░░ ░░░░░ ░░░ - +░░░░░░░░░ ░░░░░ ░░░░░░░ ░░░░░ ░░░ + Pump the brakes! A little disclaimer... svelte@next is not ready for use yet. It definitely can't diff --git a/packages/create-svelte/package.json b/packages/create-svelte/package.json index 12dc50d22ae8..dfc4fe9cc3e7 100644 --- a/packages/create-svelte/package.json +++ b/packages/create-svelte/package.json @@ -12,7 +12,7 @@ }, "scripts": { "dev": "rollup -cw", - "build": "rollup -c", + "build": "node scripts/update-versions && rollup -c", "prepare": "npm run build", "prepublishOnly": "npm run build" }, diff --git a/packages/create-svelte/scripts/update-versions.js b/packages/create-svelte/scripts/update-versions.js new file mode 100644 index 000000000000..68f5f6b3e22c --- /dev/null +++ b/packages/create-svelte/scripts/update-versions.js @@ -0,0 +1,26 @@ +const { writeFileSync } = require('fs'); +const { join } = require('path'); +const glob = require('tiny-glob/sync'); +const template_pkg = require('../template/package.json'); + +const cwd = join(__dirname, '../../'); +const pkgs = glob('*/package.json', { cwd }).map(file => require(`${cwd}/${file}`)); + +const versions = {}; + +[template_pkg.dependencies, template_pkg.devDependencies].forEach(deps => { + for (const key in deps) { + const value = deps[key]; + console.log(key, value); + if (value.startsWith('workspace:')) { + const pkg = pkgs.find(pkg => pkg.name === key); + if (pkg) { + versions[key] = pkg.version; + } + } + } +}); + +console.log(versions); + +writeFileSync(join(__dirname, '../cli/versions.js'), `export default ${JSON.stringify(versions, null, '\t')};`) \ No newline at end of file diff --git a/packages/create-svelte/template/package.json b/packages/create-svelte/template/package.json index 1cfd426b65fe..18021d2d4e2b 100644 --- a/packages/create-svelte/template/package.json +++ b/packages/create-svelte/template/package.json @@ -6,9 +6,9 @@ "build": "svelte build" }, "devDependencies": { - "@sveltejs/adapter-node": "^0.0.1", - "@sveltejs/kit": "^0.0.1", - "@sveltejs/snowpack-config": "^0.0.1", + "@sveltejs/adapter-node": "workspace:*", + "@sveltejs/kit": "workspace:*", + "@sveltejs/snowpack-config": "workspace:*", "svelte": "^3.29.0" } } From 5dac11353ff12fccd967789f7c17c1b297beab3b Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 27 Oct 2020 19:35:31 -0400 Subject: [PATCH 5/5] tidy up --- .../create-svelte/cli/modifications/add_typescript.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/create-svelte/cli/modifications/add_typescript.js b/packages/create-svelte/cli/modifications/add_typescript.js index bea9252c7c7f..49f9d018750e 100644 --- a/packages/create-svelte/cli/modifications/add_typescript.js +++ b/packages/create-svelte/cli/modifications/add_typescript.js @@ -45,17 +45,17 @@ function add_tsconfig(cwd) { "compilerOptions": { "moduleResolution": "node", "target": "es2017", - /** - Svelte Preprocess cannot figure out whether you have a value or a type, so tell TypeScript + /** + svelte-preprocess cannot figure out whether you have a value or a type, so tell TypeScript to enforce using \`import type\` instead of \`import\` for Types. */ "importsNotUsedAsValues": "error", "isolatedModules": true, /** - To have warnings/errors of the Svelte compiler at the correct position, + To have warnings/errors of the Svelte compiler at the correct position, enable source maps by default. */ - "sourceMap": true, + "sourceMap": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true