From 2560fb05d6510e4db1c293a7eb313b07630964b3 Mon Sep 17 00:00:00 2001 From: metonym Date: Wed, 2 Feb 2022 08:24:00 -0800 Subject: [PATCH 1/3] Upgrade SvelteKit and remove deprecated "target" option --- package-lock.json | 28 ++++++++++++++-------------- svelte.config.js | 2 -- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index fde2560..88bb39b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,8 +13,8 @@ "cookie": "^0.4.1" }, "devDependencies": { - "@sveltejs/adapter-node": "next", - "@sveltejs/kit": "next", + "@sveltejs/adapter-node": "^1.0.0-next.67", + "@sveltejs/kit": "^1.0.0-next.257", "svelte": "^3.44.2" } }, @@ -56,18 +56,18 @@ } }, "node_modules/@sveltejs/adapter-node": { - "version": "1.0.0-next.60", - "resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-1.0.0-next.60.tgz", - "integrity": "sha512-aOX0WEoSoy9ANHDbyul83c0F9qxI+vl//kYEhTZURY4NNnRQ4B1+QECDIv70v3SjU/aAT+56ofpvcZA++sfQxw==", + "version": "1.0.0-next.67", + "resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-1.0.0-next.67.tgz", + "integrity": "sha512-+LuLn91xARZsRANiQNIIDpMMncUTnP2pJc8tyL+FdpVvs5UtlvkYJpeCBPFqjjseRpIIbi8Slu89GCdrRXBDUg==", "dev": true, "dependencies": { "tiny-glob": "^0.2.9" } }, "node_modules/@sveltejs/kit": { - "version": "1.0.0-next.216", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.216.tgz", - "integrity": "sha512-FKg7PPlymsZ2aU8DteY1BH217M2dIAgfWzm8OVqazQn2uLbw25WbVqSJ5KdgW83mLYoxSWUNPrJX3TJNEG6jVg==", + "version": "1.0.0-next.257", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.257.tgz", + "integrity": "sha512-dt7BwynNeGl1S9ODdVGwNmemM7QZMycPq10BYhiwdCNrHf/Zn2LNQsTdaxKEB2jdj9gDCh/ZRD0HH5ovc2jUcg==", "dev": true, "dependencies": { "@sveltejs/vite-plugin-svelte": "^1.0.0-next.32", @@ -708,18 +708,18 @@ } }, "@sveltejs/adapter-node": { - "version": "1.0.0-next.60", - "resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-1.0.0-next.60.tgz", - "integrity": "sha512-aOX0WEoSoy9ANHDbyul83c0F9qxI+vl//kYEhTZURY4NNnRQ4B1+QECDIv70v3SjU/aAT+56ofpvcZA++sfQxw==", + "version": "1.0.0-next.67", + "resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-1.0.0-next.67.tgz", + "integrity": "sha512-+LuLn91xARZsRANiQNIIDpMMncUTnP2pJc8tyL+FdpVvs5UtlvkYJpeCBPFqjjseRpIIbi8Slu89GCdrRXBDUg==", "dev": true, "requires": { "tiny-glob": "^0.2.9" } }, "@sveltejs/kit": { - "version": "1.0.0-next.216", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.216.tgz", - "integrity": "sha512-FKg7PPlymsZ2aU8DteY1BH217M2dIAgfWzm8OVqazQn2uLbw25WbVqSJ5KdgW83mLYoxSWUNPrJX3TJNEG6jVg==", + "version": "1.0.0-next.257", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.257.tgz", + "integrity": "sha512-dt7BwynNeGl1S9ODdVGwNmemM7QZMycPq10BYhiwdCNrHf/Zn2LNQsTdaxKEB2jdj9gDCh/ZRD0HH5ovc2jUcg==", "dev": true, "requires": { "@sveltejs/vite-plugin-svelte": "^1.0.0-next.32", diff --git a/svelte.config.js b/svelte.config.js index 3719dbf..a541400 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -4,8 +4,6 @@ import node from '@sveltejs/adapter-node'; const config = { kit: { - // hydrate the
element in src/app.html - target: '#svelte', adapter: node() } }; From 8a630e18c5886fd6f67ed35fd8948833e448a567 Mon Sep 17 00:00:00 2001 From: metonym Date: Wed, 2 Feb 2022 08:38:19 -0800 Subject: [PATCH 2/3] Update hooks signature to use event instead of request --- src/hooks.js | 15 +++++---------- src/routes/todos/[uid].json.js | 14 ++++++++------ src/routes/todos/_api.js | 12 ++++++++---- src/routes/todos/index.json.js | 14 ++++++++------ 4 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/hooks.js b/src/hooks.js index 66dabe4..0430836 100644 --- a/src/hooks.js +++ b/src/hooks.js @@ -1,21 +1,16 @@ import cookie from 'cookie'; import { v4 as uuid } from '@lukeed/uuid'; -export const handle = async ({ request, resolve }) => { - const cookies = cookie.parse(request.headers.cookie || ''); - request.locals.userid = cookies.userid || uuid(); +export const handle = async ({ event, resolve }) => { + const cookies = cookie.parse(event.request.headers.cookie || ''); + event.locals.userid = cookies.userid || uuid(); - // TODO https://github.com/sveltejs/kit/issues/1046 - if (request.url.searchParams.has('_method')) { - request.method = request.url.searchParams.get('_method').toUpperCase(); - } - - const response = await resolve(request); + const response = await resolve(event); if (!cookies.userid) { // if this is the first time the user has visited this app, // set a cookie so that we recognise them when they return - response.headers['set-cookie'] = `userid=${request.locals.userid}; Path=/; HttpOnly`; + response.headers['set-cookie'] = `userid=${event.locals.userid}; Path=/; HttpOnly`; } return response; diff --git a/src/routes/todos/[uid].json.js b/src/routes/todos/[uid].json.js index 4373f20..74b0455 100644 --- a/src/routes/todos/[uid].json.js +++ b/src/routes/todos/[uid].json.js @@ -1,14 +1,16 @@ import { api } from './_api'; // PATCH /todos/:uid.json -export const patch = async (request) => { - return api(request, `todos/${request.locals.userid}/${request.params.uid}`, { - text: request.body.get('text'), - done: request.body.has('done') ? !!request.body.get('done') : undefined +export const patch = async (event) => { + const data = await event.request.formData(); + + return api(event, `todos/${event.locals.userid}/${event.params.uid}`, { + text: data.get('text'), + done: data.has('done') ? !!data.get('done') : undefined }); }; // DELETE /todos/:uid.json -export const del = async (request) => { - return api(request, `todos/${request.locals.userid}/${request.params.uid}`); +export const del = async (event) => { + return api(event, `todos/${event.locals.userid}/${event.params.uid}`); }; diff --git a/src/routes/todos/_api.js b/src/routes/todos/_api.js index 9dc73ad..9a798b9 100644 --- a/src/routes/todos/_api.js +++ b/src/routes/todos/_api.js @@ -11,14 +11,14 @@ const base = 'https://api.svelte.dev'; -export async function api(request, resource, data) { +export async function api(event, resource, data) { // user must have a cookie set - if (!request.locals.userid) { + if (!event.locals.userid) { return { status: 401 }; } const res = await fetch(`${base}/${resource}`, { - method: request.method, + method: event.request.method, headers: { 'content-type': 'application/json' }, @@ -29,7 +29,11 @@ export async function api(request, resource, data) { // behaviour is to show the URL corresponding to the form's "action" // attribute. in those cases, we want to redirect them back to the // /todos page, rather than showing the response - if (res.ok && request.method !== 'GET' && request.headers.accept !== 'application/json') { + if ( + res.ok && + event.request.method !== 'GET' && + event.request.headers.get('accept') !== 'application/json' + ) { return { status: 303, headers: { diff --git a/src/routes/todos/index.json.js b/src/routes/todos/index.json.js index ae2df4e..f0b0164 100644 --- a/src/routes/todos/index.json.js +++ b/src/routes/todos/index.json.js @@ -1,9 +1,9 @@ import { api } from './_api'; // GET /todos.json -export const get = async (request) => { - // request.locals.userid comes from src/hooks.js - const response = await api(request, `todos/${request.locals.userid}`); +export const get = async (event) => { + // event.locals.userid comes from src/hooks.js + const response = await api(event, `todos/${event.locals.userid}`); if (response.status === 404) { // user hasn't created a todo list. @@ -15,13 +15,15 @@ export const get = async (request) => { }; // POST /todos.json -export const post = async (request) => { - const response = await api(request, `todos/${request.locals.userid}`, { +export const post = async (event) => { + const data = await event.request.formData(); + + const response = await api(event, `todos/${event.locals.userid}`, { // because index.svelte posts a FormData object, // request.body is _also_ a (readonly) FormData // object, which allows us to get form data // with the `body.get(key)` method - text: request.body.get('text') + text: data.get('text') }); return response; From b06aeab6102155d6c1e2d48ab2b3f02f86e6ddb1 Mon Sep 17 00:00:00 2001 From: metonym Date: Wed, 2 Feb 2022 08:48:26 -0800 Subject: [PATCH 3/3] Align with latest SvelteKit sample app --- src/app.html | 6 +++--- src/hooks.js | 10 ++++++++-- src/lib/Counter.svelte | 10 +++++++--- src/lib/header/Header.svelte | 10 +++++++--- src/routes/todos/index.svelte | 9 +++++---- svelte.config.js | 7 ++++++- 6 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/app.html b/src/app.html index 97f318d..e7d2cbd 100644 --- a/src/app.html +++ b/src/app.html @@ -2,12 +2,12 @@ - + + - %svelte.head% -
%svelte.body%
+
%svelte.body%
diff --git a/src/hooks.js b/src/hooks.js index 0430836..c87a9a4 100644 --- a/src/hooks.js +++ b/src/hooks.js @@ -2,7 +2,7 @@ import cookie from 'cookie'; import { v4 as uuid } from '@lukeed/uuid'; export const handle = async ({ event, resolve }) => { - const cookies = cookie.parse(event.request.headers.cookie || ''); + const cookies = cookie.parse(event.request.headers.get('cookie') || ''); event.locals.userid = cookies.userid || uuid(); const response = await resolve(event); @@ -10,7 +10,13 @@ export const handle = async ({ event, resolve }) => { if (!cookies.userid) { // if this is the first time the user has visited this app, // set a cookie so that we recognise them when they return - response.headers['set-cookie'] = `userid=${event.locals.userid}; Path=/; HttpOnly`; + response.headers.set( + 'set-cookie', + cookie.serialize('userid', event.locals.userid, { + path: '/', + httpOnly: true + }) + ); } return response; diff --git a/src/lib/Counter.svelte b/src/lib/Counter.svelte index 166bd52..6800213 100644 --- a/src/lib/Counter.svelte +++ b/src/lib/Counter.svelte @@ -22,7 +22,7 @@
- + {Math.floor($displayed_count)}
@@ -79,13 +79,12 @@ .counter-viewport strong { position: absolute; - display: block; + display: flex; width: 100%; height: 100%; font-weight: 400; color: var(--accent-color); font-size: 4rem; - display: flex; align-items: center; justify-content: center; } @@ -95,4 +94,9 @@ width: 100%; height: 100%; } + + .hidden { + top: -100%; + user-select: none; + } diff --git a/src/lib/header/Header.svelte b/src/lib/header/Header.svelte index 7d53fa8..9361382 100644 --- a/src/lib/header/Header.svelte +++ b/src/lib/header/Header.svelte @@ -16,8 +16,12 @@
{/each} diff --git a/svelte.config.js b/svelte.config.js index a541400..3d0b9db 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -4,7 +4,12 @@ import node from '@sveltejs/adapter-node'; const config = { kit: { - adapter: node() + adapter: node(), + + // Override http methods in the Todo forms + methodOverride: { + allowed: ['PATCH', 'DELETE'] + } } };