📦 deps(thirdparty): update snapshots

This commit is contained in:
ci[bot]
2026-05-29 08:33:53 +00:00
parent fdb52f1e96
commit 06e0d13d57
1615 changed files with 232858 additions and 0 deletions
@@ -0,0 +1,409 @@
# Bun Server Patterns
HTTP, WebSocket, and streaming patterns with Bun.serve.
## Basic HTTP Server
```typescript
Bun.serve({
port: 3000,
hostname: '0.0.0.0', // Listen on all interfaces
fetch(req) {
const url = new URL(req.url);
switch (url.pathname) {
case '/':
return new Response('Hello, World!');
case '/json':
return Response.json({ ok: true });
case '/html':
return new Response('<h1>Hello</h1>', {
headers: { 'Content-Type': 'text/html' }
});
default:
return new Response('Not Found', { status: 404 });
}
},
error(err) {
console.error('Server error:', err);
return new Response(`Error: ${err.message}`, { status: 500 });
}
});
```
## Request Handling
```typescript
Bun.serve({
async fetch(req) {
const url = new URL(req.url);
// Method routing
if (req.method === 'POST' && url.pathname === '/users') {
const body = await req.json();
// Process body...
return Response.json({ id: '123', ...body }, { status: 201 });
}
// Query parameters
if (url.pathname === '/search') {
const query = url.searchParams.get('q');
const page = parseInt(url.searchParams.get('page') || '1');
// Search logic...
}
// Headers
const auth = req.headers.get('Authorization');
const contentType = req.headers.get('Content-Type');
// URL parameters (manual parsing)
const match = url.pathname.match(/^\/users\/([^/]+)$/);
if (match) {
const userId = match[1];
// Fetch user...
}
return new Response('Not Found', { status: 404 });
}
});
```
## Response Patterns
```typescript
// Plain text
new Response('Hello')
// JSON
Response.json({ data: 'value' })
// With status
new Response('Created', { status: 201 })
Response.json({ error: 'Not found' }, { status: 404 })
// With headers
new Response('data', {
headers: {
'Content-Type': 'text/plain',
'Cache-Control': 'max-age=3600',
'X-Custom-Header': 'value'
}
})
// Redirect
Response.redirect('/new-location', 302)
// Stream
new Response(readableStream, {
headers: { 'Content-Type': 'application/octet-stream' }
})
```
## File Serving
```typescript
Bun.serve({
async fetch(req) {
const url = new URL(req.url);
// Serve static files
if (url.pathname.startsWith('/static/')) {
const filepath = `./public${url.pathname}`;
const file = Bun.file(filepath);
if (!(await file.exists())) {
return new Response('Not Found', { status: 404 });
}
return new Response(file.stream(), {
headers: {
'Content-Type': file.type,
'Content-Length': file.size.toString(),
'Cache-Control': 'public, max-age=31536000'
}
});
}
// File download
if (url.pathname.startsWith('/download/')) {
const filename = url.pathname.split('/').pop();
const file = Bun.file(`./files/${filename}`);
return new Response(file.stream(), {
headers: {
'Content-Type': 'application/octet-stream',
'Content-Disposition': `attachment; filename="${filename}"`
}
});
}
}
});
```
## WebSocket Server
```typescript
type WebSocketData = {
id: string;
userId: string;
joinedAt: Date;
};
const clients = new Map<string, ServerWebSocket<WebSocketData>>();
Bun.serve<WebSocketData>({
port: 3000,
fetch(req, server) {
const url = new URL(req.url);
if (url.pathname === '/ws') {
const userId = url.searchParams.get('userId');
if (!userId) {
return new Response('userId required', { status: 400 });
}
const success = server.upgrade(req, {
data: {
id: crypto.randomUUID(),
userId,
joinedAt: new Date()
}
});
return success ? undefined : new Response('Upgrade failed', { status: 500 });
}
return new Response('Hello');
},
websocket: {
open(ws) {
clients.set(ws.data.id, ws);
ws.subscribe('broadcast');
ws.send(JSON.stringify({ type: 'connected', id: ws.data.id }));
},
message(ws, message) {
const data = JSON.parse(message.toString());
switch (data.type) {
case 'broadcast':
ws.publish('broadcast', JSON.stringify({
from: ws.data.userId,
message: data.message
}));
break;
case 'direct':
const target = clients.get(data.targetId);
target?.send(JSON.stringify({
from: ws.data.userId,
message: data.message
}));
break;
}
},
close(ws) {
clients.delete(ws.data.id);
ws.unsubscribe('broadcast');
}
}
});
```
## Streaming Responses
```typescript
// Server-Sent Events
Bun.serve({
fetch(req) {
const url = new URL(req.url);
if (url.pathname === '/events') {
const stream = new ReadableStream({
start(controller) {
const encoder = new TextEncoder();
const interval = setInterval(() => {
const event = `data: ${JSON.stringify({ time: Date.now() })}\n\n`;
controller.enqueue(encoder.encode(event));
}, 1000);
// Cleanup on close
req.signal.addEventListener('abort', () => {
clearInterval(interval);
controller.close();
});
}
});
return new Response(stream, {
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
}
});
}
}
});
// Chunked transfer
async function* generateChunks() {
for (let i = 0; i < 10; i++) {
yield `Chunk ${i}\n`;
await Bun.sleep(100);
}
}
const response = new Response(
new ReadableStream({
async start(controller) {
const encoder = new TextEncoder();
for await (const chunk of generateChunks()) {
controller.enqueue(encoder.encode(chunk));
}
controller.close();
}
})
);
```
## Middleware Pattern
```typescript
type Handler = (req: Request) => Response | Promise<Response>;
type Middleware = (req: Request, next: Handler) => Response | Promise<Response>;
function compose(...middlewares: Middleware[]): Handler {
return (req) => {
let index = 0;
const next: Handler = (req) => {
if (index >= middlewares.length) {
return new Response('Not Found', { status: 404 });
}
const middleware = middlewares[index++];
return middleware(req, next);
};
return next(req);
};
}
// Logging middleware
const logging: Middleware = async (req, next) => {
const start = Bun.nanoseconds();
const response = await next(req);
const duration = (Bun.nanoseconds() - start) / 1_000_000;
console.log(`${req.method} ${new URL(req.url).pathname} - ${duration.toFixed(2)}ms`);
return response;
};
// Auth middleware
const auth: Middleware = async (req, next) => {
const token = req.headers.get('Authorization')?.replace('Bearer ', '');
if (!token) {
return Response.json({ error: 'Unauthorized' }, { status: 401 });
}
// Validate token...
return next(req);
};
// CORS middleware
const cors: Middleware = async (req, next) => {
if (req.method === 'OPTIONS') {
return new Response(null, {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE',
'Access-Control-Allow-Headers': 'Content-Type, Authorization'
}
});
}
const response = await next(req);
response.headers.set('Access-Control-Allow-Origin', '*');
return response;
};
const handler = compose(cors, logging, auth);
Bun.serve({
fetch: handler
});
```
## Graceful Shutdown
```typescript
const server = Bun.serve({
port: 3000,
fetch(req) {
return new Response('Hello');
}
});
process.on('SIGTERM', () => {
console.log('Shutting down...');
server.stop();
process.exit(0);
});
process.on('SIGINT', () => {
console.log('Interrupted, shutting down...');
server.stop();
process.exit(0);
});
```
## Compression
```typescript
import { gzipSync, gunzipSync, deflateSync, inflateSync } from 'bun';
// Gzip compression
const data = 'Large data string...'.repeat(1000);
const compressed = gzipSync(data);
const decompressed = gunzipSync(compressed);
// Deflate
const deflated = deflateSync('data');
const inflated = inflateSync(deflated);
// Gzip HTTP response
app.get('/large-data', (c) => {
const data = generateLargeDataset();
const json = JSON.stringify(data);
const acceptEncoding = c.req.header('accept-encoding') || '';
if (acceptEncoding.includes('gzip')) {
return c.body(gzipSync(json), {
headers: {
'Content-Type': 'application/json',
'Content-Encoding': 'gzip'
}
});
}
return c.json(data);
});
```
## TLS/HTTPS
```typescript
Bun.serve({
port: 443,
tls: {
key: Bun.file('./key.pem'),
cert: Bun.file('./cert.pem'),
},
fetch(req) {
return new Response('Secure!');
}
});
```
@@ -0,0 +1,323 @@
# SQLite Patterns with bun:sqlite
Advanced patterns for database operations.
## Migrations
```typescript
const migrations = [
`CREATE TABLE IF NOT EXISTS schema_version (version INTEGER PRIMARY KEY)`,
`CREATE TABLE users (id TEXT PRIMARY KEY, email TEXT UNIQUE)`,
`ALTER TABLE users ADD COLUMN name TEXT`,
`CREATE INDEX idx_users_email ON users(email)`
];
function getCurrentVersion(db: Database): number {
try {
const result = db.query('SELECT version FROM schema_version').get() as { version: number } | undefined;
return result?.version || 0;
} catch {
return 0;
}
}
function runMigrations(db: Database) {
const currentVersion = getCurrentVersion(db);
db.transaction(() => {
for (let i = currentVersion; i < migrations.length; i++) {
console.log(`Running migration ${i + 1}...`);
db.run(migrations[i]);
}
db.run('DELETE FROM schema_version');
db.run('INSERT INTO schema_version (version) VALUES (?)', [migrations.length]);
})();
console.log(`Migrated to version ${migrations.length}`);
}
```
## Connection Pool Pattern
```typescript
class DatabasePool {
private pools = new Map<string, Database>();
get(name: string = 'default'): Database {
if (!this.pools.has(name)) {
this.pools.set(name, new Database(`${name}.db`));
}
return this.pools.get(name)!;
}
close(name?: string) {
if (name) {
this.pools.get(name)?.close();
this.pools.delete(name);
} else {
for (const db of this.pools.values()) {
db.close();
}
this.pools.clear();
}
}
}
export const dbPool = new DatabasePool();
```
## Middleware Pattern (Hono)
```typescript
import { Database } from 'bun:sqlite';
import { createFactory } from 'hono/factory';
type Env = {
Variables: {
db: Database;
};
};
const factory = createFactory<Env>();
// Option 1: Per-request connection
const dbMiddleware = factory.createMiddleware(async (c, next) => {
const db = new Database('app.db');
c.set('db', db);
try {
await next();
} finally {
db.close();
}
});
// Option 2: Pooled connection (preferred for performance)
const dbPoolMiddleware = factory.createMiddleware(async (c, next) => {
const db = dbPool.get();
c.set('db', db);
await next();
// Don't close — reuse connection
});
```
## Repository Pattern
```typescript
type User = {
id: string;
email: string;
name: string;
createdAt: Date;
};
class UserRepository {
constructor(private db: Database) {}
private stmt = {
findById: this.db.prepare('SELECT * FROM users WHERE id = ?'),
findByEmail: this.db.prepare('SELECT * FROM users WHERE email = ?'),
findAll: this.db.prepare('SELECT * FROM users ORDER BY created_at DESC LIMIT ?'),
create: this.db.prepare('INSERT INTO users (id, email, name) VALUES (?, ?, ?) RETURNING *'),
update: this.db.prepare('UPDATE users SET email = ?, name = ? WHERE id = ? RETURNING *'),
delete: this.db.prepare('DELETE FROM users WHERE id = ? RETURNING *')
};
findById(id: string): User | null {
const row = this.stmt.findById.get(id);
return row ? this.mapRow(row) : null;
}
findByEmail(email: string): User | null {
const row = this.stmt.findByEmail.get(email);
return row ? this.mapRow(row) : null;
}
findAll(limit = 100): User[] {
const rows = this.stmt.findAll.all(limit);
return rows.map(this.mapRow);
}
create(data: { email: string; name: string }): User {
const id = crypto.randomUUID();
const row = this.stmt.create.get(id, data.email, data.name);
return this.mapRow(row);
}
update(id: string, data: { email?: string; name?: string }): User | null {
const existing = this.findById(id);
if (!existing) return null;
const row = this.stmt.update.get(
data.email ?? existing.email,
data.name ?? existing.name,
id
);
return this.mapRow(row);
}
delete(id: string): boolean {
const row = this.stmt.delete.get(id);
return !!row;
}
private mapRow(row: any): User {
return {
id: row.id,
email: row.email,
name: row.name,
createdAt: new Date(row.created_at)
};
}
}
```
## Transaction Patterns
```typescript
// Simple transaction
const transferFunds = db.transaction((fromId: string, toId: string, amount: number) => {
const from = db.prepare('SELECT balance FROM accounts WHERE id = ?').get(fromId);
if (!from || from.balance < amount) {
throw new Error('Insufficient funds');
}
db.run('UPDATE accounts SET balance = balance - ? WHERE id = ?', [amount, fromId]);
db.run('UPDATE accounts SET balance = balance + ? WHERE id = ?', [amount, toId]);
return { fromId, toId, amount };
});
// Nested transaction (savepoint)
const complexOperation = db.transaction(() => {
db.run('INSERT INTO orders (id) VALUES (?)', [orderId]);
const addItem = db.transaction((itemId: string) => {
db.run('INSERT INTO order_items (order_id, item_id) VALUES (?, ?)', [orderId, itemId]);
});
for (const item of items) {
addItem(item.id); // Each runs in savepoint
}
});
// Deferred vs immediate
const deferredTx = db.transaction(() => {
// Locks acquired on first write
}).deferred();
const immediateTx = db.transaction(() => {
// Locks acquired immediately
}).immediate();
const exclusiveTx = db.transaction(() => {
// Exclusive write lock
}).exclusive();
```
## Query Helpers
```typescript
// Reusable query object
const getUserQuery = db.query('SELECT * FROM users WHERE id = ?');
const user1 = getUserQuery.get('1');
const user2 = getUserQuery.get('2');
// Values (array results)
const allEmails = db.query('SELECT email FROM users').values();
// [['alice@example.com'], ['bob@example.com'], ...]
// Named columns
const users = db.query('SELECT id, email FROM users').all();
// [{ id: '1', email: 'alice@example.com' }, ...]
```
## Full-Text Search
```typescript
// Create FTS table
db.run(`
CREATE VIRTUAL TABLE IF NOT EXISTS posts_fts USING fts5(
title,
content,
content='posts',
content_rowid='id'
)
`);
// Triggers to keep FTS in sync
db.run(`
CREATE TRIGGER IF NOT EXISTS posts_ai AFTER INSERT ON posts BEGIN
INSERT INTO posts_fts(rowid, title, content)
VALUES (new.id, new.title, new.content);
END
`);
// Search
function searchPosts(query: string) {
return db.prepare(`
SELECT posts.*
FROM posts
JOIN posts_fts ON posts.id = posts_fts.rowid
WHERE posts_fts MATCH ?
ORDER BY rank
LIMIT 20
`).all(query);
}
```
## JSON Support
```typescript
// Store JSON
db.run(`
CREATE TABLE IF NOT EXISTS settings (
user_id TEXT PRIMARY KEY,
preferences TEXT -- JSON stored as text
)
`);
// Insert JSON
db.prepare('INSERT INTO settings VALUES (?, ?)').run(
userId,
JSON.stringify({ theme: 'dark', notifications: true })
);
// Query JSON (SQLite JSON functions)
const darkUsers = db.prepare(`
SELECT user_id FROM settings
WHERE json_extract(preferences, '$.theme') = 'dark'
`).all();
// Extract JSON field
const theme = db.prepare(`
SELECT json_extract(preferences, '$.theme') as theme
FROM settings
WHERE user_id = ?
`).get(userId);
```
## Performance Tips
```typescript
// WAL mode for better concurrency
db.run('PRAGMA journal_mode = WAL');
// Increase cache size
db.run('PRAGMA cache_size = -64000'); // 64MB
// Batch inserts
const insertMany = db.transaction((users: User[]) => {
const stmt = db.prepare('INSERT INTO users VALUES (?, ?, ?)');
for (const user of users) {
stmt.run(user.id, user.email, user.name);
}
});
insertMany(thousandsOfUsers); // Much faster than individual inserts
// Index for common queries
db.run('CREATE INDEX IF NOT EXISTS idx_users_email ON users(email)');
db.run('CREATE INDEX IF NOT EXISTS idx_posts_user_id ON posts(user_id)');
```
@@ -0,0 +1,415 @@
# Testing with bun:test
Bun's built-in test runner patterns and lifecycle hooks.
## Test Structure
```typescript
import { describe, test, expect, beforeAll, afterAll, beforeEach, afterEach } from 'bun:test';
describe('feature', () => {
let resource: Resource;
beforeAll(() => {
// Suite setup — runs once before all tests
console.log('Setup test suite');
});
afterAll(() => {
// Suite cleanup — runs once after all tests
console.log('Cleanup test suite');
});
beforeEach(() => {
// Test setup — runs before each test
resource = createResource();
});
afterEach(() => {
// Test cleanup — runs after each test
resource.dispose();
});
test('behavior', () => {
expect(result).toBe(expected);
});
});
```
## Assertions
```typescript
// Equality
expect(value).toBe(expected); // Strict equality (===)
expect(obj).toEqual({ foo: 'bar' }); // Deep equality
expect(arr).toContain(item); // Array/string contains
expect(obj).toMatchObject({ key: 'value' }); // Partial object match
// Truthiness
expect(value).toBeTruthy();
expect(value).toBeFalsy();
expect(value).toBeDefined();
expect(value).toBeUndefined();
expect(value).toBeNull();
// Numbers
expect(num).toBeGreaterThan(0);
expect(num).toBeGreaterThanOrEqual(0);
expect(num).toBeLessThan(100);
expect(num).toBeLessThanOrEqual(100);
expect(num).toBeCloseTo(0.3, 5); // Float comparison
// Strings
expect(str).toMatch(/pattern/);
expect(str).toStartWith('prefix');
expect(str).toEndWith('suffix');
// Arrays
expect(arr).toHaveLength(3);
expect(arr).toContainEqual({ id: 1 });
// Exceptions
expect(fn).toThrow();
expect(fn).toThrow('error message');
expect(fn).toThrow(ErrorType);
// Negation
expect(value).not.toBe(other);
expect(arr).not.toContain(item);
```
## Async Tests
```typescript
// Async/await
test('async operation', async () => {
const result = await fetchData();
expect(result).toBeDefined();
});
// Promise resolution
test('promise resolves', async () => {
await expect(asyncFn()).resolves.toBe('success');
});
// Promise rejection
test('promise rejects', async () => {
await expect(asyncFn()).rejects.toThrow('error');
});
// Timeout (default 5000ms)
test('slow operation', async () => {
const result = await slowOperation();
expect(result).toBeDefined();
}, 10000); // 10 second timeout
```
## Database Testing
```typescript
import { Database } from 'bun:sqlite';
describe('Database operations', () => {
let db: Database;
beforeEach(() => {
// Fresh in-memory database per test
db = new Database(':memory:');
db.run(`
CREATE TABLE users (
id TEXT PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
name TEXT NOT NULL
)
`);
});
afterEach(() => {
db.close();
});
test('insert user', () => {
const user = db.prepare(`
INSERT INTO users (id, email, name)
VALUES (?, ?, ?)
RETURNING *
`).get('1', 'alice@example.com', 'Alice');
expect(user).toMatchObject({
id: '1',
email: 'alice@example.com',
name: 'Alice'
});
});
test('query user', () => {
db.run("INSERT INTO users VALUES ('1', 'alice@example.com', 'Alice')");
const user = db.prepare('SELECT * FROM users WHERE id = ?').get('1');
expect(user).toBeDefined();
expect(user.email).toBe('alice@example.com');
});
test('unique constraint', () => {
db.run("INSERT INTO users VALUES ('1', 'alice@example.com', 'Alice')");
expect(() => {
db.run("INSERT INTO users VALUES ('2', 'alice@example.com', 'Alice2')");
}).toThrow();
});
});
```
## File System Testing
```typescript
import { mkdtemp, rm } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
describe('File operations', () => {
let tempDir: string;
beforeEach(async () => {
tempDir = await mkdtemp(join(tmpdir(), 'test-'));
});
afterEach(async () => {
await rm(tempDir, { recursive: true });
});
test('write and read file', async () => {
const filepath = join(tempDir, 'test.txt');
await Bun.write(filepath, 'Hello, world!');
const file = Bun.file(filepath);
expect(await file.exists()).toBe(true);
expect(await file.text()).toBe('Hello, world!');
});
test('write JSON', async () => {
const filepath = join(tempDir, 'data.json');
const data = { name: 'test', value: 42 };
await Bun.write(filepath, JSON.stringify(data));
const file = Bun.file(filepath);
expect(await file.json()).toEqual(data);
});
});
```
## Mocking
```typescript
import { mock, spyOn } from 'bun:test';
describe('Mocking', () => {
test('mock function', () => {
const mockFn = mock(() => 'mocked');
expect(mockFn()).toBe('mocked');
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledTimes(1);
});
test('mock with arguments', () => {
const mockFn = mock((x: number) => x * 2);
mockFn(5);
expect(mockFn).toHaveBeenCalledWith(5);
});
test('spy on method', () => {
const obj = {
method: (x: number) => x * 2
};
const spy = spyOn(obj, 'method');
obj.method(5);
expect(spy).toHaveBeenCalled();
expect(spy).toHaveBeenCalledWith(5);
});
test('mock return value', () => {
const mockFn = mock(() => 'original');
mockFn.mockReturnValue('mocked');
expect(mockFn()).toBe('mocked');
mockFn.mockReturnValueOnce('once');
expect(mockFn()).toBe('once');
expect(mockFn()).toBe('mocked');
});
test('mock implementation', () => {
const mockFn = mock(() => 'original');
mockFn.mockImplementation(() => 'new implementation');
expect(mockFn()).toBe('new implementation');
});
});
```
## Mock fetch
```typescript
describe('External API calls', () => {
const originalFetch = global.fetch;
afterEach(() => {
global.fetch = originalFetch;
});
test('mock API response', async () => {
global.fetch = mock(async () =>
new Response(JSON.stringify({ data: 'mocked' }), {
status: 200,
headers: { 'Content-Type': 'application/json' }
})
);
const res = await fetch('https://api.example.com/data');
const data = await res.json();
expect(data).toEqual({ data: 'mocked' });
expect(global.fetch).toHaveBeenCalledWith('https://api.example.com/data');
});
test('mock API error', async () => {
global.fetch = mock(async () =>
new Response(JSON.stringify({ error: 'Not found' }), { status: 404 })
);
const res = await fetch('https://api.example.com/missing');
expect(res.status).toBe(404);
});
});
```
## Test Organization
```typescript
// Skip tests
test.skip('work in progress', () => {
// Not executed
});
// Mark as todo
test.todo('future feature');
// Only run specific test
test.only('focus on this', () => {
// Only this test runs in file
});
// Conditional skip
const isCI = process.env.CI === 'true';
test.skipIf(isCI)('skip in CI', () => {
// Skipped when CI=true
});
// Run if condition
test.if(!isCI)('local only', () => {
// Only runs locally
});
```
## Snapshot Testing
```typescript
import { expect, test } from 'bun:test';
test('snapshot', () => {
const result = generateOutput();
expect(result).toMatchSnapshot();
});
test('inline snapshot', () => {
const result = { name: 'test', value: 42 };
expect(result).toMatchInlineSnapshot(`
{
"name": "test",
"value": 42
}
`);
});
```
## Running Tests
```bash
# Run all tests
bun test
# Specific file
bun test src/utils.test.ts
# Specific directory
bun test src/api/
# Pattern matching
bun test --test-name-pattern "should create"
# Watch mode
bun test --watch
# Coverage
bun test --coverage
# Timeout (ms)
bun test --timeout 10000
# Bail on first failure
bun test --bail
# Rerun only failed tests
bun test --rerun-each 3
```
## Best Practices
```typescript
// ✅ Isolated tests — each test sets up its own data
describe('User service', () => {
let db: Database;
beforeEach(() => {
db = new Database(':memory:');
setupSchema(db);
});
afterEach(() => {
db.close();
});
test('creates user', () => {
const user = createUser(db, { email: 'test@example.com' });
expect(user.id).toBeDefined();
});
});
// ✅ Descriptive test names
test('returns 404 when user not found', async () => { ... });
test('validates email format before creating user', async () => { ... });
// ✅ Single assertion focus
test('user has correct email', () => {
const user = createUser({ email: 'test@example.com' });
expect(user.email).toBe('test@example.com');
});
// ❌ Avoid shared mutable state between tests
let sharedUser; // Don't do this
beforeAll(() => {
sharedUser = createUser(); // Tests may interfere
});
```