@forge/cache 0.10.0-next.1 → 0.10.0-next.2
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/out/__test__/cache.test.js +1 -1
- package/out/__test__/tunnel.test.js +67 -56
- package/out/cache.d.ts +1 -1
- package/out/cache.d.ts.map +1 -1
- package/out/cache.js +2 -3
- package/out/tunnel.d.ts +9 -3
- package/out/tunnel.d.ts.map +1 -1
- package/out/tunnel.js +64 -3
- package/out/utils/validator.d.ts +25 -5
- package/out/utils/validator.d.ts.map +1 -1
- package/out/utils/validator.js +68 -28
- package/package.json +3 -2
|
@@ -5,7 +5,7 @@ const node_fetch_1 = tslib_1.__importDefault(require("node-fetch"));
|
|
|
5
5
|
const cache_1 = require("../cache");
|
|
6
6
|
jest.mock('node-fetch');
|
|
7
7
|
const fetchMock = node_fetch_1.default;
|
|
8
|
-
describe('
|
|
8
|
+
describe('Forge Cache', () => {
|
|
9
9
|
describe('v1', () => {
|
|
10
10
|
beforeEach(() => {
|
|
11
11
|
jest.resetAllMocks();
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
3
4
|
const tunnel_1 = require("../tunnel");
|
|
4
5
|
const validator_1 = require("../utils/validator");
|
|
6
|
+
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
7
|
+
const tmp_1 = require("tmp");
|
|
5
8
|
describe('Forge Cache Tunnel', () => {
|
|
6
9
|
let cache;
|
|
7
10
|
beforeEach(() => {
|
|
8
|
-
const
|
|
9
|
-
cache = new tunnel_1.TunnelCache(
|
|
11
|
+
const fileName = (0, tmp_1.tmpNameSync)({ postfix: '.json' });
|
|
12
|
+
cache = new tunnel_1.TunnelCache(fileName);
|
|
10
13
|
});
|
|
11
14
|
test('set method', async () => {
|
|
12
15
|
const response = await cache.set('key', 'value');
|
|
@@ -18,12 +21,12 @@ describe('Forge Cache Tunnel', () => {
|
|
|
18
21
|
expect(response).toStrictEqual('value');
|
|
19
22
|
});
|
|
20
23
|
test('get method throws error for list value', async () => {
|
|
21
|
-
cache.
|
|
24
|
+
await cache.leftPush('key', 'value1');
|
|
22
25
|
try {
|
|
23
26
|
await cache.get('key');
|
|
24
27
|
}
|
|
25
28
|
catch (error) {
|
|
26
|
-
expect(error).toEqual(new validator_1.
|
|
29
|
+
expect(error).toEqual(new validator_1.WrongTypeOperationError());
|
|
27
30
|
}
|
|
28
31
|
});
|
|
29
32
|
test('setIfNotExists method', async () => {
|
|
@@ -52,9 +55,9 @@ describe('Forge Cache Tunnel', () => {
|
|
|
52
55
|
expect(response).toStrictEqual(6);
|
|
53
56
|
});
|
|
54
57
|
test('leftPush method', async () => {
|
|
55
|
-
cache.
|
|
56
|
-
const response = await cache.leftPush('key', '
|
|
57
|
-
const result = ['
|
|
58
|
+
await cache.leftPush('key', 'value1');
|
|
59
|
+
const response = await cache.leftPush('key', 'value2');
|
|
60
|
+
const result = ['value2', 'value1'].length;
|
|
58
61
|
expect(response).toStrictEqual(result);
|
|
59
62
|
});
|
|
60
63
|
test('rightPop method', async () => {
|
|
@@ -75,12 +78,12 @@ describe('Forge Cache Tunnel', () => {
|
|
|
75
78
|
expect(response).toStrictEqual(4);
|
|
76
79
|
});
|
|
77
80
|
test('incrementAndGet method throws error when key holds a list value', async () => {
|
|
78
|
-
cache.
|
|
81
|
+
await cache.leftPush('key', 'value1');
|
|
79
82
|
try {
|
|
80
83
|
await cache.incrementAndGet('key');
|
|
81
84
|
}
|
|
82
85
|
catch (error) {
|
|
83
|
-
expect(error).toEqual(new validator_1.
|
|
86
|
+
expect(error).toEqual(new validator_1.WrongTypeOperationError());
|
|
84
87
|
}
|
|
85
88
|
});
|
|
86
89
|
test('leftPush method throws error when key holds a non-list value', async () => {
|
|
@@ -89,7 +92,7 @@ describe('Forge Cache Tunnel', () => {
|
|
|
89
92
|
await cache.leftPush('key', 'newValue');
|
|
90
93
|
}
|
|
91
94
|
catch (error) {
|
|
92
|
-
expect(error).toEqual(new validator_1.
|
|
95
|
+
expect(error).toEqual(new validator_1.WrongTypeOperationError());
|
|
93
96
|
}
|
|
94
97
|
});
|
|
95
98
|
test('rightPop method throws error when key holds a non-list value', async () => {
|
|
@@ -98,7 +101,7 @@ describe('Forge Cache Tunnel', () => {
|
|
|
98
101
|
await cache.rightPop('key');
|
|
99
102
|
}
|
|
100
103
|
catch (error) {
|
|
101
|
-
expect(error).toEqual(new validator_1.
|
|
104
|
+
expect(error).toEqual(new validator_1.WrongTypeOperationError());
|
|
102
105
|
}
|
|
103
106
|
});
|
|
104
107
|
test('listLength method throws error when key holds a non-list value', async () => {
|
|
@@ -107,59 +110,67 @@ describe('Forge Cache Tunnel', () => {
|
|
|
107
110
|
await cache.listLength('key');
|
|
108
111
|
}
|
|
109
112
|
catch (error) {
|
|
110
|
-
expect(error).toEqual(new validator_1.
|
|
113
|
+
expect(error).toEqual(new validator_1.WrongTypeOperationError());
|
|
111
114
|
}
|
|
112
115
|
});
|
|
113
116
|
test('decrementAndGet method throws error when key holds a list value', async () => {
|
|
114
|
-
cache.
|
|
117
|
+
await cache.leftPush('key', 'value');
|
|
115
118
|
try {
|
|
116
119
|
await cache.decrementAndGet('key');
|
|
117
120
|
}
|
|
118
121
|
catch (error) {
|
|
119
|
-
expect(error).toEqual(new validator_1.
|
|
122
|
+
expect(error).toEqual(new validator_1.WrongTypeOperationError());
|
|
120
123
|
}
|
|
121
124
|
});
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
125
|
+
test('scan method returns empty array when no matching keys', async () => {
|
|
126
|
+
await cache.set('key1', 'value1');
|
|
127
|
+
await cache.set('key2', 'value2');
|
|
128
|
+
await cache.set('key3', 'value3');
|
|
129
|
+
await cache.set('key4', 'value4');
|
|
130
|
+
await cache.set('key5', 'value5');
|
|
131
|
+
const scanResult = await cache.scan('nonexistent*');
|
|
132
|
+
expect(scanResult.keys).toEqual([]);
|
|
133
|
+
});
|
|
134
|
+
test('scan method returns keys starting with "key" prefix', async () => {
|
|
135
|
+
await cache.set('key1', 'value1');
|
|
136
|
+
await cache.set('key2', 'value2');
|
|
137
|
+
await cache.set('otherKey1', 'value3');
|
|
138
|
+
await cache.set('otherKey2', 'value4');
|
|
139
|
+
await cache.set('key3', 'value5');
|
|
140
|
+
const scanResult = await cache.scan('key*');
|
|
141
|
+
expect(scanResult.keys).toEqual(['key1', 'key2', 'key3']);
|
|
142
|
+
});
|
|
143
|
+
test('scan method returns keys with "2" in the middle', async () => {
|
|
144
|
+
await cache.set('key1', 'value1');
|
|
145
|
+
await cache.set('key2', 'value2');
|
|
146
|
+
await cache.set('otherKey1', 'value3');
|
|
147
|
+
await cache.set('otherKey2', 'value4');
|
|
148
|
+
await cache.set('key3', 'value5');
|
|
149
|
+
const scanResult = await cache.scan('*2*');
|
|
150
|
+
expect(scanResult.keys).toEqual(['key2', 'otherKey2']);
|
|
151
|
+
});
|
|
152
|
+
test('scan method returns keys with "l?st*" redis pattern', async () => {
|
|
153
|
+
await cache.set('list1', 'value1');
|
|
154
|
+
await cache.set('list2', 'value2');
|
|
155
|
+
await cache.set('list3', 'value3');
|
|
156
|
+
await cache.set('list4', 'value4');
|
|
157
|
+
await cache.set('lest5', 'value5');
|
|
158
|
+
await cache.set('key1', 'value1');
|
|
159
|
+
const scanResult = await cache.scan('l?st*');
|
|
160
|
+
expect(scanResult.keys).toEqual(['list1', 'list2', 'list3', 'list4', 'lest5']);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
describe('Forge Cache Tunnel with json file', () => {
|
|
164
|
+
it('should save and load data from file', async () => {
|
|
165
|
+
const fileName = (0, tmp_1.tmpNameSync)({ postfix: '.json' });
|
|
166
|
+
const cache1 = new tunnel_1.TunnelCache(fileName);
|
|
167
|
+
await cache1.set('key', 'value');
|
|
168
|
+
await cache1.set('key2', 'value2');
|
|
169
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
170
|
+
const savedFileContent = fs_1.default.readFileSync(fileName, `utf-8`);
|
|
171
|
+
expect(JSON.parse(savedFileContent)).toStrictEqual({ key: 'value', key2: 'value2' });
|
|
172
|
+
const cache2 = new tunnel_1.TunnelCache(fileName);
|
|
173
|
+
const res = await cache2.get('key');
|
|
174
|
+
expect(res).toBe('value');
|
|
164
175
|
});
|
|
165
176
|
});
|
package/out/cache.d.ts
CHANGED
|
@@ -44,5 +44,5 @@ export declare class Cache implements IForgeCache {
|
|
|
44
44
|
}
|
|
45
45
|
export declare function getFetchRmsRuntimeV1(): ((path: string, options?: RequestInit) => Promise<Response>) | undefined;
|
|
46
46
|
export declare function createFetchRmsRuntimeV2(): (path: string, options?: RequestInit) => Promise<Response>;
|
|
47
|
-
export declare function connect(): Cache | TunnelCache;
|
|
47
|
+
export declare function connect(localCacheFileName?: string): Cache | TunnelCache;
|
|
48
48
|
//# sourceMappingURL=cache.d.ts.map
|
package/out/cache.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AACA,OAAkB,EAAE,WAAW,EAAE,QAAQ,IAAI,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEnF,OAAO,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}
|
package/out/cache.js
CHANGED
|
@@ -6,7 +6,6 @@ const https_1 = require("https");
|
|
|
6
6
|
const node_fetch_1 = tslib_1.__importDefault(require("node-fetch"));
|
|
7
7
|
const api_1 = require("@forge/api");
|
|
8
8
|
const tunnel_1 = require("./tunnel");
|
|
9
|
-
const __localStore = new Map();
|
|
10
9
|
class ApiError extends Error {
|
|
11
10
|
constructor(status, code, message, data) {
|
|
12
11
|
super(message);
|
|
@@ -128,10 +127,10 @@ function createFetchRmsRuntimeV2() {
|
|
|
128
127
|
};
|
|
129
128
|
}
|
|
130
129
|
exports.createFetchRmsRuntimeV2 = createFetchRmsRuntimeV2;
|
|
131
|
-
function connect() {
|
|
130
|
+
function connect(localCacheFileName) {
|
|
132
131
|
var _a;
|
|
133
132
|
if (global.__forge_tunnel__) {
|
|
134
|
-
return new tunnel_1.TunnelCache(
|
|
133
|
+
return new tunnel_1.TunnelCache(localCacheFileName);
|
|
135
134
|
}
|
|
136
135
|
const fetch = (_a = getFetchRmsRuntimeV1()) !== null && _a !== void 0 ? _a : createFetchRmsRuntimeV2();
|
|
137
136
|
return new Cache(fetch);
|
package/out/tunnel.d.ts
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { ScanResult } from './cache';
|
|
2
2
|
import { IForgeCache } from './interfaces/cache';
|
|
3
3
|
export declare type TunnelStoreType = Map<string, string | undefined | string[]>;
|
|
4
|
+
export declare const CACHE_DIR = ".forge";
|
|
5
|
+
export declare const CACHE_FILE: string;
|
|
4
6
|
export declare class TunnelCache implements IForgeCache {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
private readonly fileName;
|
|
8
|
+
private __localStore;
|
|
9
|
+
private events;
|
|
10
|
+
constructor(fileName?: string);
|
|
11
|
+
private saveToFile;
|
|
12
|
+
private loadFromFile;
|
|
7
13
|
set(key: string, value: string, opt?: {
|
|
8
14
|
ttlSeconds: number;
|
|
9
15
|
}): Promise<void>;
|
|
@@ -28,6 +34,6 @@ export declare class TunnelCache implements IForgeCache {
|
|
|
28
34
|
cursor?: string;
|
|
29
35
|
count?: number;
|
|
30
36
|
}): Promise<ScanResult>;
|
|
31
|
-
parseSuccessResponse
|
|
37
|
+
private parseSuccessResponse;
|
|
32
38
|
}
|
|
33
39
|
//# sourceMappingURL=tunnel.d.ts.map
|
package/out/tunnel.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tunnel.d.ts","sourceRoot":"","sources":["../src/tunnel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"tunnel.d.ts","sourceRoot":"","sources":["../src/tunnel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAWjD,oBAAY,eAAe,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAAC,CAAC;AAGzE,eAAO,MAAM,SAAS,WAAW,CAAC;AAClC,eAAO,MAAM,UAAU,QAA4B,CAAC;AAgBpD,qBAAa,WAAY,YAAW,WAAW;IAGjC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAFrC,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,MAAM,CAAe;gBACA,QAAQ,GAAE,MAAmB;IAY1D,OAAO,CAAC,UAAU;IAiBlB,OAAO,CAAC,YAAY;IAmBP,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5E,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IASxC,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAc9F,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAY3F,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAYpC,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAc3E,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAmBrD,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAmB7C,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAaxC,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAgB3E,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC;IAsBlG,OAAO,CAAC,oBAAoB;CAK7B"}
|
package/out/tunnel.js
CHANGED
|
@@ -1,16 +1,70 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TunnelCache = void 0;
|
|
3
|
+
exports.TunnelCache = exports.CACHE_FILE = exports.CACHE_DIR = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const fs_1 = require("fs");
|
|
4
6
|
const validator_1 = require("./utils/validator");
|
|
7
|
+
const events_1 = tslib_1.__importDefault(require("events"));
|
|
8
|
+
const path_1 = require("path");
|
|
9
|
+
const LOG_PREFIX = '@forge/cache tunnel: ';
|
|
10
|
+
exports.CACHE_DIR = '.forge';
|
|
11
|
+
exports.CACHE_FILE = exports.CACHE_DIR + '/cache.json';
|
|
12
|
+
const warn = (message, meta) => {
|
|
13
|
+
console.warn(LOG_PREFIX + message, meta !== null && meta !== void 0 ? meta : '');
|
|
14
|
+
};
|
|
15
|
+
const info = (message, meta) => {
|
|
16
|
+
console.info(LOG_PREFIX + message, meta !== null && meta !== void 0 ? meta : '');
|
|
17
|
+
};
|
|
18
|
+
const error = (err) => {
|
|
19
|
+
console.error(LOG_PREFIX, err);
|
|
20
|
+
};
|
|
5
21
|
class TunnelCache {
|
|
6
|
-
constructor(
|
|
7
|
-
this.
|
|
22
|
+
constructor(fileName = exports.CACHE_FILE) {
|
|
23
|
+
this.fileName = fileName;
|
|
24
|
+
warn('Using local implementation of @forge/cache.');
|
|
25
|
+
this.events = new events_1.default();
|
|
26
|
+
this.__localStore = this.loadFromFile();
|
|
27
|
+
this.events.on('change', () => {
|
|
28
|
+
this.saveToFile();
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
saveToFile() {
|
|
32
|
+
const obj = {};
|
|
33
|
+
for (const [k, v] of this.__localStore) {
|
|
34
|
+
obj[k] = v;
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
(0, fs_1.mkdirSync)((0, path_1.dirname)(this.fileName), { recursive: true });
|
|
38
|
+
(0, fs_1.writeFileSync)(this.fileName, JSON.stringify(obj));
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
warn('Saving cache to file failed.', err);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
loadFromFile() {
|
|
45
|
+
const _obj = new Map();
|
|
46
|
+
try {
|
|
47
|
+
if ((0, fs_1.existsSync)(this.fileName)) {
|
|
48
|
+
const data = JSON.parse((0, fs_1.readFileSync)(this.fileName, 'utf-8'));
|
|
49
|
+
for (const key in data) {
|
|
50
|
+
_obj.set(key, data[key]);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return _obj;
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
warn('Loading cache from file failed.');
|
|
57
|
+
error(err);
|
|
58
|
+
info('Initializing empty cache.');
|
|
59
|
+
return _obj;
|
|
60
|
+
}
|
|
8
61
|
}
|
|
9
62
|
async set(key, value, opt) {
|
|
10
63
|
(0, validator_1.assertIsValidKey)(key);
|
|
11
64
|
(0, validator_1.assertIsValidValue)(value);
|
|
12
65
|
(0, validator_1.assertIsSizedValue)(value);
|
|
13
66
|
this.__localStore.set(key, value);
|
|
67
|
+
this.events.emit('change');
|
|
14
68
|
}
|
|
15
69
|
async get(key) {
|
|
16
70
|
(0, validator_1.assertIsValidKey)(key);
|
|
@@ -28,6 +82,7 @@ class TunnelCache {
|
|
|
28
82
|
return result;
|
|
29
83
|
}
|
|
30
84
|
this.__localStore.set(key, value);
|
|
85
|
+
this.events.emit('change');
|
|
31
86
|
const { response: result } = await this.parseSuccessResponse('OK');
|
|
32
87
|
return result;
|
|
33
88
|
}
|
|
@@ -38,6 +93,7 @@ class TunnelCache {
|
|
|
38
93
|
(0, validator_1.assertIsSizedValue)(value);
|
|
39
94
|
const oldValue = (_a = this.__localStore.get(key)) !== null && _a !== void 0 ? _a : null;
|
|
40
95
|
this.__localStore.set(key, value);
|
|
96
|
+
this.events.emit('change');
|
|
41
97
|
const { response: result } = await this.parseSuccessResponse(oldValue);
|
|
42
98
|
return result;
|
|
43
99
|
}
|
|
@@ -45,6 +101,7 @@ class TunnelCache {
|
|
|
45
101
|
(0, validator_1.assertIsValidKey)(key);
|
|
46
102
|
if (this.__localStore.get(key)) {
|
|
47
103
|
this.__localStore.delete(key);
|
|
104
|
+
this.events.emit('change');
|
|
48
105
|
const { response: result } = await this.parseSuccessResponse(1);
|
|
49
106
|
return result;
|
|
50
107
|
}
|
|
@@ -58,6 +115,7 @@ class TunnelCache {
|
|
|
58
115
|
(0, validator_1.assertAndThrowIfArray)(oldValue);
|
|
59
116
|
const newValue = Number.parseInt((_a = oldValue) !== null && _a !== void 0 ? _a : '0') + 1;
|
|
60
117
|
this.__localStore.set(key, newValue.toString());
|
|
118
|
+
this.events.emit('change');
|
|
61
119
|
const { response: result } = await this.parseSuccessResponse(newValue);
|
|
62
120
|
return result;
|
|
63
121
|
}
|
|
@@ -71,6 +129,7 @@ class TunnelCache {
|
|
|
71
129
|
this.__localStore.set(key, []);
|
|
72
130
|
}
|
|
73
131
|
this.__localStore.get(key).unshift(value);
|
|
132
|
+
this.events.emit('change');
|
|
74
133
|
const { response: result } = await this.parseSuccessResponse(this.__localStore.get(key).length);
|
|
75
134
|
return result;
|
|
76
135
|
}
|
|
@@ -83,6 +142,7 @@ class TunnelCache {
|
|
|
83
142
|
}
|
|
84
143
|
(0, validator_1.assertAndThrowIfNotArray)(oldValue);
|
|
85
144
|
const { response: result } = await this.parseSuccessResponse(this.__localStore.get(key).pop() || null);
|
|
145
|
+
this.events.emit('change');
|
|
86
146
|
return result;
|
|
87
147
|
}
|
|
88
148
|
async listLength(key) {
|
|
@@ -103,6 +163,7 @@ class TunnelCache {
|
|
|
103
163
|
(0, validator_1.assertAndThrowIfArray)(oldValue);
|
|
104
164
|
const newValue = Number.parseInt((_a = oldValue) !== null && _a !== void 0 ? _a : '0') - 1;
|
|
105
165
|
this.__localStore.set(key, newValue.toString());
|
|
166
|
+
this.events.emit('change');
|
|
106
167
|
const { response: result } = await this.parseSuccessResponse(newValue);
|
|
107
168
|
return result;
|
|
108
169
|
}
|
package/out/utils/validator.d.ts
CHANGED
|
@@ -1,9 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
export declare class ForgeCacheTunnelError extends HttpError {
|
|
3
|
-
readonly message: string;
|
|
4
|
-
readonly reason?: any;
|
|
1
|
+
export declare class TunnelError extends Error {
|
|
5
2
|
readonly status: number;
|
|
6
|
-
|
|
3
|
+
readonly code: string;
|
|
4
|
+
readonly data?: any;
|
|
5
|
+
constructor(status: number, code: string, message: string, data?: any);
|
|
6
|
+
}
|
|
7
|
+
export declare class MinValidKeyLengthRequiredError extends TunnelError {
|
|
8
|
+
constructor(length: number, minLength: number);
|
|
9
|
+
}
|
|
10
|
+
export declare class MaxValidKeyLengthExceededError extends TunnelError {
|
|
11
|
+
constructor(length: number, maxLength: number);
|
|
12
|
+
}
|
|
13
|
+
export declare class InvalidKeyPatternError extends TunnelError {
|
|
14
|
+
constructor();
|
|
15
|
+
}
|
|
16
|
+
export declare class MaxValueSizeExceededError extends TunnelError {
|
|
17
|
+
constructor(bytes: number, maxBytes: number);
|
|
18
|
+
}
|
|
19
|
+
export declare class ValueIsRequiredError extends TunnelError {
|
|
20
|
+
constructor();
|
|
21
|
+
}
|
|
22
|
+
export declare class WrongTypeOperationError extends TunnelError {
|
|
23
|
+
constructor();
|
|
24
|
+
}
|
|
25
|
+
export declare class InvalidValueTypeError extends TunnelError {
|
|
26
|
+
constructor(type: string);
|
|
7
27
|
}
|
|
8
28
|
export declare function assertIsValidValue(value: unknown): void;
|
|
9
29
|
export declare function assertAndThrowIfArray(value: string | number | undefined | string[]): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/utils/validator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/utils/validator.ts"],"names":[],"mappings":"AASA,qBAAa,WAAY,SAAQ,KAAK;IAElC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM;IAErB,QAAQ,CAAC,IAAI,CAAC;gBAHL,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACN,IAAI,CAAC,KAAK;CAItB;AAED,qBAAa,8BAA+B,SAAQ,WAAW;gBACjD,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;CAM9C;AAED,qBAAa,8BAA+B,SAAQ,WAAW;gBACjD,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;CAM9C;AAED,qBAAa,sBAAuB,SAAQ,WAAW;;CAMtD;AAED,qBAAa,yBAA0B,SAAQ,WAAW;gBAC5C,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAM5C;AAED,qBAAa,oBAAqB,SAAQ,WAAW;;CAIpD;AAED,qBAAa,uBAAwB,SAAQ,WAAW;;CAIvD;AAED,qBAAa,qBAAsB,SAAQ,WAAW;gBACxC,IAAI,EAAE,MAAM;CAGzB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,QAOhD;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,QAIlF;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,QAIrF;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,QAc5C;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,QAIhD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,SAAe,GAAG,MAAM,CAQ7E"}
|
package/out/utils/validator.js
CHANGED
|
@@ -1,42 +1,93 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getErrorMessageObj = exports.assertIsSizedValue = exports.assertIsValidKey = exports.assertAndThrowIfNotArray = exports.assertAndThrowIfArray = exports.assertIsValidValue = exports.
|
|
3
|
+
exports.getErrorMessageObj = exports.assertIsSizedValue = exports.assertIsValidKey = exports.assertAndThrowIfNotArray = exports.assertAndThrowIfArray = exports.assertIsValidValue = exports.InvalidValueTypeError = exports.WrongTypeOperationError = exports.ValueIsRequiredError = exports.MaxValueSizeExceededError = exports.InvalidKeyPatternError = exports.MaxValidKeyLengthExceededError = exports.MinValidKeyLengthRequiredError = exports.TunnelError = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const api_1 = require("@forge/api");
|
|
6
5
|
const object_sizeof_1 = tslib_1.__importDefault(require("object-sizeof"));
|
|
7
6
|
const MIN_VALID_KEY_LENGTH = 1;
|
|
8
7
|
const MAX_VALID_KEY_LENGTH = 500;
|
|
9
8
|
const VALID_KEY_REGEX = /^(?!\s+$)[a-zA-Z0-9:._\s-#]+$/;
|
|
10
9
|
const KiB = 1024;
|
|
11
10
|
const MAX_VALID_VALUE_LENGTH = 240 * KiB;
|
|
12
|
-
class
|
|
13
|
-
constructor(
|
|
14
|
-
super(message);
|
|
15
|
-
this.message = message;
|
|
16
|
-
this.reason = reason;
|
|
11
|
+
class TunnelError extends Error {
|
|
12
|
+
constructor(status, code, message, data) {
|
|
13
|
+
super(`"title":"${message}"`);
|
|
17
14
|
this.status = status;
|
|
18
|
-
this.
|
|
15
|
+
this.code = code;
|
|
16
|
+
this.data = data;
|
|
19
17
|
}
|
|
20
18
|
}
|
|
21
|
-
exports.
|
|
19
|
+
exports.TunnelError = TunnelError;
|
|
20
|
+
class MinValidKeyLengthRequiredError extends TunnelError {
|
|
21
|
+
constructor(length, minLength) {
|
|
22
|
+
super(400, 'MIN_VALID_KEY_LENGTH_REQUIRED', 'Provided key length was under the minimum valid key length', {
|
|
23
|
+
length,
|
|
24
|
+
minLength
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.MinValidKeyLengthRequiredError = MinValidKeyLengthRequiredError;
|
|
29
|
+
class MaxValidKeyLengthExceededError extends TunnelError {
|
|
30
|
+
constructor(length, maxLength) {
|
|
31
|
+
super(400, 'MAX_VALID_KEY_LENGTH_EXCEEDED', 'Provided key length was above the maximum valid key length', {
|
|
32
|
+
length,
|
|
33
|
+
maxLength
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.MaxValidKeyLengthExceededError = MaxValidKeyLengthExceededError;
|
|
38
|
+
class InvalidKeyPatternError extends TunnelError {
|
|
39
|
+
constructor() {
|
|
40
|
+
super(400, 'INVALID_KEY_PATTERN', 'Provided key must match regex', {
|
|
41
|
+
regex: VALID_KEY_REGEX
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.InvalidKeyPatternError = InvalidKeyPatternError;
|
|
46
|
+
class MaxValueSizeExceededError extends TunnelError {
|
|
47
|
+
constructor(bytes, maxBytes) {
|
|
48
|
+
super(400, 'MAX_VALUE_SIZE_EXCEEDED', 'Provided value bytes was over maximum valid value size', {
|
|
49
|
+
bytes,
|
|
50
|
+
maxBytes
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.MaxValueSizeExceededError = MaxValueSizeExceededError;
|
|
55
|
+
class ValueIsRequiredError extends TunnelError {
|
|
56
|
+
constructor() {
|
|
57
|
+
super(400, 'VALUE_IS_REQUIRED', 'Provided value is required');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.ValueIsRequiredError = ValueIsRequiredError;
|
|
61
|
+
class WrongTypeOperationError extends TunnelError {
|
|
62
|
+
constructor() {
|
|
63
|
+
super(400, 'UnprocessableContent', 'WRONGTYPE Operation against a key holding the wrong kind of value');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.WrongTypeOperationError = WrongTypeOperationError;
|
|
67
|
+
class InvalidValueTypeError extends TunnelError {
|
|
68
|
+
constructor(type) {
|
|
69
|
+
super(400, 'INVALID_VALUE_TYPE', 'Provided value must be a string', { type });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.InvalidValueTypeError = InvalidValueTypeError;
|
|
22
73
|
function assertIsValidValue(value) {
|
|
23
74
|
if (value === undefined || value === null) {
|
|
24
|
-
throw new
|
|
75
|
+
throw new ValueIsRequiredError();
|
|
25
76
|
}
|
|
26
77
|
if (typeof value !== 'string') {
|
|
27
|
-
throw new
|
|
78
|
+
throw new InvalidValueTypeError(typeof value);
|
|
28
79
|
}
|
|
29
80
|
}
|
|
30
81
|
exports.assertIsValidValue = assertIsValidValue;
|
|
31
82
|
function assertAndThrowIfArray(value) {
|
|
32
83
|
if (value && Array.isArray(value)) {
|
|
33
|
-
throw new
|
|
84
|
+
throw new WrongTypeOperationError();
|
|
34
85
|
}
|
|
35
86
|
}
|
|
36
87
|
exports.assertAndThrowIfArray = assertAndThrowIfArray;
|
|
37
88
|
function assertAndThrowIfNotArray(value) {
|
|
38
89
|
if (value && !Array.isArray(value)) {
|
|
39
|
-
throw new
|
|
90
|
+
throw new WrongTypeOperationError();
|
|
40
91
|
}
|
|
41
92
|
}
|
|
42
93
|
exports.assertAndThrowIfNotArray = assertAndThrowIfNotArray;
|
|
@@ -45,30 +96,19 @@ function assertIsValidKey(key) {
|
|
|
45
96
|
throw new Error('Provided key must be a string');
|
|
46
97
|
}
|
|
47
98
|
if (key.length < MIN_VALID_KEY_LENGTH) {
|
|
48
|
-
throw new
|
|
49
|
-
length: key.length,
|
|
50
|
-
minLength: MIN_VALID_KEY_LENGTH
|
|
51
|
-
});
|
|
99
|
+
throw new MinValidKeyLengthRequiredError(key.length, MIN_VALID_KEY_LENGTH);
|
|
52
100
|
}
|
|
53
101
|
if (key.length > MAX_VALID_KEY_LENGTH) {
|
|
54
|
-
throw new
|
|
55
|
-
length: key.length,
|
|
56
|
-
maxLength: MAX_VALID_KEY_LENGTH
|
|
57
|
-
});
|
|
102
|
+
throw new MaxValidKeyLengthExceededError(key.length, MAX_VALID_KEY_LENGTH);
|
|
58
103
|
}
|
|
59
104
|
if (!VALID_KEY_REGEX.test(key)) {
|
|
60
|
-
throw new
|
|
61
|
-
regex: VALID_KEY_REGEX
|
|
62
|
-
});
|
|
105
|
+
throw new InvalidKeyPatternError();
|
|
63
106
|
}
|
|
64
107
|
}
|
|
65
108
|
exports.assertIsValidKey = assertIsValidKey;
|
|
66
109
|
function assertIsSizedValue(value) {
|
|
67
110
|
if ((0, object_sizeof_1.default)(value) > MAX_VALID_VALUE_LENGTH) {
|
|
68
|
-
throw new
|
|
69
|
-
bytes: (0, object_sizeof_1.default)(value),
|
|
70
|
-
maxBytes: MAX_VALID_VALUE_LENGTH
|
|
71
|
-
});
|
|
111
|
+
throw new MaxValueSizeExceededError((0, object_sizeof_1.default)(value), MAX_VALID_VALUE_LENGTH);
|
|
72
112
|
}
|
|
73
113
|
}
|
|
74
114
|
exports.assertIsSizedValue = assertIsSizedValue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forge/cache",
|
|
3
|
-
"version": "0.10.0-next.
|
|
3
|
+
"version": "0.10.0-next.2",
|
|
4
4
|
"description": "Forge Cache methods",
|
|
5
5
|
"author": "Atlassian",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@types/node": "14.18.63",
|
|
19
19
|
"@types/node-fetch": "^2.6.11",
|
|
20
|
-
"node-fetch": "2.7.0"
|
|
20
|
+
"node-fetch": "2.7.0",
|
|
21
|
+
"tmp": "^0.2.3"
|
|
21
22
|
},
|
|
22
23
|
"dependencies": {
|
|
23
24
|
"@forge/api": "^3.7.0-next.0",
|