// deno-lint-ignore-file import { CookieStore, CookieListItem, CookieInit, CookieList, CookieStoreDeleteOptions, CookieStoreGetOptions } from "@worker-tools/request-cookie-store"; import { ExtendablePromise } from "@worker-tools/extendable-promise"; import { Cookies, cookiesFrom } from "../cookies.js"; const encode = encodeURIComponent; function decodeItem(item: Item) { if (item) { item.name = decodeURIComponent(item.name); item.value = decodeURIComponent(item.value); } return item; } /** * A more opinionated cookie store implementation that * - URI-(en|de)codes cookie values and * - provides a promise that resolves when all async operations associated with this store have settled. */ export class MiddlewareCookieStore implements CookieStore { #promise: ExtendablePromise; #store: CookieStore; constructor(store: CookieStore, requestDuration: Promise) { this.#store = store; this.#promise = new ExtendablePromise(requestDuration); } get(name?: string): Promise; get(options?: CookieStoreGetOptions): Promise; async get(options?: any): Promise { return decodeItem(await this.#store.get(options)); } getAll(name?: string): Promise; getAll(options?: CookieStoreGetOptions): Promise; async getAll(options?: any): Promise { return (await this.#store.getAll(options)).map(decodeItem); } set(name: string, value: string): Promise; set(options: CookieInit): Promise; set(name: string | CookieInit, value?: string): Promise { let res: Promise; if (typeof name === 'string' && typeof value === 'string') { res = this.#store.set(encode(name), encode(value)); } else if (name && typeof name === 'object') { const options = name; options.name = encode(options.name) options.value = encode(options.value) res = this.#store.set(options); } else throw Error('Illegal invocation'); this.#promise.waitUntil(res); return res; } delete(name: string): Promise; delete(options: CookieStoreDeleteOptions): Promise; delete(options: any): Promise { const res = this.#store.delete(options) this.#promise.waitUntil(res); return res; } addEventListener(type: string, callback: EventListenerOrEventListenerObject | null, options?: boolean | AddEventListenerOptions): void; addEventListener(type: any, callback: any, options?: any): void { this.#store.addEventListener(type, callback, options); } dispatchEvent(event: Event): boolean; dispatchEvent(event: any): boolean { return this.#store.dispatchEvent(event); } removeEventListener(type: string, callback: EventListenerOrEventListenerObject | null, options?: boolean | EventListenerOptions): void; removeEventListener(type: any, callback: any, options?: any): void { this.#store.removeEventListener(type, callback, options); } /** @deprecated Name of this property might change */ get settled() { return this.#promise.settled } /** @deprecated Name of this property might change */ get allSettledPromise() { return Promise.resolve(this.#promise) } /** * If you've made changes to the store and would like to access the current cookies as an object, * it is provided as a promise here (TODO:) * @deprecated This method might change names */ get updatedCookies(): Promise { return cookiesFrom(this) } }