@podium/client 5.0.0-next.8 → 5.0.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.
@@ -1,320 +0,0 @@
1
- 'use strict';
2
-
3
- var stream = require('stream');
4
- var Metrics = require('@metrics/client');
5
- var request = require('request');
6
- var abslog = require('abslog');
7
- var utils = require('@podium/utils');
8
- var boom = require('@hapi/boom');
9
- var path = require('path');
10
- var url = require('url');
11
- var fs = require('fs');
12
- var utils$1 = require('./utils.js');
13
- var response = require('./response.js');
14
-
15
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
16
-
17
- function _interopNamespace(e) {
18
- if (e && e.__esModule) return e;
19
- var n = Object.create(null);
20
- if (e) {
21
- Object.keys(e).forEach(function (k) {
22
- if (k !== 'default') {
23
- var d = Object.getOwnPropertyDescriptor(e, k);
24
- Object.defineProperty(n, k, d.get ? d : {
25
- enumerable: true,
26
- get: function () {
27
- return e[k];
28
- }
29
- });
30
- }
31
- });
32
- }
33
- n['default'] = e;
34
- return Object.freeze(n);
35
- }
36
-
37
- var Metrics__default = /*#__PURE__*/_interopDefaultLegacy(Metrics);
38
- var request__default = /*#__PURE__*/_interopDefaultLegacy(request);
39
- var abslog__default = /*#__PURE__*/_interopDefaultLegacy(abslog);
40
- var utils__namespace = /*#__PURE__*/_interopNamespace(utils);
41
- var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
42
-
43
- /* eslint-disable no-param-reassign */
44
-
45
- const currentDirectory = path.dirname(url.fileURLToPath((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('resolver.content.js', document.baseURI).href))));
46
-
47
- const pkgJson = fs__default['default'].readFileSync(path.join(currentDirectory, '../package.json'), 'utf-8');
48
- const pkg = JSON.parse(pkgJson);
49
-
50
- const UA_STRING = `${pkg.name} ${pkg.version}`;
51
-
52
- class PodletClientContentResolver {
53
- #log;
54
- #agent;
55
- #metrics;
56
- #histogram;
57
- constructor(options = {}) {
58
- const name = options.clientName;
59
- this.#log = abslog__default['default'](options.logger);
60
- this.#agent = options.agent;
61
- this.#metrics = new Metrics__default['default']();
62
- this.#histogram = this.#metrics.histogram({
63
- name: 'podium_client_resolver_content_resolve',
64
- description: 'Time taken for success/failure of content request',
65
- labels: {
66
- name,
67
- status: null,
68
- podlet: null,
69
- },
70
- buckets: [0.001, 0.01, 0.1, 0.5, 1, 2, 10],
71
- });
72
-
73
- this.#metrics.on('error', error => {
74
- this.#log.error(
75
- 'Error emitted by metric stream in @podium/client module',
76
- error,
77
- );
78
- });
79
- }
80
-
81
- get metrics() {
82
- return this.#metrics;
83
- }
84
-
85
- resolve(outgoing) {
86
- return new Promise((resolve, reject) => {
87
- if (outgoing.kill && outgoing.throwable) {
88
- this.#log.warn(
89
- `recursion detected - failed to resolve fetching of podlet ${outgoing.recursions} times - throwing - resource: ${outgoing.name} - url: ${outgoing.manifestUri}`,
90
- );
91
- reject(
92
- boom.badGateway(
93
- `Recursion detected - failed to resolve fetching of podlet ${outgoing.recursions} times`,
94
- ),
95
- );
96
- return;
97
- }
98
-
99
- if (outgoing.kill) {
100
- this.#log.warn(
101
- `recursion detected - failed to resolve fetching of podlet ${outgoing.recursions} times - serving fallback - resource: ${outgoing.name} - url: ${outgoing.manifestUri}`,
102
- );
103
- outgoing.success = true;
104
- outgoing.pushFallback();
105
- resolve(outgoing);
106
- return;
107
- }
108
-
109
- if (outgoing.status === 'empty' && outgoing.throwable) {
110
- this.#log.warn(
111
- `no manifest available - cannot read content - throwing - resource: ${outgoing.name} - url: ${outgoing.manifestUri}`,
112
- );
113
- reject(
114
- boom.badGateway(`No manifest available - Cannot read content`),
115
- );
116
- return;
117
- }
118
-
119
- if (outgoing.status === 'empty') {
120
- this.#log.warn(
121
- `no manifest available - cannot read content - serving fallback - resource: ${outgoing.name} - url: ${outgoing.manifestUri}`,
122
- );
123
- outgoing.success = true;
124
- outgoing.pushFallback();
125
- resolve(outgoing);
126
- return;
127
- }
128
-
129
- const headers = {
130
- ...outgoing.reqOptions.headers,
131
- 'User-Agent': UA_STRING,
132
- };
133
-
134
- utils__namespace.serializeContext(headers, outgoing.context, outgoing.name);
135
-
136
- const reqOptions = {
137
- timeout: outgoing.timeout,
138
- method: 'GET',
139
- agent: this.#agent,
140
- uri: utils__namespace.uriBuilder(
141
- outgoing.reqOptions.pathname,
142
- outgoing.contentUri,
143
- ),
144
- qs: outgoing.reqOptions.query,
145
- headers,
146
- };
147
-
148
- if (outgoing.redirectable) {
149
- reqOptions.followRedirect = false;
150
- }
151
-
152
- const timer = this.#histogram.timer({
153
- labels: {
154
- podlet: outgoing.name,
155
- },
156
- });
157
-
158
- this.#log.debug(
159
- `start reading content from remote resource - manifest version is ${outgoing.manifest.version} - resource: ${outgoing.name} - url: ${outgoing.contentUri}`,
160
- );
161
-
162
- const r = request__default['default'](reqOptions);
163
-
164
- r.on('response', response$1 => {
165
- // Remote responds but with an http error code
166
- const resError = response$1.statusCode >= 400;
167
- if (resError && outgoing.throwable) {
168
- timer({
169
- labels: {
170
- status: 'failure',
171
- },
172
- });
173
-
174
- this.#log.warn(
175
- `remote resource responded with non 200 http status code for content - code: ${response$1.statusCode} - resource: ${outgoing.name} - url: ${outgoing.contentUri}`,
176
- );
177
-
178
- const errorMessage = `Could not read content. Resource responded with ${response$1.statusCode} on ${outgoing.contentUri}`;
179
-
180
- const errorOptions = {
181
- statusCode: response$1.statusCode,
182
- decorate: {
183
- statusCode: response$1.statusCode,
184
- },
185
- };
186
-
187
- reject(new boom.Boom(errorMessage, errorOptions));
188
- return;
189
- }
190
- if (resError) {
191
- timer({
192
- labels: {
193
- status: 'failure',
194
- },
195
- });
196
-
197
- this.#log.warn(
198
- `remote resource responded with non 200 http status code for content - code: ${response$1.statusCode} - resource: ${outgoing.name} - url: ${outgoing.contentUri}`,
199
- );
200
- outgoing.success = true;
201
- outgoing.pushFallback();
202
- resolve(outgoing);
203
- return;
204
- }
205
-
206
- const contentVersion = utils$1.isHeaderDefined(
207
- response$1.headers,
208
- 'podlet-version',
209
- )
210
- ? response$1.headers['podlet-version']
211
- : undefined;
212
-
213
- this.#log.debug(
214
- `got head response from remote resource for content - header version is ${response$1.headers['podlet-version']} - resource: ${outgoing.name} - url: ${outgoing.contentUri}`,
215
- );
216
-
217
- if (
218
- contentVersion !== outgoing.manifest.version &&
219
- contentVersion !== undefined
220
- ) {
221
- timer({
222
- labels: {
223
- status: 'success',
224
- },
225
- });
226
-
227
- this.#log.info(
228
- `podlet version number in header differs from cached version number - aborting request to remote resource for content - resource: ${outgoing.name} - url: ${outgoing.contentUri}`,
229
- );
230
- r.abort();
231
- outgoing.status = 'stale';
232
- return;
233
- }
234
-
235
- outgoing.success = true;
236
- outgoing.headers = response$1.headers;
237
-
238
- if (outgoing.redirectable && response$1.statusCode >= 300) {
239
- outgoing.redirect = {
240
- statusCode: response$1.statusCode,
241
- location: response$1.headers && response$1.headers.location,
242
- };
243
- }
244
-
245
- outgoing.emit(
246
- 'beforeStream',
247
- new response({
248
- headers: outgoing.headers,
249
- js: outgoing.manifest.js,
250
- css: outgoing.manifest.css,
251
- redirect: outgoing.redirect,
252
- }),
253
- );
254
-
255
- stream.pipeline([r, outgoing], (err) => {
256
- if (err) {
257
- this.#log.warn('error while piping content stream', err);
258
- }
259
- });
260
- });
261
-
262
- r.on('error', error => {
263
- // Network error
264
- if (outgoing.throwable) {
265
- timer({
266
- labels: {
267
- status: 'failure',
268
- },
269
- });
270
-
271
- this.#log.warn(
272
- `could not create network connection to remote resource when trying to request content - resource: ${outgoing.name} - url: ${outgoing.contentUri}`,
273
- );
274
- reject(
275
- boom.badGateway(
276
- `Error reading content at ${outgoing.contentUri}`,
277
- error,
278
- ),
279
- );
280
- return;
281
- }
282
-
283
- timer({
284
- labels: {
285
- status: 'failure',
286
- },
287
- });
288
-
289
- this.#log.warn(
290
- `could not create network connection to remote resource when trying to request content - resource: ${outgoing.name} - url: ${outgoing.contentUri}`,
291
- );
292
-
293
- outgoing.success = true;
294
-
295
- outgoing.pushFallback();
296
- resolve(outgoing);
297
- });
298
-
299
- r.on('end', () => {
300
- timer({
301
- labels: {
302
- status: 'success',
303
- },
304
- });
305
-
306
- this.#log.debug(
307
- `successfully read content from remote resource - resource: ${outgoing.name} - url: ${outgoing.contentUri}`,
308
- );
309
-
310
- resolve(outgoing);
311
- });
312
- });
313
- }
314
-
315
- get [Symbol.toStringTag]() {
316
- return 'PodletClientContentResolver';
317
- }
318
- }
319
-
320
- module.exports = PodletClientContentResolver;
@@ -1,167 +0,0 @@
1
- 'use strict';
2
-
3
- var request = require('request');
4
- var abslog = require('abslog');
5
- var Metrics = require('@metrics/client');
6
- var path = require('path');
7
- var url = require('url');
8
- var fs = require('fs');
9
-
10
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
11
-
12
- var request__default = /*#__PURE__*/_interopDefaultLegacy(request);
13
- var abslog__default = /*#__PURE__*/_interopDefaultLegacy(abslog);
14
- var Metrics__default = /*#__PURE__*/_interopDefaultLegacy(Metrics);
15
- var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
16
-
17
- /* eslint-disable no-param-reassign */
18
-
19
- const currentDirectory = path.dirname(url.fileURLToPath((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('resolver.fallback.js', document.baseURI).href))));
20
-
21
- const pkgJson = fs__default['default'].readFileSync(path.join(currentDirectory, '../package.json'), 'utf-8');
22
- const pkg = JSON.parse(pkgJson);
23
-
24
- const UA_STRING = `${pkg.name} ${pkg.version}`;
25
-
26
- class PodletClientFallbackResolver {
27
- #log;
28
- #agent;
29
- #metrics;
30
- #histogram;
31
- constructor(options = {}) {
32
- const name = options.clientName;
33
- this.#log = abslog__default['default'](options.logger);
34
- this.#agent = options.agent;
35
- this.#metrics = new Metrics__default['default']();
36
- this.#histogram = this.#metrics.histogram({
37
- name: 'podium_client_resolver_fallback_resolve',
38
- description: 'Time taken for success/failure of fallback request',
39
- labels: {
40
- name,
41
- status: null,
42
- podlet: null,
43
- },
44
- buckets: [0.001, 0.01, 0.1, 0.5, 1, 2, 10],
45
- });
46
-
47
- this.#metrics.on('error', error => {
48
- this.#log.error(
49
- 'Error emitted by metric stream in @podium/client module',
50
- error,
51
- );
52
- });
53
- }
54
-
55
- get metrics() {
56
- return this.#metrics;
57
- }
58
-
59
- resolve(outgoing) {
60
- return new Promise(resolve => {
61
- if (outgoing.status === 'cached') {
62
- resolve(outgoing);
63
- return;
64
- }
65
-
66
- // Manifest has no fallback, fetching of manifest likely failed.
67
- // Its not possible to fetch anything
68
- // Do not set fallback so we can serve any previous fallback we might have
69
- if (outgoing.manifest.fallback === undefined) {
70
- resolve(outgoing);
71
- return;
72
- }
73
-
74
- // If manifest fallback is empty, there is no fallback content to fetch
75
- // Set fallback to empty string
76
- if (outgoing.manifest.fallback === '') {
77
- this.#log.debug(
78
- `no fallback defined in manifest - resource: ${outgoing.name}`,
79
- );
80
- outgoing.fallback = '';
81
- resolve(outgoing);
82
- return;
83
- }
84
-
85
- // The manifest fallback holds a URI, fetch its content
86
- const headers = {
87
- 'User-Agent': UA_STRING,
88
- };
89
-
90
- const reqOptions = {
91
- timeout: outgoing.timeout,
92
- method: 'GET',
93
- agent: this.#agent,
94
- uri: outgoing.fallbackUri,
95
- headers,
96
- };
97
-
98
- const timer = this.#histogram.timer({
99
- labels: {
100
- podlet: outgoing.name,
101
- },
102
- });
103
-
104
- request__default['default'](reqOptions, (error, res, body) => {
105
- this.#log.debug(
106
- `start reading fallback content from remote resource - resource: ${outgoing.name} - url: ${outgoing.fallbackUri}`,
107
- );
108
-
109
- // Network error
110
- if (error) {
111
- timer({
112
- labels: {
113
- status: 'failure',
114
- },
115
- });
116
-
117
- this.#log.warn(
118
- `could not create network connection to remote resource for fallback content - resource: ${outgoing.name} - url: ${outgoing.fallbackUri}`,
119
- );
120
-
121
- outgoing.fallback = '';
122
- resolve(outgoing);
123
- return;
124
- }
125
-
126
- // Remote responds but with an http error code
127
- const resError = res.statusCode !== 200;
128
- if (resError) {
129
- timer({
130
- labels: {
131
- status: 'failure',
132
- },
133
- });
134
-
135
- this.#log.warn(
136
- `remote resource responded with non 200 http status code for fallback content - code: ${res.statusCode} - resource: ${outgoing.name} - url: ${outgoing.fallbackUri}`,
137
- );
138
-
139
- outgoing.fallback = '';
140
- resolve(outgoing);
141
- return;
142
- }
143
-
144
- // Response is OK. Store response body as fallback html for caching
145
- timer({
146
- labels: {
147
- status: 'success',
148
- },
149
- });
150
-
151
- // Set fallback to the fetched content
152
- outgoing.fallback = body;
153
-
154
- this.#log.debug(
155
- `successfully read fallback from remote resource - resource: ${outgoing.name} - url: ${outgoing.fallbackUri}`,
156
- );
157
- resolve(outgoing);
158
- });
159
- });
160
- }
161
-
162
- get [Symbol.toStringTag]() {
163
- return 'PodletClientFallbackResolver';
164
- }
165
- }
166
-
167
- module.exports = PodletClientFallbackResolver;
package/dist/resolver.js DELETED
@@ -1,80 +0,0 @@
1
- 'use strict';
2
-
3
- var Metrics = require('@metrics/client');
4
- var abslog = require('abslog');
5
- var assert = require('assert');
6
- var resolver_manifest = require('./resolver.manifest.js');
7
- var resolver_fallback = require('./resolver.fallback.js');
8
- var resolver_content = require('./resolver.content.js');
9
- var resolver_cache = require('./resolver.cache.js');
10
-
11
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
12
-
13
- var Metrics__default = /*#__PURE__*/_interopDefaultLegacy(Metrics);
14
- var abslog__default = /*#__PURE__*/_interopDefaultLegacy(abslog);
15
- var assert__default = /*#__PURE__*/_interopDefaultLegacy(assert);
16
-
17
- class PodletClientResolver {
18
- #cache;
19
- #manifest;
20
- #fallback;
21
- #content;
22
- #metrics;
23
- constructor(registry, options = {}) {
24
- assert__default['default'](
25
- registry,
26
- 'you must pass a "registry" object to the PodletClientResolver constructor',
27
- );
28
-
29
- const log = abslog__default['default'](options.logger);
30
- this.#cache = new resolver_cache(registry, options);
31
- this.#manifest = new resolver_manifest(options);
32
- this.#fallback = new resolver_fallback(options);
33
- this.#content = new resolver_content(options);
34
- this.#metrics = new Metrics__default['default']();
35
-
36
- this.#metrics.on('error', error => {
37
- log.error(
38
- 'Error emitted by metric stream in @podium/client module',
39
- error,
40
- );
41
- });
42
-
43
- this.#content.metrics.pipe(this.#metrics);
44
- this.#fallback.metrics.pipe(this.#metrics);
45
- this.#manifest.metrics.pipe(this.#metrics);
46
- }
47
-
48
- get metrics() {
49
- return this.#metrics;
50
- }
51
-
52
- resolve(outgoing) {
53
- return this.#cache
54
- .load(outgoing)
55
- .then(obj => this.#manifest.resolve(obj))
56
- .then(obj => this.#fallback.resolve(obj))
57
- .then(obj => this.#content.resolve(obj))
58
- .then(obj => this.#cache.save(obj))
59
- .then(obj => {
60
- if (obj.success) {
61
- return obj;
62
- }
63
- return this.resolve(obj);
64
- });
65
- }
66
-
67
- refresh(outgoing) {
68
- return this.#manifest
69
- .resolve(outgoing)
70
- .then(obj => this.#fallback.resolve(obj))
71
- .then(obj => this.#cache.save(obj))
72
- .then(obj => !!obj.manifest.name);
73
- }
74
-
75
- get [Symbol.toStringTag]() {
76
- return 'PodletClientResolver';
77
- }
78
- }
79
-
80
- module.exports = PodletClientResolver;