UNPKG

@repugraf/cross-domain-storage

Version:

Enables shared cross domain localStorage and sessionStorage

103 lines (102 loc) 3.49 kB
import { error, debugLog } from "./shared.js"; /** * Creates a server to listen to clients * * Call `listen` to start accepting client connections * * ```js * const server = getServer({ * allowedDomains: [ * { * origin: /sub1.example.com$/, * allowedMethods: ["get", "set", "remove"] * }, * { * origin: /sub2.example.com$/, * allowedMethods: ["get"] * } * ] * }); * * await server.listen(); * ``` */ const getServer = (config) => { var _a, _b; const domains = (_a = config.allowedDomains) !== null && _a !== void 0 ? _a : []; const debug = (_b = config.debug) !== null && _b !== void 0 ? _b : false; const clients = new Set(); const handler = (e) => { var _a, _b; const post = postMessage.bind(null, e.origin); const initialMessage = { id: "", source: "cross-domain-storage", isResponse: true, isError: false, result: null }; try { const data = e.data; if (data.source !== "cross-domain-storage") return; initialMessage.id = data.id; const currentDomain = domains.find(d => d.origin.test(e.origin)); if (!currentDomain) { return post({ ...initialMessage, result: `Domain not allowed (${e.origin})`, isError: true }); } const allowedMethods = (_a = currentDomain.allowedMethods) !== null && _a !== void 0 ? _a : ["get", "set", "remove"]; const allowedStorageTypes = (_b = currentDomain.allowedStorageTypes) !== null && _b !== void 0 ? _b : [ "localStorage", "sessionStorage" ]; if (!allowedMethods.includes(data.method)) { return post({ ...initialMessage, result: `Method not allowed (${data.method})`, isError: true }); } if (!allowedStorageTypes.includes(data.storageType)) { return post({ ...initialMessage, result: `Storage type not allowed (${data.storageType})`, isError: true }); } clients.add(e.origin); const result = window[data.storageType][`${data.method}Item`](data.key, data.value); debugLog(debug, `[Server] Action executed: ${data.storageType}.${data.method}Item(${data.key}${data.value ? `, ${data.value}` : ""})`); post({ ...initialMessage, result }); } catch (err) { error(debug, err); } }; /** Start listening for incoming connections */ const listen = () => { window.addEventListener("message", handler); debugLog(debug, "[Server] Listening for incoming connections"); }; /** Stop listening for incoming connections */ const stopListening = () => { window.removeEventListener("message", handler); debugLog(debug, "[Server] Stopped listening for incoming connections"); }; return { listen, stopListening, get clients() { return [...clients]; } }; }; const postMessage = (origin, message) => { var _a; (_a = window.top) === null || _a === void 0 ? void 0 : _a.postMessage(message, origin); }; export { getServer };