@podium/podlet 5.1.19 → 5.2.0-next.10
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 +7 -0
- package/README.md +65 -11
- package/lib/podlet.js +132 -36
- package/package.json +4 -3
- package/types/podlet.d.ts +51 -27
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [5.2.0-next.10](https://github.com/podium-lib/podlet/compare/v5.2.0-next.9...v5.2.0-next.10) (2024-11-06)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **deps:** update dependency @podium/proxy to v5.0.29 ([0bbc78b](https://github.com/podium-lib/podlet/commit/0bbc78b07a7f3059cb8f659a23c75896c1081b2f))
|
|
7
|
+
|
|
1
8
|
## [5.1.19](https://github.com/podium-lib/podlet/compare/v5.1.18...v5.1.19) (2024-11-04)
|
|
2
9
|
|
|
3
10
|
|
package/README.md
CHANGED
|
@@ -79,20 +79,23 @@ const podlet = new Podlet(options);
|
|
|
79
79
|
|
|
80
80
|
### options
|
|
81
81
|
|
|
82
|
-
| option
|
|
83
|
-
|
|
|
84
|
-
| name
|
|
85
|
-
| version
|
|
86
|
-
| pathname
|
|
87
|
-
| manifest
|
|
88
|
-
| content
|
|
89
|
-
| fallback
|
|
90
|
-
| logger
|
|
91
|
-
| development
|
|
82
|
+
| option | type | default | required |
|
|
83
|
+
| ------------ | --------- | ---------------- | -------- |
|
|
84
|
+
| name | `string` | | ✓ |
|
|
85
|
+
| version | `string` | | ✓ |
|
|
86
|
+
| pathname | `string` | | ✓ |
|
|
87
|
+
| manifest | `string` | `/manifest.json` | |
|
|
88
|
+
| content | `string` | `/` | |
|
|
89
|
+
| fallback | `string` | | |
|
|
90
|
+
| logger | `object` | | |
|
|
91
|
+
| development | `boolean` | `false` | |
|
|
92
|
+
| useShadowDOM | `boolean` | `false` | |
|
|
92
93
|
|
|
93
94
|
#### name
|
|
94
95
|
|
|
95
|
-
The name the podlet identifies itself by. This value
|
|
96
|
+
The name the podlet identifies itself by. This value can contain upper and lower case letters, numbers, the - character and the \_ character. No spaces.
|
|
97
|
+
When shadow DOM is used, either via the `useShadowDOM` constructor option or via the `wrapWithShadowDOM` method, the name must comply with custom element naming rules.
|
|
98
|
+
See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define#valid_custom_element_names) for more information.
|
|
96
99
|
|
|
97
100
|
_Example:_
|
|
98
101
|
|
|
@@ -257,6 +260,53 @@ further details.
|
|
|
257
260
|
|
|
258
261
|
Turns development mode on or off. See the section about development mode.
|
|
259
262
|
|
|
263
|
+
#### useShadowDOM
|
|
264
|
+
|
|
265
|
+
Turns declarative shadow DOM encapsulation on for the podlet. When enabled, the podlet content will be wrapped inside a declarative shadow DOM wrapper to isolate it from the rest of whichever
|
|
266
|
+
page it is being included on.
|
|
267
|
+
|
|
268
|
+
```js
|
|
269
|
+
const podlet = new Podlet({ ..., useShadowDOM: true });
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
Please note the following caveats when using this feature:
|
|
273
|
+
|
|
274
|
+
1. You must name your podlet following custom element naming conventions as explained here: https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define#valid_custom_element_names
|
|
275
|
+
2. In order to style your content, you will need to include your CSS inside the shadow DOM wrapper. You can do this using one of the following 2 options:
|
|
276
|
+
|
|
277
|
+
You can include a `<style>` tag before your content
|
|
278
|
+
|
|
279
|
+
```js
|
|
280
|
+
res.podiumSend(`
|
|
281
|
+
<style>
|
|
282
|
+
...styles here...
|
|
283
|
+
</style>
|
|
284
|
+
<div>...content here...</div>
|
|
285
|
+
`);
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
You can have your podlet CSS included for you by using the "shadow-dom" scope
|
|
289
|
+
|
|
290
|
+
```js
|
|
291
|
+
podlet.css({ value: '/path/to/css', scope: 'shadow-dom' });
|
|
292
|
+
res.podiumSend(`
|
|
293
|
+
<div>...content here...</div>
|
|
294
|
+
`);
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
For more fine grained control, you can use the `podlet.wrapWithShadowDOM` method directly
|
|
298
|
+
|
|
299
|
+
```js
|
|
300
|
+
const podlet = new Podlet({ ..., useShadowDOM: false });
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
```js
|
|
304
|
+
const wrapped = podlet.wrapWithShadowDOM(`<div>...content here...</div>`);
|
|
305
|
+
res.podiumSend(`
|
|
306
|
+
${wrapped}
|
|
307
|
+
`);
|
|
308
|
+
```
|
|
309
|
+
|
|
260
310
|
## Podlet Instance
|
|
261
311
|
|
|
262
312
|
The podlet instance has the following API:
|
|
@@ -551,6 +601,8 @@ Sets the pathname for a podlet's javascript assets.
|
|
|
551
601
|
When a value is set it will be internally kept and used when the podlet
|
|
552
602
|
instance is serialized into a manifest JSON string.
|
|
553
603
|
|
|
604
|
+
In addition, JS information will be serialized into a Link header and sent as an HTTP 103 early hint with content and fallback responses so that the layout client can get access to assets before the main podlet body. The layout can use this information to generate 103 early hints for the browser so that the browser can begin downloading asset files while still waiting for the podlet and layout bodys.
|
|
605
|
+
|
|
554
606
|
### options
|
|
555
607
|
|
|
556
608
|
| option | type | default | required |
|
|
@@ -647,6 +699,8 @@ Sets the options for a podlet's CSS assets.
|
|
|
647
699
|
When a value is set it will be internally kept and used when the podlet
|
|
648
700
|
instance is serialized into a manifest JSON string.
|
|
649
701
|
|
|
702
|
+
In addition, CSS information will be serialized into a Link header and sent as an HTTP 103 early hint with content and fallback responses so that the layout client can get access to assets before the main podlet body. The layout can use this information to generate 103 early hints for the browser so that the browser can begin downloading asset files while still waiting for the podlet and layout bodys.
|
|
703
|
+
|
|
650
704
|
### options
|
|
651
705
|
|
|
652
706
|
| option | type | default | required |
|
package/lib/podlet.js
CHANGED
|
@@ -7,12 +7,18 @@ import {
|
|
|
7
7
|
import * as schema from '@podium/schemas';
|
|
8
8
|
import Metrics from '@metrics/client';
|
|
9
9
|
import abslog from 'abslog';
|
|
10
|
+
// @ts-ignore
|
|
10
11
|
import objobj from 'objobj';
|
|
11
12
|
import * as utils from '@podium/utils';
|
|
12
13
|
import Proxy from '@podium/proxy';
|
|
13
14
|
import { join, dirname } from 'node:path';
|
|
14
15
|
import { fileURLToPath } from 'node:url';
|
|
16
|
+
// @ts-ignore
|
|
15
17
|
import fs from 'node:fs';
|
|
18
|
+
import assert from 'node:assert';
|
|
19
|
+
|
|
20
|
+
const customElementRegex =
|
|
21
|
+
/^(?!(annotation-xml|color-profile|font-face|font-face-src|font-face-uri|font-face-format|font-face-name|missing-glyph)$)[a-z][a-z0-9.-]*-[a-z0-9.-]*$/;
|
|
16
22
|
|
|
17
23
|
const currentDirectory = dirname(fileURLToPath(import.meta.url));
|
|
18
24
|
const pkgJson = fs.readFileSync(
|
|
@@ -25,19 +31,20 @@ const { template } = utils;
|
|
|
25
31
|
|
|
26
32
|
/**
|
|
27
33
|
* @typedef {Object} PodletOptions
|
|
28
|
-
* @property {string} name -
|
|
29
|
-
* @property {string} version -
|
|
30
|
-
* @property {string} pathname -
|
|
31
|
-
* @property {string} [manifest="/manifest.json"] -
|
|
32
|
-
* @property {string} [content="/"] -
|
|
33
|
-
* @property {string} [fallback=""] -
|
|
34
|
-
* @property {boolean} [development=false] - a boolean flag that, when true, enables additional development setup
|
|
35
|
-
* @property {
|
|
34
|
+
* @property {string} name - (required) podlet name
|
|
35
|
+
* @property {string} version - (required) podlet version
|
|
36
|
+
* @property {string} pathname - (required) podlet pathname
|
|
37
|
+
* @property {string} [manifest="/manifest.json"] - path where the podlet manifest file is served from (default '/manifest.json')
|
|
38
|
+
* @property {string} [content="/"] - path where the podlet content HTML markup is served from (default '/')
|
|
39
|
+
* @property {string} [fallback=""] - path where the podlet fallback HTML markup is served from (default '/fallback')
|
|
40
|
+
* @property {boolean} [development=false] - a boolean flag that, when true, enables additional development setup (default false)
|
|
41
|
+
* @property {boolean} [useShadowDOM=false] - a boolean flag that, when true, enables the use of ShadowDOM (default false)
|
|
42
|
+
* @property {import("abslog").AbstractLoggerOptions} [logger] - a logger to use when provided. Can be the console object if console logging is desired but can also be any Log4j compatible logging object as well. Nothing is logged if no logger is provided. (default null)
|
|
36
43
|
* @property {import("@podium/proxy").PodiumProxyOptions} [proxy] - options that can be provided to configure the @podium/proxy instance used by the podlet. See that module for details.
|
|
37
44
|
*
|
|
38
45
|
* @typedef {{ debug: 'true' | 'false', locale: string, deviceType: string, requestedBy: string, mountOrigin: string, mountPathname: string, publicPathname: string }} PodletContext
|
|
39
|
-
* @typedef {{ as?: string | false | null, crossorigin?: string | null | boolean, disabled?: boolean | '' | null, hreflang?: string | false | null, title?: string | false | null, media?: string | false | null, rel?: string | false | null, type?: string | false | null, value: string | false | null,
|
|
40
|
-
* @typedef {{ value: string | null, crossorigin?: string | null | boolean, type?: string | null | false, integrity?: string | null | false, referrerpolicy?: string | null | false, nomodule?: boolean | null | '', async?: boolean | null | '', defer?: boolean | null | '', data?: Array<{ key: string; value: string }>, strategy?: "beforeInteractive" | "afterInteractive" | "lazy", scope?: "content" | "fallback" | "all", [key: string]: any }} AssetJsLike
|
|
46
|
+
* @typedef {{ as?: string | false | null, crossorigin?: string | null | boolean, disabled?: boolean | '' | null, hreflang?: string | false | null, title?: string | false | null, media?: string | false | null, rel?: string | false | null, type?: string | false | null, value: string | false | null, strategy?: "beforeInteractive" | "afterInteractive" | "lazy" | "shadow-dom", scope?: "content" | "fallback" | "all", [key: string]: any }} AssetCssLike
|
|
47
|
+
* @typedef {{ value: string | null, crossorigin?: string | null | boolean, type?: string | null | false, integrity?: string | null | false, referrerpolicy?: string | null | false, nomodule?: boolean | null | '', async?: boolean | null | '', defer?: boolean | null | '', data?: {[key: string]: string} | Array<{ key: string; value: string }>, strategy?: "beforeInteractive" | "afterInteractive" | "lazy" | "shadow-dom", scope?: "content" | "fallback" | "all" | "shadow-dom", [key: string]: any }} AssetJsLike
|
|
41
48
|
*/
|
|
42
49
|
|
|
43
50
|
export default class PodiumPodlet {
|
|
@@ -281,10 +288,26 @@ export default class PodiumPodlet {
|
|
|
281
288
|
*/
|
|
282
289
|
metrics = new Metrics();
|
|
283
290
|
|
|
291
|
+
/**
|
|
292
|
+
* Boolean flag that, when true, enables the use of declarative ShadowDOM in the podlet.
|
|
293
|
+
*/
|
|
294
|
+
#useShadowDOM = false;
|
|
295
|
+
|
|
284
296
|
/**
|
|
285
297
|
* Creates a new instance of a Podium podlet which can be used in conjunction with your framework of choice to build podlet server apps.
|
|
286
298
|
* `name`, `version` and `pathname` constructor arguments are required. All other options are optional.
|
|
287
299
|
*
|
|
300
|
+
* * `name` - podlet name (**required**)
|
|
301
|
+
* * `version` - podlet version (**required**)
|
|
302
|
+
* * `pathname` - podlet pathname (**required**)
|
|
303
|
+
* * `manifest` - path where the podlet manifest file is served from (**default** `'/manifest.json'`)
|
|
304
|
+
* * `content` - path where the podlet content HTML markup is served from (**default** `'/'`)
|
|
305
|
+
* * `fallback` - path where the podlet fallback HTML markup is served from (**default** `'/fallback'`)
|
|
306
|
+
* * `development` - a boolean flag that, when true, enables additional development setup (**default** `false`)
|
|
307
|
+
* * `useShadowDOM` - a boolean flag that, when true, enables the use of declarative ShadowDOM in the podlet (**default** `false`)
|
|
308
|
+
* * `logger` - a logger to use when provided. Can be the console object if console logging is desired but can also be any Log4j compatible logging object as well. Nothing is logged if no logger is provided. (**default** `null`)
|
|
309
|
+
* * `proxy` - options that can be provided to configure the @podium/proxy instance used by the podlet. See that module for details. (**default**: `{}`)
|
|
310
|
+
*
|
|
288
311
|
* @see https://podium-lib.io/docs/api/podlet/#constructor
|
|
289
312
|
* @see https://podium-lib.io/docs/podlet/getting_started
|
|
290
313
|
*
|
|
@@ -305,6 +328,7 @@ export default class PodiumPodlet {
|
|
|
305
328
|
logger = undefined,
|
|
306
329
|
development = false,
|
|
307
330
|
proxy = {},
|
|
331
|
+
useShadowDOM = false,
|
|
308
332
|
}) {
|
|
309
333
|
if (schema.name(name).error)
|
|
310
334
|
throw new Error(
|
|
@@ -362,6 +386,7 @@ export default class PodiumPodlet {
|
|
|
362
386
|
this.name,
|
|
363
387
|
),
|
|
364
388
|
};
|
|
389
|
+
this.#useShadowDOM = useShadowDOM;
|
|
365
390
|
|
|
366
391
|
// Skip a tick to ensure the metric stream has been consumed
|
|
367
392
|
setImmediate(() => {
|
|
@@ -517,9 +542,9 @@ export default class PodiumPodlet {
|
|
|
517
542
|
* Takes an AssetCss instance or an object with equivalent properties, converts it to an AssetCss instance if necessary and adds it to the
|
|
518
543
|
* cssRoute array.
|
|
519
544
|
* @param { AssetCss | AssetCssLike } options
|
|
520
|
-
* @returns {
|
|
545
|
+
* @returns {AssetCss}
|
|
521
546
|
*/
|
|
522
|
-
#
|
|
547
|
+
#cssAsset(options) {
|
|
523
548
|
const clonedOptions = JSON.parse(JSON.stringify(options));
|
|
524
549
|
clonedOptions.value = this.#sanitize(
|
|
525
550
|
clonedOptions.value,
|
|
@@ -530,7 +555,7 @@ export default class PodiumPodlet {
|
|
|
530
555
|
...clonedOptions,
|
|
531
556
|
pathname: this.#pathname,
|
|
532
557
|
};
|
|
533
|
-
|
|
558
|
+
return new AssetCss(args);
|
|
534
559
|
}
|
|
535
560
|
|
|
536
561
|
/**
|
|
@@ -555,20 +580,19 @@ export default class PodiumPodlet {
|
|
|
555
580
|
css(options) {
|
|
556
581
|
if (Array.isArray(options)) {
|
|
557
582
|
for (const opts of options) {
|
|
558
|
-
this.#
|
|
583
|
+
this.cssRoute.push(this.#cssAsset(opts));
|
|
559
584
|
}
|
|
560
585
|
return;
|
|
561
586
|
}
|
|
562
|
-
this.#
|
|
587
|
+
this.cssRoute.push(this.#cssAsset(options));
|
|
563
588
|
}
|
|
564
589
|
|
|
565
590
|
/**
|
|
566
|
-
* Takes an AssetJs instance or an object with equivalent properties, converts it to an AssetJs instance if necessary and
|
|
567
|
-
* jsRoute array.
|
|
591
|
+
* Takes an AssetJs instance or an object with equivalent properties, converts it to an AssetJs instance if necessary and returns it.
|
|
568
592
|
* @param { AssetJs | AssetJsLike } options
|
|
569
|
-
* @returns {
|
|
593
|
+
* @returns {AssetJs}
|
|
570
594
|
*/
|
|
571
|
-
#
|
|
595
|
+
#jsAsset(options) {
|
|
572
596
|
const clonedOptions = JSON.parse(JSON.stringify(options));
|
|
573
597
|
clonedOptions.value = this.#sanitize(
|
|
574
598
|
clonedOptions.value,
|
|
@@ -581,19 +605,31 @@ export default class PodiumPodlet {
|
|
|
581
605
|
pathname: this.#pathname,
|
|
582
606
|
};
|
|
583
607
|
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
608
|
+
if (args.data) {
|
|
609
|
+
// validate that key value objects provided are compliant
|
|
610
|
+
if (Array.isArray(args.data)) {
|
|
611
|
+
for (const data of args.data) {
|
|
612
|
+
if (!data.key || !data.value) {
|
|
613
|
+
throw new TypeError(
|
|
614
|
+
`JS Asset data object "${JSON.stringify(data)}" must contain both a 'key' and a 'value' attribute.`,
|
|
615
|
+
);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
// Convert data attribute object structure to array of key value objects
|
|
620
|
+
else if (typeof args.data === 'object') {
|
|
621
|
+
const data = [];
|
|
622
|
+
Object.keys(args.data).forEach((key) => {
|
|
623
|
+
data.push({
|
|
624
|
+
value: args.data[key],
|
|
625
|
+
key,
|
|
626
|
+
});
|
|
591
627
|
});
|
|
592
|
-
|
|
593
|
-
|
|
628
|
+
args.data = data;
|
|
629
|
+
}
|
|
594
630
|
}
|
|
595
631
|
|
|
596
|
-
|
|
632
|
+
return new AssetJs(args);
|
|
597
633
|
}
|
|
598
634
|
|
|
599
635
|
/**
|
|
@@ -618,11 +654,11 @@ export default class PodiumPodlet {
|
|
|
618
654
|
js(options) {
|
|
619
655
|
if (Array.isArray(options)) {
|
|
620
656
|
for (const opts of options) {
|
|
621
|
-
this.#
|
|
657
|
+
this.jsRoute.push(this.#jsAsset(opts));
|
|
622
658
|
}
|
|
623
659
|
return;
|
|
624
660
|
}
|
|
625
|
-
this.#
|
|
661
|
+
this.jsRoute.push(this.#jsAsset(options));
|
|
626
662
|
}
|
|
627
663
|
|
|
628
664
|
/**
|
|
@@ -800,10 +836,50 @@ export default class PodiumPodlet {
|
|
|
800
836
|
* @returns {string}
|
|
801
837
|
*/
|
|
802
838
|
render(incoming, data, ...args) {
|
|
839
|
+
const markup = this.#useShadowDOM ? this.wrapWithShadowDOM(data) : data;
|
|
803
840
|
if (!incoming.development) {
|
|
804
|
-
return
|
|
841
|
+
return markup;
|
|
805
842
|
}
|
|
806
|
-
return this.#view(incoming,
|
|
843
|
+
return this.#view(incoming, markup, ...args);
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
/**
|
|
847
|
+
* Function that takes in the podlet content,wraps it in declarative shadow DOM and returns it.
|
|
848
|
+
* @param {string} data - the podlet content to wrap in declarative shadow DOM as an HTML markup string
|
|
849
|
+
*
|
|
850
|
+
* @example
|
|
851
|
+
* ```js
|
|
852
|
+
* const content = podlet.wrapWithShadowDOM('<div>content to render</div>');
|
|
853
|
+
* ```
|
|
854
|
+
*/
|
|
855
|
+
wrapWithShadowDOM(data) {
|
|
856
|
+
assert.ok(
|
|
857
|
+
customElementRegex.test(this.name),
|
|
858
|
+
`When using the constructor argument "useShadowDOM" or the method podlet.wrapWithShadowDOM, podlet.name must conform to custom element naming conventions. The name "${this.name}" does not comply. See https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry/define#valid_custom_element_names for more information.`,
|
|
859
|
+
);
|
|
860
|
+
|
|
861
|
+
const styles = this.cssRoute
|
|
862
|
+
.filter((css) => css.strategy === 'shadow-dom')
|
|
863
|
+
.map((css) => css.toHTML());
|
|
864
|
+
|
|
865
|
+
const scripts = this.jsRoute
|
|
866
|
+
.filter((js) => js.strategy === 'shadow-dom')
|
|
867
|
+
.map((js) => js.toHTML());
|
|
868
|
+
|
|
869
|
+
// Wrap the markup in DSD.
|
|
870
|
+
return `
|
|
871
|
+
<${this.name}>
|
|
872
|
+
<template shadowrootmode="open">
|
|
873
|
+
${styles.join('\n')}
|
|
874
|
+
${data}
|
|
875
|
+
${scripts.join('\n')}
|
|
876
|
+
</template>
|
|
877
|
+
</${this.name}>
|
|
878
|
+
<script>(()=>{function e(d){HTMLTemplateElement.prototype.hasOwnProperty("shadowRootMode")||d.querySelectorAll("template[shadowrootmode]").forEach(o=>{let
|
|
879
|
+
n=o.getAttribute("shadowrootmode"),s=o.hasAttribute("shadowrootdelegatesfocus"),t=o.parentNode.attachShadow({mode:n,delegatesFocus:s});t.appendChild(o.content),o.remove(),e(t)})}var
|
|
880
|
+
r;(r=document.currentScript)!=null&&r.previousElementSibling&&e(document.currentScript.previousElementSibling);})();
|
|
881
|
+
</script>
|
|
882
|
+
`;
|
|
807
883
|
}
|
|
808
884
|
|
|
809
885
|
/**
|
|
@@ -865,8 +941,9 @@ export default class PodiumPodlet {
|
|
|
865
941
|
);
|
|
866
942
|
}
|
|
867
943
|
|
|
868
|
-
//
|
|
944
|
+
// Determine if the request should be proxied and do if so
|
|
869
945
|
if (incoming.development && proxy) {
|
|
946
|
+
// @ts-ignore
|
|
870
947
|
await this.httpProxy.process(incoming);
|
|
871
948
|
}
|
|
872
949
|
|
|
@@ -903,6 +980,18 @@ export default class PodiumPodlet {
|
|
|
903
980
|
// if this is a proxy request then no further work should be done.
|
|
904
981
|
if (incoming.proxy) return;
|
|
905
982
|
|
|
983
|
+
const js = incoming.js.map(
|
|
984
|
+
// @ts-ignore
|
|
985
|
+
(asset) => asset.toHeader() + '; asset-type=script',
|
|
986
|
+
);
|
|
987
|
+
|
|
988
|
+
const css = incoming.css.map(
|
|
989
|
+
// @ts-ignore
|
|
990
|
+
(asset) => asset.toHeader() + '; asset-type=style',
|
|
991
|
+
);
|
|
992
|
+
|
|
993
|
+
res.header('Link', [...js, ...css].join(', '));
|
|
994
|
+
|
|
906
995
|
// set "incoming" on res.locals.podium
|
|
907
996
|
objobj.set('locals.podium', incoming, res);
|
|
908
997
|
|
|
@@ -910,8 +999,15 @@ export default class PodiumPodlet {
|
|
|
910
999
|
res.header('podlet-version', this.version);
|
|
911
1000
|
}
|
|
912
1001
|
|
|
913
|
-
res.
|
|
914
|
-
res.
|
|
1002
|
+
res.sendHeaders = () => {
|
|
1003
|
+
res.write('');
|
|
1004
|
+
return res;
|
|
1005
|
+
};
|
|
1006
|
+
|
|
1007
|
+
res.podiumSend = (data, ...args) => {
|
|
1008
|
+
res.write(this.render(incoming, data, ...args));
|
|
1009
|
+
res.end();
|
|
1010
|
+
};
|
|
915
1011
|
|
|
916
1012
|
next();
|
|
917
1013
|
} catch (error) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@podium/podlet",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.2.0-next.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Module for building page fragment servers in a micro frontend architecture.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@metrics/client": "2.5.3",
|
|
37
|
+
"@podium/schemas": "5.1.0",
|
|
37
38
|
"@podium/proxy": "5.0.29",
|
|
38
|
-
"@podium/schemas": "5.0.6",
|
|
39
39
|
"@podium/utils": "5.3.1",
|
|
40
40
|
"abslog": "2.4.4",
|
|
41
41
|
"ajv": "8.17.1",
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
"prettier": "3.3.3",
|
|
56
56
|
"semantic-release": "24.1.2",
|
|
57
57
|
"tap": "18.8.0",
|
|
58
|
-
"typescript": "5.5.4"
|
|
58
|
+
"typescript": "5.5.4",
|
|
59
|
+
"undici": "^6.19.7"
|
|
59
60
|
}
|
|
60
61
|
}
|
package/types/podlet.d.ts
CHANGED
|
@@ -73,25 +73,37 @@ declare global {
|
|
|
73
73
|
|
|
74
74
|
/**
|
|
75
75
|
* @typedef {Object} PodletOptions
|
|
76
|
-
* @property {string} name -
|
|
77
|
-
* @property {string} version -
|
|
78
|
-
* @property {string} pathname -
|
|
79
|
-
* @property {string} [manifest="/manifest.json"] -
|
|
80
|
-
* @property {string} [content="/"] -
|
|
81
|
-
* @property {string} [fallback=""] -
|
|
82
|
-
* @property {boolean} [development=false] - a boolean flag that, when true, enables additional development setup
|
|
83
|
-
* @property {
|
|
76
|
+
* @property {string} name - (required) podlet name
|
|
77
|
+
* @property {string} version - (required) podlet version
|
|
78
|
+
* @property {string} pathname - (required) podlet pathname
|
|
79
|
+
* @property {string} [manifest="/manifest.json"] - path where the podlet manifest file is served from (default '/manifest.json')
|
|
80
|
+
* @property {string} [content="/"] - path where the podlet content HTML markup is served from (default '/')
|
|
81
|
+
* @property {string} [fallback=""] - path where the podlet fallback HTML markup is served from (default '/fallback')
|
|
82
|
+
* @property {boolean} [development=false] - a boolean flag that, when true, enables additional development setup (default false)
|
|
83
|
+
* @property {boolean} [useShadowDOM=false] - a boolean flag that, when true, enables the use of ShadowDOM (default false)
|
|
84
|
+
* @property {import("abslog").AbstractLoggerOptions} [logger] - a logger to use when provided. Can be the console object if console logging is desired but can also be any Log4j compatible logging object as well. Nothing is logged if no logger is provided. (default null)
|
|
84
85
|
* @property {import("@podium/proxy").PodiumProxyOptions} [proxy] - options that can be provided to configure the @podium/proxy instance used by the podlet. See that module for details.
|
|
85
86
|
*
|
|
86
87
|
* @typedef {{ debug: 'true' | 'false', locale: string, deviceType: string, requestedBy: string, mountOrigin: string, mountPathname: string, publicPathname: string }} PodletContext
|
|
87
|
-
* @typedef {{ as?: string | false | null, crossorigin?: string | null | boolean, disabled?: boolean | '' | null, hreflang?: string | false | null, title?: string | false | null, media?: string | false | null, rel?: string | false | null, type?: string | false | null, value: string | false | null,
|
|
88
|
-
* @typedef {{ value: string | null, crossorigin?: string | null | boolean, type?: string | null | false, integrity?: string | null | false, referrerpolicy?: string | null | false, nomodule?: boolean | null | '', async?: boolean | null | '', defer?: boolean | null | '', data?: Array<{ key: string; value: string }>, strategy?: "beforeInteractive" | "afterInteractive" | "lazy", scope?: "content" | "fallback" | "all", [key: string]: any }} AssetJsLike
|
|
88
|
+
* @typedef {{ as?: string | false | null, crossorigin?: string | null | boolean, disabled?: boolean | '' | null, hreflang?: string | false | null, title?: string | false | null, media?: string | false | null, rel?: string | false | null, type?: string | false | null, value: string | false | null, strategy?: "beforeInteractive" | "afterInteractive" | "lazy" | "shadow-dom", scope?: "content" | "fallback" | "all", [key: string]: any }} AssetCssLike
|
|
89
|
+
* @typedef {{ value: string | null, crossorigin?: string | null | boolean, type?: string | null | false, integrity?: string | null | false, referrerpolicy?: string | null | false, nomodule?: boolean | null | '', async?: boolean | null | '', defer?: boolean | null | '', data?: {[key: string]: string} | Array<{ key: string; value: string }>, strategy?: "beforeInteractive" | "afterInteractive" | "lazy" | "shadow-dom", scope?: "content" | "fallback" | "all" | "shadow-dom", [key: string]: any }} AssetJsLike
|
|
89
90
|
*/
|
|
90
91
|
export default class PodiumPodlet {
|
|
91
92
|
/**
|
|
92
93
|
* Creates a new instance of a Podium podlet which can be used in conjunction with your framework of choice to build podlet server apps.
|
|
93
94
|
* `name`, `version` and `pathname` constructor arguments are required. All other options are optional.
|
|
94
95
|
*
|
|
96
|
+
* * `name` - podlet name (**required**)
|
|
97
|
+
* * `version` - podlet version (**required**)
|
|
98
|
+
* * `pathname` - podlet pathname (**required**)
|
|
99
|
+
* * `manifest` - path where the podlet manifest file is served from (**default** `'/manifest.json'`)
|
|
100
|
+
* * `content` - path where the podlet content HTML markup is served from (**default** `'/'`)
|
|
101
|
+
* * `fallback` - path where the podlet fallback HTML markup is served from (**default** `'/fallback'`)
|
|
102
|
+
* * `development` - a boolean flag that, when true, enables additional development setup (**default** `false`)
|
|
103
|
+
* * `useShadowDOM` - a boolean flag that, when true, enables the use of declarative ShadowDOM in the podlet (**default** `false`)
|
|
104
|
+
* * `logger` - a logger to use when provided. Can be the console object if console logging is desired but can also be any Log4j compatible logging object as well. Nothing is logged if no logger is provided. (**default** `null`)
|
|
105
|
+
* * `proxy` - options that can be provided to configure the @podium/proxy instance used by the podlet. See that module for details. (**default**: `{}`)
|
|
106
|
+
*
|
|
95
107
|
* @see https://podium-lib.io/docs/api/podlet/#constructor
|
|
96
108
|
* @see https://podium-lib.io/docs/podlet/getting_started
|
|
97
109
|
*
|
|
@@ -102,7 +114,7 @@ export default class PodiumPodlet {
|
|
|
102
114
|
* const podlet = new Podlet({ name: 'foo', version: '1.0.0', pathname: '/' });
|
|
103
115
|
* ```
|
|
104
116
|
*/
|
|
105
|
-
constructor({ name, version, pathname, manifest, fallback, content, logger, development, proxy, }: PodletOptions);
|
|
117
|
+
constructor({ name, version, pathname, manifest, fallback, content, logger, development, proxy, useShadowDOM, }: PodletOptions);
|
|
106
118
|
/**
|
|
107
119
|
* The name that the podlet identifies itself by. (set in the constructor) This is used internally for things like metrics but can also be used by a layout server.
|
|
108
120
|
* This value must be in camelCase.
|
|
@@ -581,6 +593,16 @@ export default class PodiumPodlet {
|
|
|
581
593
|
render<T extends {
|
|
582
594
|
[key: string]: unknown;
|
|
583
595
|
}>(incoming: HttpIncoming<T>, data: string, ...args: any[]): string;
|
|
596
|
+
/**
|
|
597
|
+
* Function that takes in the podlet content,wraps it in declarative shadow DOM and returns it.
|
|
598
|
+
* @param {string} data - the podlet content to wrap in declarative shadow DOM as an HTML markup string
|
|
599
|
+
*
|
|
600
|
+
* @example
|
|
601
|
+
* ```js
|
|
602
|
+
* const content = podlet.wrapWithShadowDOM('<div>content to render</div>');
|
|
603
|
+
* ```
|
|
604
|
+
*/
|
|
605
|
+
wrapWithShadowDOM(data: string): string;
|
|
584
606
|
/**
|
|
585
607
|
* Method for processing an incoming HTTP request. This method is intended to be used to implement support for multiple HTTP frameworks and in most cases will not need to be used directly by podlet developers when creating podlet servers.
|
|
586
608
|
*
|
|
@@ -620,35 +642,39 @@ export default class PodiumPodlet {
|
|
|
620
642
|
}
|
|
621
643
|
export type PodletOptions = {
|
|
622
644
|
/**
|
|
623
|
-
* -
|
|
645
|
+
* - (required) podlet name
|
|
624
646
|
*/
|
|
625
647
|
name: string;
|
|
626
648
|
/**
|
|
627
|
-
* -
|
|
649
|
+
* - (required) podlet version
|
|
628
650
|
*/
|
|
629
651
|
version: string;
|
|
630
652
|
/**
|
|
631
|
-
* -
|
|
653
|
+
* - (required) podlet pathname
|
|
632
654
|
*/
|
|
633
655
|
pathname: string;
|
|
634
656
|
/**
|
|
635
|
-
* -
|
|
657
|
+
* - path where the podlet manifest file is served from (default '/manifest.json')
|
|
636
658
|
*/
|
|
637
659
|
manifest?: string;
|
|
638
660
|
/**
|
|
639
|
-
* -
|
|
661
|
+
* - path where the podlet content HTML markup is served from (default '/')
|
|
640
662
|
*/
|
|
641
663
|
content?: string;
|
|
642
664
|
/**
|
|
643
|
-
* -
|
|
665
|
+
* - path where the podlet fallback HTML markup is served from (default '/fallback')
|
|
644
666
|
*/
|
|
645
667
|
fallback?: string;
|
|
646
668
|
/**
|
|
647
|
-
* - a boolean flag that, when true, enables additional development setup
|
|
669
|
+
* - a boolean flag that, when true, enables additional development setup (default false)
|
|
648
670
|
*/
|
|
649
671
|
development?: boolean;
|
|
650
672
|
/**
|
|
651
|
-
* - a
|
|
673
|
+
* - a boolean flag that, when true, enables the use of ShadowDOM (default false)
|
|
674
|
+
*/
|
|
675
|
+
useShadowDOM?: boolean;
|
|
676
|
+
/**
|
|
677
|
+
* - a logger to use when provided. Can be the console object if console logging is desired but can also be any Log4j compatible logging object as well. Nothing is logged if no logger is provided. (default null)
|
|
652
678
|
*/
|
|
653
679
|
logger?: import("abslog").AbstractLoggerOptions;
|
|
654
680
|
/**
|
|
@@ -675,11 +701,7 @@ export type AssetCssLike = {
|
|
|
675
701
|
rel?: string | false | null;
|
|
676
702
|
type?: string | false | null;
|
|
677
703
|
value: string | false | null;
|
|
678
|
-
|
|
679
|
-
key: string;
|
|
680
|
-
value: string;
|
|
681
|
-
}>;
|
|
682
|
-
strategy?: "beforeInteractive" | "afterInteractive" | "lazy";
|
|
704
|
+
strategy?: "beforeInteractive" | "afterInteractive" | "lazy" | "shadow-dom";
|
|
683
705
|
scope?: "content" | "fallback" | "all";
|
|
684
706
|
[key: string]: any;
|
|
685
707
|
};
|
|
@@ -692,12 +714,14 @@ export type AssetJsLike = {
|
|
|
692
714
|
nomodule?: boolean | null | "";
|
|
693
715
|
async?: boolean | null | "";
|
|
694
716
|
defer?: boolean | null | "";
|
|
695
|
-
data?:
|
|
717
|
+
data?: {
|
|
718
|
+
[key: string]: string;
|
|
719
|
+
} | Array<{
|
|
696
720
|
key: string;
|
|
697
721
|
value: string;
|
|
698
722
|
}>;
|
|
699
|
-
strategy?: "beforeInteractive" | "afterInteractive" | "lazy";
|
|
700
|
-
scope?: "content" | "fallback" | "all";
|
|
723
|
+
strategy?: "beforeInteractive" | "afterInteractive" | "lazy" | "shadow-dom";
|
|
724
|
+
scope?: "content" | "fallback" | "all" | "shadow-dom";
|
|
701
725
|
[key: string]: any;
|
|
702
726
|
};
|
|
703
727
|
import Proxy from '@podium/proxy';
|