@podium/client 5.1.0-beta.1 → 5.1.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.
package/CHANGELOG.md CHANGED
@@ -1,10 +1,199 @@
1
- # [5.1.0-beta.1](https://github.com/podium-lib/client/compare/v5.0.7...v5.1.0-beta.1) (2024-03-20)
1
+ # [5.1.0](https://github.com/podium-lib/client/compare/v5.0.34...v5.1.0) (2024-07-02)
2
2
 
3
3
 
4
4
  ### Features
5
5
 
6
- * add new options to register and use them in fetch ([5aed9d6](https://github.com/podium-lib/client/commit/5aed9d6303681910fc95413535345643bbfa8d62))
7
- * add support for includeBy and excludeBy options in Resource ([51eb442](https://github.com/podium-lib/client/commit/51eb442398a15b487970ebabe51a5c33f3aede29))
6
+ * conditional fetch by deviceType header ([de4e9c4](https://github.com/podium-lib/client/commit/de4e9c47eea6baf07f2dc72465699a080b6aace1))
7
+
8
+ ## [5.0.34](https://github.com/podium-lib/client/compare/v5.0.33...v5.0.34) (2024-06-18)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **deps:** update dependency undici to v6.19.2 ([ac66051](https://github.com/podium-lib/client/commit/ac66051d0600273f5d3e7c0b57be6fccf222cb83))
14
+
15
+ ## [5.0.33](https://github.com/podium-lib/client/compare/v5.0.32...v5.0.33) (2024-06-17)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * **deps:** update dependency undici to v6.19.1 ([c64b634](https://github.com/podium-lib/client/commit/c64b6343c87630fc88a2dbf37ca26044c6a81c75))
21
+
22
+ ## [5.0.32](https://github.com/podium-lib/client/compare/v5.0.31...v5.0.32) (2024-06-14)
23
+
24
+
25
+ ### Bug Fixes
26
+
27
+ * **deps:** update dependency undici to v6.19.0 ([ae67694](https://github.com/podium-lib/client/commit/ae6769416e368071a7a7ff8776856cf2307877c0))
28
+
29
+ ## [5.0.31](https://github.com/podium-lib/client/compare/v5.0.30...v5.0.31) (2024-06-05)
30
+
31
+
32
+ ### Bug Fixes
33
+
34
+ * **deps:** update dependency @podium/schemas to v5.0.5 ([1fd5c68](https://github.com/podium-lib/client/commit/1fd5c68bf97de53cdffdb26f3510f569fd8a110f))
35
+
36
+ ## [5.0.30](https://github.com/podium-lib/client/compare/v5.0.29...v5.0.30) (2024-06-04)
37
+
38
+
39
+ ### Bug Fixes
40
+
41
+ * **deps:** update dependency @podium/schemas to v5.0.4 ([d3574df](https://github.com/podium-lib/client/commit/d3574dfa36e0aa0838ed1410e8b7c0cf15559c0b))
42
+
43
+ ## [5.0.29](https://github.com/podium-lib/client/compare/v5.0.28...v5.0.29) (2024-05-29)
44
+
45
+
46
+ ### Bug Fixes
47
+
48
+ * **deps:** update dependency undici to v6.18.2 ([68b44d0](https://github.com/podium-lib/client/commit/68b44d06037a5e8323ff2b7c913838b55e44f59e))
49
+
50
+ ## [5.0.28](https://github.com/podium-lib/client/compare/v5.0.27...v5.0.28) (2024-05-26)
51
+
52
+
53
+ ### Bug Fixes
54
+
55
+ * **deps:** update dependency @podium/schemas to v5.0.3 ([089f50a](https://github.com/podium-lib/client/commit/089f50ad1bf06c7bf6ae16fcb24cec3d243dd271))
56
+
57
+ ## [5.0.27](https://github.com/podium-lib/client/compare/v5.0.26...v5.0.27) (2024-05-22)
58
+
59
+
60
+ ### Bug Fixes
61
+
62
+ * **deps:** update dependency undici to v6.18.1 ([f1d0705](https://github.com/podium-lib/client/commit/f1d0705a269aee4ddb92b75ff4d791ba02e305e9))
63
+
64
+ ## [5.0.26](https://github.com/podium-lib/client/compare/v5.0.25...v5.0.26) (2024-05-20)
65
+
66
+
67
+ ### Bug Fixes
68
+
69
+ * **deps:** update dependency undici to v6.18.0 ([3c6585f](https://github.com/podium-lib/client/commit/3c6585f0d4ce5289f63034384243892557ec67c3))
70
+
71
+ ## [5.0.25](https://github.com/podium-lib/client/compare/v5.0.24...v5.0.25) (2024-05-17)
72
+
73
+
74
+ ### Bug Fixes
75
+
76
+ * **deps:** update dependency undici to v6.17.0 ([83f8fba](https://github.com/podium-lib/client/commit/83f8fbaa6c1c417f29f76152510d14cba673abe3))
77
+
78
+ ## [5.0.24](https://github.com/podium-lib/client/compare/v5.0.23...v5.0.24) (2024-05-15)
79
+
80
+
81
+ ### Bug Fixes
82
+
83
+ * **deps:** update dependency @podium/utils to v5.0.7 ([ee4ee5b](https://github.com/podium-lib/client/commit/ee4ee5b160ff2aab130e17a3e86abdfec08d1864))
84
+
85
+ ## [5.0.23](https://github.com/podium-lib/client/compare/v5.0.22...v5.0.23) (2024-05-15)
86
+
87
+
88
+ ### Bug Fixes
89
+
90
+ * make response toJSON return type serializable ([026a723](https://github.com/podium-lib/client/commit/026a723b545c6b3b0c622851b7d164be2674e8a2))
91
+
92
+ ## [5.0.22](https://github.com/podium-lib/client/compare/v5.0.21...v5.0.22) (2024-05-15)
93
+
94
+
95
+ ### Bug Fixes
96
+
97
+ * generate type definitions before publish ([8189b01](https://github.com/podium-lib/client/commit/8189b01c54c733c760b02f2138803f9b64a6fee5))
98
+
99
+ ## [5.0.21](https://github.com/podium-lib/client/compare/v5.0.20...v5.0.21) (2024-05-14)
100
+
101
+
102
+ ### Bug Fixes
103
+
104
+ * export same types as before ([0e3c65a](https://github.com/podium-lib/client/commit/0e3c65afc0fef7e6c53ad544dc80cb7f8dc8596b))
105
+ * generate types from JSDoc ([32cac7e](https://github.com/podium-lib/client/commit/32cac7e10a76494c0d2df602f41d42a67e8e7b6c))
106
+
107
+ ## [5.0.20](https://github.com/podium-lib/client/compare/v5.0.19...v5.0.20) (2024-05-14)
108
+
109
+
110
+ ### Bug Fixes
111
+
112
+ * **deps:** update dependency @podium/schemas to v5.0.2 ([e8e2fb4](https://github.com/podium-lib/client/commit/e8e2fb45e00be74222fa19e1faba1f29829976e8))
113
+
114
+ ## [5.0.19](https://github.com/podium-lib/client/compare/v5.0.18...v5.0.19) (2024-05-13)
115
+
116
+
117
+ ### Bug Fixes
118
+
119
+ * **deps:** update dependency @podium/utils to v5.0.6 ([fb1e29f](https://github.com/podium-lib/client/commit/fb1e29f6734fc04f907c64904c535bb02faca334))
120
+
121
+ ## [5.0.18](https://github.com/podium-lib/client/compare/v5.0.17...v5.0.18) (2024-05-10)
122
+
123
+
124
+ ### Bug Fixes
125
+
126
+ * **deps:** update dependency undici to v6.16.1 ([16edd1c](https://github.com/podium-lib/client/commit/16edd1c20a34686182868f0432e3280952805450))
127
+
128
+ ## [5.0.17](https://github.com/podium-lib/client/compare/v5.0.16...v5.0.17) (2024-05-07)
129
+
130
+
131
+ ### Bug Fixes
132
+
133
+ * **deps:** update dependency undici to v6.16.0 ([8884811](https://github.com/podium-lib/client/commit/88848113650e00183f0368aa7c8642a33aaae3ec))
134
+
135
+ ## [5.0.16](https://github.com/podium-lib/client/compare/v5.0.15...v5.0.16) (2024-05-07)
136
+
137
+
138
+ ### Bug Fixes
139
+
140
+ * **deps:** update dependency @podium/utils to v5.0.5 ([4059526](https://github.com/podium-lib/client/commit/40595261f2d5b644e7cda15e7d1998cdbbb8b3c3))
141
+
142
+ ## [5.0.15](https://github.com/podium-lib/client/compare/v5.0.14...v5.0.15) (2024-05-07)
143
+
144
+
145
+ ### Bug Fixes
146
+
147
+ * Requests hang on http errors ([a9c82b6](https://github.com/podium-lib/client/commit/a9c82b6a931d92540c69c2cbf911184710dc54ee))
148
+
149
+ ## [5.0.14](https://github.com/podium-lib/client/compare/v5.0.13...v5.0.14) (2024-05-02)
150
+
151
+
152
+ ### Bug Fixes
153
+
154
+ * **deps:** update dependency abslog to v2.4.4 ([0e21e41](https://github.com/podium-lib/client/commit/0e21e41d2503387dc1d796f857a41048f5222209))
155
+
156
+ ## [5.0.13](https://github.com/podium-lib/client/compare/v5.0.12...v5.0.13) (2024-04-30)
157
+
158
+
159
+ ### Bug Fixes
160
+
161
+ * **deps:** update dependency abslog to v2.4.3 ([ea2a8ff](https://github.com/podium-lib/client/commit/ea2a8ff0cc43c97cdd853551959928d4fcc53992))
162
+
163
+ ## [5.0.12](https://github.com/podium-lib/client/compare/v5.0.11...v5.0.12) (2024-04-30)
164
+
165
+
166
+ ### Bug Fixes
167
+
168
+ * **deps:** update dependency @podium/schemas to v5.0.1 ([f6b3f56](https://github.com/podium-lib/client/commit/f6b3f56e1be12b2e5a3d5296a00488e61d354662))
169
+
170
+ ## [5.0.11](https://github.com/podium-lib/client/compare/v5.0.10...v5.0.11) (2024-04-23)
171
+
172
+
173
+ ### Bug Fixes
174
+
175
+ * **deps:** update dependency @podium/utils to v5.0.4 ([b622774](https://github.com/podium-lib/client/commit/b62277448a0fe326fdd11504a0d7787132911908))
176
+
177
+ ## [5.0.10](https://github.com/podium-lib/client/compare/v5.0.9...v5.0.10) (2024-04-12)
178
+
179
+
180
+ ### Bug Fixes
181
+
182
+ * **deps:** update dependency abslog to v2.4.2 ([f36069e](https://github.com/podium-lib/client/commit/f36069ecc3022b3e02a7b4630511fee8b8c8e21d))
183
+
184
+ ## [5.0.9](https://github.com/podium-lib/client/compare/v5.0.8...v5.0.9) (2024-04-12)
185
+
186
+
187
+ ### Bug Fixes
188
+
189
+ * **deps:** update dependency @podium/utils to v5.0.3 ([9412fa6](https://github.com/podium-lib/client/commit/9412fa6d3dd847f595fc8818a2f74374f047feeb))
190
+
191
+ ## [5.0.8](https://github.com/podium-lib/client/compare/v5.0.7...v5.0.8) (2024-04-10)
192
+
193
+
194
+ ### Bug Fixes
195
+
196
+ * **deps:** update dependency abslog to v2.4.1 ([105a16c](https://github.com/podium-lib/client/commit/105a16c0ff0215cd68984d7aad7351b4b5b623b2))
8
197
 
9
198
  ## [5.0.7](https://github.com/podium-lib/client/compare/v5.0.6...v5.0.7) (2024-02-01)
10
199
 
package/README.md CHANGED
@@ -150,18 +150,16 @@ The following values can be provided:
150
150
  - `retries` - {Number} - The number of times the client should retry to settle a version number conflict before terminating. See the section "[on retrying](#on-retrying)" for more information. Default: 4 - Optional.
151
151
  - `timeout` - {Number} - Defines how long, in milliseconds, a request should wait before the connection is terminated. Overrides the global default. Default: 1000 - Optional.
152
152
  - `throwable` - {Boolean} - Defines whether an error should be thrown if a failure occurs during the process of fetching a podium component. Defaults to `false` - Optional.
153
- - `resolveJs` - {Boolean} - Defines whether to resolve a relative JS uri for a component to be an absolute uri. Defaults to `false` - Optional.
154
- - `resolveCss` - {Boolean} - Defines whether to resolve a relative CSS uri for a component to be an absolute uri. Defaults to `false` - Optional.
155
153
  - `excludeBy` - {Object} - Lets you define a set of rules where a `fetch` call will not be resolved if it matches. - Optional.
156
- - `includeBy` - {Object} - Inverse of `excludeBy`. - Optional.
154
+ - `includeBy` - {Object} - Inverse of `excludeBy`. Setting both at the same time will throw. - Optional.
157
155
 
158
156
  ##### `excludeBy` and `includeBy`
159
157
 
160
- These options are used by `fetch` to conditionally skip fetching the podlet content based on values on the request. It's an alternative to conditionally fetching podlets in your request handler.
158
+ These options are used by `fetch` to conditionally skip fetching the podlet content based on values on the request. It's an alternative to conditionally fetching podlets in your request handler. Setting both at the same time will throw.
161
159
 
162
160
  Allowed options:
163
161
 
164
- - `deviceType` - {Array<String>} - List of values for the `x-podium-device-type` header. - Optional.
162
+ - `deviceType` - {Array<String>} - List of values for the `x-podium-device-type` header. - Optional.
165
163
 
166
164
  Example: exclude a header and footer in a hybrid web view.
167
165
 
@@ -173,7 +171,7 @@ const footer = client.register({
173
171
  uri: 'http://footer.site.com/manifest.json',
174
172
  name: 'footer',
175
173
  excludeBy: {
176
- deviceType: ["hybrid-ios", "hybrid-android"], // when footer.fetch(incoming) is called, if the incoming request has the header `x-podium-device-type: hybrid-ios`, `fetch` will return an empty response.
174
+ deviceType: ['hybrid-ios', 'hybrid-android'], // when footer.fetch(incoming) is called, if the incoming request has the header `x-podium-device-type: hybrid-ios`, `fetch` will return an empty response.
177
175
  },
178
176
  });
179
177
  ```
@@ -462,15 +460,19 @@ stream.once('beforeStream', (data) => {
462
460
  Both the .fetch() method and the .stream() method give you access to podlet asset objects and these CSS and JS asset objects will be filtered if the asset objects contain a `scope` property and that `scope` property matches the current response type (either content or fallback).
463
461
 
464
462
  For example, if the podlet manifest contains a JavaScript asset definition of the form:
463
+
465
464
  ```
466
465
  {
467
466
  js: [{ value: "https://assets.com/path/to/file.js", scope: "content" }],
468
467
  }
469
468
  ```
469
+
470
470
  And the client performs a fetch like so:
471
+
471
472
  ```js
472
473
  const result = await component.fetch();
473
474
  ```
475
+
474
476
  Then, if the podlet successfully responds from its content route, the `result.js` property will contain the asset defined above. If, however, the podlet's content route errors and the client is forced to use the podlet's fallback content, then `result.js` property will be an empty array.
475
477
 
476
478
  Possible `scope` values are `content`, `fallback` and `all`. For backwards compatibility reasons, when assets do not provide a `scope` property, they will always be included in both `content` and `fallback` responses.
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,51 @@ 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
+ * @property {import('./resource.js').RequestFilterOptions} [excludeBy] Used by `fetch` to conditionally skip fetching the podlet content based on values on the request.
64
+ * @property {import('./resource.js').RequestFilterOptions} [includeBy] Used by `fetch` to conditionally skip fetching the podlet content based on values on the request.
65
+ */
66
+
39
67
  export default class PodiumClient extends EventEmitter {
40
68
  #resources;
41
69
  #registry;
@@ -43,6 +71,12 @@ export default class PodiumClient extends EventEmitter {
43
71
  #histogram;
44
72
  #options;
45
73
  #state;
74
+
75
+ /**
76
+ * @constructor
77
+ * @param {PodiumClientOptions} options
78
+ */
79
+ // @ts-expect-error Deliberate default empty options for better error messages
46
80
  constructor(options = {}) {
47
81
  super();
48
82
  const log = abslog(options.logger);
@@ -71,7 +105,7 @@ export default class PodiumClient extends EventEmitter {
71
105
  resolveThreshold: options.resolveThreshold,
72
106
  resolveMax: options.resolveMax,
73
107
  });
74
- this.#state.on('state', state => {
108
+ this.#state.on('state', (state) => {
75
109
  this.emit('state', state);
76
110
  });
77
111
 
@@ -81,7 +115,7 @@ export default class PodiumClient extends EventEmitter {
81
115
  changefeed: true,
82
116
  ttl: options.maxAge,
83
117
  });
84
- this.#registry.on('error', error => {
118
+ this.#registry.on('error', (error) => {
85
119
  log.error(
86
120
  'Error emitted by the registry in @podium/client module',
87
121
  error,
@@ -93,7 +127,7 @@ export default class PodiumClient extends EventEmitter {
93
127
  });
94
128
 
95
129
  this.#metrics = new Metrics();
96
- this.#metrics.on('error', error => {
130
+ this.#metrics.on('error', (error) => {
97
131
  log.error(
98
132
  'Error emitted by metric stream in @podium/client module',
99
133
  error,
@@ -101,7 +135,7 @@ export default class PodiumClient extends EventEmitter {
101
135
  });
102
136
 
103
137
  this[Symbol.iterator] = () => ({
104
- items: Array.from(this.#resources).map(item => item[1]),
138
+ items: Array.from(this.#resources).map((item) => item[1]),
105
139
  next: function next() {
106
140
  return {
107
141
  done: this.items.length === 0,
@@ -130,7 +164,21 @@ export default class PodiumClient extends EventEmitter {
130
164
  return this.#state.status;
131
165
  }
132
166
 
133
- register(options = {}) {
167
+ /**
168
+ * Register a podlet so you can fetch its contents later with {@link PodiumClientResource.fetch}.
169
+ *
170
+ * @param {RegisterOptions} options
171
+ * @returns {PodiumClientResource}
172
+ *
173
+ * @example
174
+ * ```js
175
+ * const headerPodlet = layout.client.register({
176
+ * name: 'header',
177
+ * uri: 'http://header/manifest.json',
178
+ * });
179
+ * ```
180
+ */
181
+ register(options) {
134
182
  if (validateName(options.name).error)
135
183
  throw new Error(
136
184
  `The value, "${options.name}", for the required argument "name" on the .register() method is not defined or not valid.`,
@@ -147,6 +195,12 @@ export default class PodiumClient extends EventEmitter {
147
195
  );
148
196
  }
149
197
 
198
+ if (options.includeBy && options.excludeBy) {
199
+ throw new Error(
200
+ 'A podlet can only be registered with either includeBy or excludeBy, not both.',
201
+ );
202
+ }
203
+
150
204
  const resourceOptions = {
151
205
  rejectUnauthorized: this.#options.rejectUnauthorized,
152
206
  clientName: this.#options.name,
@@ -154,12 +208,13 @@ export default class PodiumClient extends EventEmitter {
154
208
  timeout: this.#options.timeout,
155
209
  logger: this.#options.logger,
156
210
  maxAge: this.#options.maxAge,
157
- includeBy: this.#options.includeBy,
158
- excludeBy: this.#options.excludeBy,
159
211
  httpsAgent: this.#options.httpsAgent,
160
212
  httpAgent: this.#options.httpAgent,
213
+ includeBy: this.#options.includeBy,
214
+ excludeBy: this.#options.excludeBy,
161
215
  ...options,
162
216
  };
217
+
163
218
  const resource = new Resource(
164
219
  this.#registry,
165
220
  this.#state,
@@ -187,12 +242,17 @@ export default class PodiumClient extends EventEmitter {
187
242
  return this.#registry.load(dump);
188
243
  }
189
244
 
245
+ /**
246
+ * Refreshes the cached podlet manifest for all {@link register}ed podlets.
247
+ */
190
248
  async refreshManifests() {
191
249
  const end = this.#histogram.timer();
192
250
 
193
251
  // Don't return this
194
252
  await Promise.all(
195
- Array.from(this.#resources).map(resource => resource[1].refresh()),
253
+ Array.from(this.#resources).map((resource) =>
254
+ resource[1].refresh(),
255
+ ),
196
256
  );
197
257
 
198
258
  end();
@@ -208,4 +268,4 @@ export default class PodiumClient extends EventEmitter {
208
268
  get [Symbol.toStringTag]() {
209
269
  return 'PodiumClient';
210
270
  }
211
- };
271
+ }