@forge/cache 0.10.0-next.2 → 0.10.0
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 +3 -4
- package/out/cache.js +24 -13
- package/out/tunnel.js +12 -12
- package/out/utils/validator.js +3 -0
- package/package.json +2 -2
|
@@ -55,7 +55,6 @@ describe('createFetch', () => {
|
|
|
55
55
|
await expect((0, cache_1.createFetchRmsRuntimeV2)()).rejects.toThrowError(new Error('RMS config not available.'));
|
|
56
56
|
});
|
|
57
57
|
it('creates a fetch that adds the right headers and url', async () => {
|
|
58
|
-
var _a;
|
|
59
58
|
global['__forge_runtime__'] = {
|
|
60
59
|
proxy: {
|
|
61
60
|
token: 'token',
|
|
@@ -72,10 +71,10 @@ describe('createFetch', () => {
|
|
|
72
71
|
};
|
|
73
72
|
const fetch = (0, cache_1.createFetchRmsRuntimeV2)();
|
|
74
73
|
await fetch('path');
|
|
75
|
-
const [absoluteUrl, options] =
|
|
74
|
+
const [absoluteUrl, options] = fetchMock.mock.lastCall ?? ['', {}];
|
|
76
75
|
expect(absoluteUrl.toString()).toEqual('https://rms/path');
|
|
77
|
-
expect((options
|
|
78
|
-
expect(options
|
|
76
|
+
expect((options?.agent)['passthrough']['keepAlive']).toBeTruthy();
|
|
77
|
+
expect(options?.headers).toMatchObject({
|
|
79
78
|
Authorization: 'Bearer token',
|
|
80
79
|
Host: 'rockmelon-storage.dev.atl-paas.net',
|
|
81
80
|
'x-b3-traceid': 'trace-id-test',
|
package/out/cache.js
CHANGED
|
@@ -7,6 +7,9 @@ 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
9
|
class ApiError extends Error {
|
|
10
|
+
status;
|
|
11
|
+
code;
|
|
12
|
+
data;
|
|
10
13
|
constructor(status, code, message, data) {
|
|
11
14
|
super(message);
|
|
12
15
|
this.status = status;
|
|
@@ -16,12 +19,11 @@ class ApiError extends Error {
|
|
|
16
19
|
}
|
|
17
20
|
exports.ApiError = ApiError;
|
|
18
21
|
async function getResponseBody(response) {
|
|
19
|
-
var _a, _b, _c;
|
|
20
22
|
const responseText = await response.text();
|
|
21
23
|
if (!response.ok) {
|
|
22
24
|
try {
|
|
23
25
|
const parsedError = JSON.parse(responseText);
|
|
24
|
-
throw new ApiError(response.status,
|
|
26
|
+
throw new ApiError(response.status, parsedError?.error?.code, `"title":"${parsedError?.error?.title}"`, parsedError?.error?.data);
|
|
25
27
|
}
|
|
26
28
|
catch (e) {
|
|
27
29
|
if (!(e instanceof ApiError)) {
|
|
@@ -41,6 +43,7 @@ async function getResponseBody(response) {
|
|
|
41
43
|
}
|
|
42
44
|
exports.getResponseBody = getResponseBody;
|
|
43
45
|
class Cache {
|
|
46
|
+
client;
|
|
44
47
|
constructor(client) {
|
|
45
48
|
this.client = client;
|
|
46
49
|
}
|
|
@@ -54,11 +57,11 @@ class Cache {
|
|
|
54
57
|
};
|
|
55
58
|
}
|
|
56
59
|
async set(key, value, opt) {
|
|
57
|
-
const response = await this.client('rms/store/set', this.buildRequest(
|
|
60
|
+
const response = await this.client('rms/store/set', this.buildRequest({ key, value, ...opt }));
|
|
58
61
|
await getResponseBody(response);
|
|
59
62
|
}
|
|
60
63
|
async setIfNotExists(key, value, opt) {
|
|
61
|
-
const response = await this.client('rms/store/setnx', this.buildRequest(
|
|
64
|
+
const response = await this.client('rms/store/setnx', this.buildRequest({ key, value, ...opt }));
|
|
62
65
|
const { response: result } = await getResponseBody(response);
|
|
63
66
|
return result;
|
|
64
67
|
}
|
|
@@ -68,17 +71,17 @@ class Cache {
|
|
|
68
71
|
return result;
|
|
69
72
|
}
|
|
70
73
|
async getAndSet(key, value, opt) {
|
|
71
|
-
const response = await this.client('rms/store/getset', this.buildRequest(
|
|
74
|
+
const response = await this.client('rms/store/getset', this.buildRequest({ key, value, ...opt }));
|
|
72
75
|
const { response: result } = await getResponseBody(response);
|
|
73
76
|
return result;
|
|
74
77
|
}
|
|
75
78
|
async incrementAndGet(key, opt) {
|
|
76
|
-
const response = await this.client('rms/store/incr', this.buildRequest(
|
|
79
|
+
const response = await this.client('rms/store/incr', this.buildRequest({ key, ...opt }));
|
|
77
80
|
const { response: result } = await getResponseBody(response);
|
|
78
81
|
return result;
|
|
79
82
|
}
|
|
80
83
|
async decrementAndGet(key, opt) {
|
|
81
|
-
const response = await this.client('rms/store/decr', this.buildRequest(
|
|
84
|
+
const response = await this.client('rms/store/decr', this.buildRequest({ key, ...opt }));
|
|
82
85
|
const { response: result } = await getResponseBody(response);
|
|
83
86
|
return result;
|
|
84
87
|
}
|
|
@@ -110,29 +113,37 @@ class Cache {
|
|
|
110
113
|
}
|
|
111
114
|
exports.Cache = Cache;
|
|
112
115
|
function getFetchRmsRuntimeV1() {
|
|
113
|
-
|
|
114
|
-
return (_a = global.api) === null || _a === void 0 ? void 0 : _a.requestRmsStore;
|
|
116
|
+
return global.api?.requestRmsStore;
|
|
115
117
|
}
|
|
116
118
|
exports.getFetchRmsRuntimeV1 = getFetchRmsRuntimeV1;
|
|
117
119
|
function createFetchRmsRuntimeV2() {
|
|
118
120
|
const agent = new https_1.Agent({ keepAlive: true });
|
|
119
121
|
return async function (path, options) {
|
|
120
122
|
const { proxy, rms, tracing } = (0, api_1.__getRuntime)();
|
|
121
|
-
if (!
|
|
123
|
+
if (!rms?.url || !rms?.host) {
|
|
122
124
|
throw new Error('RMS config not available.');
|
|
123
125
|
}
|
|
124
126
|
const rmsAgent = new String('FORGE_PRODUCT_REQUEST');
|
|
125
127
|
rmsAgent['passthrough'] = agent;
|
|
126
|
-
return await (0, node_fetch_1.default)(new URL(path, 'https://rms/'),
|
|
128
|
+
return await (0, node_fetch_1.default)(new URL(path, 'https://rms/'), {
|
|
129
|
+
...options,
|
|
130
|
+
agent: rmsAgent,
|
|
131
|
+
headers: {
|
|
132
|
+
...options?.headers,
|
|
133
|
+
Authorization: `Bearer ${proxy.token}`,
|
|
134
|
+
Host: rms.host,
|
|
135
|
+
'x-b3-traceid': tracing.traceId,
|
|
136
|
+
'x-b3-spanid': tracing.spanId
|
|
137
|
+
}
|
|
138
|
+
});
|
|
127
139
|
};
|
|
128
140
|
}
|
|
129
141
|
exports.createFetchRmsRuntimeV2 = createFetchRmsRuntimeV2;
|
|
130
142
|
function connect(localCacheFileName) {
|
|
131
|
-
var _a;
|
|
132
143
|
if (global.__forge_tunnel__) {
|
|
133
144
|
return new tunnel_1.TunnelCache(localCacheFileName);
|
|
134
145
|
}
|
|
135
|
-
const fetch =
|
|
146
|
+
const fetch = getFetchRmsRuntimeV1() ?? createFetchRmsRuntimeV2();
|
|
136
147
|
return new Cache(fetch);
|
|
137
148
|
}
|
|
138
149
|
exports.connect = connect;
|
package/out/tunnel.js
CHANGED
|
@@ -10,15 +10,18 @@ const LOG_PREFIX = '@forge/cache tunnel: ';
|
|
|
10
10
|
exports.CACHE_DIR = '.forge';
|
|
11
11
|
exports.CACHE_FILE = exports.CACHE_DIR + '/cache.json';
|
|
12
12
|
const warn = (message, meta) => {
|
|
13
|
-
console.warn(LOG_PREFIX + message, meta
|
|
13
|
+
console.warn(LOG_PREFIX + message, meta ?? '');
|
|
14
14
|
};
|
|
15
15
|
const info = (message, meta) => {
|
|
16
|
-
console.info(LOG_PREFIX + message, meta
|
|
16
|
+
console.info(LOG_PREFIX + message, meta ?? '');
|
|
17
17
|
};
|
|
18
18
|
const error = (err) => {
|
|
19
19
|
console.error(LOG_PREFIX, err);
|
|
20
20
|
};
|
|
21
21
|
class TunnelCache {
|
|
22
|
+
fileName;
|
|
23
|
+
__localStore;
|
|
24
|
+
events;
|
|
22
25
|
constructor(fileName = exports.CACHE_FILE) {
|
|
23
26
|
this.fileName = fileName;
|
|
24
27
|
warn('Using local implementation of @forge/cache.');
|
|
@@ -70,7 +73,7 @@ class TunnelCache {
|
|
|
70
73
|
(0, validator_1.assertIsValidKey)(key);
|
|
71
74
|
const value = this.__localStore.get(key);
|
|
72
75
|
(0, validator_1.assertAndThrowIfArray)(value);
|
|
73
|
-
const { response: result } = await this.parseSuccessResponse(value
|
|
76
|
+
const { response: result } = await this.parseSuccessResponse(value ?? null);
|
|
74
77
|
return result;
|
|
75
78
|
}
|
|
76
79
|
async setIfNotExists(key, value, opt) {
|
|
@@ -87,11 +90,10 @@ class TunnelCache {
|
|
|
87
90
|
return result;
|
|
88
91
|
}
|
|
89
92
|
async getAndSet(key, value, opt) {
|
|
90
|
-
var _a;
|
|
91
93
|
(0, validator_1.assertIsValidKey)(key);
|
|
92
94
|
(0, validator_1.assertIsValidValue)(value);
|
|
93
95
|
(0, validator_1.assertIsSizedValue)(value);
|
|
94
|
-
const oldValue =
|
|
96
|
+
const oldValue = this.__localStore.get(key) ?? null;
|
|
95
97
|
this.__localStore.set(key, value);
|
|
96
98
|
this.events.emit('change');
|
|
97
99
|
const { response: result } = await this.parseSuccessResponse(oldValue);
|
|
@@ -109,11 +111,10 @@ class TunnelCache {
|
|
|
109
111
|
return result;
|
|
110
112
|
}
|
|
111
113
|
async incrementAndGet(key, opt) {
|
|
112
|
-
var _a;
|
|
113
114
|
(0, validator_1.assertIsValidKey)(key);
|
|
114
115
|
const oldValue = this.__localStore.get(key);
|
|
115
116
|
(0, validator_1.assertAndThrowIfArray)(oldValue);
|
|
116
|
-
const newValue = Number.parseInt(
|
|
117
|
+
const newValue = Number.parseInt(oldValue ?? '0') + 1;
|
|
117
118
|
this.__localStore.set(key, newValue.toString());
|
|
118
119
|
this.events.emit('change');
|
|
119
120
|
const { response: result } = await this.parseSuccessResponse(newValue);
|
|
@@ -157,19 +158,18 @@ class TunnelCache {
|
|
|
157
158
|
return result;
|
|
158
159
|
}
|
|
159
160
|
async decrementAndGet(key, opt) {
|
|
160
|
-
var _a;
|
|
161
161
|
(0, validator_1.assertIsValidKey)(key);
|
|
162
162
|
const oldValue = this.__localStore.get(key);
|
|
163
163
|
(0, validator_1.assertAndThrowIfArray)(oldValue);
|
|
164
|
-
const newValue = Number.parseInt(
|
|
164
|
+
const newValue = Number.parseInt(oldValue ?? '0') - 1;
|
|
165
165
|
this.__localStore.set(key, newValue.toString());
|
|
166
166
|
this.events.emit('change');
|
|
167
167
|
const { response: result } = await this.parseSuccessResponse(newValue);
|
|
168
168
|
return result;
|
|
169
169
|
}
|
|
170
170
|
async scan(pattern, opt) {
|
|
171
|
-
const cursor =
|
|
172
|
-
const count =
|
|
171
|
+
const cursor = opt?.cursor ? Number(opt.cursor) : 0;
|
|
172
|
+
const count = opt?.count || 10;
|
|
173
173
|
const escapedPattern = pattern.replace(/([.+^${}()|\\])/g, '\\$1');
|
|
174
174
|
const regexPattern = escapedPattern.replace(/\*/g, '.*').replace(/\?/g, '.');
|
|
175
175
|
const regex = new RegExp(regexPattern);
|
|
@@ -184,7 +184,7 @@ class TunnelCache {
|
|
|
184
184
|
}
|
|
185
185
|
parseSuccessResponse(response) {
|
|
186
186
|
return Promise.resolve({
|
|
187
|
-
response: response
|
|
187
|
+
response: response ?? null
|
|
188
188
|
});
|
|
189
189
|
}
|
|
190
190
|
}
|
package/out/utils/validator.js
CHANGED
|
@@ -9,6 +9,9 @@ const VALID_KEY_REGEX = /^(?!\s+$)[a-zA-Z0-9:._\s-#]+$/;
|
|
|
9
9
|
const KiB = 1024;
|
|
10
10
|
const MAX_VALID_VALUE_LENGTH = 240 * KiB;
|
|
11
11
|
class TunnelError extends Error {
|
|
12
|
+
status;
|
|
13
|
+
code;
|
|
14
|
+
data;
|
|
12
15
|
constructor(status, code, message, data) {
|
|
13
16
|
super(`"title":"${message}"`);
|
|
14
17
|
this.status = status;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forge/cache",
|
|
3
|
-
"version": "0.10.0
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Forge Cache methods",
|
|
5
5
|
"author": "Atlassian",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"tmp": "^0.2.3"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@forge/api": "^3.7.0
|
|
24
|
+
"@forge/api": "^3.7.0",
|
|
25
25
|
"object-sizeof": "^2.6.4"
|
|
26
26
|
}
|
|
27
27
|
}
|