[examples] Update SvelteKit example with latest boilerplate (#7892)

Replaces https://github.com/vercel/vercel/pull/7674 with the latest SvelteKit boilerplate.
This commit is contained in:
Lee Robinson
2022-05-30 02:57:46 -05:00
committed by GitHub
parent b07ff7431f
commit c414288b2f
22 changed files with 2362 additions and 1900 deletions

View File

@@ -7,3 +7,4 @@ node_modules
.env.* .env.*
!.env.example !.env.example
.vercel .vercel
.output

View File

@@ -0,0 +1,13 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock

View File

@@ -0,0 +1,6 @@
{
"useTabs": false,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100
}

View File

@@ -14,31 +14,29 @@ If you're seeing this, you've probably already done this step. Congrats!
```bash ```bash
# create a new project in the current directory # create a new project in the current directory
npm init svelte@next npm init svelte
# create a new project in my-app # create a new project in my-app
npm init svelte@next my-app npm init svelte my-app
``` ```
> Note: the `@next` is temporary
## Developing ## Developing
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: Once you've created a project and installed dependencies with `pnpm install`, start a development server:
```bash ```bash
npm run dev pnpm run dev
# or start the server and open the app in a new browser tab # or start the server and open the app in a new browser tab
npm run dev -- --open pnpm run dev -- --open
``` ```
## Building ## Building
This uses the adapter-auto for SvelteKit, which detects Vercel and runs adapter-vercel on your behalf. To create a production version of your app:
```bash ```bash
npm run build pnpm run build
``` ```
> You can preview the built app with `npm run preview`, regardless of whether you installed an adapter. This should _not_ be used to serve your app in production. You can preview the production build with `npm run preview`.

View File

@@ -1,10 +1,13 @@
{ {
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".", "allowJs": true,
"paths": { "checkJs": true,
"$lib": ["src/lib"], "esModuleInterop": true,
"$lib/*": ["src/lib/*"] "forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true
} }
},
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"]
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,22 +1,29 @@
{ {
"private": true, "private": true,
"name": "sveltekit",
"version": "0.0.1",
"scripts": { "scripts": {
"dev": "svelte-kit dev", "dev": "svelte-kit dev",
"build": "svelte-kit build", "build": "svelte-kit build",
"package": "svelte-kit package", "package": "svelte-kit package",
"preview": "svelte-kit preview" "preview": "svelte-kit preview",
"prepare": "svelte-kit sync",
"check": "svelte-check --tsconfig ./jsconfig.json",
"check:watch": "svelte-check --tsconfig ./jsconfig.json --watch",
"lint": "prettier --check --plugin-search-dir=. .",
"format": "prettier --write --plugin-search-dir=. ."
}, },
"devDependencies": { "devDependencies": {
"@sveltejs/adapter-auto": "next", "@sveltejs/adapter-auto": "next",
"@sveltejs/kit": "next", "@sveltejs/kit": "next",
"svelte": "^3.46.0" "@types/cookie": "^0.4.1",
"prettier": "^2.5.1",
"prettier-plugin-svelte": "^2.5.0",
"svelte": "^3.46.0",
"svelte-check": "^2.2.6",
"typescript": "~4.6.2"
}, },
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"@fontsource/fira-mono": "^4.5.0", "@fontsource/fira-mono": "^4.5.0",
"@lukeed/uuid": "^2.0.0",
"cookie": "^0.4.1" "cookie": "^0.4.1"
} }
} }

1633
examples/sveltekit/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

15
examples/sveltekit/src/app.d.ts vendored Normal file
View File

@@ -0,0 +1,15 @@
/// <reference types="@sveltejs/kit" />
// See https://kit.svelte.dev/docs/types#app
// for information about these interfaces
declare namespace App {
interface Locals {
userid: string;
}
// interface Platform {}
// interface Session {}
// interface Stuff {}
}

View File

@@ -2,12 +2,11 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="description" content="Svelte demo app" /> <link rel="icon" href="%sveltekit.assets%/favicon.png" />
<link rel="icon" href="%svelte.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
%svelte.head% %sveltekit.head%
</head> </head>
<body> <body>
<div>%svelte.body%</div> <div>%sveltekit.body%</div>
</body> </body>
</html> </html>

View File

@@ -1,13 +1,13 @@
import cookie from 'cookie'; import * as cookie from 'cookie';
import { v4 as uuid } from '@lukeed/uuid';
/** @type {import('@sveltejs/kit').Handle} */
export const handle = async ({ event, resolve }) => { export const handle = async ({ event, resolve }) => {
const cookies = cookie.parse(event.request.headers.get('cookie') || ''); const cookies = cookie.parse(event.request.headers.get('cookie') || '');
event.locals.userid = cookies.userid || uuid(); event.locals.userid = cookies['userid'] || crypto.randomUUID();
const response = await resolve(event); const response = await resolve(event);
if (!cookies.userid) { if (!cookies['userid']) {
// if this is the first time the user has visited this app, // if this is the first time the user has visited this app,
// set a cookie so that we recognise them when they return // set a cookie so that we recognise them when they return
response.headers.set( response.headers.set(

View File

@@ -7,6 +7,10 @@
$: displayed_count.set(count); $: displayed_count.set(count);
$: offset = modulo($displayed_count, 1); $: offset = modulo($displayed_count, 1);
/**
* @param {number} n
* @param {number} m
*/
function modulo(n, m) { function modulo(n, m) {
// handle negative numbers // handle negative numbers
return ((n % m) + m) % m; return ((n % m) + m) % m;
@@ -50,6 +54,7 @@
justify-content: center; justify-content: center;
border: 0; border: 0;
background-color: transparent; background-color: transparent;
touch-action: manipulation;
color: var(--text-color); color: var(--text-color);
font-size: 2rem; font-size: 2rem;
} }

View File

@@ -2,9 +2,36 @@ import { invalidate } from '$app/navigation';
// this action (https://svelte.dev/tutorial/actions) allows us to // this action (https://svelte.dev/tutorial/actions) allows us to
// progressively enhance a <form> that already works without JS // progressively enhance a <form> that already works without JS
/**
* @param {HTMLFormElement} form
* @param {{
* pending?: ({ data, form }: { data: FormData; form: HTMLFormElement }) => void;
* error?: ({
* data,
* form,
* response,
* error
* }: {
* data: FormData;
* form: HTMLFormElement;
* response: Response | null;
* error: Error | null;
* }) => void;
* result?: ({
* data,
* form,
* response
* }: {
* data: FormData;
* response: Response;
* form: HTMLFormElement;
* }) => void;
* }} [opts]
*/
export function enhance(form, { pending, error, result } = {}) { export function enhance(form, { pending, error, result } = {}) {
let current_token; let current_token;
/** @param {SubmitEvent} e */
async function handle_submit(e) { async function handle_submit(e) {
const token = (current_token = {}); const token = (current_token = {});
@@ -37,7 +64,7 @@ export function enhance(form, { pending, error, result } = {}) {
console.error(await response.text()); console.error(await response.text());
} }
} catch (e) { } catch (e) {
if (error) { if (error && e instanceof Error) {
error({ data, form, error: e, response: null }); error({ data, form, error: e, response: null });
} else { } else {
throw e; throw e;

View File

@@ -16,6 +16,7 @@
<svelte:head> <svelte:head>
<title>About</title> <title>About</title>
<meta name="description" content="About this app" />
</svelte:head> </svelte:head>
<div class="content"> <div class="content">
@@ -26,8 +27,7 @@
following into your command line and following the prompts: following into your command line and following the prompts:
</p> </p>
<!-- TODO lose the @next! --> <pre>npm init svelte</pre>
<pre>npm init svelte@next</pre>
<p> <p>
The page you're looking at is purely static HTML, with no client-side interactivity needed. The page you're looking at is purely static HTML, with no client-side interactivity needed.

View File

@@ -8,6 +8,7 @@
<svelte:head> <svelte:head>
<title>Home</title> <title>Home</title>
<meta name="description" content="Svelte demo app" />
</svelte:head> </svelte:head>
<section> <section>

View File

@@ -11,6 +11,11 @@
const base = 'https://api.svelte.dev'; const base = 'https://api.svelte.dev';
/**
* @param {string} method
* @param {string} resource
* @param {Record<string, unknown>} [data]
*/
export function api(method, resource, data) { export function api(method, resource, data) {
return fetch(`${base}/${resource}`, { return fetch(`${base}/${resource}`, {
method, method,

View File

@@ -1,5 +1,6 @@
import { api } from './_api'; import { api } from './_api';
/** @type {import('./__types').RequestHandler} */
export const get = async ({ locals }) => { export const get = async ({ locals }) => {
// locals.userid comes from src/hooks.js // locals.userid comes from src/hooks.js
const response = await api('get', `todos/${locals.userid}`); const response = await api('get', `todos/${locals.userid}`);
@@ -27,6 +28,7 @@ export const get = async ({ locals }) => {
}; };
}; };
/** @type {import('./index').RequestHandler} */
export const post = async ({ request, locals }) => { export const post = async ({ request, locals }) => {
const form = await request.formData(); const form = await request.formData();
@@ -46,6 +48,7 @@ const redirect = {
} }
}; };
/** @type {import('./index').RequestHandler} */
export const patch = async ({ request, locals }) => { export const patch = async ({ request, locals }) => {
const form = await request.formData(); const form = await request.formData();
@@ -57,6 +60,7 @@ export const patch = async ({ request, locals }) => {
return redirect; return redirect;
}; };
/** @type {import('./index').RequestHandler} */
export const del = async ({ request, locals }) => { export const del = async ({ request, locals }) => {
const form = await request.formData(); const form = await request.formData();

View File

@@ -3,11 +3,23 @@
import { scale } from 'svelte/transition'; import { scale } from 'svelte/transition';
import { flip } from 'svelte/animate'; import { flip } from 'svelte/animate';
/**
* @typedef {{
* uid: string;
* created_at: Date;
* text: string;
* done: boolean;
* pending_delete: boolean;
* }} Todo
*/
/** @type {Todo[]} */
export let todos; export let todos;
</script> </script>
<svelte:head> <svelte:head>
<title>Todos</title> <title>Todos</title>
<meta name="description" content="A todo list app" />
</svelte:head> </svelte:head>
<div class="todos"> <div class="todos">