diff --git a/README.md b/README.md index d2918ba..419d543 100644 --- a/README.md +++ b/README.md @@ -27,15 +27,8 @@ console.log(foo); // { name: 'forgive', value: 'me' } await cookieStore.set('forget', 'it'); // get multiple cookies -const cookies = await cookieStore.getAll({ - name: 'for', - matchType: 'starts-with', -}); -const obj = {}; -for (const cookie of cookies) { - obj[cookie.name] = cookie.value; -} -console.log(obj); // { forgive: 'me', forget: 'it' } +const cookies = await cookieStore.getAll(); +console.log(obj); // [{ name: 'forgive', value: 'me' }, { name: 'forget', value: 'it' }] // delete a cookie await cookieStore.delete('forget'); diff --git a/index.tests.ts b/index.tests.ts index c6f0e3d..77baf2d 100644 --- a/index.tests.ts +++ b/index.tests.ts @@ -23,6 +23,28 @@ describe('Cookie Store', () => { expect(result).to.deep.equal({ name: foo, value: bar }); }); }); + describe('getAll', () => { + it('returns an array with all cookies if no name is provided', async () => { + const foo = 'foo'; + const bar = 'bar'; + const baz = 'baz'; + document.cookie = `${foo}=${bar}; ${bar}=${baz}`; + const result = await window.cookieStore.getAll(); + expect(result).to.deep.equal([ + { name: foo, value: bar }, + { name: bar, value: baz }, + ]); + }); + + it('returns an array with cookies that match name', async () => { + const foo = 'foo'; + const bar = 'bar'; + const baz = 'baz'; + document.cookie = `${foo}=${bar}; ${bar}=${baz}`; + const result = await window.cookieStore.getAll(bar); + expect(result).to.deep.equal([{ name: bar, value: baz }]); + }); + }); describe('set', () => { it('updates document.cookie with supplied value', async () => { await window.cookieStore.set('foo', 'bar'); @@ -33,7 +55,7 @@ describe('Cookie Store', () => { 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=/'); + expect(document.cookie).to.equal('foo=bar; Max-Age=0'); }); }); }); diff --git a/index.ts b/index.ts index c92da15..25d316e 100644 --- a/index.ts +++ b/index.ts @@ -37,6 +37,7 @@ function tryDecode( } type CookieSameSite = 'no_restriction' | 'lax' | 'strict'; +type CookieMatchType = 'equals'; interface Cookie { domain?: string; @@ -50,11 +51,15 @@ interface Cookie { interface CookieStoreDeleteOptions { name: string; - domain: null; - path: '/'; + domain?: string; + path?: string; } -type ParsedCookies = Record; +interface CookieStoreGetOptions { + name?: string; + url?: string; + matchType?: CookieMatchType; +} interface ParseOptions { decode?: boolean; @@ -83,12 +88,12 @@ interface SerializeOptions { * @private */ -function parse(str, options: ParseOptions = {}): ParsedCookies { +function parse(str, options: ParseOptions = {}): Cookie[] { if (typeof str !== 'string') { throw new TypeError('argument str must be a string'); } - const obj: ParsedCookies = {}; + const obj = []; const opt = options || {}; const pairs = str.split(pairSplitRegExp); const dec = opt.decode || decode; @@ -112,10 +117,10 @@ function parse(str, options: ParseOptions = {}): ParsedCookies { // only assign once if (undefined == obj[key]) { - obj[key] = { + obj.push({ name: key, value: tryDecode(val, dec), - }; + }); } } @@ -223,6 +228,18 @@ function serialize(name, val, options: SerializeOptions = {}): string { return str; } +function sanitizeOptions( + arg: unknown +): CookieStoreGetOptions | CookieStoreDeleteOptions { + if (!arg) { + return {}; + } + if (typeof arg === 'string') { + return { name: arg }; + } + return arg; +} + const CookieStore = { /** * Get a cookie. @@ -230,8 +247,11 @@ const CookieStore = { * @param {string} name * @return {Promise} */ - get(name): Promise { - return Promise.resolve(parse(document.cookie)[name]); + async get( + options?: CookieStoreGetOptions['name'] | CookieStoreGetOptions + ): Promise { + const { name } = sanitizeOptions(options); + return parse(document.cookie).find((cookie) => cookie.name === name); }, /** @@ -255,11 +275,16 @@ const CookieStore = { /** * Get multiple cookies. - * - * @return {Promise} */ - getAll(): Promise { - throw Error('getAll not implemented, coming soon though.'); + async getAll( + options?: CookieStoreGetOptions['name'] | CookieStoreGetOptions + ): Promise { + const { name } = sanitizeOptions(options); + if (name) { + const cookie = await this.get(name); + return [cookie]; + } + return parse(document.cookie); }, /** @@ -268,12 +293,16 @@ const CookieStore = { * @param {String} name * @return {Promise} */ - async delete(name: CookieStoreDeleteOptions['name']): Promise { + async delete( + options: CookieStoreDeleteOptions['name'] | CookieStoreDeleteOptions + ): Promise { + const { name, domain } = sanitizeOptions( + options + ) as CookieStoreDeleteOptions; const { value } = await this.get(name); const serializedValue = serialize(name, value, { maxAge: 0, - domain: null, - path: '/', + domain, }); document.cookie = serializedValue; return Promise.resolve();