anote-server-libs 0.9.4 → 0.9.6
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.
- package/models/ApiCall.ts +40 -40
- package/models/Migration.ts +43 -43
- package/models/repository/BaseModelRepository.js +19 -10
- package/models/repository/BaseModelRepository.ts +18 -11
- package/models/repository/MemoryCache.ts +87 -87
- package/models/repository/ModelDao.ts +268 -268
- package/package.json +35 -35
- package/services/WithBody.ts +65 -65
- package/services/WithTransaction.js +2 -1
- package/services/WithTransaction.ts +161 -160
- package/services/utils.js +16 -16
- package/services/utils.ts +180 -180
- package/tsconfig.json +29 -29
- package/.vscode/settings.json +0 -3
package/models/ApiCall.ts
CHANGED
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
import { ConnectionPool, DateTimeOffset, Request } from 'mssql';
|
|
2
|
-
import {Pool} from 'pg';
|
|
3
|
-
import {Logger} from 'winston';
|
|
4
|
-
import {Model, ModelDao} from './repository/ModelDao';
|
|
5
|
-
|
|
6
|
-
export interface ApiCall extends Model<string> {
|
|
7
|
-
responseCode: number;
|
|
8
|
-
responseJson: string;
|
|
9
|
-
expiresAt: Date;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export class ApiCallRepository extends ModelDao<string, ApiCall> {
|
|
13
|
-
constructor(protected pool: Pool, protected poolMssql: ConnectionPool, protected logger: Logger) {
|
|
14
|
-
super(pool, poolMssql, logger, 'api_call', 5, pool ? 'id=$1,"updatedOn"=$2,"responseCode"=$3,"responseJson"=$4,"expiresAt"=$5' :
|
|
15
|
-
'id=@1,"updatedOn"=@2,"responseCode"=@3,"responseJson"=@4,"expiresAt"=@5');
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
buildObject(q: any): ApiCall {
|
|
19
|
-
if(!q) return undefined;
|
|
20
|
-
q.id = q.id.trim();
|
|
21
|
-
q.updatedOn = q.updatedOn && new Date(q.updatedOn);
|
|
22
|
-
q.responseCode = parseInt(q.responseCode, 10);
|
|
23
|
-
q.expiresAt = q.expiresAt && new Date(q.expiresAt);
|
|
24
|
-
return q;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
serialize(instance: ApiCall, request?: Request) {
|
|
28
|
-
if(request) {
|
|
29
|
-
request.input('1', instance.id);
|
|
30
|
-
request.input('2', DateTimeOffset, instance.updatedOn);
|
|
31
|
-
request.input('3', instance.responseCode);
|
|
32
|
-
request.input('4', instance.responseJson);
|
|
33
|
-
request.input('5', DateTimeOffset, instance.expiresAt);
|
|
34
|
-
return undefined;
|
|
35
|
-
} else {
|
|
36
|
-
return [instance.id, instance.updatedOn, instance.responseCode, instance.responseJson, instance.expiresAt];
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
}
|
|
1
|
+
import { ConnectionPool, DateTimeOffset, Request } from 'mssql';
|
|
2
|
+
import {Pool} from 'pg';
|
|
3
|
+
import {Logger} from 'winston';
|
|
4
|
+
import {Model, ModelDao} from './repository/ModelDao';
|
|
5
|
+
|
|
6
|
+
export interface ApiCall extends Model<string> {
|
|
7
|
+
responseCode: number;
|
|
8
|
+
responseJson: string;
|
|
9
|
+
expiresAt: Date;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class ApiCallRepository extends ModelDao<string, ApiCall> {
|
|
13
|
+
constructor(protected pool: Pool, protected poolMssql: ConnectionPool, protected logger: Logger) {
|
|
14
|
+
super(pool, poolMssql, logger, 'api_call', 5, pool ? 'id=$1,"updatedOn"=$2,"responseCode"=$3,"responseJson"=$4,"expiresAt"=$5' :
|
|
15
|
+
'id=@1,"updatedOn"=@2,"responseCode"=@3,"responseJson"=@4,"expiresAt"=@5');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
buildObject(q: any): ApiCall {
|
|
19
|
+
if(!q) return undefined;
|
|
20
|
+
q.id = q.id.trim();
|
|
21
|
+
q.updatedOn = q.updatedOn && new Date(q.updatedOn);
|
|
22
|
+
q.responseCode = parseInt(q.responseCode, 10);
|
|
23
|
+
q.expiresAt = q.expiresAt && new Date(q.expiresAt);
|
|
24
|
+
return q;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
serialize(instance: ApiCall, request?: Request) {
|
|
28
|
+
if(request) {
|
|
29
|
+
request.input('1', instance.id);
|
|
30
|
+
request.input('2', DateTimeOffset, instance.updatedOn);
|
|
31
|
+
request.input('3', instance.responseCode);
|
|
32
|
+
request.input('4', instance.responseJson);
|
|
33
|
+
request.input('5', DateTimeOffset, instance.expiresAt);
|
|
34
|
+
return undefined;
|
|
35
|
+
} else {
|
|
36
|
+
return [instance.id, instance.updatedOn, instance.responseCode, instance.responseJson, instance.expiresAt];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
}
|
package/models/Migration.ts
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
import { ConnectionPool, Request } from 'mssql';
|
|
2
|
-
import {Pool} from 'pg';
|
|
3
|
-
import {Logger} from 'winston';
|
|
4
|
-
import {ModelDao} from './repository/ModelDao';
|
|
5
|
-
|
|
6
|
-
export interface Migration {
|
|
7
|
-
id: number;
|
|
8
|
-
hash: string;
|
|
9
|
-
sqlUp: string;
|
|
10
|
-
sqlDown: string;
|
|
11
|
-
state: number;
|
|
12
|
-
skip: boolean;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export class MigrationRepository extends ModelDao<number, Migration> {
|
|
16
|
-
constructor(protected pool: Pool, protected poolMssql: ConnectionPool, protected logger: Logger) {
|
|
17
|
-
super(pool, poolMssql, logger, 'migration', 6, pool ? 'id=$1,hash=$2,"sqlUp"=$3,"sqlDown"=$4,state=$5,skip=$6' :
|
|
18
|
-
'id=@1,hash=@2,"sqlUp"=@3,"sqlDown"=@4,state=@5,skip=@6');
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
buildObject(q: any): Migration {
|
|
22
|
-
if(!q) return undefined;
|
|
23
|
-
q.id = parseInt(q.id, 10);
|
|
24
|
-
q.hash = q.hash.trim();
|
|
25
|
-
q.state = parseInt(q.state, 10);
|
|
26
|
-
q.skip = q.skip ? true : false;
|
|
27
|
-
return q;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
serialize(instance: Migration, request?: Request) {
|
|
31
|
-
if(request) {
|
|
32
|
-
request.input('1', instance.id);
|
|
33
|
-
request.input('2', instance.hash);
|
|
34
|
-
request.input('3', instance.sqlUp);
|
|
35
|
-
request.input('4', instance.sqlDown);
|
|
36
|
-
request.input('5', instance.state);
|
|
37
|
-
request.input('6', instance.skip ? 1 : 0);
|
|
38
|
-
return undefined;
|
|
39
|
-
} else {
|
|
40
|
-
return [instance.id, instance.hash, instance.sqlUp, instance.sqlDown, instance.state, instance.skip];
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
1
|
+
import { ConnectionPool, Request } from 'mssql';
|
|
2
|
+
import {Pool} from 'pg';
|
|
3
|
+
import {Logger} from 'winston';
|
|
4
|
+
import {ModelDao} from './repository/ModelDao';
|
|
5
|
+
|
|
6
|
+
export interface Migration {
|
|
7
|
+
id: number;
|
|
8
|
+
hash: string;
|
|
9
|
+
sqlUp: string;
|
|
10
|
+
sqlDown: string;
|
|
11
|
+
state: number;
|
|
12
|
+
skip: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class MigrationRepository extends ModelDao<number, Migration> {
|
|
16
|
+
constructor(protected pool: Pool, protected poolMssql: ConnectionPool, protected logger: Logger) {
|
|
17
|
+
super(pool, poolMssql, logger, 'migration', 6, pool ? 'id=$1,hash=$2,"sqlUp"=$3,"sqlDown"=$4,state=$5,skip=$6' :
|
|
18
|
+
'id=@1,hash=@2,"sqlUp"=@3,"sqlDown"=@4,state=@5,skip=@6');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
buildObject(q: any): Migration {
|
|
22
|
+
if(!q) return undefined;
|
|
23
|
+
q.id = parseInt(q.id, 10);
|
|
24
|
+
q.hash = q.hash.trim();
|
|
25
|
+
q.state = parseInt(q.state, 10);
|
|
26
|
+
q.skip = q.skip ? true : false;
|
|
27
|
+
return q;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
serialize(instance: Migration, request?: Request) {
|
|
31
|
+
if(request) {
|
|
32
|
+
request.input('1', instance.id);
|
|
33
|
+
request.input('2', instance.hash);
|
|
34
|
+
request.input('3', instance.sqlUp);
|
|
35
|
+
request.input('4', instance.sqlDown);
|
|
36
|
+
request.input('5', instance.state);
|
|
37
|
+
request.input('6', instance.skip ? 1 : 0);
|
|
38
|
+
return undefined;
|
|
39
|
+
} else {
|
|
40
|
+
return [instance.id, instance.hash, instance.sqlUp, instance.sqlDown, instance.state, instance.skip];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -23,7 +23,7 @@ class BaseModelRepository {
|
|
|
23
23
|
this.Migration = new Migration_1.MigrationRepository(db, dbMssql, logger);
|
|
24
24
|
this.ApiCall = new ApiCall_1.ApiCallRepository(db, dbMssql, logger);
|
|
25
25
|
}
|
|
26
|
-
migrate(migrationsPath, callback, onlyAboveOrEquals = 0) {
|
|
26
|
+
migrate(migrationsPath, callback, onlyAboveOrEquals = 0, onlyBelow) {
|
|
27
27
|
(this.db ? Promise.all([
|
|
28
28
|
this.db.query(`CREATE TABLE IF NOT EXISTS migration (
|
|
29
29
|
id integer PRIMARY KEY,
|
|
@@ -70,16 +70,22 @@ END`)
|
|
|
70
70
|
hash: crypto.createHash('sha256').update(content).digest('hex')
|
|
71
71
|
};
|
|
72
72
|
});
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
migrations = migrations.filter(m => m.id >= onlyAboveOrEquals);
|
|
74
|
+
if (onlyBelow)
|
|
75
|
+
migrations = migrations.filter(m => m.id < onlyBelow);
|
|
76
|
+
if (migrationsAvailable.length === 0 && migrations.length === 0)
|
|
76
77
|
process.exit(5);
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
if (migrationsAvailable.length && migrationsAvailable.length !== (migrationsAvailable[migrationsAvailable.length - 1].id - migrationsAvailable[0].id + 1))
|
|
79
|
+
process.exit(5);
|
|
80
|
+
let highestCommon = 0;
|
|
81
|
+
while (highestCommon < migrations.length
|
|
82
|
+
&& highestCommon < migrationsAvailable.length
|
|
83
|
+
&& migrations[highestCommon]
|
|
84
|
+
&& migrationsAvailable[highestCommon]
|
|
79
85
|
&& migrations[highestCommon].hash === migrationsAvailable[highestCommon].hash)
|
|
80
86
|
highestCommon++;
|
|
81
|
-
this.applyDownUntil(migrations, migrations.length, highestCommon).then(
|
|
82
|
-
this.applyUpUntil(migrationsAvailable, Math.min(
|
|
87
|
+
this.applyDownUntil(migrations, migrations.length, highestCommon).then(appliedId => {
|
|
88
|
+
this.applyUpUntil(migrationsAvailable, Math.min(appliedId, migrations.length), migrationsAvailable.length).then(callback, process.exit);
|
|
83
89
|
}, process.exit);
|
|
84
90
|
});
|
|
85
91
|
}, () => process.exit(3));
|
|
@@ -91,13 +97,15 @@ END`)
|
|
|
91
97
|
return Promise.all(tables.map(t => client.request().query('SELECT id FROM ' + t.table + ' WITH (UPDLOCK)')));
|
|
92
98
|
}
|
|
93
99
|
applyUpUntil(migrations, current, until) {
|
|
94
|
-
if (current < until)
|
|
100
|
+
if (current < until) {
|
|
101
|
+
console.log('Applying migration ' + migrations[current].id);
|
|
95
102
|
return this.applyUp(migrations[current]).then(() => this.applyUpUntil(migrations, current + 1, until));
|
|
103
|
+
}
|
|
96
104
|
return Promise.resolve();
|
|
97
105
|
}
|
|
98
106
|
applyUp(migration) {
|
|
99
107
|
return new Promise((resolve, reject) => {
|
|
100
|
-
const sqlParts = migration.content.split(
|
|
108
|
+
const sqlParts = migration.content.split(/-{4,}/);
|
|
101
109
|
this.Migration.create({
|
|
102
110
|
id: migration.id,
|
|
103
111
|
hash: migration.hash,
|
|
@@ -126,6 +134,7 @@ END`)
|
|
|
126
134
|
applyDownUntil(migrations, current, until) {
|
|
127
135
|
if (current > until && !migrations[current - 1]?.skip) {
|
|
128
136
|
current--;
|
|
137
|
+
console.log('Reverting migration ' + migrations[current].id);
|
|
129
138
|
return this.applyDown(migrations[current]).then(() => this.applyDownUntil(migrations, current, until));
|
|
130
139
|
}
|
|
131
140
|
return Promise.resolve(current);
|
|
@@ -26,7 +26,7 @@ export class BaseModelRepository {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// TODO: alter table migration if exists without ok column
|
|
29
|
-
migrate(migrationsPath: string, callback: (() => void), onlyAboveOrEquals = 0) {
|
|
29
|
+
migrate(migrationsPath: string, callback: (() => void), onlyAboveOrEquals = 0, onlyBelow?: number) {
|
|
30
30
|
(this.db ? Promise.all([
|
|
31
31
|
this.db.query(`CREATE TABLE IF NOT EXISTS migration (
|
|
32
32
|
id integer PRIMARY KEY,
|
|
@@ -71,15 +71,19 @@ END`)])).then(() => {
|
|
|
71
71
|
hash: crypto.createHash('sha256').update(content).digest('hex')
|
|
72
72
|
};
|
|
73
73
|
});
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
74
|
+
migrations = migrations.filter(m => m.id >= onlyAboveOrEquals);
|
|
75
|
+
if(onlyBelow) migrations = migrations.filter(m => m.id < onlyBelow);
|
|
76
|
+
if(migrationsAvailable.length === 0 && migrations.length === 0) process.exit(5);
|
|
77
|
+
if(migrationsAvailable.length && migrationsAvailable.length !== (migrationsAvailable[migrationsAvailable.length - 1].id - migrationsAvailable[0].id + 1)) process.exit(5);
|
|
78
|
+
let highestCommon = 0;
|
|
79
|
+
while(highestCommon < migrations.length
|
|
80
|
+
&& highestCommon < migrationsAvailable.length
|
|
81
|
+
&& migrations[highestCommon]
|
|
82
|
+
&& migrationsAvailable[highestCommon]
|
|
83
|
+
&& migrations[highestCommon].hash === migrationsAvailable[highestCommon].hash)
|
|
80
84
|
highestCommon++;
|
|
81
|
-
this.applyDownUntil(migrations, migrations.length, highestCommon).then(
|
|
82
|
-
this.applyUpUntil(migrationsAvailable, Math.min(
|
|
85
|
+
this.applyDownUntil(migrations, migrations.length, highestCommon).then(appliedId => {
|
|
86
|
+
this.applyUpUntil(migrationsAvailable, Math.min(appliedId, migrations.length), migrationsAvailable.length).then(callback, process.exit);
|
|
83
87
|
}, process.exit);
|
|
84
88
|
});
|
|
85
89
|
}, () => process.exit(3));
|
|
@@ -93,14 +97,16 @@ END`)])).then(() => {
|
|
|
93
97
|
}
|
|
94
98
|
|
|
95
99
|
private applyUpUntil(migrations: {id: number, content: string, hash: string}[], current: number, until: number): Promise<void> {
|
|
96
|
-
if(current < until)
|
|
100
|
+
if(current < until) {
|
|
101
|
+
console.log('Applying migration ' + migrations[current].id);
|
|
97
102
|
return this.applyUp(migrations[current]).then(() => this.applyUpUntil(migrations, current + 1, until));
|
|
103
|
+
}
|
|
98
104
|
return Promise.resolve();
|
|
99
105
|
}
|
|
100
106
|
|
|
101
107
|
private applyUp(migration: {id: number, content: string, hash: string}): Promise<void> {
|
|
102
108
|
return new Promise((resolve, reject) => {
|
|
103
|
-
const sqlParts = migration.content.split(
|
|
109
|
+
const sqlParts = migration.content.split(/-{4,}/);
|
|
104
110
|
this.Migration.create({
|
|
105
111
|
id: migration.id,
|
|
106
112
|
hash: migration.hash,
|
|
@@ -127,6 +133,7 @@ END`)])).then(() => {
|
|
|
127
133
|
private applyDownUntil(migrations: Migration[], current: number, until: number): Promise<number> {
|
|
128
134
|
if(current > until && !migrations[current - 1]?.skip) {
|
|
129
135
|
current--;
|
|
136
|
+
console.log('Reverting migration ' + migrations[current].id);
|
|
130
137
|
return this.applyDown(migrations[current]).then(() => this.applyDownUntil(migrations, current, until));
|
|
131
138
|
}
|
|
132
139
|
return Promise.resolve(current);
|
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
import * as Memcached from 'memcached';
|
|
2
|
-
|
|
3
|
-
export class MemoryCache<T> {
|
|
4
|
-
|
|
5
|
-
private localCache: {[id: string]: any} = {};
|
|
6
|
-
|
|
7
|
-
constructor(private localKey: string, private cache?: Memcached) {
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
list(): Promise<T[]> {
|
|
11
|
-
if(this.cache) return new Promise(resolve => {
|
|
12
|
-
let pending = true;
|
|
13
|
-
setTimeout(() => {
|
|
14
|
-
if(pending) {
|
|
15
|
-
pending = false;
|
|
16
|
-
resolve([]);
|
|
17
|
-
}
|
|
18
|
-
}, 250);
|
|
19
|
-
this.cache.items((_, data) => {
|
|
20
|
-
if(pending) {
|
|
21
|
-
pending = false;
|
|
22
|
-
resolve(data.map(s => {
|
|
23
|
-
const value = <string>s[Object.getOwnPropertyNames(s).find(sname => sname.startsWith(this.localKey))];
|
|
24
|
-
return value && JSON.parse(value);
|
|
25
|
-
}).filter(x => x));
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
else return Promise.resolve(Object.getOwnPropertyNames(this.localCache).map(key => this.localCache[key]));
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
get(key: string | number): Promise<T> {
|
|
33
|
-
if(this.cache) return new Promise(resolve => {
|
|
34
|
-
let pending = true;
|
|
35
|
-
setTimeout(() => {
|
|
36
|
-
if(pending) {
|
|
37
|
-
pending = false;
|
|
38
|
-
resolve(undefined);
|
|
39
|
-
}
|
|
40
|
-
}, 250);
|
|
41
|
-
this.cache.get(this.localKey + key, (_, data) => {
|
|
42
|
-
if(pending) {
|
|
43
|
-
pending = false;
|
|
44
|
-
resolve(data && JSON.parse(data));
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
else return Promise.resolve(this.localCache[key]);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
set(key: string | number, val: T, time = 15 * 60): Promise<void> {
|
|
52
|
-
if(this.cache) return new Promise(resolve => this.cache.set(this.localKey + key, JSON.stringify(val), time, resolve));
|
|
53
|
-
else {
|
|
54
|
-
this.localCache[key] = val;
|
|
55
|
-
return Promise.resolve();
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
delete(key: string | number): Promise<void> {
|
|
60
|
-
if(this.cache) {
|
|
61
|
-
return new Promise(resolve => {
|
|
62
|
-
let fired = false;
|
|
63
|
-
const handler = setTimeout(() => {
|
|
64
|
-
fired = true;
|
|
65
|
-
resolve();
|
|
66
|
-
}, 50);
|
|
67
|
-
this.cache.del(this.localKey + key, () => {
|
|
68
|
-
if(!fired) {
|
|
69
|
-
clearTimeout(handler);
|
|
70
|
-
resolve();
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
} else {
|
|
75
|
-
this.localCache[key] = undefined;
|
|
76
|
-
return Promise.resolve();
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
clear() {
|
|
81
|
-
if(this.cache) {
|
|
82
|
-
this.localKey = this.localKey + '_';
|
|
83
|
-
if(this.localKey.length > 40)
|
|
84
|
-
this.localKey = this.localKey.replace(/_+$/, '');
|
|
85
|
-
} else this.localCache = {};
|
|
86
|
-
}
|
|
87
|
-
}
|
|
1
|
+
import * as Memcached from 'memcached';
|
|
2
|
+
|
|
3
|
+
export class MemoryCache<T> {
|
|
4
|
+
|
|
5
|
+
private localCache: {[id: string]: any} = {};
|
|
6
|
+
|
|
7
|
+
constructor(private localKey: string, private cache?: Memcached) {
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
list(): Promise<T[]> {
|
|
11
|
+
if(this.cache) return new Promise(resolve => {
|
|
12
|
+
let pending = true;
|
|
13
|
+
setTimeout(() => {
|
|
14
|
+
if(pending) {
|
|
15
|
+
pending = false;
|
|
16
|
+
resolve([]);
|
|
17
|
+
}
|
|
18
|
+
}, 250);
|
|
19
|
+
this.cache.items((_, data) => {
|
|
20
|
+
if(pending) {
|
|
21
|
+
pending = false;
|
|
22
|
+
resolve(data.map(s => {
|
|
23
|
+
const value = <string>s[Object.getOwnPropertyNames(s).find(sname => sname.startsWith(this.localKey))];
|
|
24
|
+
return value && JSON.parse(value);
|
|
25
|
+
}).filter(x => x));
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
else return Promise.resolve(Object.getOwnPropertyNames(this.localCache).map(key => this.localCache[key]));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get(key: string | number): Promise<T> {
|
|
33
|
+
if(this.cache) return new Promise(resolve => {
|
|
34
|
+
let pending = true;
|
|
35
|
+
setTimeout(() => {
|
|
36
|
+
if(pending) {
|
|
37
|
+
pending = false;
|
|
38
|
+
resolve(undefined);
|
|
39
|
+
}
|
|
40
|
+
}, 250);
|
|
41
|
+
this.cache.get(this.localKey + key, (_, data) => {
|
|
42
|
+
if(pending) {
|
|
43
|
+
pending = false;
|
|
44
|
+
resolve(data && JSON.parse(data));
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
else return Promise.resolve(this.localCache[key]);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
set(key: string | number, val: T, time = 15 * 60): Promise<void> {
|
|
52
|
+
if(this.cache) return new Promise(resolve => this.cache.set(this.localKey + key, JSON.stringify(val), time, resolve));
|
|
53
|
+
else {
|
|
54
|
+
this.localCache[key] = val;
|
|
55
|
+
return Promise.resolve();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
delete(key: string | number): Promise<void> {
|
|
60
|
+
if(this.cache) {
|
|
61
|
+
return new Promise(resolve => {
|
|
62
|
+
let fired = false;
|
|
63
|
+
const handler = setTimeout(() => {
|
|
64
|
+
fired = true;
|
|
65
|
+
resolve();
|
|
66
|
+
}, 50);
|
|
67
|
+
this.cache.del(this.localKey + key, () => {
|
|
68
|
+
if(!fired) {
|
|
69
|
+
clearTimeout(handler);
|
|
70
|
+
resolve();
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
} else {
|
|
75
|
+
this.localCache[key] = undefined;
|
|
76
|
+
return Promise.resolve();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
clear() {
|
|
81
|
+
if(this.cache) {
|
|
82
|
+
this.localKey = this.localKey + '_';
|
|
83
|
+
if(this.localKey.length > 40)
|
|
84
|
+
this.localKey = this.localKey.replace(/_+$/, '');
|
|
85
|
+
} else this.localCache = {};
|
|
86
|
+
}
|
|
87
|
+
}
|