{"id":19895358,"url":"https://github.com/razshare/sveltekit-server-session","last_synced_at":"2025-05-02T20:30:53.396Z","repository":{"id":230792834,"uuid":"780105033","full_name":"razshare/sveltekit-server-session","owner":"razshare","description":"Server sessions made easy with SvelteKit","archived":false,"fork":false,"pushed_at":"2024-04-26T20:23:13.000Z","size":266,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-23T10:52:56.906Z","etag":null,"topics":["session","session-management","sveltekit"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/razshare.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-03-31T17:50:25.000Z","updated_at":"2024-10-06T03:44:54.000Z","dependencies_parsed_at":"2024-04-26T21:29:29.332Z","dependency_job_id":null,"html_url":"https://github.com/razshare/sveltekit-server-session","commit_stats":null,"previous_names":["tncrazvan/svelte-session","razshare/sveltekit-server-session"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/razshare%2Fsveltekit-server-session","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/razshare%2Fsveltekit-server-session/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/razshare%2Fsveltekit-server-session/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/razshare%2Fsveltekit-server-session/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/razshare","download_url":"https://codeload.github.com/razshare/sveltekit-server-session/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252104021,"owners_count":21695402,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["session","session-management","sveltekit"],"created_at":"2024-11-12T18:36:28.818Z","updated_at":"2025-05-02T20:30:52.800Z","avatar_url":"https://github.com/razshare.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SvelteKit Server Session\n\nThis library provides an easy way to start, serve and modify server sessions.\n\nInstall with:\n\n```sh\nnpm i -D sveltekit-server-session\n```\n\n# Usage\n\n1. Open your `src/app.d.ts` file and define your _session_ key under `interface Locals`.\n    ```ts\n    // See https://kit.svelte.dev/docs/types#app\n    \n    import type { Session } from 'sveltekit-server-session';\n    \n    // for information about these interfaces\n    declare global {\n      namespace App {\n        // interface Error {}\n        interface Locals {\n          // Add type hints to \"locals\".\n          session: Session;\n        }\n        // interface PageData {}\n        // interface PageState {}\n        // interface Platform {}\n      }\n    }\n    \n    export {};\n    ```\n    This will give you proper type hints when you access your `locals` property.\n1. Create a new `src/hooks.server.js` and start the session in your `handle` function.\n    ```js\n    // src/hooks.server.js\n    import { session } from 'sveltekit-server-session';\n    \n    /**\n    * @type {import(\"@sveltejs/kit\").Handle}\n    */\n    export async function handle({ event, resolve }) {\n      // Start the session.\n      const [ sessionLocal, error ] = await session.start({\n        cookies: event.cookies,\n      })\n\n      // Check for errors.\n      if (error) {\n        return new Response(error.message, { status: 500 })\n      }\n\n      // Save session to `locals`.\n      event.locals.session = sessionLocal\n\n      // Resolve the sveltekit response.\n      const response = await resolve(event)\n\n      // Adding required headers to the response.\n      for (const [key, value] of sessionLocal.response().headers) {\n        response.headers.set(key, value)\n      }\n\n      return response\n    }\n    ```\n    This will make sure every api request has access to the session.\n1. Create an api endpoint that updates the session.\n    ```js\n    // src/routes/session/quote/update/+server.js\n    export async function PUT({ locals, request }) {\n      // Get the session data and response function.\n      const { data, response } = locals.session\n\n      // Update the \"quote\".\n      data.set('quote', await request.text())\n\n      // Respond with the new \"quote\".\n      return response(data.get('quote'))\n    }\n    ```\n1. Retrieve the session and load it into the svelte page.\n    ```js\n    // src/routes/+page.server.svelte\n    /**\n    * @type {import(\"./$types\").PageServerLoad}\n    */\n    export function load({ locals }) {\n      // Get the session data.\n      const { data } = locals.session\n\n      if (!data.has('quote')) {\n        // Set a default \"quote\".\n        data.set('quote', 'initial quote')\n      }\n\n      return {\n        // Load the \"quote\" into the page.\n        quote: data.get('quote'),\n      }\n    }\n    ```\n1. Create a svelte page.\n    ```svelte\n    \u003c!-- src/routes/+page.svelte --\u003e\n    \u003cscript\u003e\n      // Load session data.\n      /** @type {import('./$types').PageData} */\n      export let data\n\n      let sending = false\n\n      async function set() {\n        sending = true\n        // Update the session.\n        await fetch('/session/quote/update', { method: 'PUT', body: data.quote })\n        sending = false\n      }\n    \u003c/script\u003e\n\n    \u003ctextarea bind:value={data.quote}\u003e\u003c/textarea\u003e\n    \u003cbr /\u003e\n    \u003cbutton disabled={sending} on:mouseup={set}\u003e\n      \u003cspan\u003eSave\u003c/span\u003e\n    \u003c/button\u003e\n    ```\n\n\n![Peek 2024-04-01 03-15](https://github.com/tncrazvan/sveltekit-server-session/assets/6891346/c633f001-bead-4d94-9927-c1602cd1dfac)\n\n# Customization\n\nEvery single session related operation like validation, creation, update, deletion and so on, is described by `SessionInterface`.\n\nYou can use `session.setOperations()` to overwrite these operations by providing your own `SessionInterface` implementation\n```js\nsession.setOperations({\n  async exists(id) {\n    return ok(map.has(id))\n  },\n  async isValid(id) {\n    const session = map.get(id)\n    if (!session) {\n      return ok(false)\n    }\n    return ok(session.getRemainingSeconds() \u003e 0)\n  },\n  async has(id) {\n    return ok(map.has(id))\n  },\n  async get(id) {\n    return ok(map.get(id))\n  },\n  async set(id, session) {\n    map.set(id, session)\n    return ok()\n  },\n  async delete(id) {\n    map.delete(id)\n    return ok()\n  },\n})\n```\n\nThis is a simple in memory session implementation, but the sky is the limit, you could even fetch and persist sessions to a remote database.\n\n# Don't Preload\n\nSvelteKit comes with preload features baked in, however this feature may cause some inconsistent behavior when dealing with sessions.\n\nConsider the following use case,\n\n 1. Let's say I want to modify my session in some way.\u003cbr/\u003e\u003cbr/\u003e\n    ![1](https://github.com/tncrazvan/sveltekit-server-session/assets/6891346/0bff9ac4-c838-44d6-a832-48781c066c10)\n    \u003cbr/\u003e\n 2. Then I want to destroy my session, but the act of destroying it takes a while.\u003cbr/\u003e\u003cbr/\u003e\n    ![2](https://github.com/tncrazvan/sveltekit-server-session/assets/6891346/d8b90670-414f-4aff-8e1a-e4affd823eea)\n    \u003cbr/\u003e\n 3. In the meantime, by mistake, I hover over some link that preloads the previous page, with the old state.\u003cbr/\u003e\u003cbr/\u003e\n    ![3](https://github.com/tncrazvan/sveltekit-server-session/assets/6891346/13225796-0204-46e1-b60b-b1a785e1324f)\n    \u003cbr/\u003e\n 4. Then the session is finally destroyed, in this order.\u003cbr/\u003e\n     Well as you can see, when I navigate back to that page, the session state is not updated, because according to SvelteKit it has already preloaded it, and we're good to go.\u003cbr/\u003e\u003cbr/\u003e\n    ![4](https://github.com/tncrazvan/sveltekit-server-session/assets/6891346/76a8bd20-289c-4be6-b05d-41bd8266e196)\n    \u003cbr/\u003e\n\nWhich is obviously wrong.\n\nTo fix this you need to disable preloading.\n\nNavigate to your `src/app.html` file and disable preloading by settings `data-sveltekit-preload-data` to `false` on your `body` element.\n\n```html\n\u003c!DOCTYPE html/\u003e\n\u003chtml lang=\"en\"\u003e\n  \u003chead\u003e\n    \u003cmeta charset=\"utf-8\" /\u003e\n    \u003clink rel=\"icon\" href=\"%sveltekit.assets%/favicon.png\" /\u003e\n    \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\" /\u003e\n    %sveltekit.head%\n  \u003c/head\u003e\n  \u003cbody data-sveltekit-preload-data=\"false\"\u003e \u003c!-- Here. --\u003e\n    \u003cdiv\u003e%sveltekit.body%\u003c/div\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\nYou could technically disable preloading for specific cases and avoid the issue in that way, but at some point your whole application will be filled with links that point to some page that depends on the server session.\\\nIt's just simply not worth the headache.\n\n\u003e [!NOTE]\n\u003e Obviously you can still enable preload for resources like assets by manually adding \n\u003e the `data-sveltekit-preload-data=\"hover\"` attribute to specific elements in your page.\n\n# Complete Example\n\n**You can find a [complete example leveraging the recommended usage here](https://github.com/tncrazvan/sveltekit-server-session-example).**\n\n\n\u003e [!NOTE]\n\u003e Remember to run your SvelteKit server dev at least \n\u003e once to properly generate your glue types.\n\n\u003e [!NOTE]\n\u003e Sessions are only directly available under `*.server.js` and `*.server.ts` files.\\\n\u003e Sessions are meant to be private data, so they will never be directly available [under universal files](https://kit.svelte.dev/docs/load#universal-vs-server) like `+page.js`, for example.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frazshare%2Fsveltekit-server-session","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frazshare%2Fsveltekit-server-session","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frazshare%2Fsveltekit-server-session/lists"}