@nodecfdi/tough-cookie-file-store
Version:
A JSON file store implementation for tough-cookie module
209 lines (208 loc) • 6.43 kB
JavaScript
// src/file_cookie_store.ts
import { existsSync, readFileSync, writeFileSync } from "node:fs";
import { inspect } from "node:util";
import { Cookie, pathMatch, permuteDomain, Store } from "tough-cookie";
import { createPromiseCallback } from "tough-cookie/dist/utils.js";
var FileCookieStore = class extends Store {
synchronous;
/**
* @internal
*/
idx;
filePath;
constructor(filePath) {
super();
this.synchronous = true;
this.idx = /* @__PURE__ */ Object.create(null);
this.filePath = filePath;
this._loadFromFile();
}
/**
* @internal No doc because this is an overload that supports the implementation
*/
findCookie(domain, path, key, callback) {
const promiseCallback = createPromiseCallback(callback);
if (!domain || !path || !key) {
return promiseCallback.resolve(void 0);
}
const result = this.idx[domain]?.[path]?.[key];
return promiseCallback.resolve(result);
}
/**
* @internal No doc because this is an overload that supports the implementation
*/
findCookies(domain, path, allowSpecialUseDomain = false, callback) {
if (typeof allowSpecialUseDomain === "function") {
callback = allowSpecialUseDomain;
allowSpecialUseDomain = true;
}
const results = [];
const promiseCallback = createPromiseCallback(callback);
if (!domain) {
return promiseCallback.resolve([]);
}
let pathMatcher;
if (path) {
pathMatcher = function matchRFC(domainIndex) {
for (const cookiePath in domainIndex) {
if (pathMatch(path, cookiePath)) {
const pathIndex = domainIndex[cookiePath];
for (const key in pathIndex) {
const value = pathIndex[key];
if (value) {
results.push(value);
}
}
}
}
};
} else {
pathMatcher = function matchAll(domainIndex) {
for (const curPath in domainIndex) {
const pathIndex = domainIndex[curPath];
for (const key in pathIndex) {
const value = pathIndex[key];
if (value) {
results.push(value);
}
}
}
};
}
const domains = permuteDomain(domain, allowSpecialUseDomain) ?? [domain];
const { idx } = this;
for (const curDomain of domains) {
const domainIndex = idx[curDomain];
if (!domainIndex) {
continue;
}
pathMatcher(domainIndex);
}
return promiseCallback.resolve(results);
}
/**
* @internal No doc because this is an overload that supports the implementation
*/
putCookie(cookie, callback) {
const promiseCallback = createPromiseCallback(callback);
const { domain, path, key } = cookie;
if (!domain || !path || !key) {
return promiseCallback.resolve(void 0);
}
const domainEntry = this.idx[domain] ?? /* @__PURE__ */ Object.create(null);
this.idx[domain] = domainEntry;
const pathEntry = domainEntry[path] ?? /* @__PURE__ */ Object.create(null);
domainEntry[path] = pathEntry;
pathEntry[key] = cookie;
this._saveToFile();
return promiseCallback.resolve(void 0);
}
/**
* @internal No doc because this is an overload that supports the implementation
*/
updateCookie(_oldCookie, newCookie, callback) {
if (callback) {
this.putCookie(newCookie, callback);
return;
}
return this.putCookie(newCookie);
}
/**
* @internal No doc because this is an overload that supports the implementation
*/
removeCookie(domain, path, key, callback) {
const promiseCallback = createPromiseCallback(callback);
delete this.idx[domain]?.[path]?.[key];
this._saveToFile();
return promiseCallback.resolve(void 0);
}
/**
* @internal No doc because this is an overload that supports the implementation
*/
removeCookies(domain, path, callback) {
const promiseCallback = createPromiseCallback(callback);
const domainEntry = this.idx[domain];
if (domainEntry) {
if (path) {
delete domainEntry[path];
} else {
delete this.idx[domain];
}
}
this._saveToFile();
return promiseCallback.resolve(void 0);
}
/**
* @internal No doc because this is an overload that supports the implementation
*/
removeAllCookies(callback) {
const promiseCallback = createPromiseCallback(callback);
this.idx = /* @__PURE__ */ Object.create(null);
this._saveToFile();
return promiseCallback.resolve(void 0);
}
/**
* @internal No doc because this is an overload that supports the implementation
*/
getAllCookies(callback) {
const promiseCallback = createPromiseCallback(callback);
const cookies = [];
const { idx } = this;
const domains = Object.keys(idx);
for (const domain of domains) {
const domainEntry = idx[domain] ?? {};
const paths = Object.keys(domainEntry);
for (const path of paths) {
const pathEntry = domainEntry[path] ?? {};
const keys = Object.keys(pathEntry);
for (const key of keys) {
const keyEntry = pathEntry[key];
if (keyEntry) {
cookies.push(keyEntry);
}
}
}
}
cookies.sort((a, b) => {
return (a.creationIndex || 0) - (b.creationIndex || 0);
});
return promiseCallback.resolve(cookies);
}
_loadFromFile() {
let data = null;
let dataJson = null;
if (existsSync(this.filePath)) {
data = readFileSync(this.filePath, "utf8");
}
if (data) {
try {
dataJson = JSON.parse(data);
} catch (error) {
throw new AggregateError(
[error],
`Could not parse cookie file ${this.filePath}. Please ensure it is not corrupted.`
);
}
}
for (const domainName in dataJson) {
for (const pathName in dataJson[domainName]) {
for (const cookieName in dataJson[domainName][pathName]) {
dataJson[domainName][pathName][cookieName] = Cookie.fromJSON(
JSON.stringify(dataJson[domainName][pathName][cookieName])
);
}
}
}
this.idx = dataJson ?? /* @__PURE__ */ Object.create(null);
}
_saveToFile() {
writeFileSync(this.filePath, JSON.stringify(this.idx));
}
$inspect() {
return `{ idx: ${inspect(this.idx, false, 2)} }`;
}
};
export {
FileCookieStore
};
/* istanbul ignore if -- @preserve */