@podium/client 5.0.20 → 5.0.22

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.
@@ -17,11 +17,24 @@ const pkg = JSON.parse(pkgJson);
17
17
 
18
18
  const UA_STRING = `${pkg.name} ${pkg.version}`;
19
19
 
20
+ /**
21
+ * @typedef {object} PodletClientFallbackResolverOptions
22
+ * @property {string} clientName
23
+ * @property {import('./http.js').default} [http]
24
+ * @property {import('abslog').AbstractLoggerOptions} [logger]
25
+ */
26
+
20
27
  export default class PodletClientFallbackResolver {
21
28
  #log;
22
29
  #metrics;
23
30
  #histogram;
24
31
  #http;
32
+
33
+ /**
34
+ * @constructor
35
+ * @param {PodletClientFallbackResolverOptions} options
36
+ */
37
+ // @ts-expect-error Deliberate default empty options for better error messages
25
38
  constructor(options = {}) {
26
39
  this.#http = options.http || new HTTP();
27
40
  const name = options.clientName;
@@ -50,6 +63,12 @@ export default class PodletClientFallbackResolver {
50
63
  return this.#metrics;
51
64
  }
52
65
 
66
+ /**
67
+ * Resolves/fetches the podlet's fallback.
68
+ *
69
+ * @param {import('./http-outgoing.js').default} outgoing
70
+ * @returns {Promise<import('./http-outgoing.js').default>}
71
+ */
53
72
  async resolve(outgoing) {
54
73
  if (outgoing.status === 'cached') {
55
74
  return outgoing;
@@ -77,6 +96,7 @@ export default class PodletClientFallbackResolver {
77
96
  'User-Agent': UA_STRING,
78
97
  };
79
98
 
99
+ /** @type {import('./http.js').PodiumHttpClientRequestOptions} */
80
100
  const reqOptions = {
81
101
  rejectUnauthorized: outgoing.rejectUnauthorized,
82
102
  timeout: outgoing.timeout,
package/lib/resolver.js CHANGED
@@ -7,12 +7,25 @@ import Fallback from './resolver.fallback.js';
7
7
  import Content from './resolver.content.js';
8
8
  import Cache from './resolver.cache.js';
9
9
 
10
+ /**
11
+ * @typedef {object} PodletClientResolverOptions
12
+ * @property {string} clientName
13
+ * @property {import('abslog').AbstractLoggerOptions} [logger]
14
+ */
15
+
10
16
  export default class PodletClientResolver {
11
17
  #cache;
12
18
  #manifest;
13
19
  #fallback;
14
20
  #content;
15
21
  #metrics;
22
+
23
+ /**
24
+ * @constructor
25
+ * @param {import('ttl-mem-cache').default} registry
26
+ * @param {PodletClientResolverOptions} options
27
+ */
28
+ // @ts-expect-error Deliberate default empty options for better error messages
16
29
  constructor(registry, options = {}) {
17
30
  assert(
18
31
  registry,
@@ -22,12 +35,16 @@ export default class PodletClientResolver {
22
35
  const log = abslog(options.logger);
23
36
  const http = new HTTP();
24
37
  this.#cache = new Cache(registry, options);
25
- this.#manifest = new Manifest({ ...options, http });
38
+ this.#manifest = new Manifest({
39
+ clientName: options.clientName,
40
+ logger: options.logger,
41
+ http,
42
+ });
26
43
  this.#fallback = new Fallback({ ...options, http });
27
44
  this.#content = new Content({ ...options, http });
28
45
  this.#metrics = new Metrics();
29
46
 
30
- this.#metrics.on('error', error => {
47
+ this.#metrics.on('error', (error) => {
31
48
  log.error(
32
49
  'Error emitted by metric stream in @podium/client module',
33
50
  error,
@@ -43,14 +60,20 @@ export default class PodletClientResolver {
43
60
  return this.#metrics;
44
61
  }
45
62
 
63
+ /**
64
+ * Resolve the podlet's manifest, fallback and content
65
+ *
66
+ * @param {import('./http-outgoing.js').default} outgoing
67
+ * @returns {Promise<import('./http-outgoing.js').default>}
68
+ */
46
69
  resolve(outgoing) {
47
70
  return this.#cache
48
71
  .load(outgoing)
49
- .then(obj => this.#manifest.resolve(obj))
50
- .then(obj => this.#fallback.resolve(obj))
51
- .then(obj => this.#content.resolve(obj))
52
- .then(obj => this.#cache.save(obj))
53
- .then(obj => {
72
+ .then((obj) => this.#manifest.resolve(obj))
73
+ .then((obj) => this.#fallback.resolve(obj))
74
+ .then((obj) => this.#content.resolve(obj))
75
+ .then((obj) => this.#cache.save(obj))
76
+ .then((obj) => {
54
77
  if (obj.success) {
55
78
  return obj;
56
79
  }
@@ -58,15 +81,21 @@ export default class PodletClientResolver {
58
81
  });
59
82
  }
60
83
 
84
+ /**
85
+ * Refresh the podlet's cached manifest and fallback
86
+ *
87
+ * @param {import('./http-outgoing.js').default} outgoing
88
+ * @returns {Promise<boolean>} `true` if successful
89
+ */
61
90
  refresh(outgoing) {
62
91
  return this.#manifest
63
92
  .resolve(outgoing)
64
- .then(obj => this.#fallback.resolve(obj))
65
- .then(obj => this.#cache.save(obj))
66
- .then(obj => !!obj.manifest.name);
93
+ .then((obj) => this.#fallback.resolve(obj))
94
+ .then((obj) => this.#cache.save(obj))
95
+ .then((obj) => !!obj.manifest.name);
67
96
  }
68
97
 
69
98
  get [Symbol.toStringTag]() {
70
99
  return 'PodletClientResolver';
71
100
  }
72
- };
101
+ }
@@ -20,11 +20,24 @@ const pkg = JSON.parse(pkgJson);
20
20
 
21
21
  const UA_STRING = `${pkg.name} ${pkg.version}`;
22
22
 
23
+ /**
24
+ * @typedef {object} PodletClientManifestResolverOptions
25
+ * @property {string} clientName
26
+ * @property {import('abslog').AbstractLoggerOptions} [logger]
27
+ * @property {import('./http.js').default} [http]
28
+ */
29
+
23
30
  export default class PodletClientManifestResolver {
24
31
  #log;
25
32
  #metrics;
26
33
  #histogram;
27
34
  #http;
35
+
36
+ /**
37
+ * @constructor
38
+ * @param {PodletClientManifestResolverOptions} options
39
+ */
40
+ // @ts-expect-error Deliberate default empty options for better error messages
28
41
  constructor(options = {}) {
29
42
  this.#http = options.http || new HTTP();
30
43
  const name = options.clientName;
@@ -53,6 +66,10 @@ export default class PodletClientManifestResolver {
53
66
  return this.#metrics;
54
67
  }
55
68
 
69
+ /**
70
+ * @param {import('./http-outgoing.js').default} outgoing
71
+ * @returns {Promise<import('./http-outgoing.js').default>}
72
+ */
56
73
  async resolve(outgoing) {
57
74
  if (outgoing.status === 'cached') {
58
75
  return outgoing;
@@ -62,6 +79,7 @@ export default class PodletClientManifestResolver {
62
79
  'User-Agent': UA_STRING,
63
80
  };
64
81
 
82
+ /** @type {import('./http.js').PodiumHttpClientRequestOptions} */
65
83
  const reqOptions = {
66
84
  rejectUnauthorized: outgoing.rejectUnauthorized,
67
85
  timeout: outgoing.timeout,
@@ -81,11 +99,11 @@ export default class PodletClientManifestResolver {
81
99
  );
82
100
 
83
101
  try {
84
- const {
85
- statusCode,
86
- headers: hdrs,
87
- body,
88
- } = await this.#http.request(outgoing.manifestUri, reqOptions);
102
+ const response = await this.#http.request(
103
+ outgoing.manifestUri,
104
+ reqOptions,
105
+ );
106
+ const { statusCode, headers: hdrs, body } = response;
89
107
 
90
108
  // Remote responds but with an http error code
91
109
  const resError = statusCode !== 200;
@@ -105,7 +123,11 @@ export default class PodletClientManifestResolver {
105
123
  return outgoing;
106
124
  }
107
125
 
108
- const manifest = validateManifest(await body.json());
126
+ const manifest = validateManifest(
127
+ /** @type {import("@podium/schemas").PodletManifestSchema} */ (
128
+ await body.json()
129
+ ),
130
+ );
109
131
 
110
132
  // Manifest validation error
111
133
  if (manifest.error) {
@@ -158,6 +180,7 @@ export default class PodletClientManifestResolver {
158
180
  );
159
181
 
160
182
  // Construct css and js objects with absolute URIs
183
+ // @ts-expect-error We assign here what will end up as PodletManifest as defined in http-outgoing.js
161
184
  manifest.value.css = manifest.value.css.map((obj) => {
162
185
  obj.value = utils.uriRelativeToAbsolute(
163
186
  obj.value,
@@ -166,6 +189,7 @@ export default class PodletClientManifestResolver {
166
189
  return new utils.AssetCss(obj);
167
190
  });
168
191
 
192
+ // @ts-expect-error We assign here what will end up as PodletManifest as defined in http-outgoing.js
169
193
  manifest.value.js = manifest.value.js.map((obj) => {
170
194
  obj.value = utils.uriRelativeToAbsolute(
171
195
  obj.value,
@@ -179,9 +203,9 @@ export default class PodletClientManifestResolver {
179
203
 
180
204
  If .proxy is and Array, the podlet are of version 6 or newer. The Array is then an
181
205
  Array of proxy Objects ({ name: 'foo', target: '/' }) which is the new structure
182
- wanted from version 6 and onwards so leave this structure untouched.
206
+ wanted from version 6 and onwards so leave this structure untouched.
183
207
 
184
- If .proxy is an Object, the podlet are of version 5 or older where the key of the
208
+ If .proxy is an Object, the podlet are of version 5 or older where the key of the
185
209
  Object is the key of the target. If so, convert the structure to the new structure
186
210
  consisting of an Array of proxy Objects.
187
211
 
@@ -191,12 +215,12 @@ export default class PodletClientManifestResolver {
191
215
  if (Array.isArray(manifest.value.proxy)) {
192
216
  // Build absolute proxy URIs
193
217
  manifest.value.proxy = manifest.value.proxy.map((item) => ({
194
- target: utils.uriRelativeToAbsolute(
195
- item.target,
196
- outgoing.manifestUri,
197
- ),
198
- name: item.name,
199
- }));
218
+ target: utils.uriRelativeToAbsolute(
219
+ item.target,
220
+ outgoing.manifestUri,
221
+ ),
222
+ name: item.name,
223
+ }));
200
224
  } else {
201
225
  const proxies = [];
202
226
  // Build absolute proxy URIs
@@ -216,6 +240,7 @@ export default class PodletClientManifestResolver {
216
240
  END: Proxy backwards compabillity check and handling
217
241
  */
218
242
 
243
+ // @ts-expect-error We map to AssetCss and AssetJs above
219
244
  outgoing.manifest = manifest.value;
220
245
  outgoing.status = 'fresh';
221
246
 
package/lib/resource.js CHANGED
@@ -11,11 +11,35 @@ import * as utils from './utils.js';
11
11
 
12
12
  const inspect = Symbol.for('nodejs.util.inspect.custom');
13
13
 
14
+ /**
15
+ * @typedef {object} PodiumClientResourceOptions
16
+ * @property {import('abslog').AbstractLoggerOptions} [logger]
17
+ * @property {string} clientName
18
+ * @property {string} name
19
+ * @property {string} uri To the podlet's `manifest.json`
20
+ * @property {number} timeout In milliseconds
21
+ * @property {number} maxAge
22
+ * @property {number} [retries]
23
+ * @property {boolean} [throwable]
24
+ * @property {boolean} [redirectable]
25
+ * @property {boolean} [rejectUnauthorized]
26
+ * @property {import('http').Agent} [httpAgent]
27
+ * @property {import('https').Agent} [httpsAgent]
28
+ */
29
+
14
30
  export default class PodiumClientResource {
15
31
  #resolver;
16
32
  #options;
17
33
  #metrics;
18
34
  #state;
35
+
36
+ /**
37
+ * @constructor
38
+ * @param {import('ttl-mem-cache').default} registry
39
+ * @param {import('./state.js').default} state
40
+ * @param {PodiumClientResourceOptions} options
41
+ */
42
+ // @ts-expect-error Deliberate for better error messages
19
43
  constructor(registry, state, options = {}) {
20
44
  assert(
21
45
  registry,
@@ -34,7 +58,7 @@ export default class PodiumClientResource {
34
58
  this.#metrics = new Metrics();
35
59
  this.#state = state;
36
60
 
37
- this.#metrics.on('error', error => {
61
+ this.#metrics.on('error', (error) => {
38
62
  log.error(
39
63
  'Error emitted by metric stream in @podium/client module',
40
64
  error,
@@ -56,20 +80,37 @@ export default class PodiumClientResource {
56
80
  return this.#options.uri;
57
81
  }
58
82
 
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');
83
+ /**
84
+ * Fetch the podlet's content, or fallback if the podlet is unavailable.
85
+ * The podlet response includes references to its CSS and JS assets which should be included in the final HTML document.
86
+ *
87
+ * @param {import('@podium/utils').HttpIncoming} incoming Instance of HttpIncoming
88
+ * @param {import('./http-outgoing.js').PodiumClientResourceOptions} [reqOptions={}] Optional parameters to the HTTP request, such as query parameters or HTTP request headers.
89
+ * @returns {Promise<import('./response.js').default>}
90
+ *
91
+ * @example
92
+ * ```js
93
+ * const incoming = res.locals.podium; // Express server example
94
+ * const header = await headerPodlet.fetch(incoming);
95
+ * incoming.podlets = [header]; // Register the podlet's JS and CSS assets with the layout's HTML template
96
+ * ```
97
+ */
98
+ async fetch(incoming, reqOptions = {}) {
99
+ if (!utils.validateIncoming(incoming))
100
+ throw new TypeError(
101
+ 'you must pass an instance of "HttpIncoming" as the first argument to the .fetch() method',
102
+ );
61
103
  const outgoing = new HttpOutgoing(this.#options, reqOptions, incoming);
62
104
 
63
105
  this.#state.setInitializingState();
64
106
 
65
- const { manifest, headers, redirect, isFallback } = await this.#resolver.resolve(
66
- outgoing,
67
- );
107
+ const { manifest, headers, redirect, isFallback } =
108
+ await this.#resolver.resolve(outgoing);
68
109
 
69
110
  const chunks = [];
70
111
  // eslint-disable-next-line no-restricted-syntax
71
112
  for await (const chunk of outgoing) {
72
- chunks.push(chunk)
113
+ chunks.push(chunk);
73
114
  }
74
115
 
75
116
  const content = !outgoing.redirect
@@ -79,24 +120,47 @@ export default class PodiumClientResource {
79
120
  return new Response({
80
121
  headers,
81
122
  content,
82
- css: utils.filterAssets(isFallback ? "fallback" : "content", manifest.css),
83
- js: utils.filterAssets(isFallback ? "fallback" : "content", manifest.js),
123
+ css: utils.filterAssets(
124
+ isFallback ? 'fallback' : 'content',
125
+ manifest.css,
126
+ ),
127
+ js: utils.filterAssets(
128
+ isFallback ? 'fallback' : 'content',
129
+ manifest.js,
130
+ ),
84
131
  redirect,
85
132
  });
86
133
  }
87
134
 
88
- 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');
135
+ /**
136
+ * Stream the podlet's content, or fallback if the podlet is unavailable.
137
+ *
138
+ * @param {import('@podium/utils').HttpIncoming} incoming
139
+ * @param {import('./http-outgoing.js').PodiumClientResourceOptions} [reqOptions={}]
140
+ * @returns {import('./http-outgoing.js').default}
141
+ */
142
+ stream(incoming, reqOptions = {}) {
143
+ if (!utils.validateIncoming(incoming))
144
+ throw new TypeError(
145
+ 'you must pass an instance of "HttpIncoming" as the first argument to the .stream() method',
146
+ );
90
147
  const outgoing = new HttpOutgoing(this.#options, reqOptions, incoming);
91
148
  this.#state.setInitializingState();
92
149
  this.#resolver.resolve(outgoing);
93
150
  return outgoing;
94
151
  }
95
152
 
96
- refresh(incoming = {}, reqOptions = {}) {
153
+ /**
154
+ * Refresh the podlet's manifest and fallback in the cache.
155
+ *
156
+ * @param {import('@podium/utils').HttpIncoming} [incoming]
157
+ * @param {import('./http-outgoing.js').PodiumClientResourceOptions} [reqOptions={}]
158
+ * @returns {Promise<boolean>} `true` if succesful
159
+ */
160
+ refresh(incoming, reqOptions = {}) {
97
161
  const outgoing = new HttpOutgoing(this.#options, reqOptions, incoming);
98
162
  this.#state.setInitializingState();
99
- return this.#resolver.refresh(outgoing).then(obj => obj);
163
+ return this.#resolver.refresh(outgoing).then((obj) => obj);
100
164
  }
101
165
 
102
166
  [inspect]() {
@@ -110,4 +174,4 @@ export default class PodiumClientResource {
110
174
  get [Symbol.toStringTag]() {
111
175
  return 'PodiumClientResource';
112
176
  }
113
- };
177
+ }
package/lib/response.js CHANGED
@@ -1,11 +1,25 @@
1
1
  const inspect = Symbol.for('nodejs.util.inspect.custom');
2
2
 
3
+ /**
4
+ * @typedef {object} PodiumClientResponseOptions
5
+ * @property {string} [content]
6
+ * @property {object} [headers]
7
+ * @property {Array<import('@podium/utils').AssetJs>} [js]
8
+ * @property {Array<import('@podium/utils').AssetCss>} [css]
9
+ * @property {import('./http-outgoing.js').PodiumRedirect | null} [redirect]
10
+ */
11
+
3
12
  export default class PodiumClientResponse {
4
13
  #redirect;
5
14
  #content;
6
15
  #headers;
7
16
  #css;
8
17
  #js;
18
+
19
+ /**
20
+ * @constructor
21
+ * @param {PodiumClientResponseOptions} options
22
+ */
9
23
  constructor({
10
24
  content = '',
11
25
  headers = {},
@@ -71,4 +85,4 @@ export default class PodiumClientResponse {
71
85
  get [Symbol.toStringTag]() {
72
86
  return 'PodiumClientResponse';
73
87
  }
74
- };
88
+ }
package/lib/state.js CHANGED
@@ -2,12 +2,25 @@ import EventEmitter from 'events';
2
2
 
3
3
  const inspect = Symbol.for('nodejs.util.inspect.custom');
4
4
 
5
+ /**
6
+ * @typedef {object} PodiumClientStateOptions
7
+ * @property {number} [resolveThreshold=10000]
8
+ * @property {number} [resolveMax=240000]
9
+ */
10
+
5
11
  export default class PodiumClientState extends EventEmitter {
12
+ /** @type {NodeJS.Timeout | undefined} */
6
13
  #thresholdTimer;
7
14
  #threshold;
15
+ /** @type {NodeJS.Timeout | undefined} */
8
16
  #maxTimer;
17
+ /** @type {"instantiated" | "stable" | "initializing" | "unhealthy" | "unstable"} */
9
18
  #state;
10
19
  #max;
20
+
21
+ /**
22
+ * @param {PodiumClientStateOptions} [options]
23
+ */
11
24
  constructor({
12
25
  resolveThreshold = 10 * 1000,
13
26
  resolveMax = 4 * 60 * 1000,
@@ -113,4 +126,4 @@ export default class PodiumClientState extends EventEmitter {
113
126
  get [Symbol.toStringTag]() {
114
127
  return 'PodiumClientState';
115
128
  }
116
- };
129
+ }
package/lib/utils.js CHANGED
@@ -1,14 +1,12 @@
1
1
  /**
2
- * Checks if a header Oject has a header.
3
- * Will return true if the header exist and are not an empty
4
- * String or a String of whitespace.
2
+ * Checks if a header object has a header.
3
+ * Will return true if the header exist and is not an empty
4
+ * string or a string of whitespace.
5
5
  *
6
- * @param {Object} headers A headers object
7
- * @param {String} header A header value
8
- *
9
- * @returns {Boolean}
6
+ * @param {object} headers
7
+ * @param {string} header
8
+ * @returns {boolean}
10
9
  */
11
-
12
10
  export const isHeaderDefined = (headers, header) => {
13
11
  if (headers[header] === undefined || headers[header].trim() === '') {
14
12
  return false;
@@ -21,31 +19,24 @@ export const isHeaderDefined = (headers, header) => {
21
19
  * the changelog event object emitted from the internal
22
20
  * cache registry.
23
21
  *
24
- * @param {Object} item A changelog event object
25
- *
26
- * @returns {Boolean}
22
+ * @param {object} item A changelog event object
23
+ * @returns {boolean}
27
24
  */
28
-
29
- export const hasManifestChange = item => {
25
+ export const hasManifestChange = (item) => {
30
26
  const oldVersion = item.oldVal ? item.oldVal.version : '';
31
27
  const newVersion = item.newVal ? item.newVal.version : '';
32
28
  return oldVersion !== newVersion;
33
29
  };
34
30
 
35
-
36
31
  /**
37
- * Check if a value is a HttpIncoming object or not. If not, it
32
+ * Check if a value is a Podium HttpIncoming object or not. If not, it
38
33
  * assume the incoming value is a context
39
34
  *
40
- * @param {Object} incoming A object
41
- *
42
- * @returns {HttpIncoming}
43
- */
44
- export const validateIncoming = (incoming = {}) => (Object.prototype.toString.call(incoming) === '[object PodiumHttpIncoming]');
45
-
46
- /**
47
- * @typedef {import("@podium/utils").AssetCss | import("@podium/utils").AssetJs} Asset
35
+ * @param {object} incoming
36
+ * @returns {boolean}
48
37
  */
38
+ export const validateIncoming = (incoming = {}) =>
39
+ Object.prototype.toString.call(incoming) === '[object PodiumHttpIncoming]';
49
40
 
50
41
  /**
51
42
  * Filter assets array based on scope.
@@ -53,9 +44,10 @@ export const validateIncoming = (incoming = {}) => (Object.prototype.toString.ca
53
44
  * If scope property is set to "all", asset will be included.
54
45
  * If scope is set to "content" and asset scope property is set to "fallback", asset will not be included
55
46
  * If scope is set to "fallback" and asset scope property is set to "content", asset will not be included
47
+ * @template {import("@podium/utils").AssetCss | import("@podium/utils").AssetJs} T[]
56
48
  * @param {"content" | "fallback" | "all"} scope
57
- * @param {Asset[]} assets
58
- * @returns {Asset[]}
49
+ * @param {T[]} assets
50
+ * @returns {T[]}
59
51
  *
60
52
  * @example
61
53
  * ```
@@ -69,7 +61,13 @@ export const filterAssets = (scope, assets) => {
69
61
  // if undefined or null, passthrough
70
62
  if (!assets) return assets;
71
63
  // if a non array value is given, throw
72
- if (!Array.isArray(assets)) throw new TypeError(`Asset definition must be of type array. Got ${typeof assets}`);
64
+ if (!Array.isArray(assets))
65
+ throw new TypeError(
66
+ `Asset definition must be of type array. Got ${typeof assets}`,
67
+ );
73
68
  // filter the array of asset definitions to matchin scope or anything with all. Treat no scope the same as "all" for backwards compatibility.
74
- return assets.filter(asset => !asset.scope || asset.scope === scope || asset.scope === "all");
69
+ return assets.filter(
70
+ (asset) =>
71
+ !asset.scope || asset.scope === scope || asset.scope === 'all',
72
+ );
75
73
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@podium/client",
3
- "version": "5.0.20",
3
+ "version": "5.0.22",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -21,18 +21,18 @@
21
21
  "files": [
22
22
  "package.json",
23
23
  "CHANGELOG.md",
24
- "client.d.ts",
25
24
  "README.md",
26
25
  "LICENSE",
27
- "dist",
28
- "lib"
26
+ "lib",
27
+ "types"
29
28
  ],
30
29
  "main": "./lib/client.js",
31
- "types": "client.d.ts",
30
+ "types": "./types/client.d.ts",
32
31
  "scripts": {
33
32
  "lint": "eslint .",
34
33
  "lint:fix": "eslint --fix .",
35
- "test": "tap --disable-coverage --allow-empty-coverage"
34
+ "test": "tap tests/*.js --disable-coverage --allow-empty-coverage && tsc --project tsconfig.test.json",
35
+ "types": "tsc --declaration --emitDeclarationOnly"
36
36
  },
37
37
  "dependencies": {
38
38
  "@hapi/boom": "10.0.1",
@@ -46,14 +46,15 @@
46
46
  "undici": "6.16.1"
47
47
  },
48
48
  "devDependencies": {
49
+ "@babel/eslint-parser": "7.24.5",
49
50
  "@podium/test-utils": "2.5.2",
50
51
  "@semantic-release/changelog": "6.0.3",
51
52
  "@semantic-release/git": "10.0.1",
52
- "@babel/eslint-parser": "7.24.5",
53
53
  "@semantic-release/github": "10.0.3",
54
54
  "@semantic-release/npm": "12.0.0",
55
55
  "@semantic-release/release-notes-generator": "13.0.0",
56
56
  "@sinonjs/fake-timers": "11.2.2",
57
+ "@types/readable-stream": "4.0.14",
57
58
  "benchmark": "2.1.4",
58
59
  "eslint": "8.57.0",
59
60
  "eslint-config-airbnb-base": "15.0.0",
@@ -66,6 +67,7 @@
66
67
  "is-stream": "4.0.1",
67
68
  "prettier": "3.2.5",
68
69
  "semantic-release": "23.0.8",
69
- "tap": "18.7.2"
70
+ "tap": "18.7.2",
71
+ "typescript": "5.4.5"
70
72
  }
71
73
  }