@esportsplus/web-storage 0.1.44 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,11 +4,13 @@
4
4
  # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
5
5
 
6
6
  version: 2
7
+
7
8
  registries:
8
9
  npm-npmjs:
9
10
  token: ${{secrets.NPM_TOKEN}}
10
11
  type: npm-registry
11
12
  url: https://registry.npmjs.org
13
+
12
14
  updates:
13
15
  - package-ecosystem: "npm"
14
16
  directory: "/"
@@ -1,7 +1,9 @@
1
1
  name: bump
2
+
2
3
  on:
3
4
  push:
4
5
  branches: '**' # only trigger on branches, not on tags
6
+
5
7
  jobs:
6
8
  bump:
7
9
  uses: esportsplus/workflows/.github/workflows/bump.yml@main
@@ -0,0 +1,12 @@
1
+ name: dependabot automerge
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, labeled]
6
+ workflow_dispatch:
7
+
8
+ jobs:
9
+ automerge:
10
+ secrets:
11
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
12
+ uses: esportsplus/workflows/.github/workflows/dependabot.yml@main
@@ -1,4 +1,5 @@
1
1
  name: publish to npm
2
+
2
3
  on:
3
4
  release:
4
5
  types: [published]
@@ -7,8 +8,9 @@ on:
7
8
  workflows: [bump]
8
9
  types:
9
10
  - completed
11
+
10
12
  jobs:
11
13
  publish:
12
14
  secrets:
13
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN_PUBLISHING }}
14
- uses: esportsplus/workflows/.github/workflows/publish.yml@main
15
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
16
+ uses: esportsplus/workflows/.github/workflows/publish.yml@main
@@ -0,0 +1,5 @@
1
+ declare enum DriverType {
2
+ IndexedDB = 0,
3
+ LocalStorage = 1
4
+ }
5
+ export { DriverType };
@@ -0,0 +1,6 @@
1
+ var DriverType;
2
+ (function (DriverType) {
3
+ DriverType[DriverType["IndexedDB"] = 0] = "IndexedDB";
4
+ DriverType[DriverType["LocalStorage"] = 1] = "LocalStorage";
5
+ })(DriverType || (DriverType = {}));
6
+ export { DriverType };
@@ -0,0 +1,17 @@
1
+ import type { Driver } from '../types.js';
2
+ declare class IndexedDBDriver<T> implements Driver<T> {
3
+ private connection;
4
+ private name;
5
+ constructor(name: string, version: number);
6
+ all(): Promise<T>;
7
+ clear(): Promise<void>;
8
+ count(): Promise<number>;
9
+ delete(keys: (keyof T)[]): Promise<void>;
10
+ get(key: keyof T): Promise<T[keyof T] | undefined>;
11
+ keys(): Promise<(keyof T)[]>;
12
+ map(fn: (value: T[keyof T], key: keyof T, i: number) => void | Promise<void>): Promise<void>;
13
+ only(keys: (keyof T)[]): Promise<Map<keyof T, T[keyof T]>>;
14
+ replace(entries: [keyof T, T[keyof T]][]): Promise<void>;
15
+ set(key: keyof T, value: T[keyof T]): Promise<boolean>;
16
+ }
17
+ export { IndexedDBDriver };
@@ -0,0 +1,115 @@
1
+ let connections = new Map();
2
+ function connect(name, version) {
3
+ let key = `${name}:${version}`;
4
+ if (!connections.has(key)) {
5
+ connections.set(key, new Promise((resolve, reject) => {
6
+ let request = indexedDB.open(name, version);
7
+ request.onupgradeneeded = () => {
8
+ let db = request.result;
9
+ if (!db.objectStoreNames.contains(name)) {
10
+ db.createObjectStore(name);
11
+ }
12
+ };
13
+ request.onerror = () => reject(request.error);
14
+ request.onsuccess = () => resolve(request.result);
15
+ }));
16
+ }
17
+ return connections.get(key);
18
+ }
19
+ function promisify(request) {
20
+ return new Promise((resolve, reject) => {
21
+ request.onerror = () => reject(request.error);
22
+ request.onsuccess = () => resolve(request.result);
23
+ });
24
+ }
25
+ class IndexedDBDriver {
26
+ connection;
27
+ name;
28
+ constructor(name, version) {
29
+ this.connection = connect(name, version);
30
+ this.name = name;
31
+ }
32
+ async all() {
33
+ let db = await this.connection, store = db.transaction(this.name, 'readonly').objectStore(this.name), [keys, values] = await Promise.all([
34
+ promisify(store.getAllKeys()),
35
+ promisify(store.getAll())
36
+ ]), result = {};
37
+ for (let i = 0, n = keys.length; i < n; i++) {
38
+ result[keys[i]] = values[i];
39
+ }
40
+ return result;
41
+ }
42
+ async clear() {
43
+ let db = await this.connection, store = db.transaction(this.name, 'readwrite').objectStore(this.name);
44
+ await promisify(store.clear());
45
+ }
46
+ async count() {
47
+ let db = await this.connection, store = db.transaction(this.name, 'readonly').objectStore(this.name);
48
+ return promisify(store.count());
49
+ }
50
+ async delete(keys) {
51
+ let db = await this.connection, tx = db.transaction(this.name, 'readwrite'), store = tx.objectStore(this.name);
52
+ for (let i = 0, n = keys.length; i < n; i++) {
53
+ store.delete(keys[i]);
54
+ }
55
+ return new Promise((resolve, reject) => {
56
+ tx.oncomplete = () => resolve();
57
+ tx.onerror = () => reject(tx.error);
58
+ });
59
+ }
60
+ async get(key) {
61
+ let db = await this.connection, store = db.transaction(this.name, 'readonly').objectStore(this.name);
62
+ return promisify(store.get(key));
63
+ }
64
+ async keys() {
65
+ let db = await this.connection, store = db.transaction(this.name, 'readonly').objectStore(this.name);
66
+ return promisify(store.getAllKeys());
67
+ }
68
+ async map(fn) {
69
+ let db = await this.connection, store = db.transaction(this.name, 'readonly').objectStore(this.name);
70
+ return new Promise((resolve, reject) => {
71
+ let cursor = store.openCursor(), i = 0;
72
+ cursor.onerror = () => reject(cursor.error);
73
+ cursor.onsuccess = async () => {
74
+ let c = cursor.result;
75
+ if (c) {
76
+ await fn(c.value, c.key, i++);
77
+ c.continue();
78
+ }
79
+ else {
80
+ resolve();
81
+ }
82
+ };
83
+ });
84
+ }
85
+ async only(keys) {
86
+ let db = await this.connection, results = new Map(), tx = db.transaction(this.name, 'readonly'), store = tx.objectStore(this.name);
87
+ await Promise.all(keys.map((key) => promisify(store.get(key)).then((value) => {
88
+ if (value !== undefined) {
89
+ results.set(key, value);
90
+ }
91
+ })));
92
+ return results;
93
+ }
94
+ async replace(entries) {
95
+ let db = await this.connection, tx = db.transaction(this.name, 'readwrite'), store = tx.objectStore(this.name);
96
+ for (let i = 0; i < entries.length; i++) {
97
+ store.put(entries[i][1], entries[i][0]);
98
+ }
99
+ return new Promise((resolve, reject) => {
100
+ tx.oncomplete = () => resolve();
101
+ tx.onerror = () => reject(tx.error);
102
+ });
103
+ }
104
+ async set(key, value) {
105
+ try {
106
+ let db = await this.connection, store = db.transaction(this.name, 'readwrite').objectStore(this.name);
107
+ await promisify(store.put(value, key));
108
+ return true;
109
+ }
110
+ catch {
111
+ return false;
112
+ }
113
+ }
114
+ }
115
+ export { IndexedDBDriver };
@@ -0,0 +1,19 @@
1
+ import type { Driver } from '../types.js';
2
+ declare class LocalStorageDriver<T> implements Driver<T> {
3
+ private prefix;
4
+ constructor(name: string, version: number);
5
+ private getKeys;
6
+ private key;
7
+ private parse;
8
+ all(): Promise<T>;
9
+ clear(): Promise<void>;
10
+ count(): Promise<number>;
11
+ delete(keys: (keyof T)[]): Promise<void>;
12
+ get(key: keyof T): Promise<T[keyof T] | undefined>;
13
+ keys(): Promise<(keyof T)[]>;
14
+ map(fn: (value: T[keyof T], key: keyof T, i: number) => void | Promise<void>): Promise<void>;
15
+ only(keys: (keyof T)[]): Promise<Map<keyof T, T[keyof T]>>;
16
+ replace(entries: [keyof T, T[keyof T]][]): Promise<void>;
17
+ set(key: keyof T, value: T[keyof T]): Promise<boolean>;
18
+ }
19
+ export { LocalStorageDriver };
@@ -0,0 +1,94 @@
1
+ class LocalStorageDriver {
2
+ prefix;
3
+ constructor(name, version) {
4
+ this.prefix = `${name}:${version}:`;
5
+ }
6
+ getKeys() {
7
+ let keys = [];
8
+ for (let i = 0, n = localStorage.length; i < n; i++) {
9
+ let key = localStorage.key(i);
10
+ if (key && key.startsWith(this.prefix)) {
11
+ keys.push(key.slice(this.prefix.length));
12
+ }
13
+ }
14
+ return keys;
15
+ }
16
+ key(key) {
17
+ return this.prefix + String(key);
18
+ }
19
+ parse(value) {
20
+ if (value === null) {
21
+ return undefined;
22
+ }
23
+ try {
24
+ return JSON.parse(value);
25
+ }
26
+ catch {
27
+ return undefined;
28
+ }
29
+ }
30
+ async all() {
31
+ let keys = this.getKeys(), result = {};
32
+ for (let i = 0, n = keys.length; i < n; i++) {
33
+ let value = this.parse(localStorage.getItem(this.prefix + keys[i]));
34
+ if (value !== undefined) {
35
+ result[keys[i]] = value;
36
+ }
37
+ }
38
+ return result;
39
+ }
40
+ async clear() {
41
+ let keys = this.getKeys();
42
+ for (let i = 0, n = keys.length; i < n; i++) {
43
+ localStorage.removeItem(this.prefix + keys[i]);
44
+ }
45
+ }
46
+ async count() {
47
+ return this.getKeys().length;
48
+ }
49
+ async delete(keys) {
50
+ for (let i = 0, n = keys.length; i < n; i++) {
51
+ localStorage.removeItem(this.key(keys[i]));
52
+ }
53
+ }
54
+ async get(key) {
55
+ return this.parse(localStorage.getItem(this.key(key)));
56
+ }
57
+ async keys() {
58
+ return this.getKeys();
59
+ }
60
+ async map(fn) {
61
+ let keys = this.getKeys();
62
+ for (let i = 0, n = keys.length; i < n; i++) {
63
+ let value = this.parse(localStorage.getItem(this.prefix + keys[i]));
64
+ if (value !== undefined) {
65
+ await fn(value, keys[i], i);
66
+ }
67
+ }
68
+ }
69
+ async only(keys) {
70
+ let results = new Map();
71
+ for (let i = 0, n = keys.length; i < n; i++) {
72
+ let value = this.parse(localStorage.getItem(this.key(keys[i])));
73
+ if (value !== undefined) {
74
+ results.set(keys[i], value);
75
+ }
76
+ }
77
+ return results;
78
+ }
79
+ async replace(entries) {
80
+ for (let i = 0, n = entries.length; i < n; i++) {
81
+ localStorage.setItem(this.key(entries[i][0]), JSON.stringify(entries[i][1]));
82
+ }
83
+ }
84
+ async set(key, value) {
85
+ try {
86
+ localStorage.setItem(this.key(key), JSON.stringify(value));
87
+ return true;
88
+ }
89
+ catch {
90
+ return false;
91
+ }
92
+ }
93
+ }
94
+ export { LocalStorageDriver };
package/build/index.d.ts CHANGED
@@ -1 +1,21 @@
1
- export { default as local } from './local.js';
1
+ import type { Filter, Options } from './types.js';
2
+ declare class Local<T> {
3
+ private driver;
4
+ private secret;
5
+ constructor(options: Options, secret?: string);
6
+ all(): Promise<T>;
7
+ clear(): Promise<void>;
8
+ count(): Promise<number>;
9
+ delete(...keys: (keyof T)[]): Promise<void>;
10
+ filter(fn: Filter<T>): Promise<T>;
11
+ get(key: keyof T): Promise<T[keyof T] | undefined>;
12
+ keys(): Promise<(keyof T)[]>;
13
+ length(): Promise<number>;
14
+ map(fn: (value: T[keyof T], key: keyof T, i: number) => void | Promise<void>): Promise<void>;
15
+ only(...keys: (keyof T)[]): Promise<T>;
16
+ replace(values: Partial<T>): Promise<string[]>;
17
+ set(key: keyof T, value: T[keyof T]): Promise<boolean>;
18
+ }
19
+ declare const _default: <T>(options: Options, secret?: string) => Local<T>;
20
+ export default _default;
21
+ export { DriverType } from './constants.js';
package/build/index.js CHANGED
@@ -1 +1,134 @@
1
- export { default as local } from './local.js';
1
+ import { decrypt, encrypt } from '@esportsplus/crypto';
2
+ import { DriverType } from './constants.js';
3
+ import { IndexedDBDriver } from './drivers/indexeddb.js';
4
+ import { LocalStorageDriver } from './drivers/localstorage.js';
5
+ async function deserialize(value, secret) {
6
+ if (value === undefined || value === null) {
7
+ return undefined;
8
+ }
9
+ if (secret && typeof value === 'string') {
10
+ try {
11
+ value = await decrypt(value, secret);
12
+ value = JSON.parse(value);
13
+ }
14
+ catch {
15
+ return undefined;
16
+ }
17
+ }
18
+ return value;
19
+ }
20
+ async function serialize(value, secret) {
21
+ if (value === undefined || value === null) {
22
+ return value;
23
+ }
24
+ if (secret) {
25
+ return encrypt(JSON.stringify(value), secret);
26
+ }
27
+ return value;
28
+ }
29
+ class Local {
30
+ driver;
31
+ secret;
32
+ constructor(options, secret) {
33
+ this.secret = secret || null;
34
+ let { name, version = 1 } = options;
35
+ if (options.driver === DriverType.LocalStorage) {
36
+ this.driver = new LocalStorageDriver(name, version);
37
+ }
38
+ else {
39
+ this.driver = new IndexedDBDriver(name, version);
40
+ }
41
+ }
42
+ async all() {
43
+ let raw = await this.driver.all(), result = {};
44
+ for (let key in raw) {
45
+ let value = await deserialize(raw[key], this.secret);
46
+ if (value !== undefined) {
47
+ result[key] = value;
48
+ }
49
+ }
50
+ return result;
51
+ }
52
+ async clear() {
53
+ return this.driver.clear();
54
+ }
55
+ async count() {
56
+ return this.driver.count();
57
+ }
58
+ async delete(...keys) {
59
+ return this.driver.delete(keys);
60
+ }
61
+ async filter(fn) {
62
+ let i = 0, result = {}, stop = () => { stopped = true; }, stopped = false;
63
+ await this.driver.map(async (raw, key) => {
64
+ if (stopped) {
65
+ return;
66
+ }
67
+ let value = await deserialize(raw, this.secret);
68
+ if (value === undefined) {
69
+ return;
70
+ }
71
+ if (await fn({ i: i++, key, stop, value })) {
72
+ result[key] = value;
73
+ }
74
+ });
75
+ return result;
76
+ }
77
+ async get(key) {
78
+ return deserialize(await this.driver.get(key), this.secret);
79
+ }
80
+ async keys() {
81
+ return this.driver.keys();
82
+ }
83
+ length() {
84
+ return this.driver.count();
85
+ }
86
+ map(fn) {
87
+ return this.driver.map(async (raw, key, i) => {
88
+ let value = await deserialize(raw, this.secret);
89
+ if (value !== undefined) {
90
+ await fn(value, key, i);
91
+ }
92
+ });
93
+ }
94
+ async only(...keys) {
95
+ let raw = await this.driver.only(keys), result = {};
96
+ for (let [key, value] of raw) {
97
+ let deserialized = await deserialize(value, this.secret);
98
+ if (deserialized !== undefined) {
99
+ result[key] = deserialized;
100
+ }
101
+ }
102
+ return result;
103
+ }
104
+ async replace(values) {
105
+ let entries = [], failed = [];
106
+ for (let key in values) {
107
+ try {
108
+ entries.push([
109
+ key,
110
+ await serialize(values[key], this.secret)
111
+ ]);
112
+ }
113
+ catch {
114
+ failed.push(key);
115
+ }
116
+ }
117
+ if (entries.length > 0) {
118
+ await this.driver.replace(entries);
119
+ }
120
+ return failed;
121
+ }
122
+ async set(key, value) {
123
+ try {
124
+ return this.driver.set(key, await serialize(value, this.secret));
125
+ }
126
+ catch {
127
+ return false;
128
+ }
129
+ }
130
+ }
131
+ export default (options, secret) => {
132
+ return new Local(options, secret);
133
+ };
134
+ export { DriverType } from './constants.js';
package/build/types.d.ts CHANGED
@@ -1,7 +1,15 @@
1
- import localforage from 'localforage';
2
- declare enum Driver {
3
- IndexedDB = 0,
4
- LocalStorage = 1
1
+ import { DriverType } from './constants.js';
2
+ interface Driver<T> {
3
+ all(): Promise<T>;
4
+ clear(): Promise<void>;
5
+ count(): Promise<number>;
6
+ delete(keys: (keyof T)[]): Promise<void>;
7
+ get(key: keyof T): Promise<T[keyof T] | undefined>;
8
+ keys(): Promise<(keyof T)[]>;
9
+ map(fn: (value: T[keyof T], key: keyof T, i: number) => void | Promise<void>): Promise<void>;
10
+ only(keys: (keyof T)[]): Promise<Map<keyof T, T[keyof T]>>;
11
+ replace(entries: [keyof T, T[keyof T]][]): Promise<void>;
12
+ set(key: keyof T, value: T[keyof T]): Promise<boolean>;
5
13
  }
6
14
  type Filter<T> = (data: {
7
15
  i: number;
@@ -9,13 +17,9 @@ type Filter<T> = (data: {
9
17
  stop: VoidFunction;
10
18
  value: T[keyof T];
11
19
  }) => boolean | Promise<boolean>;
12
- type LocalForage = typeof localforage;
13
20
  type Options = {
14
- description?: string;
15
- driver?: string | string[];
21
+ driver?: DriverType.IndexedDB | DriverType.LocalStorage;
16
22
  name: string;
17
- size?: number;
18
- version?: number;
23
+ version: number;
19
24
  };
20
- export { Driver };
21
- export type { Filter, LocalForage, Options };
25
+ export type { Driver, Filter, Options };
package/build/types.js CHANGED
@@ -1,7 +1 @@
1
- var Driver;
2
- (function (Driver) {
3
- Driver[Driver["IndexedDB"] = 0] = "IndexedDB";
4
- Driver[Driver["LocalStorage"] = 1] = "LocalStorage";
5
- })(Driver || (Driver = {}));
6
- ;
7
- export { Driver };
1
+ export {};
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "author": "ICJR",
3
3
  "dependencies": {
4
- "@esportsplus/crypto": "^0.1.0",
5
- "localforage": "^1.10.0"
4
+ "@esportsplus/crypto": "^0.2.3"
6
5
  },
7
6
  "description": "Web storage utility",
8
7
  "devDependencies": {
@@ -11,9 +10,13 @@
11
10
  "main": "build/index.js",
12
11
  "name": "@esportsplus/web-storage",
13
12
  "private": false,
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/esportsplus/web-storage"
16
+ },
14
17
  "type": "module",
15
18
  "types": "build/index.d.ts",
16
- "version": "0.1.44",
19
+ "version": "0.3.1",
17
20
  "scripts": {
18
21
  "build": "tsc && tsc-alias",
19
22
  "-": "-"
@@ -0,0 +1,6 @@
1
+ enum DriverType {
2
+ IndexedDB,
3
+ LocalStorage
4
+ }
5
+
6
+ export { DriverType };