diff --git a/README.md b/README.md index 690d704..bfd945e 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,15 @@ Vercel builder for Sapper with SSR enabled * [x] Deploy your Sapper app as a Lambda in 30 seconds. * [x] Serve all static assets from a CDN. -## Basic usage +## Automatic configuration + +Run `npx vercel-sapper` on an existing project. + +Or create a new project with `npx vercel-sapper my-project` + +_🧪 This feature is experimental, let us know what you think => https://github.com/thgh/vercel-sapper/pull/47_ + +## Manual configuration You must make 3 changes to your project to get started: diff --git a/bin.js b/bin.js new file mode 100755 index 0000000..16dfb56 --- /dev/null +++ b/bin.js @@ -0,0 +1,144 @@ +#!/usr/bin/env node + +const fs = require('fs') +const { join } = require('path') + +;(async () => { + console.log( + yellow( + '🧪 This feature is experimental, let us know what you think' + + '=> https://github.com/thgh/vercel-sapper/pull/47\n' + ) + ) + // Fallback to current working directory + const dir = process.argv[2] || '.' + + // TODO: Create a new project if the directory is empty + // Create a new project if the directory does not exist + if (!fs.existsSync(dir)) { + await degit(dir) + } + + // Configure the project for Vercel + patch(dir) + + console.log(green('\nDeploy your Sapper project:\n')) + console.log(' cd', dir) + console.log(' vercel\n') +})() + +function degit(dir) { + return new Promise((resolve) => { + console.log(green('degit'), `sveltejs/sapper-template#rollup`) + require('child_process').execFile( + 'npx', + ['degit', 'sveltejs/sapper-template#rollup', dir], + (err, stdout, stderr) => { + if (err) { + console.error(red('something went wrong with degit'), err) + return + } + + stdout && console.log(stdout.trim()) + stderr && console.log(stderr.trim()) + console.log(green('Created'), `Sapper project in ${dir}`) + resolve() + } + ) + }) +} + +async function patch(dir) { + try { + if (!fs.existsSync(join(dir, 'src/server.js'))) { + throw new Error( + 'expected src/server.js to exist, is this really a Sapper project?' + ) + } + const server = fs.readFileSync(join(dir, 'src/server.js'), 'utf8') + fs.writeFileSync(join(dir, 'src/server.js'), patchServer(server)) + console.log(green('Patched'), 'src/server.js') + } catch (e) { + console.error(red(e.message)) + } + + try { + if (fs.existsSync(join(dir, 'vercel.json'))) { + throw new Error('vercel.json already exists') + } + fs.writeFileSync( + join(dir, 'vercel.json'), + `{ + "version": 2, + "builds": [ + { + "src": "package.json", + "use": "vercel-sapper" + } + ] +}` + ) + console.log(green('Created'), 'vercel.json') + } catch (e) { + console.error(red(e.message)) + } + + try { + if (fs.existsSync(join(dir, '.vercelignore'))) { + throw new Error('.vercelignore already exists') + } + fs.writeFileSync( + join(dir, '.vercelignore'), + `__sapper__ +cypress +node_modules` + ) + console.log(green('Created'), '.vercelignore') + } catch (e) { + console.error(red(e.message)) + } +} + +function patchServer(server) { + if (server.includes('export default')) { + throw new Error('src/server.js was already patched') + } + if (server.includes('module.exports')) { + throw new Error('src/server.js was already patched') + } + if (!server.includes('polka()') && !server.includes('express()')) { + throw new Error('src/server.js should contain polka() or express()') + } + + // Simplest case + if (server.includes('\npolka()')) { + return server.replace('\npolka()', '\nexport default polka()') + } + if (server.includes('\nexpress()')) { + return server.replace('\nexpress()', '\nexport default express()') + } + + // Server is assigned to variable + if (server.includes('= polka()')) { + return server.replace('= polka()', '= (module.exports = polka())') + } + if (server.includes('= express()')) { + return server.replace('= express()', '= (module.exports = express())') + } + + throw new Error( + 'src/server.js needs manual patch: https://www.npmjs.com/package/vercel-sapper#manual-configuration' + ) +} + +function red(text) { + return '\u001b[1m\u001b[31m' + text + '\u001b[39m\u001b[22m' +} + +function green(text) { + return '\u001b[1m\u001b[32m' + text + '\u001b[39m\u001b[22m' +} + +function yellow(text) { + return '\u001b[1m\u001b[33m' + text + '\u001b[39m\u001b[22m' +} diff --git a/package.json b/package.json index 6db88c6..28dc9ff 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,11 @@ "license": "MIT", "description": "Vercel builder for Sapper with SSR enabled", "main": "index.js", + "bin": { + "vercel-sapper": "./bin.js" + }, "files": [ + "bin.js", "index.js", "lib", "yarn.lock"