ketting 7.2.0 → 7.3.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.
Files changed (51) hide show
  1. package/LICENSE +1 -1
  2. package/browser/ketting.min.js +1 -1
  3. package/browser/ketting.min.js.map +1 -1
  4. package/dist/client.d.ts +24 -4
  5. package/dist/client.js +96 -29
  6. package/dist/client.js.map +1 -1
  7. package/dist/http/fetcher.js +1 -1
  8. package/dist/http/fetcher.js.map +1 -1
  9. package/dist/link.js +2 -2
  10. package/dist/link.js.map +1 -1
  11. package/dist/middlewares/cache.js +20 -44
  12. package/dist/middlewares/cache.js.map +1 -1
  13. package/dist/middlewares/warning.js +1 -1
  14. package/dist/middlewares/warning.js.map +1 -1
  15. package/dist/resource.js +6 -6
  16. package/dist/resource.js.map +1 -1
  17. package/dist/src/client.d.ts +24 -4
  18. package/dist/state/base-state.js +3 -3
  19. package/dist/state/base-state.js.map +1 -1
  20. package/dist/state/binary.js +1 -1
  21. package/dist/state/binary.js.map +1 -1
  22. package/dist/state/collection-json.js +1 -1
  23. package/dist/state/collection-json.js.map +1 -1
  24. package/dist/state/hal.js +8 -6
  25. package/dist/state/hal.js.map +1 -1
  26. package/dist/state/head.js +1 -1
  27. package/dist/state/head.js.map +1 -1
  28. package/dist/state/html.js +3 -3
  29. package/dist/state/html.js.map +1 -1
  30. package/dist/state/jsonapi.js +1 -1
  31. package/dist/state/jsonapi.js.map +1 -1
  32. package/dist/state/siren.js +3 -3
  33. package/dist/state/siren.js.map +1 -1
  34. package/dist/state/text.js +1 -1
  35. package/dist/state/text.js.map +1 -1
  36. package/dist/util/html.js +2 -2
  37. package/dist/util/html.js.map +1 -1
  38. package/dist/util/html.web.js +2 -2
  39. package/dist/util/html.web.js.map +1 -1
  40. package/dist/util/uri-template.js +1 -1
  41. package/dist/util/uri-template.js.map +1 -1
  42. package/dist/util/uri.js +3 -3
  43. package/dist/util/uri.js.map +1 -1
  44. package/package.json +8 -7
  45. package/src/action.ts +1 -1
  46. package/src/client.ts +118 -33
  47. package/src/http/fetcher.ts +1 -1
  48. package/src/link.ts +1 -1
  49. package/src/middlewares/cache.ts +18 -49
  50. package/src/resource.ts +1 -1
  51. package/src/state/hal.ts +4 -3
@@ -15,8 +15,6 @@ import Client from '../client';
15
15
  */
16
16
  export default function(client: Client): FetchMiddleware {
17
17
 
18
- const cacheDependencies: Map<string, Set<string>> = new Map();
19
-
20
18
  return async(request, next) => {
21
19
 
22
20
  /**
@@ -38,10 +36,10 @@ export default function(client: Client): FetchMiddleware {
38
36
  if (response.headers.has('Link')) {
39
37
  for (const httpLink of LinkHeader.parse(response.headers.get('Link')!).rel('inv-by')) {
40
38
  const uri = resolve(request.url, httpLink.uri);
41
- if (cacheDependencies.has(uri)) {
42
- cacheDependencies.get(uri)!.add(request.url);
39
+ if (client.cacheDependencies.has(uri)) {
40
+ client.cacheDependencies.get(uri)!.add(request.url);
43
41
  } else {
44
- cacheDependencies.set(uri, new Set([request.url]));
42
+ client.cacheDependencies.set(uri, new Set([request.url]));
45
43
  }
46
44
  }
47
45
  }
@@ -57,10 +55,13 @@ export default function(client: Client): FetchMiddleware {
57
55
  }
58
56
 
59
57
  // We just processed an unsafe method, lets notify all subsystems.
60
- let expireUris = new Set<string>();
61
- if (!noStaleEvent && request.method !== 'DELETE') {
62
- // Sorry for the double negative
63
- expireUris.add(request.url);
58
+ const stale = [];
59
+ const deleted = [];
60
+
61
+ if (request.method === 'DELETE') {
62
+ deleted.push(request.url);
63
+ } else if (!noStaleEvent) {
64
+ stale.push(request.url);
64
65
  }
65
66
 
66
67
  // If the response had a Link: rel=invalidate header, we want to
@@ -68,17 +69,22 @@ export default function(client: Client): FetchMiddleware {
68
69
  if (response.headers.has('Link')) {
69
70
  for (const httpLink of LinkHeader.parse(response.headers.get('Link')!).rel('invalidates')) {
70
71
  const uri = resolve(request.url, httpLink.uri);
71
- expireUris.add(uri);
72
+ stale.push(uri);
72
73
  }
73
74
  }
74
75
 
75
76
  // Location headers should also expire
76
77
  if (response.headers.has('Location')) {
77
- expireUris.add(
78
+ stale.push(
78
79
  resolve(request.url, response.headers.get('Location')!)
79
80
  );
80
81
  }
81
- // Content-Location headers should also expire
82
+
83
+ client.clearResourceCache(stale, deleted);
84
+
85
+ // If the response had a 'Content-Location' header, it means that the
86
+ // response body is the _new_ state for the url in the content-location
87
+ // header, so we store it!
82
88
  if (response.headers.has('Content-Location')) {
83
89
  const cl = resolve(request.url, response.headers.get('Content-Location')!);
84
90
  const clState = await client.getStateForResponse(
@@ -88,45 +94,8 @@ export default function(client: Client): FetchMiddleware {
88
94
  client.cacheState(clState);
89
95
  }
90
96
 
91
- expireUris = expandCacheDependencies(expireUris, cacheDependencies);
92
- for (const uri of expireUris) {
93
- client.cache.delete(uri);
94
-
95
- const resource = client.resources.get(uri);
96
- if (resource) {
97
- // We have a resource for this object, notify it as well.
98
- resource.emit('stale');
99
- }
100
- }
101
- if (request.method === 'DELETE') {
102
- client.cache.delete(request.url);
103
- const resource = client.resources.get(request.url);
104
- if (resource) {
105
- resource.emit('delete');
106
- }
107
- }
108
-
109
97
  return response;
110
98
 
111
99
  };
112
100
 
113
101
  }
114
-
115
- function expandCacheDependencies(uris: Set<string>, dependencies: Map<string, Set<string>>, output?: Set<string>): Set<string> {
116
-
117
- if (!output) output = new Set();
118
-
119
- for(const uri of uris) {
120
-
121
- if (!output.has(uri)) {
122
- output.add(uri);
123
- if (dependencies.has(uri)) {
124
- expandCacheDependencies(dependencies.get(uri)!, dependencies, output);
125
- }
126
- }
127
-
128
- }
129
-
130
- return output;
131
-
132
- }
package/src/resource.ts CHANGED
@@ -307,7 +307,7 @@ export class Resource<T = any> extends EventEmitter {
307
307
  */
308
308
  clearCache(): void {
309
309
 
310
- this.client.cache.delete(this.uri);
310
+ this.client.clearResourceCache([this.uri],[]);
311
311
 
312
312
  }
313
313
 
package/src/state/hal.ts CHANGED
@@ -204,7 +204,7 @@ function parseHalLink(context: string, rel: string, links: hal.HalLink[]): Link[
204
204
  */
205
205
  function parseHalEmbedded(client: Client, context: string, body: hal.HalResource, headers: Headers): HalState<any>[] {
206
206
 
207
- if (body._embedded === undefined) {
207
+ if (body._embedded === undefined || !body._embedded) {
208
208
  return [];
209
209
  }
210
210
 
@@ -222,8 +222,9 @@ function parseHalEmbedded(client: Client, context: string, body: hal.HalResource
222
222
  }
223
223
  for (const embeddedItem of embeddedList) {
224
224
 
225
- if (embeddedItem._links === undefined || embeddedItem._links.self === undefined || Array.isArray(embeddedItem._links.self)) {
226
- // Skip any embedded without a self link.
225
+ if (embeddedItem._links?.self?.href === undefined) {
226
+ // eslint-disable-next-line no-console
227
+ console.warn('An item in _embedded was ignored. Each item must have a single "self" link');
227
228
  continue;
228
229
  }
229
230