From 52f57b9720d0ec5f08e80e3c5ac72418d7eb6445 Mon Sep 17 00:00:00 2001 From: Michael Jackson Date: Fri, 20 Dec 2024 10:15:59 -0800 Subject: [PATCH] Several Cookie improvements --- packages/headers/CHANGELOG.md | 13 +++++++- packages/headers/src/lib/accept-encoding.ts | 16 ++++----- packages/headers/src/lib/accept-language.ts | 20 ++++++------ packages/headers/src/lib/accept.ts | 22 ++++++------- packages/headers/src/lib/cookie.test.ts | 22 ++++++------- packages/headers/src/lib/cookie.ts | 36 ++++++++++++--------- 6 files changed, 71 insertions(+), 58 deletions(-) diff --git a/packages/headers/CHANGELOG.md b/packages/headers/CHANGELOG.md index 475479b..daf01af 100644 --- a/packages/headers/CHANGELOG.md +++ b/packages/headers/CHANGELOG.md @@ -4,8 +4,19 @@ This is the changelog for [`headers`](https://github.com/mjackson/remix-the-web/ ## HEAD -- BREAKING CHANGE: `cookie.delete(name)` returns `void` instead of `boolean` +This release contains several improvements to `Cookie` that bring it more in line with other headers like `Accept`, `AcceptEncoding`, and `AcceptLanguage`. + +- BREAKING CHANGE: `cookie.names()` and `cookie.values()` are now getters that return `string[]` instead of methods that return `IterableIterator` - BREAKING CHANGE: `cookie.forEach()` calls its callback with `(name, value, cookie)` instead of `(value, name, map)` +- BREAKING CHANGE: `cookie.delete(name)` returns `void` instead of `boolean` + +```ts +// before +let cookieNames = Array.from(headers.cookie.names()); + +// after +let cookieNames = headers.cookie.names; +``` ## v0.9.0 (2024-12-20) diff --git a/packages/headers/src/lib/accept-encoding.ts b/packages/headers/src/lib/accept-encoding.ts index 715c06a..96e157a 100644 --- a/packages/headers/src/lib/accept-encoding.ts +++ b/packages/headers/src/lib/accept-encoding.ts @@ -55,7 +55,7 @@ export class AcceptEncoding implements HeaderValue, Iterable<[string, number]> { } #sort() { - this.#map = new Map([...this.#map].sort(([, a], [, b]) => b - a)); + this.#map = new Map([...this.#map].sort((a, b) => b[1] - a[1])); } /** @@ -72,6 +72,13 @@ export class AcceptEncoding implements HeaderValue, Iterable<[string, number]> { return Array.from(this.#map.values()); } + /** + * The number of encodings in the header. + */ + get size(): number { + return this.#map.size; + } + /** * Returns `true` if the header matches the given encoding (i.e. it is "acceptable"). * @param encoding The encoding to check. @@ -173,13 +180,6 @@ export class AcceptEncoding implements HeaderValue, Iterable<[string, number]> { } } - /** - * The number of encodings in the header. - */ - get size(): number { - return this.#map.size; - } - toString(): string { let pairs: string[] = []; diff --git a/packages/headers/src/lib/accept-language.ts b/packages/headers/src/lib/accept-language.ts index 63b1804..ca2767b 100644 --- a/packages/headers/src/lib/accept-language.ts +++ b/packages/headers/src/lib/accept-language.ts @@ -55,23 +55,30 @@ export class AcceptLanguage implements HeaderValue, Iterable<[string, number]> { } #sort() { - this.#map = new Map([...this.#map].sort(([, a], [, b]) => b - a)); + this.#map = new Map([...this.#map].sort((a, b) => b[1] - a[1])); } /** - * An array of all locale identifiers in the header. + * An array of all languages in the header. */ get languages(): string[] { return Array.from(this.#map.keys()); } /** - * An array of all weight values in the header. + * An array of all weights (q values) in the header. */ get weights(): number[] { return Array.from(this.#map.values()); } + /** + * The number of languages in the header. + */ + get size(): number { + return this.#map.size; + } + /** * Returns `true` if the header matches the given language (i.e. it is "acceptable"). * @param language The locale identifier of the language to check. @@ -179,13 +186,6 @@ export class AcceptLanguage implements HeaderValue, Iterable<[string, number]> { } } - /** - * The number of languages in the header. - */ - get size(): number { - return this.#map.size; - } - toString(): string { let pairs: string[] = []; diff --git a/packages/headers/src/lib/accept.ts b/packages/headers/src/lib/accept.ts index eb50610..684c84c 100644 --- a/packages/headers/src/lib/accept.ts +++ b/packages/headers/src/lib/accept.ts @@ -55,7 +55,7 @@ export class Accept implements HeaderValue, Iterable<[string, number]> { } #sort() { - this.#map = new Map([...this.#map].sort(([, a], [, b]) => b - a)); + this.#map = new Map([...this.#map].sort((a, b) => b[1] - a[1])); } /** @@ -66,12 +66,19 @@ export class Accept implements HeaderValue, Iterable<[string, number]> { } /** - * An array of weight values in the header. + * An array of all weights (q values) in the header. */ get weights(): number[] { return Array.from(this.#map.values()); } + /** + * The number of media types in the `Accept` header. + */ + get size(): number { + return this.#map.size; + } + /** * Returns `true` if the header matches the given media type (i.e. it is "acceptable"). * @param mediaType The media type to check. @@ -110,9 +117,7 @@ export class Accept implements HeaderValue, Iterable<[string, number]> { getPreferred(mediaTypes: string[]): string | null { let sorted = mediaTypes .map((mediaType) => [mediaType, this.getWeight(mediaType)] as const) - .sort((a, b) => { - return b[1] - a[1]; - }); + .sort((a, b) => b[1] - a[1]); let first = sorted[0]; @@ -179,13 +184,6 @@ export class Accept implements HeaderValue, Iterable<[string, number]> { } } - /** - * The number of media types in the `Accept` header. - */ - get size(): number { - return this.#map.size; - } - toString(): string { let pairs: string[] = []; diff --git a/packages/headers/src/lib/cookie.test.ts b/packages/headers/src/lib/cookie.test.ts index 7367bfe..56b2d22 100644 --- a/packages/headers/src/lib/cookie.test.ts +++ b/packages/headers/src/lib/cookie.test.ts @@ -42,6 +42,16 @@ describe('Cookie', () => { assert.equal(header.get('name2'), 'value2'); }); + it('gets all names', () => { + let header = new Cookie('name1=value1; name2=value2'); + assert.deepEqual(header.names, ['name1', 'name2']); + }); + + it('gets all values', () => { + let header = new Cookie('name1=value1; name2=value2'); + assert.deepEqual(header.values, ['value1', 'value2']); + }); + it('sets and gets values', () => { let header = new Cookie(); header.set('name', 'value'); @@ -73,18 +83,6 @@ describe('Cookie', () => { assert.equal(header.size, 0); }); - it('iterates over names', () => { - let header = new Cookie('name1=value1; name2=value2'); - let names = Array.from(header.names()); - assert.deepEqual(names, ['name1', 'name2']); - }); - - it('iterates over values', () => { - let header = new Cookie('name1=value1; name2=value2'); - let values = Array.from(header.values()); - assert.deepEqual(values, ['value1', 'value2']); - }); - it('iterates over entries', () => { let header = new Cookie('name1=value1; name2=value2'); let entries = Array.from(header.entries()); diff --git a/packages/headers/src/lib/cookie.ts b/packages/headers/src/lib/cookie.ts index 2d327b0..d10d2e5 100644 --- a/packages/headers/src/lib/cookie.ts +++ b/packages/headers/src/lib/cookie.ts @@ -36,6 +36,27 @@ export class Cookie implements HeaderValue, Iterable<[string, string]> { } } + /** + * An array of the names of the cookies in the header. + */ + get names(): string[] { + return Array.from(this.#map.keys()); + } + + /** + * An array of the values of the cookies in the header. + */ + get values(): string[] { + return Array.from(this.#map.values()); + } + + /** + * The number of cookies in the header. + */ + get size(): number { + return this.#map.size; + } + /** * Gets the value of a cookie with the given name from the header. * @param name The name of the cookie. @@ -78,14 +99,6 @@ export class Cookie implements HeaderValue, Iterable<[string, string]> { this.#map.clear(); } - names(): IterableIterator { - return this.#map.keys(); - } - - values(): IterableIterator { - return this.#map.values(); - } - entries(): IterableIterator<[string, string]> { return this.#map.entries(); } @@ -100,13 +113,6 @@ export class Cookie implements HeaderValue, Iterable<[string, string]> { } } - /** - * The number of cookies in the header. - */ - get size(): number { - return this.#map.size; - } - toString(): string { let pairs: string[] = [];