or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cookie-jar.mdcookie-operations.mdindex.mdstores.mdutilities.md

stores.mddocs/

0

# Store Implementations

1

2

Pluggable storage system for cookie persistence supporting both synchronous and asynchronous operations with complete CRUD functionality and efficient indexing.

3

4

## Capabilities

5

6

### Store Base Class

7

8

Abstract base class defining the interface for cookie storage implementations.

9

10

```typescript { .api }

11

/**

12

* Base class for cookie storage implementations

13

* Provides the interface for pluggable storage backends

14

*/

15

class Store {

16

// Properties

17

synchronous: boolean; // Whether store supports synchronous operations

18

19

// Methods that should be implemented by subclasses (throw errors in base class)

20

findCookie(

21

domain: string | null,

22

path: string | null,

23

key: string | null

24

): Promise<Cookie | undefined>;

25

findCookie(

26

domain: string | null,

27

path: string | null,

28

key: string | null,

29

callback: Callback<Cookie | undefined>

30

): void;

31

32

findCookies(

33

domain: string | null,

34

path: string | null,

35

allowSpecialUseDomain?: boolean

36

): Promise<Cookie[]>;

37

findCookies(

38

domain: string | null,

39

path: string | null,

40

allowSpecialUseDomain?: boolean,

41

callback?: Callback<Cookie[]>

42

): void;

43

44

putCookie(cookie: Cookie): Promise<void>;

45

putCookie(cookie: Cookie, callback: ErrorCallback): void;

46

47

updateCookie(oldCookie: Cookie, newCookie: Cookie): Promise<void>;

48

updateCookie(oldCookie: Cookie, newCookie: Cookie, callback: ErrorCallback): void;

49

50

removeCookie(domain: string | null, path: string | null, key: string | null): Promise<void>;

51

removeCookie(domain: string | null, path: string | null, key: string | null, callback: ErrorCallback): void;

52

53

removeCookies(domain: string, path: string | null): Promise<void>;

54

removeCookies(domain: string, path: string | null, callback: ErrorCallback): void;

55

56

removeAllCookies(): Promise<void>;

57

removeAllCookies(callback: ErrorCallback): void;

58

59

getAllCookies(): Promise<Cookie[]>;

60

getAllCookies(callback: Callback<Cookie[]>): void;

61

}

62

```

63

64

### Store Method Descriptions

65

66

Core CRUD operations that all store implementations must provide.

67

68

```typescript { .api }

69

/**

70

* Retrieves a specific cookie by domain, path, and key

71

* @param domain - Cookie domain (null matches any domain)

72

* @param path - Cookie path (null matches any path)

73

* @param key - Cookie key/name (null matches any key)

74

* @returns Promise resolving to found cookie or undefined

75

*/

76

findCookie(

77

domain: string | null,

78

path: string | null,

79

key: string | null

80

): Promise<Cookie | undefined>;

81

82

/**

83

* Finds all cookies matching given domain and path

84

* @param domain - Domain to match cookies against

85

* @param path - Path to match cookies against (null matches all paths)

86

* @param allowSpecialUseDomain - Whether to allow special use domains

87

* @returns Promise resolving to array of matching cookies

88

*/

89

findCookies(

90

domain: string | null,

91

path: string | null,

92

allowSpecialUseDomain?: boolean

93

): Promise<Cookie[]>;

94

95

/**

96

* Stores a new cookie, replacing any existing cookie with same domain/path/key

97

* @param cookie - Cookie to store

98

* @returns Promise that resolves when storage is complete

99

*/

100

putCookie(cookie: Cookie): Promise<void>;

101

102

/**

103

* Updates an existing cookie with new values

104

* @param oldCookie - Existing cookie to replace

105

* @param newCookie - New cookie data

106

* @returns Promise that resolves when update is complete

107

*/

108

updateCookie(oldCookie: Cookie, newCookie: Cookie): Promise<void>;

109

110

/**

111

* Removes a specific cookie by domain, path, and key

112

* @param domain - Cookie domain (null matches any domain)

113

* @param path - Cookie path (null matches any path)

114

* @param key - Cookie key/name (null matches any key)

115

* @returns Promise that resolves when removal is complete

116

*/

117

removeCookie(domain: string | null, path: string | null, key: string | null): Promise<void>;

118

119

/**

120

* Removes cookies matching domain and path

121

* @param domain - Domain to match

122

* @param path - Path to match (null removes all paths in domain)

123

* @returns Promise that resolves when removal is complete

124

*/

125

removeCookies(domain: string, path: string | null): Promise<void>;

126

127

/**

128

* Removes all cookies from the store

129

* @returns Promise that resolves when cleanup is complete

130

*/

131

removeAllCookies(): Promise<void>;

132

133

/**

134

* Retrieves all cookies from the store

135

* @returns Promise resolving to array of all stored cookies

136

*/

137

getAllCookies(): Promise<Cookie[]>;

138

```

139

140

### MemoryCookieStore

141

142

Default in-memory store implementation with efficient indexing and synchronous operation support.

143

144

```typescript { .api }

145

/**

146

* Default in-memory cookie store implementation

147

* Provides efficient storage using nested domain/path/key indexing

148

*/

149

class MemoryCookieStore extends Store {

150

// Properties

151

synchronous: boolean; // Always true - supports synchronous operations

152

153

// Constructor

154

constructor();

155

156

// Implements all Store methods with in-memory storage

157

findCookie(domain: string | null, path: string | null, key: string | null): Promise<Cookie | undefined>;

158

findCookies(domain: string, path: string, allowSpecialUseDomain?: boolean): Promise<Cookie[]>;

159

putCookie(cookie: Cookie): Promise<void>;

160

updateCookie(oldCookie: Cookie, newCookie: Cookie): Promise<void>;

161

removeCookie(domain: string, path: string, key: string): Promise<void>;

162

removeCookies(domain: string, path: string): Promise<void>;

163

removeAllCookies(): Promise<void>;

164

getAllCookies(): Promise<Cookie[]>;

165

}

166

```

167

168

**Usage Examples:**

169

170

```typescript

171

import { MemoryCookieStore, CookieJar, Cookie } from "tough-cookie";

172

173

// Create memory store

174

const store = new MemoryCookieStore();

175

176

// Use with CookieJar

177

const jar = new CookieJar(store);

178

179

// Store is synchronous

180

console.log(store.synchronous); // true

181

182

// Can be used directly

183

const cookie = new Cookie({

184

key: 'session',

185

value: 'abc123',

186

domain: 'example.com',

187

path: '/'

188

});

189

190

await store.putCookie(cookie);

191

const found = await store.findCookie('example.com', '/', 'session');

192

console.log(found?.value); // 'abc123'

193

```

194

195

### Store Internal Structure

196

197

The memory store uses an efficient nested indexing structure for fast lookups.

198

199

```typescript { .api }

200

/**

201

* Internal structure for MemoryCookieStore indexing

202

* Provides O(1) average case lookups by domain/path/key

203

*/

204

type MemoryCookieStoreIndex = {

205

[domain: string]: {

206

[path: string]: {

207

[key: string]: Cookie

208

}

209

}

210

}

211

```

212

213

## Custom Store Implementation

214

215

### Creating Custom Stores

216

217

To create a custom store, extend the Store base class and implement all abstract methods.

218

219

**Example: Simple File-based Store**

220

221

```typescript

222

import { Store, Cookie, Callback, ErrorCallback } from "tough-cookie";

223

import * as fs from 'fs/promises';

224

import * as path from 'path';

225

226

class FileCookieStore extends Store {

227

private storePath: string;

228

229

constructor(filePath: string) {

230

super();

231

this.synchronous = false; // Async file operations

232

this.storePath = filePath;

233

}

234

235

async findCookie(

236

domain: string | null,

237

path: string | null,

238

key: string | null

239

): Promise<Cookie | undefined> {

240

const cookies = await this.getAllCookies();

241

return cookies.find(cookie =>

242

(domain === null || cookie.domain === domain) &&

243

(path === null || cookie.path === path) &&

244

(key === null || cookie.key === key)

245

);

246

}

247

248

async findCookies(

249

domain: string,

250

path: string,

251

allowSpecialUseDomain?: boolean

252

): Promise<Cookie[]> {

253

const cookies = await this.getAllCookies();

254

return cookies.filter(cookie =>

255

cookie.domain === domain &&

256

(cookie.path?.startsWith(path) || false)

257

);

258

}

259

260

async putCookie(cookie: Cookie): Promise<void> {

261

const cookies = await this.getAllCookies();

262

263

// Remove existing cookie with same domain/path/key

264

const filtered = cookies.filter(c =>

265

!(c.domain === cookie.domain &&

266

c.path === cookie.path &&

267

c.key === cookie.key)

268

);

269

270

filtered.push(cookie);

271

await this.saveAllCookies(filtered);

272

}

273

274

async updateCookie(oldCookie: Cookie, newCookie: Cookie): Promise<void> {

275

const cookies = await this.getAllCookies();

276

const index = cookies.findIndex(c =>

277

c.domain === oldCookie.domain &&

278

c.path === oldCookie.path &&

279

c.key === oldCookie.key

280

);

281

282

if (index !== -1) {

283

cookies[index] = newCookie;

284

await this.saveAllCookies(cookies);

285

}

286

}

287

288

async removeCookie(domain: string, path: string, key: string): Promise<void> {

289

const cookies = await this.getAllCookies();

290

const filtered = cookies.filter(c =>

291

!(c.domain === domain && c.path === path && c.key === key)

292

);

293

await this.saveAllCookies(filtered);

294

}

295

296

async removeCookies(domain: string, path: string): Promise<void> {

297

const cookies = await this.getAllCookies();

298

const filtered = cookies.filter(c =>

299

!(c.domain === domain && c.path === path)

300

);

301

await this.saveAllCookies(filtered);

302

}

303

304

async removeAllCookies(): Promise<void> {

305

await this.saveAllCookies([]);

306

}

307

308

async getAllCookies(): Promise<Cookie[]> {

309

try {

310

const data = await fs.readFile(this.storePath, 'utf8');

311

const parsed = JSON.parse(data);

312

return parsed.map((cookieData: any) => Cookie.fromJSON(cookieData)).filter(Boolean);

313

} catch (error) {

314

if ((error as any).code === 'ENOENT') {

315

return []; // File doesn't exist yet

316

}

317

throw error;

318

}

319

}

320

321

private async saveAllCookies(cookies: Cookie[]): Promise<void> {

322

const serialized = cookies.map(cookie => cookie.toJSON());

323

await fs.mkdir(path.dirname(this.storePath), { recursive: true });

324

await fs.writeFile(this.storePath, JSON.stringify(serialized, null, 2));

325

}

326

}

327

328

// Usage

329

const fileStore = new FileCookieStore('./cookies.json');

330

const jar = new CookieJar(fileStore);

331

```

332

333

### Store Callback Pattern

334

335

All store methods support both Promise and callback patterns for compatibility.

336

337

```typescript

338

import { MemoryCookieStore, Cookie } from "tough-cookie";

339

340

const store = new MemoryCookieStore();

341

const cookie = new Cookie({ key: 'test', value: 'value' });

342

343

// Promise-based usage

344

await store.putCookie(cookie);

345

const found = await store.findCookie('example.com', '/', 'test');

346

347

// Callback-based usage

348

store.putCookie(cookie, (error) => {

349

if (error) {

350

console.error('Failed to store cookie:', error);

351

return;

352

}

353

354

store.findCookie('example.com', '/', 'test', (error, result) => {

355

if (error) {

356

console.error('Failed to find cookie:', error);

357

return;

358

}

359

console.log('Found cookie:', result);

360

});

361

});

362

```

363

364

### Store Performance Considerations

365

366

**MemoryCookieStore Performance:**

367

- O(1) average case lookup by exact domain/path/key

368

- O(n) worst case for domain/path matching operations

369

- Efficient for applications with moderate cookie counts

370

- Memory usage grows linearly with number of stored cookies

371

372

**Custom Store Guidelines:**

373

- Implement efficient indexing for your storage backend

374

- Consider async operations for I/O bound stores (files, databases)

375

- Handle concurrent access appropriately

376

- Implement proper error handling for storage failures

377

- Consider cleanup of expired cookies in background operations

378

379

## Types

380

381

```typescript { .api }

382

interface Callback<T> {

383

(error: Error, result?: never): void;

384

(error: null, result: T): void;

385

}

386

387

interface ErrorCallback {

388

(error: Error | null): void;

389

}

390

```