Skip to content

Commit 192a684

Browse files
committed
chore: upgrade to TypeScript 6
1 parent 0dfc309 commit 192a684

15 files changed

Lines changed: 229 additions & 72 deletions

lib/asset-css.js

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export default class PodiumAssetCss {
4242
#hreflang;
4343
#prefix;
4444
#title;
45+
/** @type {string} */
4546
#value;
4647
#media;
4748
#type;
@@ -53,19 +54,19 @@ export default class PodiumAssetCss {
5354
/**
5455
* @constructor
5556
* @param {object} options
56-
* @param {boolean | string | null} [options.crossorigin]
57-
* @param {string | null} [options.hreflang=""]
58-
* @param {boolean | null} [options.prefix=false]
59-
* @param {boolean | null} [options.disabled=false]
60-
* @param {string | null} [options.pathname=""]
61-
* @param {string | null} [options.title=""]
62-
* @param {string | null} [options.media=""]
63-
* @param {string | null} [options.type="text/css"]
64-
* @param {string | null} [options.rel="stylesheet"]
65-
* @param {string | null} [options.as=""]
66-
* @param {string | null} [options.value]
67-
* @param {string | null} [options.strategy]
68-
* @param {string | null} [options.scope]
57+
* @param {boolean | string} [options.crossorigin]
58+
* @param {string} [options.hreflang=""]
59+
* @param {boolean} [options.prefix=false]
60+
* @param {boolean} [options.disabled=false]
61+
* @param {string} [options.pathname=""]
62+
* @param {string} [options.title=""]
63+
* @param {string} [options.media=""]
64+
* @param {string} [options.type="text/css"]
65+
* @param {string} [options.rel="stylesheet"]
66+
* @param {string} [options.as=""]
67+
* @param {string} [options.value]
68+
* @param {string} [options.strategy]
69+
* @param {string} [options.scope]
6970
*/
7071
constructor({
7172
crossorigin = undefined,
@@ -89,7 +90,7 @@ export default class PodiumAssetCss {
8990

9091
this.#pathname = pathname;
9192
this.#prefix = prefix;
92-
this.#value = value;
93+
this.#value = /** @type {string} */ (value);
9394

9495
this.#crossorigin = crossorigin;
9596
this.#disabled = disabled;

lib/asset-js.js

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export default class PodiumAssetJs {
4444
#pathname;
4545
#nomodule;
4646
#prefix;
47+
/** @type {string} */
4748
#value;
4849
#async;
4950
#defer;
@@ -55,19 +56,19 @@ export default class PodiumAssetJs {
5556
/**
5657
* @constructor
5758
* @param {object} options
58-
* @param {string | null} [options.referrerpolicy]
59-
* @param {boolean | string | null} [options.crossorigin]
60-
* @param {string | null} [options.integrity]
61-
* @param {string | null} [options.pathname]
62-
* @param {boolean | null} [options.nomodule=false]
63-
* @param {boolean | null} [options.prefix=false]
64-
* @param {string | null} [options.value]
65-
* @param {boolean | null} [options.async=false]
66-
* @param {boolean | null} [options.defer=false]
67-
* @param {string | null} [options.type="default"]
68-
* @param {array} [options.data]
69-
* @param {string | null} [options.strategy]
70-
* @param {string | null} [options.scope]
59+
* @param {string} [options.referrerpolicy]
60+
* @param {boolean | string} [options.crossorigin]
61+
* @param {string} [options.integrity]
62+
* @param {string} [options.pathname]
63+
* @param {boolean} [options.nomodule=false]
64+
* @param {boolean} [options.prefix=false]
65+
* @param {string} [options.value]
66+
* @param {boolean} [options.async=false]
67+
* @param {boolean} [options.defer=false]
68+
* @param {string} [options.type="default"]
69+
* @param {Array<{ key: string, value?: unknown }>} [options.data]
70+
* @param {string} [options.strategy]
71+
* @param {string} [options.scope]
7172
*/
7273
constructor({
7374
referrerpolicy = '',
@@ -92,7 +93,7 @@ export default class PodiumAssetJs {
9293

9394
this.#pathname = pathname;
9495
this.#prefix = prefix;
95-
this.#value = value;
96+
this.#value = /** @type {string} */ (value);
9697

9798
this.#referrerpolicy = referrerpolicy;
9899
this.#crossorigin = crossorigin;
@@ -239,10 +240,9 @@ export default class PodiumAssetJs {
239240
.filter(([key, value]) => value && key !== 'value')
240241
.flatMap(([key, value]) => {
241242
if (key === 'data') {
242-
// @ts-ignore
243-
return value.map(
244-
({ key, value }) => `data-${key}=${value}`,
245-
);
243+
return /** @type {Array<{ key: string, value?: unknown }>} */ (
244+
value
245+
).map(({ key, value }) => `data-${key}=${value}`);
246246
}
247247
return [`${key}=${value}`];
248248
});

lib/assets.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@ import { EventEmitter } from 'node:events';
33
export class Assets extends EventEmitter {
44
#expectedAssets = new Set();
55
#receivedAssets = new Map();
6-
#js;
7-
#css;
6+
7+
/** @type {Array<import('./asset-js.js').JavaScriptAsset | string>} */
8+
#js = [];
9+
10+
/** @type {Array<import('./asset-css.js').CssAsset | string>} */
11+
#css = [];
812

913
// pointless constructor with super to appease TS which cryptically errors otherwise.
1014
constructor() {

lib/html-document.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export const document = (incoming, body = '', head = '') => {
1313
incoming.view.locale ||
1414
incoming.context['podium-locale'] ||
1515
incoming.context.locale ||
16-
incoming.params.locale ||
16+
incoming.params?.locale ||
1717
'en-US';
1818

1919
// backwards compatibility for scripts and styles
@@ -28,13 +28,17 @@ export const document = (incoming, body = '', head = '') => {
2828
<meta charset="${incoming.view.encoding ? incoming.view.encoding : 'utf-8'}">
2929
<meta name="viewport" content="width=device-width, initial-scale=1">
3030
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
31-
${styles.map(utils.buildLinkElement).join('\n ')}
31+
${
32+
// @ts-expect-error We filter out strings before this
33+
styles.map(utils.buildLinkElement).join('\n ')
34+
}
3235
${scripts
3336
.filter(
3437
(script) =>
3538
typeof script !== 'string' &&
3639
script.strategy === 'beforeInteractive',
3740
)
41+
// @ts-expect-error We filter out strings before this
3842
.map(utils.buildScriptElement)
3943
.join('\n ')}
4044
<title>${incoming.view.title ? incoming.view.title : ''}</title>
@@ -49,6 +53,7 @@ export const document = (incoming, body = '', head = '') => {
4953
script.strategy === 'afterInteractive' ||
5054
!script.strategy,
5155
)
56+
// @ts-expect-error We filter out strings before this
5257
.map(utils.buildScriptElement)
5358
.join('\n ')}
5459
${scripts

lib/html-utils.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export const buildScriptAttributes = (obj) => {
7171
* @returns {object}
7272
*/
7373
export const buildReactScriptAttributes = (obj) => {
74+
/** @type {Record<string, unknown>} */
7475
const attrs = {};
7576
for (const { key, value } of buildScriptAttributes(obj)) {
7677
if (key === 'crossorigin') attrs.crossOrigin = value || '';
@@ -145,6 +146,7 @@ export const buildLinkAttributes = (obj) => {
145146
* @returns {object}
146147
*/
147148
export const buildReactLinkAttributes = (obj) => {
149+
/** @type {Record<string, unknown>} */
148150
const attrs = {};
149151
for (const { key, value } of buildLinkAttributes(obj)) {
150152
if (key === 'crossorigin') attrs.crossOrigin = value || '';

lib/html.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import escapeHtml from 'escape-html';
33
/**
44
* Escape an untrusted string so it can be safely included in HTML.
55
*
6-
* @param {unknown} string
6+
* @param {string | null | undefined} string
77
* @returns {string}
88
*/
99
export function escape(string) {
@@ -38,7 +38,7 @@ export function html(strings, ...values) {
3838
/** @type {DangerouslyIncludeUnescapedHTML} */ (value).content,
3939
);
4040
} else {
41-
result.push(escape(value));
41+
result.push(escape(String(value)));
4242
}
4343
}
4444
result.push(strings.at(-1));
@@ -61,6 +61,9 @@ export function html(strings, ...values) {
6161
export class DangerouslyIncludeUnescapedHTML {
6262
#content;
6363

64+
/**
65+
* @param {{ __content: string}} param0
66+
*/
6467
constructor({ __content }) {
6568
this.#content = __content;
6669
}

lib/http-incoming.js

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,16 @@ import { Assets } from './assets.js';
33

44
const inspect = Symbol.for('nodejs.util.inspect.custom');
55

6+
/**
7+
* @param {unknown} request
8+
* @returns {URL}
9+
*/
610
const urlFromRequest = (request) => {
11+
// @ts-expect-error
712
const protocol = request?.protocol || 'http';
13+
// @ts-expect-error
814
const host = request?.headers?.host || 'localhost';
15+
// @ts-expect-error
916
const url = request?.url || '';
1017
return new URL(url, `${protocol.replace(':', '')}://${host}`);
1118
};
@@ -135,15 +142,21 @@ export default class HttpIncoming {
135142

136143
podlets.forEach((podlet) => {
137144
if (podlet.css) {
138-
podlet.css.forEach((item) => {
139-
this.#css.push(item);
140-
});
145+
podlet.css.forEach(
146+
/** @param {import("./asset-css.js").CssAsset} item */
147+
(item) => {
148+
this.#css.push(item);
149+
},
150+
);
141151
}
142152

143153
if (podlet.js) {
144-
podlet.js.forEach((item) => {
145-
this.#js.push(item);
146-
});
154+
podlet.js.forEach(
155+
/** @param {import("./asset-js.js").JavaScriptAsset} item */
156+
(item) => {
157+
this.#js.push(item);
158+
},
159+
);
147160
}
148161
});
149162
}

lib/utils.js

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,15 +114,20 @@ export const uriRelativeToAbsolute = (input = '', base = '', extra = '') => {
114114
* @returns {object} The http response object
115115
*/
116116
export const setAtLocalsPodium = (response = {}, property, value) => {
117+
// @ts-expect-error We know response is an object
117118
if (!response.locals) {
119+
// @ts-expect-error We know response is an object
118120
response.locals = {};
119121
}
120122

123+
// @ts-expect-error We know response is an object
121124
if (!response.locals.podium) {
125+
// @ts-expect-error We know response is an object
122126
response.locals.podium = {};
123127
}
124128

125129
if (isString(property) && property !== '') {
130+
// @ts-expect-error We know response is an object
126131
response.locals.podium[property] = value;
127132
}
128133

@@ -133,20 +138,23 @@ export const setAtLocalsPodium = (response = {}, property, value) => {
133138
* Get the value from a property on .locals.podium on an HTTP response object.
134139
* Ensures that .locals.podium exists on the http response object.
135140
*
136-
* @param {object} [response] An HTTP response object.
141+
* @param {unknown} [response] An HTTP response object.
137142
* @param {string} [property] Property for the value.
138143
* @returns {object | null} The property, or `null` if it does not exist.
139144
*/
140145
export const getFromLocalsPodium = (response = {}, property) => {
146+
// @ts-expect-error We know response is an object
141147
if (!response.locals) {
142148
return null;
143149
}
144150

151+
// @ts-expect-error We know response is an object
145152
if (!response.locals.podium) {
146153
return null;
147154
}
148155

149156
if (isString(property) && property !== '') {
157+
// @ts-expect-error We know response is an object
150158
return response.locals.podium[property];
151159
}
152160

@@ -175,8 +183,8 @@ export const duplicateOnLocalsPodium = (
175183
/**
176184
* Serialize a context object into an HTTP header object, calling the function if a context value is callable.
177185
*
178-
* @param {object} [headers={}] An HTTP headers object the context will be copied to.
179-
* @param {object} [context={}] A context object to copy from.
186+
* @param {Record<string, string>} [headers={}] An HTTP headers object the context will be copied to.
187+
* @param {Record<string, string | ((arg: unknown) => string)>} [context={}] A context object to copy from.
180188
* @param {unknown} [arg=""] An argument value passed on to the function if a context value is a function.
181189
* @returns {object} An object with deserialized context properties and values.
182190
*
@@ -193,14 +201,18 @@ export const duplicateOnLocalsPodium = (
193201
* ```
194202
*/
195203
export const serializeContext = (headers = {}, context = {}, arg = '') => {
204+
/** @type {Record<string, string>} */
196205
const localHeaders = headers;
197206
Object.keys(context).forEach((key) => {
198207
if (isString(context[key])) {
199-
localHeaders[key] = context[key];
208+
localHeaders[key] = /** @type {string} */ (context[key]);
200209
}
201210

202211
if (isFunction(context[key])) {
203-
localHeaders[key] = context[key](arg);
212+
const contextFn = /** @type {((arg: unknown) => string)} */ (
213+
context[key]
214+
);
215+
localHeaders[key] = contextFn(arg);
204216
}
205217
});
206218
return localHeaders;
@@ -209,7 +221,7 @@ export const serializeContext = (headers = {}, context = {}, arg = '') => {
209221
/**
210222
* Deserialize a context object from an HTTP header object.
211223
*
212-
* @param {object} [headers={}] An HTTP headers object the context will be extracted from.
224+
* @param {Record<string, string>} [headers={}] An HTTP headers object the context will be extracted from.
213225
* @param {string} [prefix="podium"] The prefix used to mark what properties are context properties.
214226
* @returns {object} An object with deserialized context properties and values.
215227
*
@@ -225,6 +237,7 @@ export const serializeContext = (headers = {}, context = {}, arg = '') => {
225237
* ```
226238
*/
227239
export const deserializeContext = (headers = {}, prefix = 'podium') => {
240+
/** @type {Record<string, string>} */
228241
const context = {};
229242
Object.keys(headers).forEach((key) => {
230243
if (key.startsWith(prefix)) {

0 commit comments

Comments
 (0)