@podium/client 5.0.7 → 5.1.0-beta.1

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,11 @@
1
+ # [5.1.0-beta.1](https://github.com/podium-lib/client/compare/v5.0.7...v5.1.0-beta.1) (2024-03-20)
2
+
3
+
4
+ ### Features
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))
8
+
1
9
  ## [5.0.7](https://github.com/podium-lib/client/compare/v5.0.6...v5.0.7) (2024-02-01)
2
10
 
3
11
 
package/README.md CHANGED
@@ -152,6 +152,31 @@ The following values can be provided:
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
153
  - `resolveJs` - {Boolean} - Defines whether to resolve a relative JS uri for a component to be an absolute uri. Defaults to `false` - Optional.
154
154
  - `resolveCss` - {Boolean} - Defines whether to resolve a relative CSS uri for a component to be an absolute uri. Defaults to `false` - Optional.
155
+ - `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.
157
+
158
+ ##### `excludeBy` and `includeBy`
159
+
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.
161
+
162
+ Allowed options:
163
+
164
+ - `deviceType` - {Array<String>} - List of values for the `x-podium-device-type` header. - Optional.
165
+
166
+ Example: exclude a header and footer in a hybrid web view.
167
+
168
+ ```js
169
+ import Client from '@podium/client';
170
+ const client = new Client();
171
+
172
+ const footer = client.register({
173
+ uri: 'http://footer.site.com/manifest.json',
174
+ name: 'footer',
175
+ 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.
177
+ },
178
+ });
179
+ ```
155
180
 
156
181
  ### .js()
157
182
 
package/client.d.ts CHANGED
@@ -129,7 +129,12 @@ declare namespace PodiumClient {
129
129
  redirectable?: boolean;
130
130
  resolveJs?: boolean;
131
131
  resolveCss?: boolean;
132
+ includeBy?: RequestFilterOptions;
133
+ excludeBy?: RequestFilterOptions;
132
134
  }
135
+ export type RequestFilterOptions = {
136
+ deviceType?: Array<string>;
137
+ };
133
138
 
134
139
  export interface PodiumRedirect {
135
140
  readonly statusCode: number;
package/lib/client.js CHANGED
@@ -62,6 +62,8 @@ export default class PodiumClient extends EventEmitter {
62
62
  rejectUnauthorized: REJECT_UNAUTHORIZED,
63
63
  httpAgent: HTTP_AGENT,
64
64
  httpsAgent: HTTPS_AGENT,
65
+ includeBy: undefined,
66
+ excludeBy: undefined,
65
67
  ...options,
66
68
  };
67
69
 
@@ -152,6 +154,8 @@ export default class PodiumClient extends EventEmitter {
152
154
  timeout: this.#options.timeout,
153
155
  logger: this.#options.logger,
154
156
  maxAge: this.#options.maxAge,
157
+ includeBy: this.#options.includeBy,
158
+ excludeBy: this.#options.excludeBy,
155
159
  httpsAgent: this.#options.httpsAgent,
156
160
  httpAgent: this.#options.httpAgent,
157
161
  ...options,
package/lib/resource.js CHANGED
@@ -34,7 +34,7 @@ export default class PodiumClientResource {
34
34
  this.#metrics = new Metrics();
35
35
  this.#state = state;
36
36
 
37
- this.#metrics.on('error', error => {
37
+ this.#metrics.on('error', (error) => {
38
38
  log.error(
39
39
  'Error emitted by metric stream in @podium/client module',
40
40
  error,
@@ -57,19 +57,71 @@ export default class PodiumClientResource {
57
57
  }
58
58
 
59
59
  async fetch(incoming = {}, reqOptions = {}) {
60
- if (!utils.validateIncoming(incoming)) throw new TypeError('you must pass an instance of "HttpIncoming" as the first argument to the .fetch() method');
60
+ if (!utils.validateIncoming(incoming))
61
+ throw new TypeError(
62
+ 'you must pass an instance of "HttpIncoming" as the first argument to the .fetch() method',
63
+ );
61
64
  const outgoing = new HttpOutgoing(this.#options, reqOptions, incoming);
62
65
 
66
+ if (this.#options.excludeBy) {
67
+ /**
68
+ * @type {string[] | undefined}
69
+ */
70
+ const exclucedDeviceTypes = this.#options.excludeBy.deviceType;
71
+ if (Array.isArray(exclucedDeviceTypes)) {
72
+ const deviceTypeHeader =
73
+ incoming.request.headers['x-podium-device-type'];
74
+
75
+ for (let i = 0; i < exclucedDeviceTypes.length; i += 1) {
76
+ const shouldSkip =
77
+ exclucedDeviceTypes[i] === deviceTypeHeader;
78
+ if (shouldSkip) {
79
+ return new Response({
80
+ headers: {},
81
+ content: '',
82
+ css: [],
83
+ js: [],
84
+ redirect: '',
85
+ });
86
+ }
87
+ }
88
+ }
89
+ }
90
+
91
+ if (this.#options.includeBy) {
92
+ /**
93
+ * @type {string[] | undefined}
94
+ */
95
+ const includeDeviceTypes = this.#options.includeBy.deviceType;
96
+ if (Array.isArray(includeDeviceTypes)) {
97
+ const deviceTypeHeader =
98
+ incoming.request.headers['x-podium-device-type'];
99
+
100
+ const shouldRequest =
101
+ !deviceTypeHeader ||
102
+ includeDeviceTypes.includes(deviceTypeHeader);
103
+
104
+ if (!shouldRequest) {
105
+ return new Response({
106
+ headers: {},
107
+ content: '',
108
+ css: [],
109
+ js: [],
110
+ redirect: '',
111
+ });
112
+ }
113
+ }
114
+ }
115
+
63
116
  this.#state.setInitializingState();
64
117
 
65
- const { manifest, headers, redirect, isFallback } = await this.#resolver.resolve(
66
- outgoing,
67
- );
118
+ const { manifest, headers, redirect, isFallback } =
119
+ await this.#resolver.resolve(outgoing);
68
120
 
69
121
  const chunks = [];
70
122
  // eslint-disable-next-line no-restricted-syntax
71
123
  for await (const chunk of outgoing) {
72
- chunks.push(chunk)
124
+ chunks.push(chunk);
73
125
  }
74
126
 
75
127
  const content = !outgoing.redirect
@@ -79,14 +131,23 @@ export default class PodiumClientResource {
79
131
  return new Response({
80
132
  headers,
81
133
  content,
82
- css: utils.filterAssets(isFallback ? "fallback" : "content", manifest.css),
83
- js: utils.filterAssets(isFallback ? "fallback" : "content", manifest.js),
134
+ css: utils.filterAssets(
135
+ isFallback ? 'fallback' : 'content',
136
+ manifest.css,
137
+ ),
138
+ js: utils.filterAssets(
139
+ isFallback ? 'fallback' : 'content',
140
+ manifest.js,
141
+ ),
84
142
  redirect,
85
143
  });
86
144
  }
87
145
 
88
146
  stream(incoming = {}, reqOptions = {}) {
89
- if (!utils.validateIncoming(incoming)) throw new TypeError('you must pass an instance of "HttpIncoming" as the first argument to the .stream() method');
147
+ if (!utils.validateIncoming(incoming))
148
+ throw new TypeError(
149
+ 'you must pass an instance of "HttpIncoming" as the first argument to the .stream() method',
150
+ );
90
151
  const outgoing = new HttpOutgoing(this.#options, reqOptions, incoming);
91
152
  this.#state.setInitializingState();
92
153
  this.#resolver.resolve(outgoing);
@@ -96,7 +157,7 @@ export default class PodiumClientResource {
96
157
  refresh(incoming = {}, reqOptions = {}) {
97
158
  const outgoing = new HttpOutgoing(this.#options, reqOptions, incoming);
98
159
  this.#state.setInitializingState();
99
- return this.#resolver.refresh(outgoing).then(obj => obj);
160
+ return this.#resolver.refresh(outgoing).then((obj) => obj);
100
161
  }
101
162
 
102
163
  [inspect]() {
@@ -110,4 +171,4 @@ export default class PodiumClientResource {
110
171
  get [Symbol.toStringTag]() {
111
172
  return 'PodiumClientResource';
112
173
  }
113
- };
174
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@podium/client",
3
- "version": "5.0.7",
3
+ "version": "5.1.0-beta.1",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -55,17 +55,17 @@
55
55
  "@semantic-release/release-notes-generator": "12.1.0",
56
56
  "@sinonjs/fake-timers": "11.2.2",
57
57
  "benchmark": "2.1.4",
58
- "eslint": "8.56.0",
58
+ "eslint": "8.57.0",
59
59
  "eslint-config-airbnb-base": "15.0.0",
60
60
  "eslint-config-prettier": "9.1.0",
61
61
  "eslint-plugin-import": "2.29.1",
62
62
  "eslint-plugin-prettier": "5.1.3",
63
- "express": "4.18.2",
63
+ "express": "4.18.3",
64
64
  "get-stream": "8.0.1",
65
65
  "http-proxy": "1.18.1",
66
66
  "is-stream": "3.0.0",
67
- "prettier": "3.2.4",
68
- "semantic-release": "23.0.0",
67
+ "prettier": "3.2.5",
68
+ "semantic-release": "23.0.2",
69
69
  "tap": "18.7.0"
70
70
  }
71
71
  }