diff --git a/packages/headers/CHANGELOG.md b/packages/headers/CHANGELOG.md index 2994d87..475479b 100644 --- a/packages/headers/CHANGELOG.md +++ b/packages/headers/CHANGELOG.md @@ -2,6 +2,11 @@ This is the changelog for [`headers`](https://github.com/mjackson/remix-the-web/tree/main/packages/headers). It follows [semantic versioning](https://semver.org/). +## HEAD + +- BREAKING CHANGE: `cookie.delete(name)` returns `void` instead of `boolean` +- BREAKING CHANGE: `cookie.forEach()` calls its callback with `(name, value, cookie)` instead of `(value, name, map)` + ## v0.9.0 (2024-12-20) This release tightens up the type safety and brings `SuperHeaders` more in line with the built-in `Headers` interface. diff --git a/packages/headers/src/lib/cookie.test.ts b/packages/headers/src/lib/cookie.test.ts index 3d2d35b..7367bfe 100644 --- a/packages/headers/src/lib/cookie.test.ts +++ b/packages/headers/src/lib/cookie.test.ts @@ -43,16 +43,21 @@ describe('Cookie', () => { }); it('sets and gets values', () => { - let header = new Cookie(''); + let header = new Cookie(); header.set('name', 'value'); assert.equal(header.get('name'), 'value'); }); + it('returns `null` for nonexistent values', () => { + let header = new Cookie(); + assert.equal(header.get('name'), null); + }); + it('deletes values', () => { let header = new Cookie('name=value'); - assert.equal(header.delete('name'), true); - assert.equal(header.delete('nonexistent'), false); - assert.equal(header.get('name'), undefined); + assert.equal(header.has('name'), true); + header.delete('name'); + assert.equal(header.has('name'), false); }); it('checks if value exists', () => { @@ -63,19 +68,11 @@ describe('Cookie', () => { it('clears all values', () => { let header = new Cookie('name1=value1; name2=value2'); + assert.equal(header.size, 2); header.clear(); assert.equal(header.size, 0); }); - it('iterates over entries', () => { - let header = new Cookie('name1=value1; name2=value2'); - let entries = Array.from(header.entries()); - assert.deepEqual(entries, [ - ['name1', 'value1'], - ['name2', 'value2'], - ]); - }); - it('iterates over names', () => { let header = new Cookie('name1=value1; name2=value2'); let names = Array.from(header.names()); @@ -88,10 +85,19 @@ describe('Cookie', () => { assert.deepEqual(values, ['value1', 'value2']); }); + it('iterates over entries', () => { + let header = new Cookie('name1=value1; name2=value2'); + let entries = Array.from(header.entries()); + assert.deepEqual(entries, [ + ['name1', 'value1'], + ['name2', 'value2'], + ]); + }); + it('uses forEach correctly', () => { let header = new Cookie('name1=value1; name2=value2'); let result: [string, string][] = []; - header.forEach((value, name) => { + header.forEach((name, value) => { result.push([name, value]); }); assert.deepEqual(result, [ diff --git a/packages/headers/src/lib/cookie.ts b/packages/headers/src/lib/cookie.ts index 3bfd8da..2d327b0 100644 --- a/packages/headers/src/lib/cookie.ts +++ b/packages/headers/src/lib/cookie.ts @@ -37,44 +37,47 @@ export class Cookie implements HeaderValue, Iterable<[string, string]> { } /** - * Gets the value of a cookie with the given name from the `Cookie` header. + * Gets the value of a cookie with the given name from the header. + * @param name The name of the cookie. + * @returns The value of the cookie, or `null` if the cookie does not exist. */ - get(name: string): string | undefined { - return this.#map.get(name); + get(name: string): string | null { + return this.#map.get(name) ?? null; } /** - * Sets a cookie with the given name and value in the `Cookie` header. + * Sets a cookie with the given name and value in the header. + * @param name The name of the cookie. + * @param value The value of the cookie. */ set(name: string, value: string): void { this.#map.set(name, value); } /** - * Removes a cookie with the given name from the `Cookie` header. + * Removes a cookie with the given name from the header. + * @param name The name of the cookie. */ - delete(name: string): boolean { - return this.#map.delete(name); + delete(name: string): void { + this.#map.delete(name); } /** - * True if a cookie with the given name exists in the `Cookie` header. + * True if a cookie with the given name exists in the header. + * @param name The name of the cookie. + * @returns True if a cookie with the given name exists in the header. */ has(name: string): boolean { return this.#map.has(name); } /** - * Removes all cookies from the `Cookie` header. + * Removes all cookies from the header. */ clear(): void { this.#map.clear(); } - entries(): IterableIterator<[string, string]> { - return this.#map.entries(); - } - names(): IterableIterator { return this.#map.keys(); } @@ -83,19 +86,22 @@ export class Cookie implements HeaderValue, Iterable<[string, string]> { return this.#map.values(); } + entries(): IterableIterator<[string, string]> { + return this.#map.entries(); + } + [Symbol.iterator](): IterableIterator<[string, string]> { return this.entries(); } - forEach( - callback: (value: string, key: string, map: Map) => void, - thisArg?: any, - ): void { - this.#map.forEach(callback, thisArg); + forEach(callback: (name: string, value: string, header: Cookie) => void, thisArg?: any): void { + for (let [name, value] of this) { + callback.call(thisArg, name, value, this); + } } /** - * The number of cookies in the `Cookie` header. + * The number of cookies in the header. */ get size(): number { return this.#map.size;