1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.Resource = void 0;
|
4 | const state_1 = require("./state");
|
5 | const uri_1 = require("./util/uri");
|
6 | const follow_promise_1 = require("./follow-promise");
|
7 | const link_1 = require("./link");
|
8 | const events_1 = require("events");
|
9 | const fetch_body_helper_1 = require("./util/fetch-body-helper");
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | class Resource extends events_1.EventEmitter {
|
17 | |
18 |
|
19 |
|
20 |
|
21 |
|
22 | constructor(client, uri) {
|
23 | super();
|
24 | this.client = client;
|
25 | this.uri = uri;
|
26 | this.activeRefresh = null;
|
27 | }
|
28 | |
29 |
|
30 |
|
31 |
|
32 |
|
33 | get(getOptions) {
|
34 | const state = this.client.cache.get(this.uri);
|
35 | if (!state) {
|
36 | return this.refresh(getOptions);
|
37 | }
|
38 | return Promise.resolve(state);
|
39 | }
|
40 | |
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 | async head(headOptions) {
|
47 | let state = this.client.cache.get(this.uri);
|
48 | if (state) {
|
49 | return state;
|
50 | }
|
51 | const response = await this.fetchOrThrow(optionsToRequestInit('HEAD', headOptions));
|
52 | state = await state_1.headStateFactory(this.uri, response);
|
53 | return state;
|
54 | }
|
55 | |
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 | refresh(getOptions) {
|
62 | const params = {
|
63 | cache: 'reload',
|
64 | };
|
65 | if ((getOptions === null || getOptions === void 0 ? void 0 : getOptions.getContentHeaders) && !(getOptions === null || getOptions === void 0 ? void 0 : getOptions.headers)) {
|
66 | params.headers = getOptions.getContentHeaders();
|
67 | }
|
68 | else if (!(getOptions === null || getOptions === void 0 ? void 0 : getOptions.getContentHeaders) && (getOptions === null || getOptions === void 0 ? void 0 : getOptions.headers)) {
|
69 | params.headers = getOptions.headers;
|
70 | }
|
71 | else if ((getOptions === null || getOptions === void 0 ? void 0 : getOptions.getContentHeaders) && (getOptions === null || getOptions === void 0 ? void 0 : getOptions.headers)) {
|
72 | params.headers = getOptions.getContentHeaders();
|
73 | params.headers = Object.assign(Object.assign({}, getOptions.headers), params.headers);
|
74 | }
|
75 | if (!this.activeRefresh) {
|
76 | this.activeRefresh = (async () => {
|
77 | try {
|
78 | const response = await this.fetchOrThrow(params);
|
79 | const state = await this.client.getStateForResponse(this.uri, response);
|
80 | this.updateCache(state);
|
81 | return state;
|
82 | }
|
83 | finally {
|
84 | this.activeRefresh = null;
|
85 | }
|
86 | })();
|
87 | }
|
88 | return this.activeRefresh;
|
89 | }
|
90 | |
91 |
|
92 |
|
93 | async put(options) {
|
94 | const requestInit = optionsToRequestInit('PUT', options);
|
95 | |
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 | if (state_1.isState(options)) {
|
104 | requestInit.headers.set('X-KETTING-NO-STALE', '1');
|
105 | }
|
106 | await this.fetchOrThrow(requestInit);
|
107 | if (state_1.isState(options)) {
|
108 | this.updateCache(options);
|
109 | }
|
110 | }
|
111 | |
112 |
|
113 |
|
114 | async delete() {
|
115 | await this.fetchOrThrow({ method: 'DELETE' });
|
116 | }
|
117 | |
118 |
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 | async post(options) {
|
126 | const response = await this.fetchOrThrow(optionsToRequestInit('POST', options));
|
127 | return this.client.getStateForResponse(this.uri, response);
|
128 | }
|
129 | |
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 |
|
136 |
|
137 |
|
138 | async postFollow(options) {
|
139 | const response = await this.fetchOrThrow(optionsToRequestInit('POST', options));
|
140 | switch (response.status) {
|
141 | case 201:
|
142 | if (response.headers.has('location')) {
|
143 | return this.go(response.headers.get('location'));
|
144 | }
|
145 | throw new Error('Could not follow after a 201 request, because the server did not reply with a Location header');
|
146 | case 204:
|
147 | case 205:
|
148 | return this;
|
149 | default:
|
150 | throw new Error('Did not receive a 201, 204 or 205 status code so we could not follow to the next resource');
|
151 | }
|
152 | }
|
153 | |
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 | async patch(options) {
|
161 | const response = await this.fetchOrThrow(optionsToRequestInit('PATCH', options));
|
162 | if (response.status === 200) {
|
163 | return await this.client.getStateForResponse(this.uri, response);
|
164 | }
|
165 | }
|
166 | |
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 | follow(rel, variables) {
|
174 | return new follow_promise_1.FollowPromiseOne(this, rel, variables);
|
175 | }
|
176 | |
177 |
|
178 |
|
179 |
|
180 |
|
181 |
|
182 | followAll(rel) {
|
183 | return new follow_promise_1.FollowPromiseMany(this, rel);
|
184 | }
|
185 | |
186 |
|
187 |
|
188 |
|
189 |
|
190 |
|
191 |
|
192 |
|
193 | go(uri) {
|
194 | uri = uri_1.resolve(this.uri, uri);
|
195 | return this.client.go(uri);
|
196 | }
|
197 | |
198 |
|
199 |
|
200 | fetch(init) {
|
201 | return this.client.fetcher.fetch(this.uri, init);
|
202 | }
|
203 | |
204 |
|
205 |
|
206 |
|
207 |
|
208 |
|
209 | fetchOrThrow(init) {
|
210 | return this.client.fetcher.fetchOrThrow(this.uri, init);
|
211 | }
|
212 | |
213 |
|
214 |
|
215 |
|
216 |
|
217 | updateCache(state) {
|
218 | if (state.uri !== this.uri) {
|
219 | throw new Error('When calling updateCache on a resource, the uri of the State object must match the uri of the Resource');
|
220 | }
|
221 | this.client.cacheState(state);
|
222 | }
|
223 | |
224 |
|
225 |
|
226 | clearCache() {
|
227 | this.client.cache.delete(this.uri);
|
228 | }
|
229 | |
230 |
|
231 |
|
232 |
|
233 |
|
234 |
|
235 |
|
236 | async link(rel) {
|
237 | const state = await this.get();
|
238 | const link = state.links.get(rel);
|
239 | if (!link) {
|
240 | throw new link_1.LinkNotFound(`Link with rel: ${rel} not found on ${this.uri}`);
|
241 | }
|
242 | return link;
|
243 | }
|
244 | |
245 |
|
246 |
|
247 |
|
248 |
|
249 | async links(rel) {
|
250 | const state = await this.get();
|
251 | if (!rel) {
|
252 | return state.links.getAll();
|
253 | }
|
254 | else {
|
255 | return state.links.getMany(rel);
|
256 | }
|
257 | }
|
258 | |
259 |
|
260 |
|
261 |
|
262 |
|
263 |
|
264 |
|
265 | async hasLink(rel) {
|
266 | const state = await this.get();
|
267 | return state.links.has(rel);
|
268 | }
|
269 | }
|
270 | exports.Resource = Resource;
|
271 | exports.default = Resource;
|
272 | function optionsToRequestInit(method, options) {
|
273 | if (!options) {
|
274 | return {
|
275 | method,
|
276 | headers: new Headers(),
|
277 | };
|
278 | }
|
279 | let headers;
|
280 | if (options.getContentHeaders) {
|
281 | headers = new Headers(options.getContentHeaders());
|
282 | }
|
283 | else if (options.headers) {
|
284 | headers = new Headers(options.headers);
|
285 | }
|
286 | else {
|
287 | headers = new Headers();
|
288 | }
|
289 | if (!headers.has('Content-Type')) {
|
290 | headers.set('Content-Type', 'application/json');
|
291 | }
|
292 | let body;
|
293 | if (options.serializeBody !== undefined) {
|
294 | body = options.serializeBody();
|
295 | }
|
296 | else if (options.data) {
|
297 | body = options.data;
|
298 | if (fetch_body_helper_1.needsJsonStringify(body)) {
|
299 | body = JSON.stringify(body);
|
300 | }
|
301 | }
|
302 | else {
|
303 | body = null;
|
304 | }
|
305 | return {
|
306 | method,
|
307 | body,
|
308 | headers,
|
309 | };
|
310 | }
|
311 |
|
\ | No newline at end of file |