@forge/storage 1.3.1 → 1.3.2-experimental-2a9dda4

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/CHANGELOG.md ADDED
@@ -0,0 +1,328 @@
1
+ # @forge/storage
2
+
3
+ ## 1.3.2-experimental-2a9dda4
4
+
5
+ ### Patch Changes
6
+
7
+ - eb084dba: Added capabilities for enabling Custom entities
8
+
9
+ ## 1.3.2
10
+
11
+ ### Patch Changes
12
+
13
+ - 61d41c6: Bumping dependencies via Renovate:
14
+
15
+ - @types/react-reconciler
16
+
17
+ - ba6d381: Bumping dependencies via Renovate:
18
+
19
+ - @types/cross-spawn
20
+
21
+ - 4a070c4: Bumping dependencies via Renovate:
22
+
23
+ - command-exists
24
+
25
+ - 37eee39: Bumping dependencies via Renovate:
26
+
27
+ - ajv
28
+
29
+ - 444ada4: Bumping dependencies via Renovate:
30
+
31
+ - @changesets/types
32
+
33
+ - 66da5d9: Bumping dependencies via Renovate:
34
+
35
+ - conf
36
+
37
+ - decbf80: Bumping dependencies via Renovate:
38
+
39
+ - @types/react
40
+
41
+ - 2b1589f: Bumping dependencies via Renovate:
42
+
43
+ - @types/minimatch
44
+
45
+ - 6386221: Bumping dependencies via Renovate:
46
+
47
+ - @types/lodash
48
+
49
+ - 203f465: Bumping dependencies via Renovate:
50
+
51
+ - @types/inquirer
52
+
53
+ - 51d8225: Bumping dependencies via Renovate:
54
+
55
+ - @types/xml
56
+
57
+ - c810119: Bumping dependencies via Renovate:
58
+
59
+ - @atlassian/logger-interface
60
+
61
+ - d6d7226: Bumping dependencies via Renovate:
62
+
63
+ - @types/history
64
+
65
+ - 5d6f948: Bumping dependencies via Renovate:
66
+
67
+ - @changesets/apply-release-plan
68
+
69
+ - 0d52cdb: Bumping dependencies via Renovate:
70
+
71
+ - @types/uuid
72
+
73
+ - 1508104: Bumping dependencies via Renovate:
74
+
75
+ - @types/cheerio
76
+
77
+ - ff5d0f8: Bumping dependencies via Renovate:
78
+
79
+ - @types/supertest
80
+
81
+ - 8970da8: Bumping dependencies via Renovate:
82
+
83
+ - @types/concat-stream
84
+
85
+ ## 1.3.2-next.8
86
+
87
+ ### Patch Changes
88
+
89
+ - 4a070c4: Bumping dependencies via Renovate:
90
+
91
+ - command-exists
92
+
93
+ - 66da5d9: Bumping dependencies via Renovate:
94
+
95
+ - conf
96
+
97
+ - decbf80: Bumping dependencies via Renovate:
98
+
99
+ - @types/react
100
+
101
+ ## 1.3.2-next.7
102
+
103
+ ### Patch Changes
104
+
105
+ - 37eee39: Bumping dependencies via Renovate:
106
+
107
+ - ajv
108
+
109
+ ## 1.3.2-next.6
110
+
111
+ ### Patch Changes
112
+
113
+ - 61d41c6: Bumping dependencies via Renovate:
114
+
115
+ - @types/react-reconciler
116
+
117
+ - ba6d381: Bumping dependencies via Renovate:
118
+
119
+ - @types/cross-spawn
120
+
121
+ - 203f465: Bumping dependencies via Renovate:
122
+
123
+ - @types/inquirer
124
+
125
+ - ff5d0f8: Bumping dependencies via Renovate:
126
+
127
+ - @types/supertest
128
+
129
+ ## 1.3.2-next.5
130
+
131
+ ### Patch Changes
132
+
133
+ - 0d52cdb: Bumping dependencies via Renovate:
134
+
135
+ - @types/uuid
136
+
137
+ ## 1.3.2-next.4
138
+
139
+ ### Patch Changes
140
+
141
+ - 51d8225: Bumping dependencies via Renovate:
142
+
143
+ - @types/xml
144
+
145
+ ## 1.3.2-next.3
146
+
147
+ ### Patch Changes
148
+
149
+ - 2b1589f: Bumping dependencies via Renovate:
150
+
151
+ - @types/minimatch
152
+
153
+ - 5d6f948: Bumping dependencies via Renovate:
154
+
155
+ - @changesets/apply-release-plan
156
+
157
+ ## 1.3.2-next.2
158
+
159
+ ### Patch Changes
160
+
161
+ - 6386221: Bumping dependencies via Renovate:
162
+
163
+ - @types/lodash
164
+
165
+ ## 1.3.2-next.1
166
+
167
+ ### Patch Changes
168
+
169
+ - 444ada4: Bumping dependencies via Renovate:
170
+
171
+ - @changesets/types
172
+
173
+ - d6d7226: Bumping dependencies via Renovate:
174
+
175
+ - @types/history
176
+
177
+ - 8970da8: Bumping dependencies via Renovate:
178
+
179
+ - @types/concat-stream
180
+
181
+ ## 1.3.2-next.0
182
+
183
+ ### Patch Changes
184
+
185
+ - c810119: Bumping dependencies via Renovate:
186
+
187
+ - @atlassian/logger-interface
188
+
189
+ - 1508104: Bumping dependencies via Renovate:
190
+
191
+ - @types/cheerio
192
+
193
+ ## 1.3.1
194
+
195
+ ### Patch Changes
196
+
197
+ - 8e2a5a6: Update node-fetch version
198
+
199
+ ## 1.3.1-next.0
200
+
201
+ ### Patch Changes
202
+
203
+ - 8e2a5a6: Update node-fetch version
204
+
205
+ ## 1.3.0
206
+
207
+ ### Minor Changes
208
+
209
+ - 3c3c42b: Updated EAP filter names to be more readable
210
+
211
+ ## 1.3.0-next.0
212
+
213
+ ### Minor Changes
214
+
215
+ - 3c3c42b9: Updated EAP filter names to be more readable
216
+
217
+ ## 1.2.0
218
+
219
+ ### Minor Changes
220
+
221
+ - 21e392d: Added new filters for Early Access Program
222
+
223
+ ## 1.2.0-next.0
224
+
225
+ ### Minor Changes
226
+
227
+ - 21e392d: Added new filters for Early Access Program
228
+
229
+ ## 1.1.0
230
+
231
+ ### Minor Changes
232
+
233
+ - 0d7fe27: Support secret storage API
234
+
235
+ ## 1.1.0-next.0
236
+
237
+ ### Minor Changes
238
+
239
+ - 0d7fe27: Support secret storage API
240
+
241
+ ## 1.0.5
242
+
243
+ ### Patch Changes
244
+
245
+ - 0700578: Fix GraphQL query naming convention
246
+
247
+ ## 1.0.5-next.0
248
+
249
+ ### Patch Changes
250
+
251
+ - 0700578: Fix GraphQL query naming convention
252
+
253
+ ## 1.0.4
254
+
255
+ ### Patch Changes
256
+
257
+ - 5ff60ec: FRGE-273 Remove engines for storage and resolver
258
+
259
+ ## 1.0.4-next.0
260
+
261
+ ### Patch Changes
262
+
263
+ - 5ff60ec: FRGE-273 Remove engines for storage and resolver
264
+
265
+ ## 1.0.3
266
+
267
+ ### Patch Changes
268
+
269
+ - 9b496aa: Fixed parsing of response for cleanup functions
270
+
271
+ ## 1.0.3-next.0
272
+
273
+ ### Patch Changes
274
+
275
+ - 9b496aa: Fixed parsing of response for cleanup functions
276
+
277
+ ## 1.0.2
278
+
279
+ ### Patch Changes
280
+
281
+ - c7c6de2: Support larger list queries for GDPR purposes
282
+
283
+ ## 1.0.2-next.0
284
+
285
+ ### Patch Changes
286
+
287
+ - c7c6de2: Support larger list queries for GDPR purposes
288
+
289
+ ## 1.0.1
290
+
291
+ ### Patch Changes
292
+
293
+ - c0e9085: Improve README
294
+
295
+ ## 1.0.1-next.0
296
+
297
+ ### Patch Changes
298
+
299
+ - c0e9085: Improve README
300
+
301
+ ## 1.0.0
302
+
303
+ ### Major Changes
304
+
305
+ - 1daf2c5: Forge packages to 1.0.0 for upcoming platform GA 🎉
306
+
307
+ ## 1.0.0-next.0
308
+
309
+ ### Major Changes
310
+
311
+ - 1daf2c5: Forge is now generally available 🎉
312
+
313
+ ## 0.0.2
314
+
315
+ ### Patch Changes
316
+
317
+ - 843a703: Add forge-storage library
318
+
319
+ ## 0.0.2-next.0
320
+
321
+ ### Patch Changes
322
+
323
+ - 843a703: Add forge-storage library
324
+
325
+ ## 0.0.1
326
+
327
+ - First release
328
+ - Refactored from `forge-api` package
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const errors_1 = require("../errors");
4
4
  const global_storage_1 = require("../global-storage");
5
- const queries_1 = require("../queries");
5
+ const gql_queries_1 = require("../gql-queries");
6
6
  const contextAri = 'app-ari';
7
7
  const getStorage = (apiClientMock) => new global_storage_1.GlobalStorage(() => contextAri, apiClientMock);
8
8
  const getApiClientMock = (response, statusCode = 200) => {
@@ -128,13 +128,6 @@ describe('GlobalStorage', () => {
128
128
  expect(apiClientMock).toHaveBeenCalled();
129
129
  await expect(response).rejects.toThrow(errors_1.APIError.forErrorCode('CURSOR_INVALID', 'error message'));
130
130
  });
131
- it('should throw an error if the storage API returns a non 200 status code', async () => {
132
- const apiClientMock = getApiClientMock(undefined, 400);
133
- const globalStorage = getStorage(apiClientMock);
134
- const response = globalStorage.get('testKey');
135
- expect(apiClientMock).toHaveBeenCalled();
136
- await expect(response).rejects.toThrow(errors_1.APIError.forStatus(400));
137
- });
138
131
  it('should throw an error if the response is not a valid JSON', async () => {
139
132
  const apiClientMock = getApiClientMockInvalidJson('test', 200);
140
133
  const globalStorage = getStorage(apiClientMock);
@@ -319,6 +312,211 @@ describe('GlobalStorage', () => {
319
312
  });
320
313
  });
321
314
  });
315
+ describe('getEntity', () => {
316
+ it('should call the storage API, passing the provided entity name and entity key and returning the stored value', async () => {
317
+ const apiClientMock = getApiClientMock({
318
+ data: {
319
+ appStoredCustomEntity: {
320
+ value: 'testValue'
321
+ }
322
+ }
323
+ });
324
+ const globalStorage = getStorage(apiClientMock);
325
+ const returnedValue = await globalStorage.getEntity('testEntityName', 'testEntityKey');
326
+ verifyApiClientCalledWith(apiClientMock, {
327
+ contextAri,
328
+ entityName: 'testEntityName',
329
+ key: 'testEntityKey'
330
+ });
331
+ expect(returnedValue).toEqual('testValue');
332
+ });
333
+ it('should call the storage API, passing the provided entity key and returning undefined if the key doesnt exist', async () => {
334
+ const apiClientMock = getApiClientMock({
335
+ data: {
336
+ appStoredCustomEntity: {
337
+ value: null
338
+ }
339
+ }
340
+ });
341
+ const globalStorage = getStorage(apiClientMock);
342
+ const returnedValue = await globalStorage.getEntity('testEntityName', 'testEntityKey');
343
+ verifyApiClientCalledWith(apiClientMock, {
344
+ contextAri,
345
+ entityName: 'testEntityName',
346
+ key: 'testEntityKey'
347
+ });
348
+ expect(returnedValue).toEqual(undefined);
349
+ });
350
+ it('should call the storage API, passing the provided key and returning the stored falsey value 0', async () => {
351
+ const apiClientMock = getApiClientMock({
352
+ data: {
353
+ appStoredCustomEntity: {
354
+ value: 0
355
+ }
356
+ }
357
+ });
358
+ const globalStorage = getStorage(apiClientMock);
359
+ const returnedValue = await globalStorage.getEntity('testEntityName', 'testEntityKey');
360
+ verifyApiClientCalledWith(apiClientMock, {
361
+ contextAri,
362
+ entityName: 'testEntityName',
363
+ key: 'testEntityKey'
364
+ });
365
+ expect(returnedValue).toEqual(0);
366
+ });
367
+ it('should call the storage API, passing the provided key and returning the stored empty string', async () => {
368
+ const apiClientMock = getApiClientMock({
369
+ data: {
370
+ appStoredCustomEntity: {
371
+ value: ''
372
+ }
373
+ }
374
+ });
375
+ const globalStorage = getStorage(apiClientMock);
376
+ const returnedValue = await globalStorage.getEntity('testEntityName', 'testEntityKey');
377
+ verifyApiClientCalledWith(apiClientMock, {
378
+ contextAri,
379
+ entityName: 'testEntityName',
380
+ key: 'testEntityKey'
381
+ });
382
+ expect(returnedValue).toEqual('');
383
+ });
384
+ it('should throw an error with the returned status for non-200 status codes', async () => {
385
+ const apiClientMock = getApiClientMock(undefined, 400);
386
+ const globalStorage = getStorage(apiClientMock);
387
+ const response = globalStorage.getEntity('testEntityName', 'testEntityKey');
388
+ expect(apiClientMock).toHaveBeenCalled();
389
+ await expect(response).rejects.toThrow(errors_1.APIError.forStatus(400));
390
+ });
391
+ it('should throw an error with the returned error message for failed responses', async () => {
392
+ const apiClientMock = getApiClientMock({
393
+ errors: [INVALID_CURSOR_ERROR]
394
+ }, 200);
395
+ const globalStorage = getStorage(apiClientMock);
396
+ const response = globalStorage.getEntity('testEntityName', 'testEntityKey');
397
+ expect(apiClientMock).toHaveBeenCalled();
398
+ await expect(response).rejects.toThrow(errors_1.APIError.forErrorCode('CURSOR_INVALID', 'error message'));
399
+ });
400
+ it('should throw an error if the response is not a valid JSON', async () => {
401
+ const apiClientMock = getApiClientMockInvalidJson('test', 200);
402
+ const globalStorage = getStorage(apiClientMock);
403
+ const response = globalStorage.getEntity('testEntityName', 'testEntityKey');
404
+ expect(apiClientMock).toHaveBeenCalled();
405
+ await expect(response).rejects.toThrow(errors_1.APIError.forUnexpected('Response text was not a valid JSON: test'));
406
+ });
407
+ });
408
+ describe('setEntity', () => {
409
+ it('should call the storage API, passing the provided entity name, entity key and value', async () => {
410
+ const apiClientMock = getApiClientMock({
411
+ data: {
412
+ appStorageCustomEntity: {
413
+ setAppStoredCustomEntity: {
414
+ success: true
415
+ }
416
+ }
417
+ }
418
+ });
419
+ const globalStorage = getStorage(apiClientMock);
420
+ await globalStorage.setEntity('testEntityName', 'testEntityKey', 'testValue');
421
+ verifyApiClientCalledWith(apiClientMock, {
422
+ input: {
423
+ contextAri,
424
+ entityName: 'testEntityName',
425
+ key: 'testEntityKey',
426
+ value: 'testValue'
427
+ }
428
+ });
429
+ });
430
+ it('should throw an error if the storage API returns successful = false', async () => {
431
+ const apiClientMock = getApiClientMock({
432
+ data: {
433
+ appStorageCustomEntity: {
434
+ setAppStoredCustomEntity: {
435
+ success: false,
436
+ errors: [INVALID_CURSOR_ERROR]
437
+ }
438
+ }
439
+ }
440
+ });
441
+ const globalStorage = getStorage(apiClientMock);
442
+ const response = globalStorage.setEntity('testEntityName', 'testEntityKey', 'testValue');
443
+ expect(apiClientMock).toHaveBeenCalled();
444
+ await expect(response).rejects.toThrow(errors_1.APIError.forErrorCode('INVALID_CURSOR', 'error message'));
445
+ });
446
+ it('should throw an error if the storage API returns a non 200 status code', async () => {
447
+ const apiClientMock = getApiClientMockInvalidJson('', 400);
448
+ const globalStorage = getStorage(apiClientMock);
449
+ const response = globalStorage.setEntity('testEntityName', 'testEntityKey', 'testValue');
450
+ expect(apiClientMock).toHaveBeenCalled();
451
+ await expect(response).rejects.toThrow(errors_1.APIError.forStatus(400));
452
+ });
453
+ it('should throw a 500 error if success=false but no errors were returned', async () => {
454
+ const apiClientMock = getApiClientMock({
455
+ data: {
456
+ appStorageCustomEntity: {
457
+ setAppStoredCustomEntity: {
458
+ success: false
459
+ }
460
+ }
461
+ }
462
+ });
463
+ const globalStorage = getStorage(apiClientMock);
464
+ await expect(globalStorage.setEntity('testEntityName', 'testEntityKey', 'testValue')).rejects.toThrow(errors_1.APIError.forStatus(500));
465
+ verifyApiClientCalledWith(apiClientMock, {
466
+ input: {
467
+ contextAri,
468
+ entityName: 'testEntityName',
469
+ key: 'testEntityKey',
470
+ value: 'testValue'
471
+ }
472
+ });
473
+ });
474
+ });
475
+ describe('deleteEntity', () => {
476
+ it('should call the storage API, passing the provided entity name and key', async () => {
477
+ const apiClientMock = getApiClientMock({
478
+ data: {
479
+ appStorageCustomEntity: {
480
+ deleteAppStoredCustomEntity: {
481
+ success: true
482
+ }
483
+ }
484
+ }
485
+ });
486
+ const globalStorage = getStorage(apiClientMock);
487
+ await globalStorage.deleteEntity('testEntityName', 'testEntityKey');
488
+ verifyApiClientCalledWith(apiClientMock, {
489
+ input: {
490
+ contextAri,
491
+ entityName: 'testEntityName',
492
+ key: 'testEntityKey'
493
+ }
494
+ });
495
+ });
496
+ it('should throw an error if the storage API returns successful = false', async () => {
497
+ const apiClientMock = getApiClientMock({
498
+ data: {
499
+ appStorageCustomEntity: {
500
+ deleteAppStoredCustomEntity: {
501
+ success: false,
502
+ errors: [INVALID_CURSOR_ERROR]
503
+ }
504
+ }
505
+ }
506
+ });
507
+ const globalStorage = getStorage(apiClientMock);
508
+ const response = globalStorage.deleteEntity('testEntityKey', 'testEntityKey');
509
+ expect(apiClientMock).toHaveBeenCalled();
510
+ await expect(response).rejects.toThrow(errors_1.APIError.forErrorCode('CURSOR_INVALID', 'error message'));
511
+ });
512
+ it('should throw an error if the storage API returns a non 200 status code and has no body', async () => {
513
+ const apiClientMock = getApiClientMockInvalidJson('', 400);
514
+ const globalStorage = getStorage(apiClientMock);
515
+ const response = globalStorage.deleteEntity('testEntityKey', 'testEntityKey');
516
+ expect(apiClientMock).toHaveBeenCalled();
517
+ await expect(response).rejects.toThrow(errors_1.APIError.forStatus(400));
518
+ });
519
+ });
322
520
  describe('list', () => {
323
521
  it('should call the storage API with the provided parameters', async () => {
324
522
  const apiClientMock = getApiClientMock({
@@ -347,7 +545,7 @@ describe('GlobalStorage', () => {
347
545
  where,
348
546
  cursor,
349
547
  limit
350
- }, (0, queries_1.listQuery)(contextAri, {}).query);
548
+ }, gql_queries_1.UntypedQueries.listQuery(contextAri, {}).query);
351
549
  expect(response).toEqual(expect.objectContaining({
352
550
  results: [
353
551
  { key: 'key1', value: 'testValue' },
@@ -384,7 +582,7 @@ describe('GlobalStorage', () => {
384
582
  where,
385
583
  cursor,
386
584
  limit
387
- }, (0, queries_1.listQueryForCleanup)(contextAri, {}).query);
585
+ }, gql_queries_1.UntypedQueries.listQueryForCleanup(contextAri, {}).query);
388
586
  expect(response).toEqual(expect.objectContaining({
389
587
  results: [
390
588
  { key: 'key1', value: 'testValue' },
@@ -409,7 +607,7 @@ describe('GlobalStorage', () => {
409
607
  where: null,
410
608
  cursor: null,
411
609
  limit: null
412
- }, (0, queries_1.listQuery)(contextAri, {}).query);
610
+ }, gql_queries_1.UntypedQueries.listQuery(contextAri, {}).query);
413
611
  });
414
612
  it('should handle an empty result set', async () => {
415
613
  const apiClientMock = getApiClientMock({