@forge/cache 0.3.2-next.0 → 0.4.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/README.md CHANGED
@@ -12,9 +12,13 @@ const result = await cacheClient.setIfNotExists("hello", "3", { ttlSeconds: 10 }
12
12
 
13
13
  const result = await cacheClient.get("hello");
14
14
 
15
+ const result = await cacheClient.getAndSet("hello", "3", { ttlSeconds: 10 });
16
+
15
17
  const result = await cacheClient.incrementAndGet("hello");
16
18
 
17
19
  const result = await cacheClient.decrementAndGet("hello");
18
20
 
19
21
  const result = await cacheClient.delete("hello");
22
+
23
+ const result = await cacheClient.scan("hello*", { cursor: "10", count: 10 });
20
24
  ```
@@ -155,11 +155,22 @@ describe('Cache', () => {
155
155
  describe('get', () => {
156
156
  it('handles success', async () => {
157
157
  const { cache, fetch } = buildCache();
158
- fetch.mockResolvedValueOnce({ ok: true, text: async () => JSON.stringify({ value: 'asdfasdf' }), status: 200 });
158
+ fetch.mockResolvedValueOnce({
159
+ ok: true,
160
+ text: async () => JSON.stringify({ response: 'asdfasdf' }),
161
+ status: 200
162
+ });
159
163
  const result = await cache.get('key');
160
164
  expect(result).toEqual('asdfasdf');
161
165
  expect(fetch.mock.lastCall).toMatchSnapshot();
162
166
  });
167
+ it('handles success when key does not exist', async () => {
168
+ const { cache, fetch } = buildCache();
169
+ fetch.mockResolvedValueOnce({ ok: true, text: async () => JSON.stringify({ response: null }), status: 200 });
170
+ const result = await cache.get('key');
171
+ expect(result).toBeNull();
172
+ expect(fetch.mock.lastCall).toMatchSnapshot();
173
+ });
163
174
  it('handles failure', async () => {
164
175
  const { cache, fetch } = buildCache();
165
176
  fetch.mockResolvedValueOnce({ ok: false, text: async () => 'Not allowed', status: 403 });
@@ -167,6 +178,42 @@ describe('Cache', () => {
167
178
  expect(fetch.mock.lastCall).toMatchSnapshot();
168
179
  });
169
180
  });
181
+ describe('getAndSet', () => {
182
+ it('handles success', async () => {
183
+ const { cache, fetch } = buildCache();
184
+ fetch.mockResolvedValueOnce({
185
+ ok: true,
186
+ text: async () => JSON.stringify({ response: 'oldValue' }),
187
+ status: 200
188
+ });
189
+ const result = await cache.getAndSet('key', 'newValue');
190
+ expect(result).toEqual('oldValue');
191
+ expect(fetch.mock.lastCall).toMatchSnapshot();
192
+ });
193
+ it('handles success when key does not exist', async () => {
194
+ const { cache, fetch } = buildCache();
195
+ fetch.mockResolvedValueOnce({ ok: true, text: async () => JSON.stringify({ response: null }), status: 200 });
196
+ const result = await cache.getAndSet('key', 'value');
197
+ expect(result).toBeNull();
198
+ expect(fetch.mock.lastCall).toMatchSnapshot();
199
+ });
200
+ it('handles success with ttl', async () => {
201
+ const { cache, fetch } = buildCache();
202
+ fetch.mockResolvedValueOnce({
203
+ ok: true,
204
+ text: async () => JSON.stringify({ response: 'oldValue' }),
205
+ status: 200
206
+ });
207
+ await cache.getAndSet('key', 'newValue', { ttlSeconds: 100 });
208
+ expect(fetch.mock.lastCall).toMatchSnapshot();
209
+ });
210
+ it('handles failure', async () => {
211
+ const { cache, fetch } = buildCache();
212
+ fetch.mockResolvedValueOnce({ ok: false, text: async () => 'Not allowed', status: 403 });
213
+ await expect(cache.getAndSet('key', 'value', { ttlSeconds: 100 })).rejects.toMatchError(new api_1.HttpError('403: Not allowed'));
214
+ expect(fetch.mock.lastCall).toMatchSnapshot();
215
+ });
216
+ });
170
217
  describe('incrementAndGet', () => {
171
218
  it('handles success', async () => {
172
219
  const { cache, fetch } = buildCache();
@@ -226,4 +273,36 @@ describe('Cache', () => {
226
273
  expect(fetch.mock.lastCall).toMatchSnapshot();
227
274
  });
228
275
  });
276
+ describe('scan', () => {
277
+ it('handles success', async () => {
278
+ const { cache, fetch } = buildCache();
279
+ const expectedResponse = { cursor: '0', keys: ['key1', 'key2'] };
280
+ fetch.mockResolvedValueOnce({ ok: true, text: async () => JSON.stringify(expectedResponse), status: 200 });
281
+ const actualResponse = await cache.scan('key*');
282
+ expect(actualResponse).toEqual(expectedResponse);
283
+ expect(fetch.mock.lastCall).toMatchSnapshot();
284
+ });
285
+ it('handles success with cursor', async () => {
286
+ const { cache, fetch } = buildCache();
287
+ const expectedResponse = { cursor: '0', keys: ['key2'] };
288
+ fetch.mockResolvedValueOnce({ ok: true, text: async () => JSON.stringify(expectedResponse), status: 200 });
289
+ const actualResponse = await cache.scan('key*', { cursor: '1' });
290
+ expect(actualResponse).toEqual(expectedResponse);
291
+ expect(fetch.mock.lastCall).toMatchSnapshot();
292
+ });
293
+ it('handles success with count', async () => {
294
+ const { cache, fetch } = buildCache();
295
+ const expectedResponse = { cursor: '0', keys: ['key1'] };
296
+ fetch.mockResolvedValueOnce({ ok: true, text: async () => JSON.stringify(expectedResponse), status: 200 });
297
+ const actualResponse = await cache.scan('key*', { count: 1 });
298
+ expect(actualResponse).toEqual(expectedResponse);
299
+ expect(fetch.mock.lastCall).toMatchSnapshot();
300
+ });
301
+ it('handles failure', async () => {
302
+ const { cache, fetch } = buildCache();
303
+ fetch.mockResolvedValueOnce({ ok: false, text: async () => 'Not allowed', status: 403 });
304
+ await expect(cache.scan('key*', { cursor: '0', count: 2 })).rejects.toMatchError(new api_1.HttpError('403: Not allowed'));
305
+ expect(fetch.mock.lastCall).toMatchSnapshot();
306
+ });
307
+ });
229
308
  });
package/out/cache.d.ts CHANGED
@@ -11,10 +11,17 @@ export declare class Cache {
11
11
  setIfNotExists(key: string, value: string, opt?: {
12
12
  ttlSeconds: number;
13
13
  }): Promise<'OK' | null>;
14
- get(key: string): Promise<string>;
14
+ get(key: string): Promise<string | null>;
15
+ getAndSet(key: string, value: string, opt?: {
16
+ ttlSeconds: number;
17
+ }): Promise<string | null>;
15
18
  incrementAndGet(key: string): Promise<number>;
16
19
  decrementAndGet(key: string): Promise<number>;
17
20
  delete(key: string): Promise<number>;
21
+ scan(pattern: string, opt?: {
22
+ cursor?: string;
23
+ count?: number;
24
+ }): Promise<JSON>;
18
25
  }
19
26
  export declare function getFetchRmsRuntimeV1(): ((path: string, options?: RequestInit) => Promise<Response>) | undefined;
20
27
  export declare function createFetchRmsRuntimeV2(): (path: string, options?: RequestInit) => Promise<Response>;
@@ -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;AAInF,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAC,CAAC;AAGzE,wBAAsB,eAAe,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAYtE;AAED,qBAAa,KAAK;IACJ,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC;IAGtF,OAAO,CAAC,YAAY;IAUP,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAM5E,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;IAO9F,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAOjC,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAO7C,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAO7C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAMlD;AAED,wBAAgB,oBAAoB,IAAI,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,SAAS,CAE/G;AAID,wBAAgB,uBAAuB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CA2BpG;AAED,wBAAgB,OAAO,UAItB"}
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;AAInF,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAC,CAAC;AAGzE,wBAAsB,eAAe,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAYtE;AAED,qBAAa,KAAK;IACJ,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC;IAGtF,OAAO,CAAC,YAAY;IAUP,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAM5E,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;IAO9F,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAOxC,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;IAO3F,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAO7C,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAO7C,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAOpC,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,IAAI,CAAC;CAM7F;AAED,wBAAgB,oBAAoB,IAAI,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,SAAS,CAE/G;AAID,wBAAgB,uBAAuB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CA2BpG;AAED,wBAAgB,OAAO,UAItB"}
package/out/cache.js CHANGED
@@ -40,7 +40,12 @@ class Cache {
40
40
  }
41
41
  async get(key) {
42
42
  const response = await this.client('rms/store/get', this.buildRequest({ key }));
43
- const { value: result } = await getResponseBody(response);
43
+ const { response: result } = await getResponseBody(response);
44
+ return result;
45
+ }
46
+ async getAndSet(key, value, opt) {
47
+ const response = await this.client('rms/store/getset', this.buildRequest(Object.assign({ key, value }, opt)));
48
+ const { response: result } = await getResponseBody(response);
44
49
  return result;
45
50
  }
46
51
  async incrementAndGet(key) {
@@ -58,6 +63,11 @@ class Cache {
58
63
  const { response: result } = await getResponseBody(response);
59
64
  return result;
60
65
  }
66
+ async scan(pattern, opt) {
67
+ const { cursor, count } = opt || {};
68
+ const response = await this.client('rms/store/scan', this.buildRequest({ cursor, pattern, count }));
69
+ return await getResponseBody(response);
70
+ }
61
71
  }
62
72
  exports.Cache = Cache;
63
73
  function getFetchRmsRuntimeV1() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forge/cache",
3
- "version": "0.3.2-next.0",
3
+ "version": "0.4.0-next.2",
4
4
  "description": "Forge Cache methods",
5
5
  "author": "Atlassian",
6
6
  "license": "UNLICENSED",
@@ -16,10 +16,10 @@
16
16
  },
17
17
  "devDependencies": {
18
18
  "@types/node": "14.18.59",
19
- "@types/node-fetch": "^2.6.4",
19
+ "@types/node-fetch": "^2.6.5",
20
20
  "node-fetch": "2.7.0"
21
21
  },
22
22
  "dependencies": {
23
- "@forge/api": "^2.19.1-next.0"
23
+ "@forge/api": "^2.19.1-next.1"
24
24
  }
25
25
  }