Skip to content

Commit

Permalink
Support Session Storage and refactor the storage APIs (WebSQL will be…
Browse files Browse the repository at this point in the history
… fixed soon)
  • Loading branch information
MovByte committed Dec 30, 2024
1 parent 68726c4 commit fbae1c4
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 97 deletions.
3 changes: 0 additions & 3 deletions AeroSandbox/src/interceptors/storage/sharedStorage.ts

This file was deleted.

12 changes: 4 additions & 8 deletions AeroSandbox/src/interceptors/storage/sql.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
import { type APIInterceptor, SupportEnum } from "$types/apiInterceptors.d.ts";
import { proxyLocation } from "$shared/proxyLocation";

/**
* The id to use for escaping the SQL storage key
* @param cookieStoreId
* @returns
*/
const createHandler = (cookieStoreId?) => {
const createHandler = () => {
return (target, that, args) => {
const [key]: [string] = args;

let newKey = $aero.config.sandbox.storageKey + key;
if (cookieStoreId) {
newKey = `${cookieStoreId}_${newKey}`;
}
const newKey = `${proxyLocation().origin}_sql_${key}`;

args[0] = newKey;

Expand All @@ -30,6 +25,7 @@ const createHandler = (cookieStoreId?) => {
};
};

// FIXME: This is all deprecated way of doing thiigs
export default [
{
createStorageProxyHandlers: cookieStoreId =>
Expand Down
28 changes: 27 additions & 1 deletion AeroSandbox/src/interceptors/storage/storage.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,29 @@
import { type APIInterceptor, SupportEnum } from "$types/apiInterceptors";

import genStorageAPIInterceptors from "$util/storageAPIInterceptorsGeneric";
import { proxyLocation } from "$shared/proxyLocation";

export default genStorageAPIInterceptors("storage");
export default [
...genStorageAPIInterceptors("sharedStorage", $aero.sandbox.config.sharedStorageId),
...genStorageAPIInterceptors("storage", $aero.sandbox.config.storageStoreId),
...genStorageAPIInterceptors("sessionStorage", `${$aero.sandbox.config.sessionStoreId}_${$aero.clientId}`),
// This is needed for Session Storage only
{
init: () => {
// Remove the keys from the previous sessions
for (let i = 0; i < sessionStorage.length; i++) {
const realKey = sessionStorage.key(i);
if (realKey.startsWith(proxyLocation().origin)) {
const keyWithoutOriginEscape = realKey.replace(new RegExp(`^${proxyLocation().origin}_`), "");
if (
// Is key from a previous session?
keyWithoutOriginEscape.startsWith(`${$aero.sandbox.config.sessionStoreId}_`))
sessionStorage.removeItem(realKey);
}
}
},
globalProp: "sessionStorage",
forStorage: true,
supports: SupportEnum.widelyAvailable
}
] as APIInterceptor[]
60 changes: 33 additions & 27 deletions AeroSandbox/src/interceptors/util/storage.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,44 @@
import { type GeneratorCtxTypeProxyHandler } from "$types/apiInterceptors";
/**
* Note: The cookie store ID is so that we can store data from other storage types when the storage is exhausted from them. We need to know what is actually a cookie.
* @module
*/

import { storagePrefix } from "$shared/storage";

const storageNomenclatureHandlers: { [key: string]: GeneratorCtxTypeProxyHandler } = {
prefix: (ctx) => ({
apply: (target, that, args) => {
const [key] = args;
args[0] = prefixKey(ctx.cookieStoreId, key);
return Reflect.apply(target, that, args);
function genStorageNomenclatureHandlers(storeId): { [key: string]: ProxyHandler<Storage> } {
return {
prefix: {
apply: (target, that, args) => {
const [key] = args;
args[0] = prefixKey(storeId, key);
return Reflect.apply(target, that, args);
}
},
unprefix: {
apply: (target, that, args) => {
const [key] = args;
args[0] = unprefixKey(storeId, key);
return Reflect.apply(target, that, args);
}
}
} as ProxyHandler<Storage>),
unprefix: (ctx) => ({
apply: (target, that, args) => {
const [key] = args;
args[0] = unprefixKey(ctx.cookieStoreId, key);
return Reflect.apply(target, that, args);
}
} as ProxyHandler<Storage>),
};
}
}


function prefixKey(cookieStoreId, key: string): string {
function prefixKey(prefix, key: string): string {
let proxifiedKey = storagePrefix(key);
if (cookieStoreId) {
proxifiedKey = `${cookieStoreId}_${proxifiedKey}`;
if (prefix) {
proxifiedKey = `${prefix}_${proxifiedKey}`;
}
return proxifiedKey;
}
function unprefixKey(cookieStoreId, key: string): string {
if (!key.startsWith(cookieStoreId))
$aero.logger.fatalErr("Failed to unprefix the key (the key does not belong to the current cookie store)");
const keyWithoutCookieStoreId = key.replace(new RegExp(`^${cookieStoreId}`), "");
if (!keyWithoutCookieStoreId.startsWith(storagePrefix("")))
$aero.logger.fatalErr("Failed to unprefix the key (the key does not have the storage prefix)");
return keyWithoutCookieStoreId.replace(storagePrefix(""), "");
/** Works for everything except Session Storage */
function unprefixKey(storeId: string, key: string): string {
const storeIdKey = storagePrefix(storeId);
if (!key.startsWith(storeIdKey))
$aero.logger.fatalErr(`Failed to unprefix the key (the key does not have the expected cookie store key prefix, "${storeIdKey}")!`);
const keyWithoutStoreIdKey = key.replace(new RegExp(`^${storeIdKey}`), "");
return keyWithoutStoreIdKey;
}

export { storageNomenclatureHandlers };
export { genStorageNomenclatureHandlers, prefixKey, unprefixKey };
58 changes: 0 additions & 58 deletions AeroSandbox/src/interceptors/util/storageAPIInterceptorsGeneric.ts

This file was deleted.

59 changes: 59 additions & 0 deletions AeroSandbox/src/interceptors/util/storageApiInterceptorsGeneric.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { type APIInterceptor, SupportEnum } from "$types/apiInterceptors.d.ts";

import { genStorageNomenclatureHandlers, unprefixKey } from "./storage";
import { storagePrefix } from "$shared/storage";

export default function genStorageApiInterceptors(key: string, storeId: string): APIInterceptor[] {
const storageNomenclatureHandlers = genStorageNomenclatureHandlers(storeId);
const storageAPIInterceptorsGeneric = [
{
proxyHandler: {
apply(target, _that, _args) {
const storageApi = key === "sessionStorage" ? localStorage : target;
for (let i = 0; i < storageApi.length; i++) {
const realKey = storageApi.key(i);
const storeIdKey = storagePrefix(storeId);
if (realKey.startsWith(storeIdKey))
storageApi.removeItem(realKey);
}
}
} as ProxyHandler<Storage>,
globalProp: ".clear"
},
{
proxyHandler: storageNomenclatureHandlers.unprefix,
globalProp: ".getItem"
},
{
proxyHandler: {
apply(target, _that, args) {
const storageApi = key === "sessionStorage" ? localStorage : target;
const [getIndex] = args;
const proxifiedKeys: string[] = [];
for (let i = 0; i < storageApi.length; i++) {
const realKey = storageApi.key(i);
const storeIdKey = storagePrefix(storeId);
if (realKey.startsWith(storeIdKey))
proxifiedKeys.push(unprefixKey(storeId, realKey));
}
return proxifiedKeys[getIndex];
}
} as ProxyHandler<Storage>,
globalProp: ".key"
},
{
proxyHandler: storageNomenclatureHandlers.prefix,
globalProp: ".setItem"
},
{
proxyHandler: storageNomenclatureHandlers.unprefix,
globalProp: ".removeItem"
},
] as APIInterceptor[];
return storageAPIInterceptorsGeneric.map(apiInterceptor => {
apiInterceptor.forStorage = true;
apiInterceptor.globalProp = key + apiInterceptor.globalProp;
apiInterceptor.supports = key === "sharedStorage" ? SupportEnum.shippingChromium | SupportEnum.draft : SupportEnum.widelyAvailable;
return apiInterceptor;
});
}

0 comments on commit fbae1c4

Please sign in to comment.