From fe99d16e29a4efbe76ed14c50b2f5efdc57d0330 Mon Sep 17 00:00:00 2001 From: Mark Kennedy Date: Sat, 8 Aug 2020 07:21:19 -0400 Subject: [PATCH] Update delete method (#36) * Return cookie object from get method * Improve delete method and documentation * Add basic test for delete method --- README.md | 2 +- index.tests.ts | 15 ++++++++++++--- index.ts | 44 +++++++++++++++++++++++++++++++++++--------- 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 1ea3c46..d2918ba 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ import 'cookie-store'; await cookieStore.set('forgive', 'me'); // get a cookie const foo = await cookieStore.get('forgive'); -console.log(foo); // 'me' +console.log(foo); // { name: 'forgive', value: 'me' } // set another cookie await cookieStore.set('forget', 'it'); diff --git a/index.tests.ts b/index.tests.ts index 5c0972a..c6f0e3d 100644 --- a/index.tests.ts +++ b/index.tests.ts @@ -16,9 +16,11 @@ describe('Cookie Store', () => { }); describe('get', () => { it('returns cookie matching supplied name', async () => { - document.cookie = 'foo=bar'; - const foo = await window.cookieStore.get('foo'); - expect(foo).to.equal('bar'); + const foo = 'foo'; + const bar = 'bar'; + document.cookie = `${foo}=${bar}`; + const result = await window.cookieStore.get(foo); + expect(result).to.deep.equal({ name: foo, value: bar }); }); }); describe('set', () => { @@ -27,4 +29,11 @@ describe('Cookie Store', () => { expect(document.cookie).to.equal('foo=bar'); }); }); + describe('delete', () => { + it('sets max age to 0 on cookie that matches supplied name', async () => { + document.cookie = 'foo=bar'; + await window.cookieStore.delete('foo'); + expect(document.cookie).to.equal('foo=bar; Max-Age=0; Path=/'); + }); + }); }); diff --git a/index.ts b/index.ts index 4ed5f71..c92da15 100644 --- a/index.ts +++ b/index.ts @@ -25,7 +25,6 @@ const fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/; * @param {function} decode * @private */ - function tryDecode( str: string, decode: ((encodedURIComponent: string) => string) | boolean @@ -37,7 +36,25 @@ function tryDecode( } } -type ParsedCookies = Record; +type CookieSameSite = 'no_restriction' | 'lax' | 'strict'; + +interface Cookie { + domain?: string; + expires?: number; + name: string; + path?: string; + secure?: boolean; + sameSite?: CookieSameSite; + value: string; +} + +interface CookieStoreDeleteOptions { + name: string; + domain: null; + path: '/'; +} + +type ParsedCookies = Record; interface ParseOptions { decode?: boolean; @@ -95,7 +112,10 @@ function parse(str, options: ParseOptions = {}): ParsedCookies { // only assign once if (undefined == obj[key]) { - obj[key] = tryDecode(val, dec); + obj[key] = { + name: key, + value: tryDecode(val, dec), + }; } } @@ -210,8 +230,8 @@ const CookieStore = { * @param {string} name * @return {Promise} */ - get(name): Promise { - return Promise.resolve(parse(document.cookie)[name] as string); + get(name): Promise { + return Promise.resolve(parse(document.cookie)[name]); }, /** @@ -221,7 +241,7 @@ const CookieStore = { * @param {string} value * @return {Promise} */ - set(name, value): Promise { + set(name: string, value: string): Promise { return new Promise((resolve, reject) => { try { const cookieString = serialize(name, value); @@ -245,12 +265,18 @@ const CookieStore = { /** * Remove a cookie. * + * @param {String} name * @return {Promise} */ - delete(name): Promise { - return this.get(name).then((str) => { - document.cookie = document.cookie.replace(str, ''); + async delete(name: CookieStoreDeleteOptions['name']): Promise { + const { value } = await this.get(name); + const serializedValue = serialize(name, value, { + maxAge: 0, + domain: null, + path: '/', }); + document.cookie = serializedValue; + return Promise.resolve(); }, };