@podium/client 5.0.19 → 5.0.21

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 CHANGED
@@ -1,3 +1,18 @@
1
+ ## [5.0.21](https://github.com/podium-lib/client/compare/v5.0.20...v5.0.21) (2024-05-14)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * export same types as before ([0e3c65a](https://github.com/podium-lib/client/commit/0e3c65afc0fef7e6c53ad544dc80cb7f8dc8596b))
7
+ * generate types from JSDoc ([32cac7e](https://github.com/podium-lib/client/commit/32cac7e10a76494c0d2df602f41d42a67e8e7b6c))
8
+
9
+ ## [5.0.20](https://github.com/podium-lib/client/compare/v5.0.19...v5.0.20) (2024-05-14)
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * **deps:** update dependency @podium/schemas to v5.0.2 ([e8e2fb4](https://github.com/podium-lib/client/commit/e8e2fb45e00be74222fa19e1faba1f29829976e8))
15
+
1
16
  ## [5.0.19](https://github.com/podium-lib/client/compare/v5.0.18...v5.0.19) (2024-05-13)
2
17
 
3
18
 
package/lib/client.js CHANGED
@@ -1,16 +1,17 @@
1
1
  import EventEmitter from 'events';
2
- import {uriStrict as validateUriStrict, name as validateName } from'@podium/schemas';
2
+ import {
3
+ uriStrict as validateUriStrict,
4
+ name as validateName,
5
+ } from '@podium/schemas';
3
6
  import Metrics from '@metrics/client';
4
7
  import abslog from 'abslog';
5
8
  import Cache from 'ttl-mem-cache';
6
9
  import http from 'http';
7
10
  import https from 'https';
8
-
9
11
  import Resource from './resource.js';
10
12
  import State from './state.js';
11
13
 
12
14
  const inspect = Symbol.for('nodejs.util.inspect.custom');
13
-
14
15
  const HTTP_AGENT_OPTIONS = {
15
16
  keepAlive: true,
16
17
  maxSockets: 10,
@@ -18,24 +19,49 @@ const HTTP_AGENT_OPTIONS = {
18
19
  timeout: 60000,
19
20
  keepAliveMsecs: 30000,
20
21
  };
21
-
22
22
  const HTTPS_AGENT_OPTIONS = {
23
23
  ...HTTP_AGENT_OPTIONS,
24
24
  maxCachedSessions: 10,
25
25
  };
26
-
27
26
  const REJECT_UNAUTHORIZED = true;
28
-
29
27
  const HTTP_AGENT = new http.Agent(HTTP_AGENT_OPTIONS);
30
-
31
28
  const HTTPS_AGENT = new https.Agent(HTTPS_AGENT_OPTIONS);
32
-
33
29
  const RETRIES = 4;
34
-
35
30
  const TIMEOUT = 1000; // 1 seconds
36
-
37
31
  const MAX_AGE = Infinity;
38
32
 
33
+ /**
34
+ * @typedef {import('./resource.js').default} PodiumClientResource
35
+ * @typedef {import('./resource.js').PodiumClientResourceOptions} PodiumClientResourceOptions
36
+ * @typedef {import('./response.js').default} PodiumClientResponse
37
+ * @typedef {import('./http-outgoing.js').PodiumRedirect} PodiumRedirect
38
+ * @typedef {import('@podium/schemas').PodletManifestSchema} PodletManifest
39
+ */
40
+
41
+ /**
42
+ * @typedef {object} PodiumClientOptions
43
+ * @property {string} name
44
+ * @property {import('abslog').AbstractLoggerOptions} [logger]
45
+ * @property {number} [retries=4]
46
+ * @property {number} [timeout=1000] In milliseconds
47
+ * @property {number} [maxAge=Infinity]
48
+ * @property {boolean} [rejectUnauthorized=true]
49
+ * @property {number} [resolveThreshold]
50
+ * @property {number} [resolveMax]
51
+ * @property {import('http').Agent} [httpAgent]
52
+ * @property {import('https').Agent} [httpsAgent]
53
+ */
54
+
55
+ /**
56
+ * @typedef {object} RegisterOptions
57
+ * @property {string} name A unique name for the podlet
58
+ * @property {string} uri URL to the podlet's `manifest.json`
59
+ * @property {number} [retries=4] Number of retries before serving fallback
60
+ * @property {number} [timeout=1000] In milliseconds, the amount of time to wait before serving fallback.
61
+ * @property {boolean} [throwable=false] Set to `true` and surround `fetch` in `try/catch` to serve different content in case podlet is unavailable. Will not server fallback content.
62
+ * @property {boolean} [redirectable=false] Set to `true` to allow podlet to respond with a redirect. You need to look for the redirect response from the podlet and return a redirect response to the browser yourself.
63
+ */
64
+
39
65
  export default class PodiumClient extends EventEmitter {
40
66
  #resources;
41
67
  #registry;
@@ -43,6 +69,12 @@ export default class PodiumClient extends EventEmitter {
43
69
  #histogram;
44
70
  #options;
45
71
  #state;
72
+
73
+ /**
74
+ * @constructor
75
+ * @param {PodiumClientOptions} options
76
+ */
77
+ // @ts-expect-error Deliberate default empty options for better error messages
46
78
  constructor(options = {}) {
47
79
  super();
48
80
  const log = abslog(options.logger);
@@ -69,7 +101,7 @@ export default class PodiumClient extends EventEmitter {
69
101
  resolveThreshold: options.resolveThreshold,
70
102
  resolveMax: options.resolveMax,
71
103
  });
72
- this.#state.on('state', state => {
104
+ this.#state.on('state', (state) => {
73
105
  this.emit('state', state);
74
106
  });
75
107
 
@@ -79,7 +111,7 @@ export default class PodiumClient extends EventEmitter {
79
111
  changefeed: true,
80
112
  ttl: options.maxAge,
81
113
  });
82
- this.#registry.on('error', error => {
114
+ this.#registry.on('error', (error) => {
83
115
  log.error(
84
116
  'Error emitted by the registry in @podium/client module',
85
117
  error,
@@ -91,7 +123,7 @@ export default class PodiumClient extends EventEmitter {
91
123
  });
92
124
 
93
125
  this.#metrics = new Metrics();
94
- this.#metrics.on('error', error => {
126
+ this.#metrics.on('error', (error) => {
95
127
  log.error(
96
128
  'Error emitted by metric stream in @podium/client module',
97
129
  error,
@@ -99,7 +131,7 @@ export default class PodiumClient extends EventEmitter {
99
131
  });
100
132
 
101
133
  this[Symbol.iterator] = () => ({
102
- items: Array.from(this.#resources).map(item => item[1]),
134
+ items: Array.from(this.#resources).map((item) => item[1]),
103
135
  next: function next() {
104
136
  return {
105
137
  done: this.items.length === 0,
@@ -128,7 +160,21 @@ export default class PodiumClient extends EventEmitter {
128
160
  return this.#state.status;
129
161
  }
130
162
 
131
- register(options = {}) {
163
+ /**
164
+ * Register a podlet so you can fetch its contents later with {@link PodiumClientResource.fetch}.
165
+ *
166
+ * @param {RegisterOptions} options
167
+ * @returns {PodiumClientResource}
168
+ *
169
+ * @example
170
+ * ```js
171
+ * const headerPodlet = layout.client.register({
172
+ * name: 'header',
173
+ * uri: 'http://header/manifest.json',
174
+ * });
175
+ * ```
176
+ */
177
+ register(options) {
132
178
  if (validateName(options.name).error)
133
179
  throw new Error(
134
180
  `The value, "${options.name}", for the required argument "name" on the .register() method is not defined or not valid.`,
@@ -183,12 +229,17 @@ export default class PodiumClient extends EventEmitter {
183
229
  return this.#registry.load(dump);
184
230
  }
185
231
 
232
+ /**
233
+ * Refreshes the cached podlet manifest for all {@link register}ed podlets.
234
+ */
186
235
  async refreshManifests() {
187
236
  const end = this.#histogram.timer();
188
237
 
189
238
  // Don't return this
190
239
  await Promise.all(
191
- Array.from(this.#resources).map(resource => resource[1].refresh()),
240
+ Array.from(this.#resources).map((resource) =>
241
+ resource[1].refresh(),
242
+ ),
192
243
  );
193
244
 
194
245
  end();
@@ -204,4 +255,4 @@ export default class PodiumClient extends EventEmitter {
204
255
  get [Symbol.toStringTag]() {
205
256
  return 'PodiumClient';
206
257
  }
207
- };
258
+ }
@@ -3,26 +3,84 @@
3
3
  import { PassThrough } from 'stream';
4
4
  import assert from 'assert';
5
5
 
6
+ /**
7
+ * @typedef {object} PodiumClientHttpOutgoingOptions
8
+ * @property {string} name
9
+ * @property {string} uri To the podlet's `manifest.json`
10
+ * @property {number} timeout In milliseconds
11
+ * @property {number} maxAge
12
+ * @property {number} [retries=4]
13
+ * @property {boolean} [throwable=false]
14
+ * @property {boolean} [redirectable=false]
15
+ * @property {boolean} [rejectUnauthorized=true]
16
+ * @property {import('http').Agent} [httpAgent]
17
+ * @property {import('https').Agent} [httpsAgent]
18
+ */
19
+
20
+ /**
21
+ * @typedef {object} PodiumClientResourceOptions
22
+ * @property {string} [pathname]
23
+ * @property {import('http').IncomingHttpHeaders} [headers]
24
+ * @property {object} [query]
25
+ */
26
+
27
+ /**
28
+ * @typedef {object} PodiumRedirect
29
+ * @property {number} statusCode;
30
+ * @property {string} location;
31
+ */
32
+
33
+ /**
34
+ * @typedef {object} PodletProxySchema
35
+ * @property {string} target
36
+ * @property {string} name
37
+ */
38
+
39
+ /**
40
+ * @typedef {object} PodletManifest Similar to the schema's manifest, but with instances of AssetCss and AssetJs from `@podium/utils` and default values.
41
+ * @property {string} name
42
+ * @property {string} version
43
+ * @property {string} content
44
+ * @property {string} fallback
45
+ * @property {Array<import('@podium/utils').AssetJs>} js
46
+ * @property {Array<import('@podium/utils').AssetCss>} css
47
+ * @property {Record<string, string> | Array<PodletProxySchema>} proxy
48
+ * @property {string} team
49
+ */
50
+
6
51
  export default class PodletClientHttpOutgoing extends PassThrough {
7
52
  #rejectUnauthorized;
8
53
  #killRecursions;
9
54
  #killThreshold;
10
55
  #redirectable;
11
56
  #reqOptions;
12
- #isFallback;
57
+ #isFallback = false;
13
58
  #throwable;
59
+ /** @type {PodletManifest} */
14
60
  #manifest;
15
61
  #incoming;
16
- #redirect;
62
+ /** @type {null | PodiumRedirect} */
63
+ #redirect = null;
17
64
  #timeout;
18
65
  #success;
19
66
  #headers;
20
67
  #maxAge;
68
+ /** @type {'empty' | 'fresh' | 'cached' | 'stale'} */
21
69
  #status;
22
70
  #name;
23
- #uri;
24
- constructor(
25
- {
71
+ #uri;
72
+
73
+ /**
74
+ * @constructor
75
+ * @param {PodiumClientHttpOutgoingOptions} options
76
+ * @param {PodiumClientResourceOptions} [reqOptions]
77
+ * @param {import('@podium/utils').HttpIncoming} [incoming]
78
+ */
79
+ // @ts-expect-error Deliberate default empty options for better error messages
80
+ constructor(options = {}, reqOptions, incoming) {
81
+ super();
82
+
83
+ const {
26
84
  rejectUnauthorized = true,
27
85
  throwable = false,
28
86
  redirectable = false,
@@ -31,11 +89,7 @@ export default class PodletClientHttpOutgoing extends PassThrough {
31
89
  maxAge,
32
90
  name = '',
33
91
  uri,
34
- } = {},
35
- reqOptions,
36
- incoming,
37
- ) {
38
- super();
92
+ } = options;
39
93
 
40
94
  assert(
41
95
  uri,
@@ -45,7 +99,6 @@ export default class PodletClientHttpOutgoing extends PassThrough {
45
99
  // If requests to https sites should reject on unsigned sertificates
46
100
  this.#rejectUnauthorized = rejectUnauthorized;
47
101
 
48
- // A HttpIncoming object
49
102
  this.#incoming = incoming;
50
103
 
51
104
  // Kill switch for breaking the recursive promise chain
@@ -67,6 +120,7 @@ export default class PodletClientHttpOutgoing extends PassThrough {
67
120
  // Manifest which is either retrieved from the registry or
68
121
  // remote podlet (in other words its not saved in registry yet)
69
122
  this.#manifest = {
123
+ // @ts-expect-error Internal property
70
124
  _fallback: '',
71
125
  };
72
126
 
@@ -82,14 +136,6 @@ export default class PodletClientHttpOutgoing extends PassThrough {
82
136
  // How long the manifest should be cached before refetched
83
137
  this.#maxAge = maxAge;
84
138
 
85
- // What status the manifest is in. This is used to tell what actions need to
86
- // be performed throughout the resolving process to complete a request.
87
- //
88
- // The different statuses can be:
89
- // "empty" - there is no manifest available - we are in process of fetching it
90
- // "fresh" - the manifest has been fetched but is not stored in cache yet
91
- // "cached" - the manifest was retrieved from cache
92
- // "stale" - the manifest is outdated, a new manifest needs to be fetched
93
139
  this.#status = 'empty';
94
140
 
95
141
  // Name of the resource (name given to client)
@@ -100,13 +146,6 @@ export default class PodletClientHttpOutgoing extends PassThrough {
100
146
 
101
147
  // Whether the user can handle redirects manually.
102
148
  this.#redirectable = redirectable;
103
-
104
- // When redirectable is true, this object should be populated with redirect information
105
- // such that a user can perform manual redirection
106
- this.#redirect = null;
107
-
108
- // When isfallback is true, content fetch has failed and fallback will be served instead
109
- this.#isFallback = false;
110
149
  }
111
150
 
112
151
  get rejectUnauthorized() {
@@ -130,10 +169,12 @@ export default class PodletClientHttpOutgoing extends PassThrough {
130
169
  }
131
170
 
132
171
  get fallback() {
172
+ // @ts-expect-error Internal property
133
173
  return this.#manifest._fallback;
134
174
  }
135
175
 
136
176
  set fallback(value) {
177
+ // @ts-expect-error Internal property
137
178
  this.#manifest._fallback = value;
138
179
  }
139
180
 
@@ -169,6 +210,16 @@ export default class PodletClientHttpOutgoing extends PassThrough {
169
210
  this.#maxAge = value;
170
211
  }
171
212
 
213
+ /**
214
+ * What status the manifest is in. This is used to tell what actions need to
215
+ * be performed throughout the resolving process to complete a request.
216
+ *
217
+ * The different statuses can be:
218
+ * - `"empty"` - there is no manifest available - we are in process of fetching it
219
+ * - `"fresh"` - the manifest has been fetched but is not stored in cache yet
220
+ * - `"cached"` - the manifest was retrieved from cache
221
+ * - `"stale"` - the manifest is outdated, a new manifest needs to be fetched
222
+ */
172
223
  get status() {
173
224
  return this.#status;
174
225
  }
@@ -193,18 +244,33 @@ export default class PodletClientHttpOutgoing extends PassThrough {
193
244
  return this.#manifest.content;
194
245
  }
195
246
 
247
+ /**
248
+ * Kill switch for breaking the recursive promise chain in case it is never able to completely resolve.
249
+ * This is true if the number of recursions matches the threshold.
250
+ */
196
251
  get kill() {
197
252
  return this.#killRecursions === this.#killThreshold;
198
253
  }
199
254
 
255
+ /**
256
+ * The number of recursions before the request should be {@link kill}ed
257
+ */
200
258
  get recursions() {
201
259
  return this.#killRecursions;
202
260
  }
203
261
 
262
+ /**
263
+ * Set the number of recursions before the request should be {@link kill}ed
264
+ */
204
265
  set recursions(value) {
205
266
  this.#killRecursions = value;
206
267
  }
207
268
 
269
+ /**
270
+ * When {@link redirectable} is `true` this is populated with redirect information so you can send a redirect response to the browser from your layout.
271
+ *
272
+ * @see https://podium-lib.io/docs/layout/handling_redirects
273
+ */
208
274
  get redirect() {
209
275
  return this.#redirect;
210
276
  }
@@ -213,6 +279,11 @@ export default class PodletClientHttpOutgoing extends PassThrough {
213
279
  this.#redirect = value;
214
280
  }
215
281
 
282
+ /**
283
+ * Whether the podlet can signal redirects to the layout.
284
+ *
285
+ * @see https://podium-lib.io/docs/layout/handling_redirects
286
+ */
216
287
  get redirectable() {
217
288
  return this.#redirectable;
218
289
  }
@@ -222,17 +293,22 @@ export default class PodletClientHttpOutgoing extends PassThrough {
222
293
  }
223
294
 
224
295
  /**
225
- * Boolean getter that indicates whether the client is responding with a content or fallback payload.
296
+ * True if the client has returned the podlet's fallback.
297
+ *
226
298
  * @example
227
- * ```
299
+ *
300
+ * ```js
228
301
  * if (outgoing.isFallback) console.log("Fallback!");
229
302
  * ```
303
+ *
304
+ * @see https://podium-lib.io/docs/podlet/fallbacks
230
305
  */
231
306
  get isFallback() {
232
- return this.#isFallback;
307
+ return this.#isFallback;
233
308
  }
234
309
 
235
310
  pushFallback() {
311
+ // @ts-expect-error Internal property
236
312
  this.push(this.#manifest._fallback);
237
313
  this.push(null);
238
314
  this.#isFallback = true;
@@ -241,4 +317,4 @@ export default class PodletClientHttpOutgoing extends PassThrough {
241
317
  get [Symbol.toStringTag]() {
242
318
  return 'PodletClientHttpOutgoing';
243
319
  }
244
- };
320
+ }
package/lib/http.js CHANGED
@@ -1,8 +1,28 @@
1
1
  import { request } from 'undici';
2
2
 
3
+ /**
4
+ * @typedef {object} PodiumHttpClientRequestOptions
5
+ * @property {'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'CONNECT' | 'OPTIONS' | 'TRACE' | 'PATCH'} method
6
+ * @property {boolean} [json]
7
+ * @property {boolean} [rejectUnauthorized]
8
+ * @property {boolean} [follow]
9
+ * @property {number} [timeout]
10
+ * @property {number} [bodyTimeout]
11
+ * @property {object} [query]
12
+ * @property {import('http').IncomingHttpHeaders} [headers]
13
+ */
14
+
3
15
  export default class HTTP {
16
+ /**
17
+ * @param {string} url
18
+ * @param {PodiumHttpClientRequestOptions} options
19
+ * @returns {Promise<Pick<import('undici').Dispatcher.ResponseData, 'statusCode' | 'headers' | 'body'>>}
20
+ */
4
21
  async request(url, options) {
5
- const { statusCode, headers, body } = await request(new URL(url), options);
22
+ const { statusCode, headers, body } = await request(
23
+ new URL(url),
24
+ options,
25
+ );
6
26
  return { statusCode, headers, body };
7
27
  }
8
28
  }
@@ -5,9 +5,20 @@ import clonedeep from 'lodash.clonedeep';
5
5
  import abslog from 'abslog';
6
6
  import assert from 'assert';
7
7
 
8
+ /**
9
+ * @typedef {object} PodletClientCacheResolverOptions
10
+ * @property {import('abslog').AbstractLoggerOptions} [logger]
11
+ */
12
+
8
13
  export default class PodletClientCacheResolver {
9
14
  #registry;
10
15
  #log;
16
+
17
+ /**
18
+ * @constructor
19
+ * @param {import('ttl-mem-cache').default} registry
20
+ * @param {PodletClientCacheResolverOptions} options
21
+ */
11
22
  constructor(registry, options = {}) {
12
23
  assert(
13
24
  registry,
@@ -17,8 +28,14 @@ export default class PodletClientCacheResolver {
17
28
  this.#log = abslog(options.logger);
18
29
  }
19
30
 
31
+ /**
32
+ * Loads the podlet's manifest from cache if not stale
33
+ *
34
+ * @param {import('./http-outgoing.js').default} outgoing
35
+ * @returns {Promise<import('./http-outgoing.js').default>}
36
+ */
20
37
  load(outgoing) {
21
- return new Promise(resolve => {
38
+ return new Promise((resolve) => {
22
39
  if (outgoing.status !== 'stale') {
23
40
  const cached = this.#registry.get(outgoing.name);
24
41
  if (cached) {
@@ -33,8 +50,14 @@ export default class PodletClientCacheResolver {
33
50
  });
34
51
  }
35
52
 
53
+ /**
54
+ * Saves the podlet's manifest to the cache
55
+ *
56
+ * @param {import('./http-outgoing.js').default} outgoing
57
+ * @returns {Promise<import('./http-outgoing.js').default>}
58
+ */
36
59
  save(outgoing) {
37
- return new Promise(resolve => {
60
+ return new Promise((resolve) => {
38
61
  if (outgoing.status === 'fresh') {
39
62
  this.#registry.set(
40
63
  outgoing.name,
@@ -55,4 +78,4 @@ export default class PodletClientCacheResolver {
55
78
  get [Symbol.toStringTag]() {
56
79
  return 'PodletClientCacheResolver';
57
80
  }
58
- };
81
+ }
@@ -21,11 +21,24 @@ const pkg = JSON.parse(pkgJson);
21
21
 
22
22
  const UA_STRING = `${pkg.name} ${pkg.version}`;
23
23
 
24
+ /**
25
+ * @typedef {object} PodletClientContentResolverOptions
26
+ * @property {string} clientName
27
+ * @property {import('./http.js').default} [http]
28
+ * @property {import('abslog').AbstractLoggerOptions} [logger]
29
+ */
30
+
24
31
  export default class PodletClientContentResolver {
25
32
  #log;
26
33
  #metrics;
27
34
  #histogram;
28
35
  #http;
36
+
37
+ /**
38
+ * @constructor
39
+ * @param {PodletClientContentResolverOptions} options
40
+ */
41
+ // @ts-expect-error Deliberate default empty options for better error messages
29
42
  constructor(options = {}) {
30
43
  this.#http = options.http || new HTTP();
31
44
  const name = options.clientName;
@@ -54,6 +67,12 @@ export default class PodletClientContentResolver {
54
67
  return this.#metrics;
55
68
  }
56
69
 
70
+ /**
71
+ * Resolves/fetches the podlet's content.
72
+ *
73
+ * @param {import('./http-outgoing.js').default} outgoing
74
+ * @returns {Promise<import('./http-outgoing.js').default>}
75
+ */
57
76
  async resolve(outgoing) {
58
77
  if (outgoing.kill && outgoing.throwable) {
59
78
  this.#log.warn(
@@ -71,12 +90,12 @@ export default class PodletClientContentResolver {
71
90
  outgoing.success = true;
72
91
  outgoing.pushFallback();
73
92
  outgoing.emit(
74
- 'beforeStream',
75
- new Response({
76
- js: utils.filterAssets("fallback", outgoing.manifest.js),
77
- css: utils.filterAssets("fallback", outgoing.manifest.css),
78
- }),
79
- );
93
+ 'beforeStream',
94
+ new Response({
95
+ js: utils.filterAssets('fallback', outgoing.manifest.js),
96
+ css: utils.filterAssets('fallback', outgoing.manifest.css),
97
+ }),
98
+ );
80
99
  return outgoing;
81
100
  }
82
101
 
@@ -94,12 +113,12 @@ export default class PodletClientContentResolver {
94
113
  outgoing.success = true;
95
114
  outgoing.pushFallback();
96
115
  outgoing.emit(
97
- 'beforeStream',
98
- new Response({
99
- js: utils.filterAssets("fallback", outgoing.manifest.js),
100
- css: utils.filterAssets("fallback", outgoing.manifest.css),
101
- }),
102
- );
116
+ 'beforeStream',
117
+ new Response({
118
+ js: utils.filterAssets('fallback', outgoing.manifest.js),
119
+ css: utils.filterAssets('fallback', outgoing.manifest.css),
120
+ }),
121
+ );
103
122
  return outgoing;
104
123
  }
105
124
 
@@ -113,8 +132,9 @@ export default class PodletClientContentResolver {
113
132
  const uri = putils.uriBuilder(
114
133
  outgoing.reqOptions.pathname,
115
134
  outgoing.contentUri,
116
- )
135
+ );
117
136
 
137
+ /** @type {import('./http.js').PodiumHttpClientRequestOptions} */
118
138
  const reqOptions = {
119
139
  rejectUnauthorized: outgoing.rejectUnauthorized,
120
140
  bodyTimeout: outgoing.timeout,
@@ -183,11 +203,17 @@ export default class PodletClientContentResolver {
183
203
  outgoing.success = true;
184
204
  outgoing.pushFallback();
185
205
  outgoing.emit(
186
- 'beforeStream',
187
- new Response({
188
- js: utils.filterAssets("fallback", outgoing.manifest.js),
189
- css: utils.filterAssets("fallback", outgoing.manifest.css),
190
- }),
206
+ 'beforeStream',
207
+ new Response({
208
+ js: utils.filterAssets(
209
+ 'fallback',
210
+ outgoing.manifest.js,
211
+ ),
212
+ css: utils.filterAssets(
213
+ 'fallback',
214
+ outgoing.manifest.css,
215
+ ),
216
+ }),
191
217
  );
192
218
 
193
219
  // Body must be consumed; https://github.com/nodejs/undici/issues/583#issuecomment-855384858
@@ -227,6 +253,7 @@ export default class PodletClientContentResolver {
227
253
  if (outgoing.redirectable && statusCode >= 300) {
228
254
  outgoing.redirect = {
229
255
  statusCode,
256
+ // @ts-expect-error TODO: look into what happens if the podlet returns more than one location header
230
257
  location: hdrs && hdrs.location,
231
258
  };
232
259
  }
@@ -235,8 +262,8 @@ export default class PodletClientContentResolver {
235
262
  'beforeStream',
236
263
  new Response({
237
264
  headers: outgoing.headers,
238
- js: utils.filterAssets("content", outgoing.manifest.js),
239
- css: utils.filterAssets("content", outgoing.manifest.css),
265
+ js: utils.filterAssets('content', outgoing.manifest.js),
266
+ css: utils.filterAssets('content', outgoing.manifest.css),
240
267
  redirect: outgoing.redirect,
241
268
  }),
242
269
  );
@@ -260,10 +287,7 @@ export default class PodletClientContentResolver {
260
287
  this.#log.warn(
261
288
  `could not create network connection to remote resource when trying to request content - resource: ${outgoing.name} - url: ${uri}`,
262
289
  );
263
- throw badGateway(
264
- `Error reading content at ${uri}`,
265
- error,
266
- );
290
+ throw badGateway(`Error reading content at ${uri}`, error);
267
291
  }
268
292
 
269
293
  timer({
@@ -280,12 +304,12 @@ export default class PodletClientContentResolver {
280
304
 
281
305
  outgoing.pushFallback();
282
306
  outgoing.emit(
283
- 'beforeStream',
284
- new Response({
285
- js: utils.filterAssets("fallback", outgoing.manifest.js),
286
- css: utils.filterAssets("fallback", outgoing.manifest.css),
287
- }),
288
- );
307
+ 'beforeStream',
308
+ new Response({
309
+ js: utils.filterAssets('fallback', outgoing.manifest.js),
310
+ css: utils.filterAssets('fallback', outgoing.manifest.css),
311
+ }),
312
+ );
289
313
 
290
314
  return outgoing;
291
315
  }