@repugraf/cross-domain-storage
Version:
Enables shared cross domain localStorage and sessionStorage
103 lines (102 loc) • 3.49 kB
JavaScript
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 };