@lwrjs/view-registry 0.13.0-alpha.0 → 0.13.0-alpha.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/build/cjs/index.cjs +6 -3
- package/build/cjs/linkers/legacy_view_bootstrap.cjs +5 -2
- package/build/cjs/linkers/view_bootstrap.cjs +5 -2
- package/build/cjs/utils.cjs +28 -6
- package/build/cjs/view-handler.cjs +3 -0
- package/build/es/index.js +11 -6
- package/build/es/linkers/legacy_view_bootstrap.js +7 -3
- package/build/es/linkers/view_bootstrap.js +7 -3
- package/build/es/utils.d.ts +13 -1
- package/build/es/utils.js +34 -5
- package/build/es/view-handler.js +4 -0
- package/package.json +8 -8
package/build/cjs/index.cjs
CHANGED
|
@@ -57,7 +57,7 @@ var LwrViewRegistry = class {
|
|
|
57
57
|
observer.onAssetSourceChange(({payload}) => this.onAssetSourceChange(payload));
|
|
58
58
|
}
|
|
59
59
|
async onModuleDefinitionChange(moduleDefinition) {
|
|
60
|
-
if (
|
|
60
|
+
if ((0, import_shared_utils.isLocalDev)()) {
|
|
61
61
|
this.viewDefinitions.clear();
|
|
62
62
|
return;
|
|
63
63
|
}
|
|
@@ -80,7 +80,7 @@ var LwrViewRegistry = class {
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
async onViewSourceChange(compiledView) {
|
|
83
|
-
if (
|
|
83
|
+
if ((0, import_shared_utils.isLocalDev)()) {
|
|
84
84
|
this.viewDefinitions.clear();
|
|
85
85
|
return;
|
|
86
86
|
}
|
|
@@ -194,6 +194,8 @@ var LwrViewRegistry = class {
|
|
|
194
194
|
return viewDefinition2.viewDefinition;
|
|
195
195
|
}
|
|
196
196
|
}
|
|
197
|
+
const updatableViewParams = {...viewParams};
|
|
198
|
+
(0, import_utils.generateViewNonce)(updatableViewParams);
|
|
197
199
|
const pendingViewDefCacheKey = viewDefCacheKey + viewParamKey;
|
|
198
200
|
const viewDefinition = await this.pendingViewDefinitions.execute(pendingViewDefCacheKey, () => (0, import_instrumentation.getTracer)().trace({
|
|
199
201
|
name: import_instrumentation.ViewSpan.RenderView,
|
|
@@ -201,7 +203,8 @@ var LwrViewRegistry = class {
|
|
|
201
203
|
view: view.id,
|
|
202
204
|
ssr: view.bootstrap?.ssr === true
|
|
203
205
|
}
|
|
204
|
-
}, () => this.renderView(view,
|
|
206
|
+
}, () => this.renderView(view, updatableViewParams, runtimeEnvironment, runtimeParams, renderOptions)));
|
|
207
|
+
viewDefinition.nonce = (0, import_utils.getViewNonce)(updatableViewParams);
|
|
205
208
|
if (cacheDisabled === false) {
|
|
206
209
|
const route = this.globalConfig.routes.find((r) => r.id === view.id);
|
|
207
210
|
const ttl = (0, import_shared_utils.shortestTtl)(viewDefinition.cache?.ttl, route?.cache?.ttl);
|
|
@@ -101,6 +101,7 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
101
101
|
groups: new Map()
|
|
102
102
|
};
|
|
103
103
|
const isSSR = view.bootstrap?.ssr;
|
|
104
|
+
const nonce = (0, import_utils.getViewNonce)(viewParams);
|
|
104
105
|
let bootstrapModuleRef, versionedSpecifier = bootstrapSpecifier;
|
|
105
106
|
const customElementsRecords = [];
|
|
106
107
|
const flattenedElements = (0, import_utils2.flattenCustomElements)(customElements, isSSR);
|
|
@@ -125,6 +126,7 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
125
126
|
if (!def.inline && !def.src) {
|
|
126
127
|
throw Error(`Invalid Shim ${shimBundle}: ${JSON.stringify(def)}`);
|
|
127
128
|
}
|
|
129
|
+
(0, import_utils.addExternalScriptNonce)(def, nonce);
|
|
128
130
|
requiredResources.push(def);
|
|
129
131
|
const errorShimDef = await resourceRegistry.getResource({specifier: "lwr-error-shim.js", version}, runtimeEnvironment, runtimeParams);
|
|
130
132
|
if (!errorShimDef) {
|
|
@@ -133,6 +135,7 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
133
135
|
if (!errorShimDef.inline && !errorShimDef.src) {
|
|
134
136
|
throw Error(`Invalid Shim lwr-error-shim.js: ${JSON.stringify(errorShimDef)}`);
|
|
135
137
|
}
|
|
138
|
+
(0, import_utils.addExternalScriptNonce)(errorShimDef, nonce);
|
|
136
139
|
requiredResources.push(errorShimDef);
|
|
137
140
|
}
|
|
138
141
|
const bootstrapModuleGraph = await (0, import_shared_utils.getModuleGraphs)(bootstrapSpecifier, {includeUris: true, includeLinkedDefinitions: true, depth}, moduleRegistry, defRegistry, runtimeEnvironment, runtimeParams, visitedCache);
|
|
@@ -146,7 +149,7 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
146
149
|
if (!uri) {
|
|
147
150
|
throw Error(`Invalid Module Resource ${versionedSpecifier}`);
|
|
148
151
|
}
|
|
149
|
-
moduleResources.push((0, import_utils.getModuleResourceByUri)(uri, runtimeEnvironment, {isPreload: false, isSSR}));
|
|
152
|
+
moduleResources.push((0, import_utils.getModuleResourceByUri)(uri, runtimeEnvironment, {isPreload: false, isSSR, nonce}));
|
|
150
153
|
for (const depSpecifier of bootstrapModuleGraph.graphs[0].static) {
|
|
151
154
|
const uri2 = getPreloadUri(depSpecifier, bootstrapModuleGraph.uriMap);
|
|
152
155
|
if (uri2) {
|
|
@@ -235,7 +238,7 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
235
238
|
}
|
|
236
239
|
const dedupedUris = [...new Set(viewPreloads.uris)];
|
|
237
240
|
for (const preloadUri of dedupedUris) {
|
|
238
|
-
moduleResources.push((0, import_utils.getModuleResourceByUri)(preloadUri, runtimeEnvironment, {isPreload: true, isSSR}));
|
|
241
|
+
moduleResources.push((0, import_utils.getModuleResourceByUri)(preloadUri, runtimeEnvironment, {isPreload: true, isSSR, nonce}));
|
|
239
242
|
}
|
|
240
243
|
const htmlResources = await Promise.all([...configResources, ...requiredResources, ...moduleResources].map(import_utils.generateHtmlTag));
|
|
241
244
|
return {
|
|
@@ -90,6 +90,7 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
90
90
|
groups: new Map()
|
|
91
91
|
};
|
|
92
92
|
const isSSR = view.bootstrap?.ssr;
|
|
93
|
+
const nonce = (0, import_utils.getViewNonce)(viewParams);
|
|
93
94
|
let bootstrapModuleRef, versionedSpecifier = bootstrapSpecifier;
|
|
94
95
|
let importMetadata = {imports: {}};
|
|
95
96
|
const customElementsRecords = [];
|
|
@@ -105,6 +106,7 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
105
106
|
if (!def.inline && !def.src) {
|
|
106
107
|
throw Error(`Invalid Shim ${shimBundle}: ${JSON.stringify(def)}`);
|
|
107
108
|
}
|
|
109
|
+
(0, import_utils.addExternalScriptNonce)(def, nonce);
|
|
108
110
|
requiredResources.push(def);
|
|
109
111
|
const errorShimDef = await resourceRegistry.getResource({specifier: "lwr-error-shim.js", version}, runtimeEnvironment, runtimeParams);
|
|
110
112
|
if (!errorShimDef) {
|
|
@@ -113,6 +115,7 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
113
115
|
if (!errorShimDef.inline && !errorShimDef.src) {
|
|
114
116
|
throw Error(`Invalid Shim lwr-error-shim.js: ${JSON.stringify(errorShimDef)}`);
|
|
115
117
|
}
|
|
118
|
+
(0, import_utils.addExternalScriptNonce)(errorShimDef, nonce);
|
|
116
119
|
requiredResources.push(errorShimDef);
|
|
117
120
|
}
|
|
118
121
|
const bootstrapModuleGraph = await (0, import_shared_utils.getModuleGraphs)(bootstrapSpecifier, {includeUris: true, includeLinkedDefinitions: true, depth}, moduleRegistry, defRegistry, runtimeEnvironment, runtimeParams, visitedCache);
|
|
@@ -126,7 +129,7 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
126
129
|
if (!uri) {
|
|
127
130
|
throw Error(`Invalid Module Resource ${versionedSpecifier}`);
|
|
128
131
|
}
|
|
129
|
-
moduleResources.push((0, import_utils.getModuleResourceByUri)(uri, runtimeEnvironment, {isPreload: false, isSSR}));
|
|
132
|
+
moduleResources.push((0, import_utils.getModuleResourceByUri)(uri, runtimeEnvironment, {isPreload: false, isSSR, nonce}));
|
|
130
133
|
for (const depSpecifier of bootstrapModuleGraph.graphs[0].static) {
|
|
131
134
|
const uri2 = getPreloadUri(depSpecifier, bootstrapModuleGraph.uriMap);
|
|
132
135
|
if (uri2) {
|
|
@@ -215,7 +218,7 @@ async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
215
218
|
}
|
|
216
219
|
const dedupedUris = [...new Set(viewPreloads.uris)];
|
|
217
220
|
for (const preloadUri of dedupedUris) {
|
|
218
|
-
moduleResources.push((0, import_utils.getModuleResourceByUri)(preloadUri, runtimeEnvironment, {isPreload: true, isSSR}));
|
|
221
|
+
moduleResources.push((0, import_utils.getModuleResourceByUri)(preloadUri, runtimeEnvironment, {isPreload: true, isSSR, nonce}));
|
|
219
222
|
}
|
|
220
223
|
const htmlResources = await Promise.all([...configResources, ...requiredResources, ...moduleResources].map(import_utils.generateHtmlTag));
|
|
221
224
|
const mapping = (0, import_shared_utils.getMappingUriPrefix)(runtimeEnvironment, runtimeParams);
|
package/build/cjs/utils.cjs
CHANGED
|
@@ -24,11 +24,14 @@ var __toModule = (module2) => {
|
|
|
24
24
|
// packages/@lwrjs/view-registry/src/utils.ts
|
|
25
25
|
__markAsModule(exports);
|
|
26
26
|
__export(exports, {
|
|
27
|
+
addExternalScriptNonce: () => addExternalScriptNonce,
|
|
27
28
|
createJsonModule: () => createJsonModule,
|
|
28
29
|
generateHtmlTag: () => generateHtmlTag,
|
|
29
30
|
generatePageContext: () => generatePageContext,
|
|
31
|
+
generateViewNonce: () => generateViewNonce,
|
|
30
32
|
getModuleResource: () => getModuleResource,
|
|
31
33
|
getModuleResourceByUri: () => getModuleResourceByUri,
|
|
34
|
+
getViewNonce: () => getViewNonce,
|
|
32
35
|
isViewResponse: () => isViewResponse,
|
|
33
36
|
normalizeRenderOptions: () => normalizeRenderOptions,
|
|
34
37
|
normalizeRenderedResult: () => normalizeRenderedResult,
|
|
@@ -38,17 +41,19 @@ __export(exports, {
|
|
|
38
41
|
var import_path = __toModule(require("path"));
|
|
39
42
|
var import_shared_utils = __toModule(require("@lwrjs/shared-utils"));
|
|
40
43
|
var import_identity = __toModule(require("@lwrjs/app-service/identity"));
|
|
44
|
+
var import_crypto = __toModule(require("crypto"));
|
|
41
45
|
function generateExternalStyle(src) {
|
|
42
46
|
return `<link rel="stylesheet" href="${src}">`;
|
|
43
47
|
}
|
|
44
|
-
function generateExternalScript(type = "application/javascript", src, async, defer) {
|
|
48
|
+
function generateExternalScript(type = "application/javascript", src, async, defer, nonce) {
|
|
45
49
|
let scriptLoadOrder = "";
|
|
46
50
|
if (defer) {
|
|
47
51
|
scriptLoadOrder = " defer";
|
|
48
52
|
} else if (async) {
|
|
49
53
|
scriptLoadOrder = " async";
|
|
50
54
|
}
|
|
51
|
-
|
|
55
|
+
const nonceAttr = nonce ? ` nonce="${nonce}"` : "";
|
|
56
|
+
return `<script type="${type}"${scriptLoadOrder}${nonceAttr} src="${src}"></script>`;
|
|
52
57
|
}
|
|
53
58
|
function generateLinkPreloadTag({href, type}) {
|
|
54
59
|
if (type === "module") {
|
|
@@ -57,13 +62,13 @@ function generateLinkPreloadTag({href, type}) {
|
|
|
57
62
|
return `<link rel="preload" href="${href}" type="${type}" />`;
|
|
58
63
|
}
|
|
59
64
|
}
|
|
60
|
-
function generateExternalTag({type, src = "", async, defer, isPreload}) {
|
|
65
|
+
function generateExternalTag({type, src = "", async, defer, isPreload, nonce}) {
|
|
61
66
|
if (isPreload) {
|
|
62
67
|
return generateLinkPreloadTag({href: src, type});
|
|
63
68
|
} else if (type === "text/css") {
|
|
64
69
|
return generateExternalStyle(src);
|
|
65
70
|
} else {
|
|
66
|
-
return generateExternalScript(type, src, async, defer);
|
|
71
|
+
return generateExternalScript(type, src, async, defer, nonce);
|
|
67
72
|
}
|
|
68
73
|
}
|
|
69
74
|
async function generateInlineTag({specifier, type, content, stream, nonce}) {
|
|
@@ -223,14 +228,15 @@ async function getModuleResource(moduleId, runtimeEnvironment, moduleResourceMet
|
|
|
223
228
|
};
|
|
224
229
|
}
|
|
225
230
|
function getModuleResourceByUri(uri, runtimeEnvironment, moduleResourceMeta) {
|
|
226
|
-
const {isSSR = false, isPreload = false} = moduleResourceMeta;
|
|
231
|
+
const {isSSR = false, isPreload = false, nonce} = moduleResourceMeta;
|
|
227
232
|
const {format} = runtimeEnvironment;
|
|
228
233
|
return {
|
|
229
234
|
src: uri,
|
|
230
235
|
type: format === "amd" ? "application/javascript" : "module",
|
|
231
236
|
async: !isSSR && isPreload,
|
|
232
237
|
defer: isSSR,
|
|
233
|
-
isPreload: format !== "amd" && isPreload
|
|
238
|
+
isPreload: format !== "amd" && isPreload,
|
|
239
|
+
nonce
|
|
234
240
|
};
|
|
235
241
|
}
|
|
236
242
|
async function createJsonModule(specifier, moduleRegistry, environment, params) {
|
|
@@ -252,3 +258,19 @@ async function createJsonModule(specifier, moduleRegistry, environment, params)
|
|
|
252
258
|
}
|
|
253
259
|
};
|
|
254
260
|
}
|
|
261
|
+
function getViewNonce(viewParams) {
|
|
262
|
+
return viewParams?.page?.nonce;
|
|
263
|
+
}
|
|
264
|
+
function generateViewNonce(viewParams) {
|
|
265
|
+
const nonce = import_crypto.default.randomBytes(16).toString("base64");
|
|
266
|
+
if (!viewParams.page) {
|
|
267
|
+
viewParams.page = {nonce};
|
|
268
|
+
} else {
|
|
269
|
+
viewParams.page.nonce = nonce;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
function addExternalScriptNonce(def, nonce) {
|
|
273
|
+
if (!def.inline) {
|
|
274
|
+
def.nonce = nonce;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
@@ -148,6 +148,9 @@ var LwrViewHandler = class {
|
|
|
148
148
|
throw (0, import_diagnostics.createSingleDiagnosticError)({description: import_diagnostics.descriptions.APPLICATION.ROUTE_HANDLER_ERROR(route.id, message)}, import_diagnostics.LwrApplicationError);
|
|
149
149
|
}
|
|
150
150
|
});
|
|
151
|
+
if (response?.locale) {
|
|
152
|
+
runtimeParams.locale = response.locale;
|
|
153
|
+
}
|
|
151
154
|
return response;
|
|
152
155
|
}
|
|
153
156
|
getBoundApi(viewRequest, route, runtimeEnvironment, runtimeParams) {
|
package/build/es/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { InflightTasks, createStringBuilder, extractMetadataFromHtml, getCacheKeyFromJson, getSpecifier, normalizeResourcePath, shortestTtl, } from '@lwrjs/shared-utils';
|
|
1
|
+
import { InflightTasks, createStringBuilder, extractMetadataFromHtml, getCacheKeyFromJson, getSpecifier, isLocalDev, normalizeResourcePath, shortestTtl, } from '@lwrjs/shared-utils';
|
|
2
2
|
import { getTracer, ViewSpan } from '@lwrjs/instrumentation';
|
|
3
|
-
import { normalizeRenderOptions, normalizeRenderedResult, reduceSourceAssetReferences } from './utils.js';
|
|
3
|
+
import { generateViewNonce, getViewNonce, normalizeRenderOptions, normalizeRenderedResult, reduceSourceAssetReferences, } from './utils.js';
|
|
4
4
|
import { linkLwrResources } from './linkers/link-lwr-resources.js';
|
|
5
5
|
import { LRUCache } from 'lru-cache';
|
|
6
6
|
import { DiagnosticsError, LwrServerError, createSingleDiagnosticError, descriptions, logger, } from '@lwrjs/diagnostics';
|
|
@@ -37,7 +37,7 @@ export class LwrViewRegistry {
|
|
|
37
37
|
}
|
|
38
38
|
async onModuleDefinitionChange(moduleDefinition) {
|
|
39
39
|
// TODO we will make this more robust in the future w/ full MRT HMR
|
|
40
|
-
if (
|
|
40
|
+
if (isLocalDev()) {
|
|
41
41
|
this.viewDefinitions.clear();
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
@@ -63,7 +63,7 @@ export class LwrViewRegistry {
|
|
|
63
63
|
}
|
|
64
64
|
async onViewSourceChange(compiledView) {
|
|
65
65
|
// TODO we will make this more robust in the future w/ full MRT HMR
|
|
66
|
-
if (
|
|
66
|
+
if (isLocalDev()) {
|
|
67
67
|
this.viewDefinitions.clear();
|
|
68
68
|
return;
|
|
69
69
|
}
|
|
@@ -152,7 +152,7 @@ export class LwrViewRegistry {
|
|
|
152
152
|
debug: runtimeEnvironment.debug,
|
|
153
153
|
});
|
|
154
154
|
logger.debug(`[view-registry][hasViewDefinition] viewDefId=${viewDefId}`);
|
|
155
|
-
// viewParams is an unbounded object and can be very large (17MB/view for developer.salesforce.com). Allowing
|
|
155
|
+
// viewParams is an unbounded object and can be very large (17MB/view for developer.salesforce.com). Allowing consumers
|
|
156
156
|
// to provide a simple override avoids the excess memory / performance overhead of serializing & storing the viewParams
|
|
157
157
|
// on every request, while still reusing our caching logic.
|
|
158
158
|
const viewParamKey = viewParamCacheKey
|
|
@@ -196,6 +196,9 @@ export class LwrViewRegistry {
|
|
|
196
196
|
return viewDefinition.viewDefinition;
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
|
+
// If we missed cache generate a nonce in the page context (we do not want it part of the cache key)
|
|
200
|
+
const updatableViewParams = { ...viewParams };
|
|
201
|
+
generateViewNonce(updatableViewParams);
|
|
199
202
|
const pendingViewDefCacheKey = viewDefCacheKey + viewParamKey;
|
|
200
203
|
const viewDefinition = await this.pendingViewDefinitions.execute(pendingViewDefCacheKey, () => getTracer().trace({
|
|
201
204
|
name: ViewSpan.RenderView,
|
|
@@ -203,7 +206,9 @@ export class LwrViewRegistry {
|
|
|
203
206
|
view: view.id,
|
|
204
207
|
ssr: view.bootstrap?.ssr === true,
|
|
205
208
|
},
|
|
206
|
-
}, () => this.renderView(view,
|
|
209
|
+
}, () => this.renderView(view, updatableViewParams, runtimeEnvironment, runtimeParams, renderOptions)));
|
|
210
|
+
// Once the view is generated add the nonce to the response so it can be cached and then added to the headers
|
|
211
|
+
viewDefinition.nonce = getViewNonce(updatableViewParams);
|
|
207
212
|
if (cacheDisabled === false) {
|
|
208
213
|
const route = this.globalConfig.routes.find((r) => r.id === view.id);
|
|
209
214
|
const ttl = shortestTtl(viewDefinition.cache?.ttl, route?.cache?.ttl);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { logger } from '@lwrjs/diagnostics';
|
|
2
2
|
import { kebabCaseToModuleSpecifier, getModuleGraphs, GraphDepth, getModuleUriPrefix, explodeSpecifier, isBundler, getHydrateDirective, isGroupie, isExternalSpecifier, } from '@lwrjs/shared-utils';
|
|
3
3
|
import { AppResourceEnum, getAppSpecifier } from '@lwrjs/app-service/identity';
|
|
4
|
-
import { generateHtmlTag, getModuleResourceByUri } from '../utils.js';
|
|
4
|
+
import { addExternalScriptNonce, generateHtmlTag, getModuleResourceByUri, getViewNonce } from '../utils.js';
|
|
5
5
|
import { flattenCustomElements, getViewBootstrapConfigurationResource, getViewHmrConfigurationResource, } from './utils.js';
|
|
6
6
|
import { setPreloadModulesMeta, getPreloadModulesMeta } from './preload-utils.js';
|
|
7
7
|
function includeIdFactory(bundleConfig) {
|
|
@@ -92,6 +92,8 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
92
92
|
};
|
|
93
93
|
// Determine if server side rendering view modules
|
|
94
94
|
const isSSR = view.bootstrap?.ssr;
|
|
95
|
+
// Page level nonce for script tags
|
|
96
|
+
const nonce = getViewNonce(viewParams);
|
|
95
97
|
// ABS module and custom element references
|
|
96
98
|
let bootstrapModuleRef, versionedSpecifier = bootstrapSpecifier;
|
|
97
99
|
const customElementsRecords = [];
|
|
@@ -126,6 +128,7 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
126
128
|
if (!def.inline && !def.src) {
|
|
127
129
|
throw Error(`Invalid Shim ${shimBundle}: ${JSON.stringify(def)}`);
|
|
128
130
|
}
|
|
131
|
+
addExternalScriptNonce(def, nonce);
|
|
129
132
|
requiredResources.push(def);
|
|
130
133
|
// Always inline the error shim script after the shim
|
|
131
134
|
const errorShimDef = (await resourceRegistry.getResource({ specifier: 'lwr-error-shim.js', version }, runtimeEnvironment, runtimeParams));
|
|
@@ -136,6 +139,7 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
136
139
|
if (!errorShimDef.inline && !errorShimDef.src) {
|
|
137
140
|
throw Error(`Invalid Shim lwr-error-shim.js: ${JSON.stringify(errorShimDef)}`);
|
|
138
141
|
}
|
|
142
|
+
addExternalScriptNonce(errorShimDef, nonce);
|
|
139
143
|
requiredResources.push(errorShimDef);
|
|
140
144
|
}
|
|
141
145
|
// ------- Application Bootstrap module
|
|
@@ -155,7 +159,7 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
155
159
|
if (!uri) {
|
|
156
160
|
throw Error(`Invalid Module Resource ${versionedSpecifier}`);
|
|
157
161
|
}
|
|
158
|
-
moduleResources.push(getModuleResourceByUri(uri, runtimeEnvironment, { isPreload: false, isSSR }));
|
|
162
|
+
moduleResources.push(getModuleResourceByUri(uri, runtimeEnvironment, { isPreload: false, isSSR, nonce }));
|
|
159
163
|
// PRELOAD the bootstrap module static dependencies as preloaded script resources
|
|
160
164
|
for (const depSpecifier of bootstrapModuleGraph.graphs[0].static) {
|
|
161
165
|
const uri = getPreloadUri(depSpecifier, bootstrapModuleGraph.uriMap);
|
|
@@ -265,7 +269,7 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
265
269
|
const dedupedUris = [...new Set(viewPreloads.uris)];
|
|
266
270
|
// PRELOAD script resources for preload module URIs after the bootstrap module
|
|
267
271
|
for (const preloadUri of dedupedUris) {
|
|
268
|
-
moduleResources.push(getModuleResourceByUri(preloadUri, runtimeEnvironment, { isPreload: true, isSSR }));
|
|
272
|
+
moduleResources.push(getModuleResourceByUri(preloadUri, runtimeEnvironment, { isPreload: true, isSSR, nonce }));
|
|
269
273
|
}
|
|
270
274
|
// generate html partial
|
|
271
275
|
const htmlResources = await Promise.all([...configResources, ...requiredResources, ...moduleResources].map(generateHtmlTag));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { logger } from '@lwrjs/diagnostics';
|
|
2
2
|
import { kebabCaseToModuleSpecifier, toImportMetadata, getModuleGraphs, getMappingUriPrefix, GraphDepth, explodeSpecifier, isBundler, getHydrateDirective, isGroupie, } from '@lwrjs/shared-utils';
|
|
3
3
|
import { AppResourceEnum, getAppSpecifier } from '@lwrjs/app-service/identity';
|
|
4
|
-
import { generateHtmlTag, getModuleResourceByUri } from '../utils.js';
|
|
4
|
+
import { addExternalScriptNonce, generateHtmlTag, getModuleResourceByUri, getViewNonce } from '../utils.js';
|
|
5
5
|
import { flattenCustomElements, getViewBootstrapConfigurationResource, getViewHmrConfigurationResource, } from './utils.js';
|
|
6
6
|
import { setPreloadModulesMeta, getPreloadModulesMeta } from './preload-utils.js';
|
|
7
7
|
export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
@@ -75,6 +75,8 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
75
75
|
};
|
|
76
76
|
// Determine if server side rendering view modules
|
|
77
77
|
const isSSR = view.bootstrap?.ssr;
|
|
78
|
+
// Page level nonce for script tags
|
|
79
|
+
const nonce = getViewNonce(viewParams);
|
|
78
80
|
// ABS module and custom element references
|
|
79
81
|
let bootstrapModuleRef, versionedSpecifier = bootstrapSpecifier;
|
|
80
82
|
let importMetadata = { imports: {} };
|
|
@@ -94,6 +96,7 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
94
96
|
if (!def.inline && !def.src) {
|
|
95
97
|
throw Error(`Invalid Shim ${shimBundle}: ${JSON.stringify(def)}`);
|
|
96
98
|
}
|
|
99
|
+
addExternalScriptNonce(def, nonce);
|
|
97
100
|
requiredResources.push(def);
|
|
98
101
|
// Always inline the error shim script after the shim
|
|
99
102
|
const errorShimDef = (await resourceRegistry.getResource({ specifier: 'lwr-error-shim.js', version }, runtimeEnvironment, runtimeParams));
|
|
@@ -104,6 +107,7 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
104
107
|
if (!errorShimDef.inline && !errorShimDef.src) {
|
|
105
108
|
throw Error(`Invalid Shim lwr-error-shim.js: ${JSON.stringify(errorShimDef)}`);
|
|
106
109
|
}
|
|
110
|
+
addExternalScriptNonce(errorShimDef, nonce);
|
|
107
111
|
requiredResources.push(errorShimDef);
|
|
108
112
|
}
|
|
109
113
|
// ------- Application Bootstrap module
|
|
@@ -122,7 +126,7 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
122
126
|
if (!uri) {
|
|
123
127
|
throw Error(`Invalid Module Resource ${versionedSpecifier}`);
|
|
124
128
|
}
|
|
125
|
-
moduleResources.push(getModuleResourceByUri(uri, runtimeEnvironment, { isPreload: false, isSSR }));
|
|
129
|
+
moduleResources.push(getModuleResourceByUri(uri, runtimeEnvironment, { isPreload: false, isSSR, nonce }));
|
|
126
130
|
// PRELOAD the bootstrap module static dependencies as preloaded script resources
|
|
127
131
|
for (const depSpecifier of bootstrapModuleGraph.graphs[0].static) {
|
|
128
132
|
const uri = getPreloadUri(depSpecifier, bootstrapModuleGraph.uriMap);
|
|
@@ -234,7 +238,7 @@ export async function getHtmlResources(view, viewParams, resourceContext) {
|
|
|
234
238
|
// PRELOAD script resources for preload module URIs after the bootstrap module
|
|
235
239
|
const dedupedUris = [...new Set(viewPreloads.uris)];
|
|
236
240
|
for (const preloadUri of dedupedUris) {
|
|
237
|
-
moduleResources.push(getModuleResourceByUri(preloadUri, runtimeEnvironment, { isPreload: true, isSSR }));
|
|
241
|
+
moduleResources.push(getModuleResourceByUri(preloadUri, runtimeEnvironment, { isPreload: true, isSSR, nonce }));
|
|
238
242
|
}
|
|
239
243
|
// generate html partial
|
|
240
244
|
const htmlResources = await Promise.all([...configResources, ...requiredResources, ...moduleResources].map(generateHtmlTag));
|
package/build/es/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AssetReference, JsonCompatible, LinkedViewDefinition, LwrErrorRoute, LwrRoute, ModuleBundler, ModuleId, ModuleJson, ModuleRegistry, NormalizedRenderingResult, PublicModuleRegistry, RenderOptions, RenderedAssetReference, RenderingResult, ResourceDefinition, RouteHandlerViewResponse, RuntimeEnvironment, RuntimeParams, ViewModuleResourceContext, ViewPageContext, ViewRequest, ViewResponse } from '@lwrjs/types';
|
|
1
|
+
import type { AssetReference, JsonCompatible, LinkedViewDefinition, LwrErrorRoute, LwrRoute, ModuleBundler, ModuleId, ModuleJson, ModuleRegistry, NormalizedRenderingResult, PublicModuleRegistry, RenderOptions, RenderedAssetReference, RenderingResult, ResourceDefinition, RouteHandlerViewResponse, RuntimeEnvironment, RuntimeParams, ViewModuleResourceContext, ViewPageContext, ViewParams, ViewRequest, ViewResponse } from '@lwrjs/types';
|
|
2
2
|
export type HTMLResource = Partial<ResourceDefinition>;
|
|
3
3
|
export declare function generateHtmlTag(definition: HTMLResource): Promise<string>;
|
|
4
4
|
export declare function normalizeRenderedResult({ renderedView, metadata, options, cache, }: RenderingResult): NormalizedRenderingResult;
|
|
@@ -10,4 +10,16 @@ export declare function toJsonFormat(viewRequest: ViewRequest, viewDefinition: L
|
|
|
10
10
|
export declare function getModuleResource(moduleId: Pick<ModuleId, 'specifier' | 'version'>, runtimeEnvironment: RuntimeEnvironment, moduleResourceMeta: ViewModuleResourceContext, defRegistry: ModuleRegistry | ModuleBundler, runtimeParams: RuntimeParams): Promise<ResourceDefinition>;
|
|
11
11
|
export declare function getModuleResourceByUri(uri: string, runtimeEnvironment: RuntimeEnvironment, moduleResourceMeta: ViewModuleResourceContext): ResourceDefinition;
|
|
12
12
|
export declare function createJsonModule(specifier: string, moduleRegistry: PublicModuleRegistry, environment: RuntimeEnvironment, params: RuntimeParams): Promise<ModuleJson>;
|
|
13
|
+
/**
|
|
14
|
+
* Get the nonce set on the page context of the view params
|
|
15
|
+
*/
|
|
16
|
+
export declare function getViewNonce(viewParams: ViewParams): string;
|
|
17
|
+
/**
|
|
18
|
+
* Generate a nonce in the page context of the view params
|
|
19
|
+
*/
|
|
20
|
+
export declare function generateViewNonce(viewParams: ViewParams): void;
|
|
21
|
+
/**
|
|
22
|
+
* Add a nonce to a script definition in view if it is external (not inline)
|
|
23
|
+
*/
|
|
24
|
+
export declare function addExternalScriptNonce(def: ResourceDefinition, nonce: string): void;
|
|
13
25
|
//# sourceMappingURL=utils.d.ts.map
|
package/build/es/utils.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { basename, extname } from 'path';
|
|
2
2
|
import { explodeSpecifier, getMappingUriPrefix, getSpecifier, getClientBootstrapConfigurationUri, mimeLookup, DEFAULT_TITLE, streamToString, } from '@lwrjs/shared-utils';
|
|
3
3
|
import { AppResourceEnum, getAppSpecifier, ResourceIdentityTypes, } from '@lwrjs/app-service/identity';
|
|
4
|
+
import crypto from 'crypto';
|
|
4
5
|
function generateExternalStyle(src) {
|
|
5
6
|
return `<link rel="stylesheet" href="${src}">`;
|
|
6
7
|
}
|
|
7
|
-
function generateExternalScript(type = 'application/javascript', src, async, defer) {
|
|
8
|
+
function generateExternalScript(type = 'application/javascript', src, async, defer, nonce) {
|
|
8
9
|
let scriptLoadOrder = '';
|
|
9
10
|
if (defer) {
|
|
10
11
|
scriptLoadOrder = ' defer';
|
|
@@ -12,7 +13,8 @@ function generateExternalScript(type = 'application/javascript', src, async, def
|
|
|
12
13
|
else if (async) {
|
|
13
14
|
scriptLoadOrder = ' async';
|
|
14
15
|
}
|
|
15
|
-
|
|
16
|
+
const nonceAttr = nonce ? ` nonce="${nonce}"` : '';
|
|
17
|
+
return `<script type="${type}"${scriptLoadOrder}${nonceAttr} src="${src}"></script>`;
|
|
16
18
|
}
|
|
17
19
|
function generateLinkPreloadTag({ href, type }) {
|
|
18
20
|
if (type === 'module') {
|
|
@@ -22,7 +24,7 @@ function generateLinkPreloadTag({ href, type }) {
|
|
|
22
24
|
return `<link rel="preload" href="${href}" type="${type}" />`;
|
|
23
25
|
}
|
|
24
26
|
}
|
|
25
|
-
function generateExternalTag({ type, src = '', async, defer, isPreload }) {
|
|
27
|
+
function generateExternalTag({ type, src = '', async, defer, isPreload, nonce }) {
|
|
26
28
|
if (isPreload) {
|
|
27
29
|
return generateLinkPreloadTag({ href: src, type: type });
|
|
28
30
|
}
|
|
@@ -30,7 +32,7 @@ function generateExternalTag({ type, src = '', async, defer, isPreload }) {
|
|
|
30
32
|
return generateExternalStyle(src);
|
|
31
33
|
}
|
|
32
34
|
else {
|
|
33
|
-
return generateExternalScript(type, src, async, defer);
|
|
35
|
+
return generateExternalScript(type, src, async, defer, nonce);
|
|
34
36
|
}
|
|
35
37
|
}
|
|
36
38
|
async function generateInlineTag({ specifier, type, content, stream, nonce }) {
|
|
@@ -203,7 +205,7 @@ export async function getModuleResource(moduleId, runtimeEnvironment, moduleReso
|
|
|
203
205
|
};
|
|
204
206
|
}
|
|
205
207
|
export function getModuleResourceByUri(uri, runtimeEnvironment, moduleResourceMeta) {
|
|
206
|
-
const { isSSR = false, isPreload = false } = moduleResourceMeta;
|
|
208
|
+
const { isSSR = false, isPreload = false, nonce } = moduleResourceMeta;
|
|
207
209
|
const { format } = runtimeEnvironment;
|
|
208
210
|
return {
|
|
209
211
|
src: uri,
|
|
@@ -213,6 +215,7 @@ export function getModuleResourceByUri(uri, runtimeEnvironment, moduleResourceMe
|
|
|
213
215
|
// only use link preload for ESM for compat reasons.
|
|
214
216
|
// AMD should use regular script tags for preloading
|
|
215
217
|
isPreload: format !== 'amd' && isPreload,
|
|
218
|
+
nonce,
|
|
216
219
|
};
|
|
217
220
|
}
|
|
218
221
|
// Given a specifier and resource type, return the JSON serialized Module data
|
|
@@ -236,4 +239,30 @@ export async function createJsonModule(specifier, moduleRegistry, environment, p
|
|
|
236
239
|
},
|
|
237
240
|
};
|
|
238
241
|
}
|
|
242
|
+
/**
|
|
243
|
+
* Get the nonce set on the page context of the view params
|
|
244
|
+
*/
|
|
245
|
+
export function getViewNonce(viewParams) {
|
|
246
|
+
return viewParams?.page?.nonce;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Generate a nonce in the page context of the view params
|
|
250
|
+
*/
|
|
251
|
+
export function generateViewNonce(viewParams) {
|
|
252
|
+
const nonce = crypto.randomBytes(16).toString('base64');
|
|
253
|
+
if (!viewParams.page) {
|
|
254
|
+
viewParams.page = { nonce };
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
viewParams.page.nonce = nonce;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Add a nonce to a script definition in view if it is external (not inline)
|
|
262
|
+
*/
|
|
263
|
+
export function addExternalScriptNonce(def, nonce) {
|
|
264
|
+
if (!def.inline) {
|
|
265
|
+
def.nonce = nonce;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
239
268
|
//# sourceMappingURL=utils.js.map
|
package/build/es/view-handler.js
CHANGED
|
@@ -165,6 +165,10 @@ export class LwrViewHandler {
|
|
|
165
165
|
throw createSingleDiagnosticError({ description: descriptions.APPLICATION.ROUTE_HANDLER_ERROR(route.id, message) }, LwrApplicationError);
|
|
166
166
|
}
|
|
167
167
|
});
|
|
168
|
+
// if the locale was returned by the route handler update the runtime time params
|
|
169
|
+
if (response?.locale) {
|
|
170
|
+
runtimeParams.locale = response.locale;
|
|
171
|
+
}
|
|
168
172
|
return response;
|
|
169
173
|
}
|
|
170
174
|
/*
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.13.0-alpha.
|
|
7
|
+
"version": "0.13.0-alpha.10",
|
|
8
8
|
"homepage": "https://developer.salesforce.com/docs/platform/lwr/overview",
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
@@ -30,17 +30,17 @@
|
|
|
30
30
|
"build/**/*.d.ts"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@lwrjs/app-service": "0.13.0-alpha.
|
|
34
|
-
"@lwrjs/diagnostics": "0.13.0-alpha.
|
|
35
|
-
"@lwrjs/instrumentation": "0.13.0-alpha.
|
|
36
|
-
"@lwrjs/shared-utils": "0.13.0-alpha.
|
|
37
|
-
"lru-cache": "^10.2.
|
|
33
|
+
"@lwrjs/app-service": "0.13.0-alpha.10",
|
|
34
|
+
"@lwrjs/diagnostics": "0.13.0-alpha.10",
|
|
35
|
+
"@lwrjs/instrumentation": "0.13.0-alpha.10",
|
|
36
|
+
"@lwrjs/shared-utils": "0.13.0-alpha.10",
|
|
37
|
+
"lru-cache": "^10.2.2"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@lwrjs/types": "0.13.0-alpha.
|
|
40
|
+
"@lwrjs/types": "0.13.0-alpha.10"
|
|
41
41
|
},
|
|
42
42
|
"engines": {
|
|
43
43
|
"node": ">=18.0.0"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "53e2a825868b4c9b1662419b531c80be13afd779"
|
|
46
46
|
}
|