https://github.com/maxiviper117/example-asynclocalstorage-sveltekit
https://github.com/maxiviper117/example-asynclocalstorage-sveltekit
asynclocalstorage example sveltekit
Last synced: 20 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/maxiviper117/example-asynclocalstorage-sveltekit
- Owner: Maxiviper117
- Created: 2025-02-21T11:05:19.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-03-16T12:45:17.000Z (over 1 year ago)
- Last Synced: 2025-03-16T13:35:08.534Z (over 1 year ago)
- Topics: asynclocalstorage, example, sveltekit
- Language: TypeScript
- Homepage:
- Size: 39.1 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# example-AsyncLocalStorage-sveltekit
This project demonstrates how to use Node.js' AsyncLocalStorage within a SvelteKit application to manage per-request data without the need for passing data manually through each load function.
## Overview
In this example, the AsyncLocalStorage is initialized in the server hooks and is used to store the authenticated user and other request-specific data.
## How AsyncLocalStorage Works
AsyncLocalStorage provides a way to store data throughout the lifetime of an asynchronous operation. It allows you to create a storage context that is unique to each asynchronous execution chain. This is particularly useful in web applications where you need to maintain request-specific data across various asynchronous operations without explicitly passing it around.
### Key Concepts
1. **Context Creation**: A new context is created at the beginning of each request using `asyncLocalStorage.run()`. This context is a Map object that can store key-value pairs.
2. **Setting Data**: Data can be stored in the context using the `setRequestData` function. This function retrieves the current context and sets the specified key-value pair.
3. **Getting Data**: Data can be retrieved from the context using the `getRequestData` function. This function retrieves the current context and gets the value associated with the specified key.
## Advantages Over event.locals and Load Function Waterfalls
1. **Simplified Data Propagation**: With AsyncLocalStorage, data such as the authenticated user is set once during the request lifecycle and then accessed anywhere within that lifecycle, eliminating the need to manually pass values through `event.locals` in each load function.
2. **Avoiding Load Function Waterfalls**: Instead of using `await parent()` in nested load functions, which can lead to complex chaining of asynchronous calls, AsyncLocalStorage allows direct access to the context data, thereby reducing boilerplate code.
3. **Centralized Context Management**: Managing request-specific data with AsyncLocalStorage centralizes the data access layer. This not only simplifies the code by avoiding repetitive data passing but also minimizes potential errors in distributed data flow.
## Code Snippets
### 1. Initialization in hooks
The following snippet shows how the context is created and used in the `handle` hook to store the authenticated user:
```typescript
// src/hooks.server.ts
import { getUserFromToken } from '$lib/server/auth';
import { runWithContext, setRequestData } from '$lib/server/requestContext';
export const handle = async ({ event, resolve }) => {
return runWithContext(async () => {
const token = event.cookies.get('auth_token');
if (token) {
const user = await getUserFromToken(token);
setRequestData('user', user);
} else {
console.warn('No valid auth token found');
setRequestData('user', null);
}
return await resolve(event);
});
};
```
### 2. Context Management with AsyncLocalStorage
This snippet from `src/lib/server/requestContext.ts` demonstrates how AsyncLocalStorage is used to maintain a per-request store:
```typescript
// src/lib/server/requestContext.ts
import { AsyncLocalStorage } from 'node:async_hooks';
const asyncLocalStorage = new AsyncLocalStorage>();
export function runWithContext(fn: () => T) {
return asyncLocalStorage.run(new Map(), fn);
}
export function setRequestData(key: string, value: T) {
const store = asyncLocalStorage.getStore();
if (store) {
store.set(key, value);
} else {
console.error('AsyncLocalStorage store is not available');
}
}
export function getRequestData(key: string): T | undefined {
const store = asyncLocalStorage.getStore();
return store ? store.get(key) : undefined;
}
```
### 3. Accessing the Stored Data
The user information stored in AsyncLocalStorage can be accessed from other modules, such as in the authentication helper:
```typescript
// src/lib/server/authUser.ts
import { getRequestData } from '$lib/server/requestContext';
import type { AuthUser } from '$lib/types/authUser';
export function getAuthenticatedUser() {
return getRequestData('user');
}
```
> [!WARNING]
> Node.js' AsyncLocalStorage is only available on the server. It cannot be used in client-side code.
## Getting Started
1. Install dependencies with your package manager (e.g., `pnpm install`).
2. Run the development server with `pnpm dev`.
3. Explore the code in the `src/hooks.server.ts` and `src/lib/server/` directories to see how AsyncLocalStorage is integrated.