mirror of
https://github.com/wassname/talk.git
synced 2026-09-12 13:01:11 +08:00
Full PromisifiedStorage + Simplifications
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`should call clear 1`] = `"{\\"a\\":\\"0\\",\\"b\\":\\"1\\",\\"d\\":\\"3\\"}"`;
|
||||
@@ -1,2 +1,4 @@
|
||||
export { default as buildURL } from "./buildURL";
|
||||
export { default as ensureEndSlash } from "./ensureEndSlash";
|
||||
export { default as startsWith } from "./startsWith";
|
||||
export { default as prefixStorage } from "./prefixStorage";
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import sinon from "sinon";
|
||||
import { createInMemoryStorage } from "../testUtils";
|
||||
import prefixStorage from "./prefixStorage";
|
||||
|
||||
it("should get nth key", () => {
|
||||
const storage = createInMemoryStorage({
|
||||
a: "0",
|
||||
b: "1",
|
||||
"talk:c": "2",
|
||||
d: "3",
|
||||
"talk:e": "4",
|
||||
});
|
||||
|
||||
const prefixed = prefixStorage(storage, "talk:");
|
||||
expect(prefixed.key(0)).toBe("talk:c");
|
||||
expect(prefixed.key(1)).toBe("talk:e");
|
||||
expect(prefixed.key(2)).toBeNull();
|
||||
});
|
||||
|
||||
it("should call clear", () => {
|
||||
const storage = createInMemoryStorage({
|
||||
a: "0",
|
||||
b: "1",
|
||||
"talk:c": "2",
|
||||
d: "3",
|
||||
"talk:e": "4",
|
||||
});
|
||||
|
||||
const prefixed = prefixStorage(storage, "talk:");
|
||||
prefixed.clear();
|
||||
expect(storage.toString()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should call length", () => {
|
||||
const storage = createInMemoryStorage({
|
||||
a: "0",
|
||||
b: "1",
|
||||
"talk:c": "2",
|
||||
d: "3",
|
||||
"talk:e": "4",
|
||||
});
|
||||
|
||||
const prefixed = prefixStorage(storage, "talk:");
|
||||
expect(prefixed.length).toBe(2);
|
||||
});
|
||||
|
||||
it("should prefix setItem", () => {
|
||||
const storage = {
|
||||
setItem: sinon.mock().withArgs("talk:key", "value"),
|
||||
};
|
||||
|
||||
const prefixed = prefixStorage(storage as any, "talk:");
|
||||
prefixed.setItem("key", "value");
|
||||
storage.setItem.verify();
|
||||
});
|
||||
|
||||
it("should prefix removeItem", () => {
|
||||
const storage = {
|
||||
removeItem: sinon.mock().withArgs("talk:key"),
|
||||
};
|
||||
|
||||
const prefixed = prefixStorage(storage as any, "talk:");
|
||||
prefixed.removeItem("key");
|
||||
storage.removeItem.verify();
|
||||
});
|
||||
|
||||
it("should prefix getItem", () => {
|
||||
const ret = "value";
|
||||
const storage = {
|
||||
getItem: sinon
|
||||
.mock()
|
||||
.withArgs("talk:key")
|
||||
.returns(ret),
|
||||
};
|
||||
|
||||
const prefixed = prefixStorage(storage as any, "talk:");
|
||||
expect(prefixed.getItem("key")).toBe(ret);
|
||||
(storage.getItem as any).verify();
|
||||
});
|
||||
@@ -0,0 +1,66 @@
|
||||
import startsWith from "./startsWith";
|
||||
|
||||
/**
|
||||
* PrefixedStorage decorates a Storage and prefixes keys in
|
||||
* getItem, setItem and removeItem with given prefix.
|
||||
*/
|
||||
class PrefixedStorage implements Storage {
|
||||
private storage: Storage;
|
||||
private prefix: string;
|
||||
|
||||
constructor(storage: Storage, prefix: string) {
|
||||
this.storage = storage;
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
get length() {
|
||||
let count = 0;
|
||||
for (let i = 0; i < this.storage.length; i++) {
|
||||
if (startsWith(this.storage.key(i)!, this.prefix)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public clear() {
|
||||
const toBeDeleted = [];
|
||||
for (let i = 0; i < this.storage.length; i++) {
|
||||
const key = this.storage.key(i)!;
|
||||
if (startsWith(key, this.prefix)) {
|
||||
toBeDeleted.push(key);
|
||||
}
|
||||
}
|
||||
toBeDeleted.forEach(key => this.storage.removeItem(key));
|
||||
}
|
||||
|
||||
public key(n: number) {
|
||||
let count = 0;
|
||||
for (let i = 0; i < this.storage.length; i++) {
|
||||
const key = this.storage.key(i)!;
|
||||
if (startsWith(key, this.prefix)) {
|
||||
if (count === n) {
|
||||
return key;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public getItem(key: string) {
|
||||
return this.storage.getItem(`${this.prefix}${key}`);
|
||||
}
|
||||
|
||||
public setItem(key: string, value: string) {
|
||||
return this.storage.setItem(`${this.prefix}${key}`, value);
|
||||
}
|
||||
|
||||
public removeItem(key: string) {
|
||||
return this.storage.removeItem(`${this.prefix}${key}`);
|
||||
}
|
||||
}
|
||||
|
||||
export default function prefixStorage(storage: Storage, prefix: string) {
|
||||
return new PrefixedStorage(storage, prefix);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import startsWith from "./startsWith";
|
||||
|
||||
it("should work correctly", () => {
|
||||
const str1 = "Saturday night plans";
|
||||
expect(startsWith(str1, "Sat")).toBe(true);
|
||||
expect(startsWith(str1, "Sat", 3)).toBe(false);
|
||||
});
|
||||
@@ -0,0 +1,4 @@
|
||||
/** A substitute for string.startsWith */
|
||||
export default function startsWith(str: string, search: string, pos?: number) {
|
||||
return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search;
|
||||
}
|
||||
Reference in New Issue
Block a user