@podium/podlet 5.0.0 → 5.0.2
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 +14 -0
- package/README.md +4 -4
- package/lib/podlet.js +675 -124
- package/package.json +23 -20
- package/types/podlet.d.ts +663 -0
- package/index.d.ts +0 -114
package/lib/podlet.js
CHANGED
|
@@ -5,33 +5,320 @@
|
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
7
|
HttpIncoming,
|
|
8
|
+
// @ts-ignore
|
|
8
9
|
pathnameBuilder,
|
|
9
10
|
AssetCss,
|
|
10
11
|
AssetJs,
|
|
11
12
|
} from '@podium/utils';
|
|
13
|
+
// @ts-ignore
|
|
12
14
|
import * as schema from '@podium/schemas';
|
|
13
15
|
import Metrics from '@metrics/client';
|
|
16
|
+
// @ts-ignore
|
|
14
17
|
import abslog from 'abslog';
|
|
18
|
+
// @ts-ignore
|
|
15
19
|
import objobj from 'objobj';
|
|
16
20
|
import * as utils from '@podium/utils';
|
|
21
|
+
// @ts-ignore
|
|
17
22
|
import Proxy from '@podium/proxy';
|
|
18
|
-
import { join, dirname } from 'path';
|
|
19
|
-
import { fileURLToPath } from 'url';
|
|
20
|
-
import fs from 'fs';
|
|
23
|
+
import { join, dirname } from 'node:path';
|
|
24
|
+
import { fileURLToPath } from 'node:url';
|
|
25
|
+
import fs from 'node:fs';
|
|
21
26
|
|
|
22
27
|
const currentDirectory = dirname(fileURLToPath(import.meta.url));
|
|
23
|
-
const pkgJson = fs.readFileSync(
|
|
28
|
+
const pkgJson = fs.readFileSync(
|
|
29
|
+
join(currentDirectory, '../package.json'),
|
|
30
|
+
'utf-8',
|
|
31
|
+
);
|
|
24
32
|
const pkg = JSON.parse(pkgJson);
|
|
25
33
|
|
|
34
|
+
// @ts-ignore
|
|
26
35
|
const { template } = utils;
|
|
27
36
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
/**
|
|
38
|
+
* @typedef {(...args: any) => void} LogFunction
|
|
39
|
+
* @typedef {{ trace: LogFunction, debug: LogFunction, info: LogFunction, warn: LogFunction, error: LogFunction, fatal: LogFunction }} AbsLogger
|
|
40
|
+
*
|
|
41
|
+
* @typedef {Object} PodletOptions
|
|
42
|
+
* @property {string} name - (required) podlet name
|
|
43
|
+
* @property {string} version - (required) podlet version
|
|
44
|
+
* @property {string} pathname - (required) podlet pathname
|
|
45
|
+
* @property {string} [manifest] - path where the podlet manifest file is served from (default '/manifest.json')
|
|
46
|
+
* @property {string} [content] - path where the podlet content HTML markup is served from (default '/')
|
|
47
|
+
* @property {string} [fallback] - path where the podlet fallback HTML markup is served from (default '/fallback')
|
|
48
|
+
* @property {boolean} [development] - a boolean flag that, when true, enables additional development setup (default false)
|
|
49
|
+
* @property {Console | AbsLogger} [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)
|
|
50
|
+
* @property {import("@podium/proxy").default.PodiumProxyOptions} proxy - options that can be provided to configure the @podium/proxy instance used by the podlet. See that module for details.
|
|
51
|
+
*
|
|
52
|
+
* @typedef {{ debug: 'true' | 'false', locale: string, deviceType: string, requestedBy: string, mountOrigin: string, mountPathname: string, publicPathname: string }} PodletContext
|
|
53
|
+
* @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, data?: Array<{ key: string; value: string }>, strategy?: "beforeInteractive" | "afterInteractive" | "lazy", scope?: "content" | "fallback" | "all", [key: string]: any }} AssetCssLike
|
|
54
|
+
* @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
|
|
55
|
+
*/
|
|
33
56
|
|
|
34
57
|
export default class PodiumPodlet {
|
|
58
|
+
/**
|
|
59
|
+
* Podium document template. A custom document template is set by using the .view() method in the podlet and layout modules.
|
|
60
|
+
*
|
|
61
|
+
* @see https://podium-lib.io/docs/api/document
|
|
62
|
+
*
|
|
63
|
+
* @example ```js
|
|
64
|
+
* const podlet = new Podlet({ ... });
|
|
65
|
+
* podlet.view(myDocumentTemplate);
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
#view = template;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* 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.
|
|
72
|
+
* This value must be in camelCase.
|
|
73
|
+
*
|
|
74
|
+
* @see https://podium-lib.io/docs/api/podlet/#name
|
|
75
|
+
*
|
|
76
|
+
* @example ```js
|
|
77
|
+
* const podlet = new Podlet({ name: 'foo', ... });
|
|
78
|
+
* podlet.name // foo
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
name = '';
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Pathname for where a podlet is mounted in an HTTP server.
|
|
85
|
+
* It is important that this value matches where the entry point of a route is in an HTTP server since
|
|
86
|
+
* this value is used to define where the manifest is for the podlet.
|
|
87
|
+
* (set in the constructor)
|
|
88
|
+
*
|
|
89
|
+
* The podlet.pathname() method is used to access this property
|
|
90
|
+
*
|
|
91
|
+
* @see https://podium-lib.io/docs/api/podlet/#pathname
|
|
92
|
+
*/
|
|
93
|
+
#pathname = '';
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The current version of the podlet. (set in the constructor)
|
|
97
|
+
* It is important that this value be updated when a new version of the podlet is deployed since the page (layout)
|
|
98
|
+
* that the podlet is displayed in uses this value to know whether to refresh the podlet's manifest and fallback content or not.
|
|
99
|
+
*
|
|
100
|
+
* @see https://podium-lib.io/docs/api/podlet/#version
|
|
101
|
+
*
|
|
102
|
+
* @example ```js
|
|
103
|
+
* const podlet = new Podlet({ version: '1.0.0', ... });
|
|
104
|
+
* podlet.version // 1.0.0
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
version = '';
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* The podlet development property (set in the constructor)
|
|
111
|
+
* Used to make podlet development simple without the need to run a layout server locally
|
|
112
|
+
* Do not run a podlet in development mode when deploying to production.
|
|
113
|
+
*
|
|
114
|
+
* @see https://podium-lib.io/docs/api/podlet/#development
|
|
115
|
+
* @see https://podium-lib.io/docs/api/podlet/#development-mode
|
|
116
|
+
*
|
|
117
|
+
* @example ```js
|
|
118
|
+
* const podlet = new Podlet({ development: true, ... });
|
|
119
|
+
* podlet.development // true
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
development = false;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* A logger. The abstract logger "Abslog" is used to make it possible to provide different kinds of loggers.
|
|
126
|
+
* The logger can be provided via the 'logger' constructor argument.
|
|
127
|
+
*
|
|
128
|
+
* @see https://www.npmjs.com/package/abslog
|
|
129
|
+
*
|
|
130
|
+
* @example ```js
|
|
131
|
+
* const podlet = new Podlet({ logger: console, ... });
|
|
132
|
+
* podlet.log.trace('trace log to the console')
|
|
133
|
+
* podlet.log.debug('debug log to the console')
|
|
134
|
+
* podlet.log.info('info log to the console')
|
|
135
|
+
* podlet.log.warn('warn log to the console')
|
|
136
|
+
* podlet.log.error('error log to the console')
|
|
137
|
+
* podlet.log.fatal('fatal log to the console')
|
|
138
|
+
* ```
|
|
139
|
+
*
|
|
140
|
+
* @type {AbsLogger}
|
|
141
|
+
*/
|
|
142
|
+
log;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* An instance of the `@podium/proxy` module
|
|
146
|
+
* @see https://github.com/podium-lib/proxy
|
|
147
|
+
*/
|
|
148
|
+
httpProxy;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* The pathname for the manifest of the podlet. Defaults to /manifest.json. (set in the constructor)
|
|
152
|
+
* The value should be relative to the value set on the pathname argument.
|
|
153
|
+
* In other words if a podlet is mounted into an HTTP server at /foo and the manifest is at /foo/component.json, pathname will be /foo and manifestRoute will be /component.json
|
|
154
|
+
*
|
|
155
|
+
* @see https://podium-lib.io/docs/api/podlet/#manifest
|
|
156
|
+
*
|
|
157
|
+
* @example ```js
|
|
158
|
+
* const podlet = new Podlet({ manifest: '/manifest.json', ... });
|
|
159
|
+
* podlet.manifestRoute // /manifest.json
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
manifestRoute = '/manifest.json';
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* The pathname for the content route of the podlet. Defaults to /. (set in the constructor)
|
|
166
|
+
* The value should be relative to the value set on the pathname argument.
|
|
167
|
+
* In other words if a podlet is mounted into an HTTP server at /foo and the content is at /foo/content, pathname will be /foo and contentRoute will be /content
|
|
168
|
+
*
|
|
169
|
+
* @see https://podium-lib.io/docs/api/podlet/#content
|
|
170
|
+
*
|
|
171
|
+
* @example ```js
|
|
172
|
+
* const podlet = new Podlet({ content: '/foo', ... });
|
|
173
|
+
* podlet.contentRoute // /foo
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
contentRoute = '/';
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* The pathname for the fallback route of the podlet. Defaults to /fallback. (set in the constructor)
|
|
180
|
+
* The value should be relative to the value set on the pathname argument.
|
|
181
|
+
* In other words if a podlet is mounted into an HTTP server at /foo and the fallback is at /foo/fallback, pathname will be /foo and fallbackRoute will be /fallback
|
|
182
|
+
*
|
|
183
|
+
* @see https://podium-lib.io/docs/api/podlet/#fallback
|
|
184
|
+
*
|
|
185
|
+
* @example ```js
|
|
186
|
+
* const podlet = new Podlet({ fallback: '/fallback', ... });
|
|
187
|
+
* podlet.fallbackRoute // /fallback
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
fallbackRoute = '';
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* An object that holds information about defined proxy routes. Proxy routes are defined using the podlet.proxy(...) method and up to 4 proxy routes
|
|
194
|
+
* may be defined per podlet.
|
|
195
|
+
*
|
|
196
|
+
* @see https://podium-lib.io/docs/api/podlet#proxy-target-name-
|
|
197
|
+
* @see https://podium-lib.io/docs/podlet/proxying
|
|
198
|
+
*
|
|
199
|
+
* @example ```js
|
|
200
|
+
* const podlet = new Podlet({ ... });
|
|
201
|
+
* podlet.proxy({ target: '/api', name: 'api' })
|
|
202
|
+
* podlet.proxyRoutes // { api: '/api' }
|
|
203
|
+
* ```
|
|
204
|
+
*
|
|
205
|
+
* @type {Record<string, string>}
|
|
206
|
+
*/
|
|
207
|
+
proxyRoutes = {};
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* An object containing a set of Podium context values configured for podlet development.
|
|
211
|
+
* This is necessary when the podlet is in development mode because requests do not come from a layout (which is what normally sends the context information)
|
|
212
|
+
* These base context values can be overridden by providing a default context using the podlet.defaults() method
|
|
213
|
+
* in which case the baseContext and the defaultContext will be merged together to provide the development context object.
|
|
214
|
+
* This is not used at all when the podlet is not in development mode or when it is in development mode but the request to the podlet comes from a Podium layout.
|
|
215
|
+
*
|
|
216
|
+
* @see https://podium-lib.io/docs/podlet/context
|
|
217
|
+
* @see https://podium-lib.io/docs/api/podlet#development-mode
|
|
218
|
+
* @see https://podium-lib.io/docs/api/podlet#defaultscontext
|
|
219
|
+
*
|
|
220
|
+
* @example ```js
|
|
221
|
+
* const podlet = new Podlet({ name: 'foo', pathname: '/bar', ... });
|
|
222
|
+
* podlet.baseContext; // { debug: 'false', locale: 'en-US', deviceType: 'desktop', requestedBy: this.name, mountOrigin: '', mountPathname: '/bar', publicPathname: '/bar/podium-resource/foo' }
|
|
223
|
+
* ```
|
|
224
|
+
*
|
|
225
|
+
* @type {PodletContext}
|
|
226
|
+
*/
|
|
227
|
+
baseContext;
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* An object containing a set of Podium context values configured for podlet development.
|
|
231
|
+
* This is necessary when the podlet is in development mode because requests do not come from a layout (which is what normally sends the context information)
|
|
232
|
+
* These default context values override the `baseContext` values set by the package and can be set using the podlet.defaults() method
|
|
233
|
+
* in which case the baseContext and the defaultContext will be merged together to provide the development context object.
|
|
234
|
+
* This is not used at all when the podlet is not in development mode or when it is in development mode but the request to the podlet comes from a Podium layout.
|
|
235
|
+
*
|
|
236
|
+
* @see https://podium-lib.io/docs/podlet/context
|
|
237
|
+
* @see https://podium-lib.io/docs/api/podlet#development-mode
|
|
238
|
+
* @see https://podium-lib.io/docs/api/podlet#defaultscontext
|
|
239
|
+
*
|
|
240
|
+
* @example ```js
|
|
241
|
+
* const podlet = new Podlet({ name: 'foo', pathname: '/bar', ... });
|
|
242
|
+
* podlet.defaults({ debug: 'true', locale: 'nb' });
|
|
243
|
+
* podlet.baseContext; // { debug: 'true', locale: 'nb', deviceType: 'desktop', requestedBy: this.name, mountOrigin: '', mountPathname: '/bar', publicPathname: '/bar/podium-resource/foo' }
|
|
244
|
+
* ```
|
|
245
|
+
*
|
|
246
|
+
* @type {PodletContext}
|
|
247
|
+
*/
|
|
248
|
+
defaultContext;
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Property that holds the podlet's CSS asset references. Objects in the array are AssetCss instances. Asset references can be added using the podlet.css() method.
|
|
252
|
+
*
|
|
253
|
+
* @see https://podium-lib.io/docs/api/podlet/#cssoptionsoptions
|
|
254
|
+
* @see https://podium-lib.io/docs/api/assets#assetcss
|
|
255
|
+
* @see https://podium-lib.io/docs/api/assets
|
|
256
|
+
*
|
|
257
|
+
* @example ```js
|
|
258
|
+
* const podlet = new Podlet({ ... });
|
|
259
|
+
* podlet.css({ value: 'https://my.assets.com/styles.css' });
|
|
260
|
+
* podlet.cssRoute // [ AssetCss{ value: 'https://my.assets.com/styles.css' } ]
|
|
261
|
+
* ```
|
|
262
|
+
*
|
|
263
|
+
* @type {AssetCss[]}
|
|
264
|
+
*/
|
|
265
|
+
cssRoute = [];
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Property that holds the podlet's JS asset references. Objects in the array are AssetJs instances. Asset references can be added using the podlet.js() method.
|
|
269
|
+
*
|
|
270
|
+
* @see https://podium-lib.io/docs/api/podlet/#jsoptionsoptions
|
|
271
|
+
* @see https://podium-lib.io/docs/api/assets#assetjs
|
|
272
|
+
* @see https://podium-lib.io/docs/api/assets
|
|
273
|
+
*
|
|
274
|
+
* @example ```js
|
|
275
|
+
* const podlet = new Podlet({ ... });
|
|
276
|
+
* podlet.js({ value: 'https://my.assets.com/scripts.js' });
|
|
277
|
+
* podlet.jsRoute // [ AssetJs{ value: 'https://my.assets.com/scripts.js' } ]
|
|
278
|
+
* ```
|
|
279
|
+
*
|
|
280
|
+
* @type {AssetJs[]}
|
|
281
|
+
*/
|
|
282
|
+
jsRoute = [];
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Metrics client stream object that can be used to consume metrics out of a Podium podlet.
|
|
286
|
+
* @see https://www.npmjs.com/package/@metrics/client for detailed documentation
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* ```js
|
|
290
|
+
* const podlet = new Podlet(...);
|
|
291
|
+
* podlet.metrics.pipe(...);
|
|
292
|
+
* // or
|
|
293
|
+
* podlet.metrics.on('data', chunk => { ... });
|
|
294
|
+
* ```
|
|
295
|
+
*/
|
|
296
|
+
metrics = new Metrics();
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Creates a new instance of a Podium podlet which can be used in conjunction with your framework of choice to build podlet server apps.
|
|
300
|
+
* `name`, `version` and `pathname` constructor arguments are required. All other options are optional.
|
|
301
|
+
*
|
|
302
|
+
* * `name` - podlet name (**required**)
|
|
303
|
+
* * `version` - podlet version (**required**)
|
|
304
|
+
* * `pathname` - podlet pathname (**required**)
|
|
305
|
+
* * `manifest` - path where the podlet manifest file is served from (**default** `'/manifest.json'`)
|
|
306
|
+
* * `content` - path where the podlet content HTML markup is served from (**default** `'/'`)
|
|
307
|
+
* * `fallback` - path where the podlet fallback HTML markup is served from (**default** `'/fallback'`)
|
|
308
|
+
* * `development` - a boolean flag that, when true, enables additional development setup (**default** `false`)
|
|
309
|
+
* * `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`)
|
|
310
|
+
* * `proxy` - options that can be provided to configure the @podium/proxy instance used by the podlet. See that module for details. (**default**: `{}`)
|
|
311
|
+
*
|
|
312
|
+
* @see https://podium-lib.io/docs/api/podlet/#constructor
|
|
313
|
+
* @see https://podium-lib.io/docs/podlet/getting_started
|
|
314
|
+
*
|
|
315
|
+
* @param {PodletOptions} options
|
|
316
|
+
*
|
|
317
|
+
* @example
|
|
318
|
+
* ```
|
|
319
|
+
* const podlet = new Podlet({ name: 'foo', version: '1.0.0', pathname: '/' });
|
|
320
|
+
* ```
|
|
321
|
+
*/
|
|
35
322
|
constructor({
|
|
36
323
|
name = '',
|
|
37
324
|
version = '',
|
|
@@ -42,7 +329,7 @@ export default class PodiumPodlet {
|
|
|
42
329
|
logger = undefined,
|
|
43
330
|
development = false,
|
|
44
331
|
proxy = {},
|
|
45
|
-
}
|
|
332
|
+
}) {
|
|
46
333
|
if (schema.name(name).error)
|
|
47
334
|
throw new Error(
|
|
48
335
|
`The value, "${name}", for the required argument "name" on the Podlet constructor is not defined or not valid.`,
|
|
@@ -73,94 +360,39 @@ export default class PodiumPodlet {
|
|
|
73
360
|
`The value, "${fallback}", for the optional argument "fallback" on the Podlet constructor is not valid.`,
|
|
74
361
|
);
|
|
75
362
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
Object.defineProperty(this, 'manifestRoute', {
|
|
89
|
-
value: this[_sanitize](manifest),
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
Object.defineProperty(this, 'contentRoute', {
|
|
93
|
-
value: this[_sanitize](content),
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
Object.defineProperty(this, 'fallbackRoute', {
|
|
97
|
-
value: this[_sanitize](fallback),
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
Object.defineProperty(this, 'cssRoute', {
|
|
101
|
-
value: [],
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
Object.defineProperty(this, 'jsRoute', {
|
|
105
|
-
value: [],
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
Object.defineProperty(this, 'proxyRoutes', {
|
|
109
|
-
value: {},
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
Object.defineProperty(this, 'log', {
|
|
113
|
-
value: abslog(logger),
|
|
363
|
+
this.name = name;
|
|
364
|
+
this.version = version;
|
|
365
|
+
this.#pathname = this.#sanitize(pathname);
|
|
366
|
+
this.manifestRoute = this.#sanitize(manifest);
|
|
367
|
+
this.contentRoute = this.#sanitize(content);
|
|
368
|
+
this.fallbackRoute = this.#sanitize(fallback);
|
|
369
|
+
this.log = abslog(logger);
|
|
370
|
+
this.development = development;
|
|
371
|
+
this.httpProxy = new Proxy({
|
|
372
|
+
pathname: this.#pathname,
|
|
373
|
+
logger: this.log,
|
|
374
|
+
...proxy,
|
|
114
375
|
});
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
376
|
+
this.baseContext = {
|
|
377
|
+
debug: 'false',
|
|
378
|
+
locale: 'en-US',
|
|
379
|
+
deviceType: 'desktop',
|
|
380
|
+
requestedBy: this.name,
|
|
381
|
+
mountOrigin: '',
|
|
382
|
+
mountPathname: this.#pathname,
|
|
383
|
+
publicPathname: pathnameBuilder(
|
|
384
|
+
this.httpProxy.pathname,
|
|
385
|
+
this.httpProxy.prefix,
|
|
386
|
+
this.name,
|
|
125
387
|
),
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
Object.defineProperty(this, 'baseContext', {
|
|
129
|
-
value: {
|
|
130
|
-
debug: 'false',
|
|
131
|
-
locale: 'en-US',
|
|
132
|
-
deviceType: 'desktop',
|
|
133
|
-
requestedBy: this.name,
|
|
134
|
-
mountOrigin: '',
|
|
135
|
-
mountPathname: this._pathname,
|
|
136
|
-
publicPathname: pathnameBuilder(
|
|
137
|
-
this.httpProxy.pathname,
|
|
138
|
-
this.httpProxy.prefix,
|
|
139
|
-
this.name,
|
|
140
|
-
),
|
|
141
|
-
},
|
|
142
|
-
writable: false,
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
Object.defineProperty(this, 'defaultContext', {
|
|
146
|
-
value: {},
|
|
147
|
-
writable: true,
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
Object.defineProperty(this, 'metrics', {
|
|
151
|
-
enumerable: true,
|
|
152
|
-
value: new Metrics(),
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
Object.defineProperty(this, '_view', {
|
|
156
|
-
value: template,
|
|
157
|
-
writable: true,
|
|
158
|
-
});
|
|
388
|
+
};
|
|
159
389
|
|
|
160
390
|
// Skip a tick to ensure the metric stream has been consumed
|
|
161
391
|
setImmediate(() => {
|
|
162
392
|
const moduleVersion = pkg.version;
|
|
163
|
-
const segments = moduleVersion
|
|
393
|
+
const segments = moduleVersion
|
|
394
|
+
.split('.')
|
|
395
|
+
.map((value) => parseInt(value, 10));
|
|
164
396
|
|
|
165
397
|
const versionGauge = this.metrics.gauge({
|
|
166
398
|
name: 'podium_podlet_version_info',
|
|
@@ -176,7 +408,8 @@ export default class PodiumPodlet {
|
|
|
176
408
|
versionGauge.set(1);
|
|
177
409
|
});
|
|
178
410
|
|
|
179
|
-
|
|
411
|
+
// @ts-ignore
|
|
412
|
+
this.metrics.on('error', (error) => {
|
|
180
413
|
this.log.error(
|
|
181
414
|
'Error emitted by metric stream in @podium/podlet module',
|
|
182
415
|
error,
|
|
@@ -188,44 +421,177 @@ export default class PodiumPodlet {
|
|
|
188
421
|
return 'PodiumPodlet';
|
|
189
422
|
}
|
|
190
423
|
|
|
424
|
+
/**
|
|
425
|
+
* Method that returns the pathname for where a podlet is mounted in an HTTP server.
|
|
426
|
+
* It is important that this value matches where the entry point of a route is in an HTTP server since
|
|
427
|
+
* this value is used to define where the manifest is for the podlet.
|
|
428
|
+
* (set in the constructor)
|
|
429
|
+
*
|
|
430
|
+
* @see https://podium-lib.io/docs/api/podlet/#pathname
|
|
431
|
+
*
|
|
432
|
+
* @example
|
|
433
|
+
* The method returns the value of `pathname` as defined in the podlet constructor
|
|
434
|
+
* ```js
|
|
435
|
+
* const podlet = new Podlet({ pathname: '/foo', ... });
|
|
436
|
+
* podlet.pathname() // /foo
|
|
437
|
+
* ```
|
|
438
|
+
*
|
|
439
|
+
* @example
|
|
440
|
+
* This method is typically used when defining routes to ensure the pathname is prepended to any routes
|
|
441
|
+
* ```js
|
|
442
|
+
* const podlet = new Podlet({ pathname: '/foo', content: '/bar', ... });
|
|
443
|
+
* app.get(podlet.pathname() + '/bar', (req, res) => res.podiumSend(...));
|
|
444
|
+
* ```
|
|
445
|
+
*/
|
|
191
446
|
pathname() {
|
|
192
|
-
return this
|
|
447
|
+
return this.#pathname;
|
|
193
448
|
}
|
|
194
449
|
|
|
450
|
+
/**
|
|
451
|
+
* Method that returns the pathname for where a podlet's manifest route is to be mounted.
|
|
452
|
+
* By default the podlet's pathname value is prepended to the manifest value.
|
|
453
|
+
*
|
|
454
|
+
* @example
|
|
455
|
+
* Prefix is true by default which will prepend the pathname (/foo) in this example
|
|
456
|
+
* ```js
|
|
457
|
+
* const podlet = new Podlet({ pathname: '/foo', manifest: '/manifest.json', ... });
|
|
458
|
+
* podlet.manifest() // /foo/manifest.json
|
|
459
|
+
* podlet.manifest({ prefix: false }) // /manifest.json
|
|
460
|
+
* ```
|
|
461
|
+
*
|
|
462
|
+
* @example
|
|
463
|
+
* This method is typically used when defining the manifest route
|
|
464
|
+
* ```js
|
|
465
|
+
* const podlet = new Podlet({ ... });
|
|
466
|
+
* app.get(podlet.manifest(), (req, res) => res.send(podlet));
|
|
467
|
+
* ```
|
|
468
|
+
*
|
|
469
|
+
* @param {{ prefix?: boolean }} [options]
|
|
470
|
+
* @returns {string}
|
|
471
|
+
*/
|
|
195
472
|
manifest({ prefix = true } = {}) {
|
|
196
|
-
return this
|
|
473
|
+
return this.#sanitize(this.manifestRoute, prefix);
|
|
197
474
|
}
|
|
198
475
|
|
|
476
|
+
/**
|
|
477
|
+
* Method that returns the pathname for where a podlet's content route is to be mounted.
|
|
478
|
+
* By default the podlet's pathname value is prepended to the content value.
|
|
479
|
+
*
|
|
480
|
+
* @example
|
|
481
|
+
* Prefix is true by default which will prepend the pathname (/foo) in this example
|
|
482
|
+
* ```js
|
|
483
|
+
* const podlet = new Podlet({ pathname: '/foo', content: '/', ... });
|
|
484
|
+
* podlet.content() // /foo
|
|
485
|
+
* podlet.content({ prefix: false }) // /
|
|
486
|
+
* ```
|
|
487
|
+
*
|
|
488
|
+
* @example
|
|
489
|
+
* This method is typically used when defining the content route
|
|
490
|
+
* ```js
|
|
491
|
+
* const podlet = new Podlet({ ... });
|
|
492
|
+
* app.get(podlet.content(), (req, res) => res.podiumSend(...));
|
|
493
|
+
* ```
|
|
494
|
+
*
|
|
495
|
+
* @param {{ prefix?: boolean }} [options]
|
|
496
|
+
* @returns {string}
|
|
497
|
+
*/
|
|
199
498
|
content({ prefix = true } = {}) {
|
|
200
|
-
return this
|
|
499
|
+
return this.#sanitize(this.contentRoute, prefix);
|
|
201
500
|
}
|
|
202
501
|
|
|
502
|
+
/**
|
|
503
|
+
* Method that returns the pathname for where a podlet's fallback route is to be mounted.
|
|
504
|
+
* By default the podlet's pathname value is prepended to the fallback value.
|
|
505
|
+
*
|
|
506
|
+
* @example
|
|
507
|
+
* Prefix is true by default which will prepend the pathname (/foo) in this example
|
|
508
|
+
* ```js
|
|
509
|
+
* const podlet = new Podlet({ pathname: '/foo', fallback: '/fallback', ... });
|
|
510
|
+
* podlet.fallback() // /foo/fallback
|
|
511
|
+
* podlet.fallback({ prefix: false }) // /fallback
|
|
512
|
+
* ```
|
|
513
|
+
*
|
|
514
|
+
* @example
|
|
515
|
+
* This method is typically used when defining the fallback route
|
|
516
|
+
* ```js
|
|
517
|
+
* const podlet = new Podlet({ ... });
|
|
518
|
+
* app.get(podlet.fallback(), (req, res) => res.podiumSend(...));
|
|
519
|
+
* ```
|
|
520
|
+
*
|
|
521
|
+
* @param {{ prefix?: boolean }} [options]
|
|
522
|
+
* @returns {string}
|
|
523
|
+
*/
|
|
203
524
|
fallback({ prefix = true } = {}) {
|
|
204
|
-
return this
|
|
525
|
+
return this.#sanitize(this.fallbackRoute, prefix);
|
|
205
526
|
}
|
|
206
527
|
|
|
207
|
-
|
|
528
|
+
/**
|
|
529
|
+
* Takes an AssetCss instance or an object with equivalent properties, converts it to an AssetCss instance if necessary and adds it to the
|
|
530
|
+
* cssRoute array.
|
|
531
|
+
* @param { AssetCss | AssetCssLike } options
|
|
532
|
+
* @returns {void}
|
|
533
|
+
*/
|
|
534
|
+
#addCssAsset(options) {
|
|
208
535
|
const clonedOptions = JSON.parse(JSON.stringify(options));
|
|
209
|
-
clonedOptions.value = this
|
|
210
|
-
|
|
536
|
+
clonedOptions.value = this.#sanitize(
|
|
537
|
+
clonedOptions.value,
|
|
538
|
+
clonedOptions.prefix,
|
|
539
|
+
);
|
|
540
|
+
const args = {
|
|
541
|
+
prefix: true,
|
|
542
|
+
...clonedOptions,
|
|
543
|
+
pathname: this.#pathname,
|
|
544
|
+
};
|
|
211
545
|
this.cssRoute.push(new AssetCss(args));
|
|
212
546
|
}
|
|
213
547
|
|
|
214
|
-
|
|
548
|
+
/**
|
|
549
|
+
* Method used to set CSS asset references for a podlet. Accepts an AssetCss object, a plain JS object with the same properties as an AssetCss object or
|
|
550
|
+
* an array containing AssetCss or plain JS objects. Asset references set in this way can be accessed via `podlet.cssRoute` and
|
|
551
|
+
* will be added to the podlet manifest file for sending to the layout
|
|
552
|
+
*
|
|
553
|
+
* @see https://podium-lib.io/docs/api/podlet/#cssoptionsoptions
|
|
554
|
+
* @see https://podium-lib.io/docs/api/assets#assetcss
|
|
555
|
+
* @see https://podium-lib.io/docs/api/assets
|
|
556
|
+
*
|
|
557
|
+
* @example ```js
|
|
558
|
+
* const podlet = new Podlet({ ... });
|
|
559
|
+
* podlet.css(new AssetCss{ value: 'https://my.assets.com/styles.css' });
|
|
560
|
+
* podlet.css({ value: 'https://my.assets.com/styles.css' });
|
|
561
|
+
* podlet.css([new AssetCss{ value: 'https://my.assets.com/styles.css' }, { value: 'https://my.assets.com/styles.css' }]);
|
|
562
|
+
* ```
|
|
563
|
+
*
|
|
564
|
+
* @param { AssetCss | AssetCss[] | AssetCssLike | AssetCssLike[] } options
|
|
565
|
+
* @returns {void}
|
|
566
|
+
*/
|
|
567
|
+
css(options) {
|
|
215
568
|
if (Array.isArray(options)) {
|
|
216
569
|
for (const opts of options) {
|
|
217
|
-
this
|
|
570
|
+
this.#addCssAsset(opts);
|
|
218
571
|
}
|
|
219
572
|
return;
|
|
220
573
|
}
|
|
221
|
-
this
|
|
574
|
+
this.#addCssAsset(options);
|
|
222
575
|
}
|
|
223
576
|
|
|
224
|
-
|
|
577
|
+
/**
|
|
578
|
+
* Takes an AssetJs instance or an object with equivalent properties, converts it to an AssetJs instance if necessary and adds it to the
|
|
579
|
+
* jsRoute array.
|
|
580
|
+
* @param { AssetJs | AssetJsLike } options
|
|
581
|
+
* @returns {void}
|
|
582
|
+
*/
|
|
583
|
+
#addJsAsset(options) {
|
|
225
584
|
const clonedOptions = JSON.parse(JSON.stringify(options));
|
|
226
|
-
clonedOptions.value = this
|
|
585
|
+
clonedOptions.value = this.#sanitize(
|
|
586
|
+
clonedOptions.value,
|
|
587
|
+
clonedOptions.prefix,
|
|
588
|
+
);
|
|
227
589
|
|
|
228
|
-
const args = {
|
|
590
|
+
const args = {
|
|
591
|
+
prefix: true,
|
|
592
|
+
...clonedOptions,
|
|
593
|
+
pathname: this.#pathname,
|
|
594
|
+
};
|
|
229
595
|
|
|
230
596
|
// Convert data attribute object structure to array of key value objects
|
|
231
597
|
if (typeof args.data === 'object' && args.data !== null) {
|
|
@@ -235,24 +601,69 @@ export default class PodiumPodlet {
|
|
|
235
601
|
value: args.data[key],
|
|
236
602
|
key,
|
|
237
603
|
});
|
|
238
|
-
})
|
|
604
|
+
});
|
|
239
605
|
args.data = data;
|
|
240
606
|
}
|
|
241
607
|
|
|
242
608
|
this.jsRoute.push(new AssetJs(args));
|
|
243
609
|
}
|
|
244
610
|
|
|
245
|
-
|
|
611
|
+
/**
|
|
612
|
+
* Method used to set JS asset references for a podlet. Accepts an AssetJs object, a plain JS object with the same properties as an AssetJs object or
|
|
613
|
+
* an array containing AssetJs or plain JS objects. Asset references set in this way can be accessed via `podlet.jsRoute` and
|
|
614
|
+
* will be added to the podlet manifest file for sending to the layout
|
|
615
|
+
*
|
|
616
|
+
* @see https://podium-lib.io/docs/api/podlet/#jsoptionsoptions
|
|
617
|
+
* @see https://podium-lib.io/docs/api/assets#assetjs
|
|
618
|
+
* @see https://podium-lib.io/docs/api/assets
|
|
619
|
+
*
|
|
620
|
+
* @example ```js
|
|
621
|
+
* const podlet = new Podlet({ ... });
|
|
622
|
+
* podlet.js(new AssetJs{ value: 'https://my.assets.com/scripts.js' });
|
|
623
|
+
* podlet.js({ value: 'https://my.assets.com/scripts.js' });
|
|
624
|
+
* podlet.js([new AssetJs{ value: 'https://my.assets.com/scripts.js' }, { value: 'https://my.assets.com/scripts.js' }]);
|
|
625
|
+
* ```
|
|
626
|
+
*
|
|
627
|
+
* @param {AssetJs | AssetJs[] | AssetJsLike | AssetJsLike[] } [options]
|
|
628
|
+
* @returns {void}
|
|
629
|
+
*/
|
|
630
|
+
js(options) {
|
|
246
631
|
if (Array.isArray(options)) {
|
|
247
632
|
for (const opts of options) {
|
|
248
|
-
this
|
|
633
|
+
this.#addJsAsset(opts);
|
|
249
634
|
}
|
|
250
635
|
return;
|
|
251
636
|
}
|
|
252
|
-
this
|
|
637
|
+
this.#addJsAsset(options);
|
|
253
638
|
}
|
|
254
639
|
|
|
255
|
-
|
|
640
|
+
/**
|
|
641
|
+
* Method for defining proxy targets to be mounted in a layout server.
|
|
642
|
+
* Accepts an object with `target` and `name` keys where target is the relative or absolute path to proxy requests to and name is an identifier
|
|
643
|
+
* to distinguish it from other proxy endpoints. It's common to define a target of "/api" and a name of just "api". The method returns the target so that
|
|
644
|
+
* it's possible to both define the proxy and the route at the same time.
|
|
645
|
+
*
|
|
646
|
+
* For a detailed overview of how proxying works, please see the proxying guide for further details.
|
|
647
|
+
*
|
|
648
|
+
* @see https://podium-lib.io/docs/podlet/proxying
|
|
649
|
+
* @see https://podium-lib.io/docs/api/podlet#proxy-target-name-
|
|
650
|
+
*
|
|
651
|
+
* @example
|
|
652
|
+
* ```js
|
|
653
|
+
* podlet.proxy({ name: 'api', target: '/api' }); // returns /api
|
|
654
|
+
* ```
|
|
655
|
+
*
|
|
656
|
+
* @example
|
|
657
|
+
* Define the proxy and route at the same time
|
|
658
|
+
* ```js
|
|
659
|
+
* // proxy mounted at /api in the app
|
|
660
|
+
* app.get(podlet.proxy({ name: 'api', target: '/api' }), (req, res) => res.sendStatus(200));
|
|
661
|
+
* ```
|
|
662
|
+
*
|
|
663
|
+
* @param {{ target: string; name: string }} options
|
|
664
|
+
* @returns {string}
|
|
665
|
+
*/
|
|
666
|
+
proxy({ target, name }) {
|
|
256
667
|
if (schema.uri(target).error)
|
|
257
668
|
throw new Error(
|
|
258
669
|
`Value on argument variable "target", "${target}", is not valid`,
|
|
@@ -272,12 +683,38 @@ export default class PodiumPodlet {
|
|
|
272
683
|
this.proxyRoutes[name] = target;
|
|
273
684
|
|
|
274
685
|
if (this.development) {
|
|
275
|
-
|
|
686
|
+
// @ts-ignore
|
|
687
|
+
this.httpProxy.register(this.name, this.toJSON());
|
|
276
688
|
}
|
|
277
689
|
|
|
278
690
|
return target;
|
|
279
691
|
}
|
|
280
692
|
|
|
693
|
+
/**
|
|
694
|
+
* Method to alter the default context set when in development mode.
|
|
695
|
+
* In a production setup, this is not necessary since the context values are sent to the podlet from the layout.
|
|
696
|
+
* By default, the context will contain the following context values, all of which can be overridden.
|
|
697
|
+
*
|
|
698
|
+
* * `debug:` 'false',
|
|
699
|
+
* * `locale:` 'en-EN',
|
|
700
|
+
* * `deviceType:` 'desktop',
|
|
701
|
+
* * `requestedBy:` '<podlet name>',
|
|
702
|
+
* * `mountOrigin:` 'http://localhost:port',
|
|
703
|
+
* * `mountPathname:` '/<podlet pathname>',
|
|
704
|
+
* * `publicPathname:` '/:pathname/podium_resource/:manifestname',
|
|
705
|
+
*
|
|
706
|
+
* @see https://podium-lib.io/docs/api/podlet#defaultscontext
|
|
707
|
+
*
|
|
708
|
+
* @example
|
|
709
|
+
* Example of overriding deviceType
|
|
710
|
+
* ```js
|
|
711
|
+
* const podlet = new Podlet({ ... });
|
|
712
|
+
* podlet.defaults({ deviceType: 'mobile' });
|
|
713
|
+
* ```
|
|
714
|
+
*
|
|
715
|
+
* @param {any} context
|
|
716
|
+
* @returns {any}
|
|
717
|
+
*/
|
|
281
718
|
defaults(context = null) {
|
|
282
719
|
if (context) {
|
|
283
720
|
this.defaultContext = context;
|
|
@@ -285,15 +722,61 @@ export default class PodiumPodlet {
|
|
|
285
722
|
return { ...this.baseContext, ...this.defaultContext };
|
|
286
723
|
}
|
|
287
724
|
|
|
288
|
-
|
|
725
|
+
/**
|
|
726
|
+
* Method to set a Podium document template to be used when the podlet is in development mode.
|
|
727
|
+
* Must be used in conjunction with with the `.podiumSend()` method or the `podlet.render()` in the content/fallback route to have any effect.
|
|
728
|
+
* Has no effect when the podlet is not in development mode or if a request to the podlet comes from a Podium layout.
|
|
729
|
+
*
|
|
730
|
+
* @see https://podium-lib.io/docs/api/document
|
|
731
|
+
*
|
|
732
|
+
* @example
|
|
733
|
+
* A document template can be provided using the podlet.view method
|
|
734
|
+
* ```js
|
|
735
|
+
* const podlet = new Podlet({ ... });
|
|
736
|
+
* podlet.view(myDocumentTemplate);
|
|
737
|
+
* ```
|
|
738
|
+
*
|
|
739
|
+
* @example
|
|
740
|
+
* You need to call podiumSend or podlet.render to make use of the template you provided with podlet.view
|
|
741
|
+
* ```js
|
|
742
|
+
* app.get(podlet.content(), (req, res) => {
|
|
743
|
+
* res.podiumSend(`...podlet markup here...`);
|
|
744
|
+
* // or
|
|
745
|
+
* podlet.render(res.locals.podium, `...podlet markup here...`)
|
|
746
|
+
* });
|
|
747
|
+
* ```
|
|
748
|
+
*
|
|
749
|
+
* @template {{ [key: string]: unknown }} T
|
|
750
|
+
* @param {( incoming: HttpIncoming<T>, fragment: string, ...args: unknown[]) => string} fn
|
|
751
|
+
* @returns {void}
|
|
752
|
+
*/
|
|
753
|
+
view(fn) {
|
|
754
|
+
// @ts-ignore
|
|
289
755
|
if (!utils.isFunction(fn)) {
|
|
290
756
|
throw new Error(
|
|
291
757
|
`Value on argument variable "template" must be a function`,
|
|
292
758
|
);
|
|
293
759
|
}
|
|
294
|
-
this
|
|
760
|
+
this.#view = fn;
|
|
295
761
|
}
|
|
296
762
|
|
|
763
|
+
/**
|
|
764
|
+
* Method for serialising the podlet instance into a plain JS object. Called automatically when stringifying the podlet with JSON.stringify(podlet).
|
|
765
|
+
* Doing so will result in a correct Podium manifest file string and so is suitable for usage in a manifest route hook.
|
|
766
|
+
*
|
|
767
|
+
* @see https://podium-lib.io/docs/podlet/getting_started#step-7-create-a-manifest-route
|
|
768
|
+
*
|
|
769
|
+
* @example
|
|
770
|
+
* ```js
|
|
771
|
+
* app.get(podlet.manifest(), (req, res) => res.send(JSON.stringify(podlet)));
|
|
772
|
+
* ```
|
|
773
|
+
*
|
|
774
|
+
* @example
|
|
775
|
+
* In frameworks that automatically serialise JS objects, such as Express, you can omit JSON.stringify
|
|
776
|
+
* ```js
|
|
777
|
+
* app.get(podlet.manifest(), (req, res) => res.send(podlet));
|
|
778
|
+
* ```
|
|
779
|
+
*/
|
|
297
780
|
toJSON() {
|
|
298
781
|
return {
|
|
299
782
|
name: this.name,
|
|
@@ -306,24 +789,58 @@ export default class PodiumPodlet {
|
|
|
306
789
|
};
|
|
307
790
|
}
|
|
308
791
|
|
|
792
|
+
/**
|
|
793
|
+
* Method to render the document template. Will, by default, render the document template provided by Podium unless a custom document template is set using the .view method.
|
|
794
|
+
* In most HTTP frameworks this method can be ignored in favour of res.podiumSend().
|
|
795
|
+
* If present, res.podiumSend() has the advantage that it's not necessary to pass in an HttpIncoming object as the first argument.
|
|
796
|
+
*
|
|
797
|
+
* @see https://podium-lib.io/docs/api/podlet#renderhttpincoming-fragment-args
|
|
798
|
+
*
|
|
799
|
+
* @example
|
|
800
|
+
* ```js
|
|
801
|
+
* app.get(podlet.content(), (req, res) => {
|
|
802
|
+
* const incoming = res.locals.podium;
|
|
803
|
+
* const document = podlet.render(incoming, '<div>content to render</div>');
|
|
804
|
+
* res.send(document);
|
|
805
|
+
* });
|
|
806
|
+
* ```
|
|
807
|
+
*
|
|
808
|
+
* @template {{ [key: string]: unknown }} T
|
|
809
|
+
* @param {HttpIncoming<T>} incoming - Instance of Podium HttpIncoming object
|
|
810
|
+
* @param {string} data - the podlet content as an HTML markup string
|
|
811
|
+
* @param {...any} args - additional args depending on the template and what values it accepts
|
|
812
|
+
* @returns {string}
|
|
813
|
+
*/
|
|
309
814
|
render(incoming, data, ...args) {
|
|
310
815
|
if (!incoming.development) {
|
|
311
816
|
return data;
|
|
312
817
|
}
|
|
313
|
-
return this
|
|
818
|
+
return this.#view(incoming, data, ...args);
|
|
314
819
|
}
|
|
315
820
|
|
|
821
|
+
/**
|
|
822
|
+
* 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.
|
|
823
|
+
*
|
|
824
|
+
* What it does:
|
|
825
|
+
* * Handles detection of development mode and sets the appropriate defaults
|
|
826
|
+
* * Runs context deserializing on the incoming request and sets a context object at HttpIncoming.context.
|
|
827
|
+
* * Returns an HttpIncoming object.
|
|
828
|
+
*
|
|
829
|
+
* @see https://podium-lib.io/docs/api/podlet#processhttpincoming
|
|
830
|
+
*
|
|
831
|
+
* @param {HttpIncoming} incoming
|
|
832
|
+
* @param {{ proxy?: boolean }} [options]
|
|
833
|
+
* @returns {Promise<HttpIncoming>}
|
|
834
|
+
*/
|
|
316
835
|
async process(incoming, { proxy = true } = {}) {
|
|
317
836
|
incoming.name = this.name;
|
|
318
837
|
incoming.css = this.cssRoute.filter(
|
|
319
838
|
({ scope = 'all' }) =>
|
|
320
|
-
scope === this
|
|
321
|
-
scope === 'all',
|
|
839
|
+
scope === this.#currentScope(incoming) || scope === 'all',
|
|
322
840
|
);
|
|
323
841
|
incoming.js = this.jsRoute.filter(
|
|
324
842
|
({ scope = 'all' }) =>
|
|
325
|
-
scope === this
|
|
326
|
-
scope === 'all',
|
|
843
|
+
scope === this.#currentScope(incoming) || scope === 'all',
|
|
327
844
|
);
|
|
328
845
|
|
|
329
846
|
// Determine if request comes from layout server or not
|
|
@@ -349,6 +866,7 @@ export default class PodiumPodlet {
|
|
|
349
866
|
)}"`,
|
|
350
867
|
);
|
|
351
868
|
} else {
|
|
869
|
+
// @ts-ignore
|
|
352
870
|
incoming.context = utils.deserializeContext(
|
|
353
871
|
incoming.request.headers,
|
|
354
872
|
);
|
|
@@ -367,9 +885,26 @@ export default class PodiumPodlet {
|
|
|
367
885
|
return incoming;
|
|
368
886
|
}
|
|
369
887
|
|
|
888
|
+
/**
|
|
889
|
+
* A Connect/Express compatible middleware function which takes care of the multiple operations needed for a podlet to operate correctly. This function is more or less a wrapper for the .process() method.
|
|
890
|
+
* Returns an array of middleware that will create an HttpIncoming object and store it at res.locals.podium.
|
|
891
|
+
*
|
|
892
|
+
* **Important:** *This middleware must be mounted before defining any routes.*
|
|
893
|
+
*
|
|
894
|
+
* @see https://podium-lib.io/docs/api/podlet#middleware
|
|
895
|
+
*
|
|
896
|
+
* @example
|
|
897
|
+
* ```js
|
|
898
|
+
* const app = express();
|
|
899
|
+
* app.use(podlet.middleware());
|
|
900
|
+
* ```
|
|
901
|
+
*
|
|
902
|
+
* @returns {(req: any, res: any, next: function) => Promise<void>}
|
|
903
|
+
*/
|
|
370
904
|
middleware() {
|
|
371
905
|
return async (req, res, next) => {
|
|
372
906
|
const incoming = new HttpIncoming(req, res);
|
|
907
|
+
// @ts-ignore
|
|
373
908
|
incoming.url = new URL(
|
|
374
909
|
req.originalUrl,
|
|
375
910
|
`${req.protocol}://${req.get('host')}`,
|
|
@@ -397,17 +932,33 @@ export default class PodiumPodlet {
|
|
|
397
932
|
};
|
|
398
933
|
}
|
|
399
934
|
|
|
400
|
-
|
|
401
|
-
|
|
935
|
+
/**
|
|
936
|
+
* Sanitizes a uri and returns the resulting uri.
|
|
937
|
+
* If prefix is true (default false) and the uri is relative, the podlet pathname will be prepended to the uri
|
|
938
|
+
* @param {string} uri
|
|
939
|
+
* @param {boolean} prefix
|
|
940
|
+
* @returns {string}
|
|
941
|
+
*/
|
|
942
|
+
#sanitize(uri, prefix = false) {
|
|
943
|
+
const pathname = prefix ? this.#pathname : '';
|
|
402
944
|
if (uri) {
|
|
945
|
+
// @ts-ignore
|
|
403
946
|
return utils.uriIsRelative(uri)
|
|
404
|
-
?
|
|
947
|
+
? // @ts-ignore
|
|
948
|
+
utils.pathnameBuilder(pathname, uri)
|
|
405
949
|
: uri;
|
|
406
950
|
}
|
|
407
951
|
return uri;
|
|
408
952
|
}
|
|
409
953
|
|
|
410
|
-
|
|
954
|
+
/**
|
|
955
|
+
* Determines the current scope, "content", "fallback" or "all" using url matching.
|
|
956
|
+
* Scopes are used with asset objects that include a "scope" property
|
|
957
|
+
*
|
|
958
|
+
* @param {HttpIncoming} incoming
|
|
959
|
+
* @returns {'fallback' | 'content' | 'all'}
|
|
960
|
+
*/
|
|
961
|
+
#currentScope(incoming) {
|
|
411
962
|
const fallback = this.fallback({ prefix: true });
|
|
412
963
|
const content = this.content({ prefix: true });
|
|
413
964
|
const { pathname } = incoming.url;
|
|
@@ -423,4 +974,4 @@ export default class PodiumPodlet {
|
|
|
423
974
|
|
|
424
975
|
return 'all';
|
|
425
976
|
}
|
|
426
|
-
}
|
|
977
|
+
}
|