@lwrjs/shared-utils 0.15.0-alpha.9 → 0.15.1
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/cookie.cjs +21 -0
- package/build/cjs/env.cjs +32 -12
- package/build/cjs/graph.cjs +10 -2
- package/build/cjs/headers.cjs +15 -0
- package/build/cjs/html-meta.cjs +73 -36
- package/build/cjs/identity.cjs +2 -0
- package/build/cjs/index.cjs +2 -0
- package/build/es/cookie.d.ts +2 -0
- package/build/es/cookie.js +10 -0
- package/build/es/env.d.ts +1 -1
- package/build/es/env.js +54 -40
- package/build/es/graph.js +15 -2
- package/build/es/headers.d.ts +2 -0
- package/build/es/headers.js +4 -0
- package/build/es/html-meta.d.ts +1 -1
- package/build/es/html-meta.js +87 -36
- package/build/es/identity.d.ts +1 -0
- package/build/es/identity.js +1 -0
- package/build/es/index.d.ts +2 -0
- package/build/es/index.js +2 -0
- package/package.json +7 -7
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __markAsModule = (target) => __defProp(target, "__esModule", {value: true});
|
|
3
|
+
var __export = (target, all) => {
|
|
4
|
+
for (var name in all)
|
|
5
|
+
__defProp(target, name, {get: all[name], enumerable: true});
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
// packages/@lwrjs/shared-utils/src/cookie.ts
|
|
9
|
+
__markAsModule(exports);
|
|
10
|
+
__export(exports, {
|
|
11
|
+
cookieStringToObject: () => cookieStringToObject
|
|
12
|
+
});
|
|
13
|
+
function cookieStringToObject(cookieString) {
|
|
14
|
+
return cookieString.split(";").reduce((cookies, cookie) => {
|
|
15
|
+
const [name, value] = cookie.trim().split("=");
|
|
16
|
+
if (name && value) {
|
|
17
|
+
cookies[name] = decodeURIComponent(value);
|
|
18
|
+
}
|
|
19
|
+
return cookies;
|
|
20
|
+
}, {});
|
|
21
|
+
}
|
package/build/cjs/env.cjs
CHANGED
|
@@ -14,25 +14,39 @@ __export(exports, {
|
|
|
14
14
|
getFeatureFlags: () => getFeatureFlags,
|
|
15
15
|
isLambdaEnv: () => isLambdaEnv,
|
|
16
16
|
isLocalDev: () => isLocalDev,
|
|
17
|
-
|
|
17
|
+
parseRequestDepth: () => parseRequestDepth
|
|
18
18
|
});
|
|
19
19
|
if (getFeatureFlags().REEVALUATE_MODULES && !getFeatureFlags().LEGACY_LOADER) {
|
|
20
20
|
throw new Error("REEVALUATE_MODULES is only supported with LEGACY_LOADER");
|
|
21
21
|
}
|
|
22
22
|
function getFeatureFlags() {
|
|
23
23
|
return {
|
|
24
|
-
ASSETS_ON_LAMBDA:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
LWR_TRACING:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
ASSETS_ON_LAMBDA: parseBooleanFlag("ASSETS_ON_LAMBDA"),
|
|
25
|
+
BUNDLE_CACHE_SIZE: parseStringFlag("BUNDLE_CACHE_SIZE"),
|
|
26
|
+
ENABLE_NONCE: parseBooleanFlag("ENABLE_NONCE"),
|
|
27
|
+
EXPERIMENTAL_UNVERSIONED_ALIASES: parseBooleanFlag("EXPERIMENTAL_UNVERSIONED_ALIASES"),
|
|
28
|
+
LEGACY_LOADER: parseBooleanFlag("LEGACY_LOADER"),
|
|
29
|
+
LWR_TRACING: parseTracingFlag(),
|
|
30
|
+
MAX_VIEW_CACHE_TTL: parseStringFlag("MAX_VIEW_CACHE_TTL"),
|
|
31
|
+
REEVALUATE_MODULES: parseBooleanFlag("REEVALUATE_MODULES"),
|
|
32
|
+
SSR_COMPILER_ENABLED: parseBooleanFlag("SSR_COMPILER_ENABLED"),
|
|
33
|
+
SSR_LOADER_PER_REQUEST: parseBooleanFlag("SSR_LOADER_PER_REQUEST"),
|
|
34
|
+
SSR_WITH_CSR_FALLBACK: parseBooleanFlag("SSR_WITH_CSR_FALLBACK"),
|
|
35
|
+
VIEW_CACHE_SIZE: parseStringFlag("VIEW_CACHE_SIZE"),
|
|
36
|
+
EXPERIMENTAL_ASSET_HEADERS: parseStringFlag("EXPERIMENTAL_ASSET_HEADERS")
|
|
34
37
|
};
|
|
35
38
|
}
|
|
39
|
+
function parseBooleanFlag(flag) {
|
|
40
|
+
return process.env[flag]?.toLowerCase() === "true" || false;
|
|
41
|
+
}
|
|
42
|
+
function parseStringFlag(flag) {
|
|
43
|
+
const value = process.env[flag]?.trim();
|
|
44
|
+
return value || void 0;
|
|
45
|
+
}
|
|
46
|
+
function parseTracingFlag() {
|
|
47
|
+
const tracingValue = process.env.LWR_TRACING?.toLowerCase();
|
|
48
|
+
return tracingValue && tracingValue !== "off" ? process.env.LWR_TRACING : void 0;
|
|
49
|
+
}
|
|
36
50
|
function isLambdaEnv() {
|
|
37
51
|
return process.env.AWS_LAMBDA_FUNCTION_NAME !== void 0;
|
|
38
52
|
}
|
|
@@ -53,7 +67,7 @@ function buildEnvironmentContext(runtimeParams) {
|
|
|
53
67
|
}
|
|
54
68
|
var REQUEST_DEPTH_HEADER = "X-SFDC-Request-Depth";
|
|
55
69
|
var REQUEST_DEPTH_KEY = REQUEST_DEPTH_HEADER.toLowerCase();
|
|
56
|
-
function
|
|
70
|
+
function parseRequestDepth(headers = {}, query = {}) {
|
|
57
71
|
let maxDepth = 0;
|
|
58
72
|
const value = headers && headers[REQUEST_DEPTH_KEY];
|
|
59
73
|
if (value) {
|
|
@@ -73,5 +87,11 @@ function parseRequestDepthHeader(headers = {}) {
|
|
|
73
87
|
}
|
|
74
88
|
}
|
|
75
89
|
}
|
|
90
|
+
if (query[REQUEST_DEPTH_KEY]) {
|
|
91
|
+
const queryValue = parseInt(query[REQUEST_DEPTH_KEY], 10);
|
|
92
|
+
if (!isNaN(queryValue) && queryValue > maxDepth) {
|
|
93
|
+
maxDepth = queryValue;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
76
96
|
return maxDepth;
|
|
77
97
|
}
|
package/build/cjs/graph.cjs
CHANGED
|
@@ -118,9 +118,17 @@ async function getModuleGraphs(specifier, options, moduleRegistry, defRegistry,
|
|
|
118
118
|
}
|
|
119
119
|
const flattened = [];
|
|
120
120
|
await traverse(moduleDef, depth, flattened, 0, acc, defRegistry, runtimeEnvironment, runtimeParams);
|
|
121
|
+
let extraFlat = new Set();
|
|
122
|
+
if (options.includeUris || options.includeLinkedDefinitions) {
|
|
123
|
+
const allDeps = flattened.reduce((all, node) => {
|
|
124
|
+
all.push(node.specifier, ...node.static, ...node.dynamicRefs);
|
|
125
|
+
return all;
|
|
126
|
+
}, []).filter((dep) => acc.has(dep));
|
|
127
|
+
extraFlat = new Set(allDeps);
|
|
128
|
+
}
|
|
121
129
|
const uriMap = {};
|
|
122
130
|
if (options.includeUris) {
|
|
123
|
-
for (const visitedSpecifier of
|
|
131
|
+
for (const visitedSpecifier of extraFlat.keys()) {
|
|
124
132
|
const moduleId = await (0, import_identity.getVersionedModuleId)(visitedSpecifier, moduleRegistry, runtimeParams);
|
|
125
133
|
const uri = await defRegistry.resolveModuleUri(moduleId, runtimeEnvironment, runtimeParams);
|
|
126
134
|
uriMap[visitedSpecifier] = uri;
|
|
@@ -128,7 +136,7 @@ async function getModuleGraphs(specifier, options, moduleRegistry, defRegistry,
|
|
|
128
136
|
}
|
|
129
137
|
const linkedDefinitions = {};
|
|
130
138
|
if (options.includeLinkedDefinitions) {
|
|
131
|
-
for (const visitedSpecifier of
|
|
139
|
+
for (const visitedSpecifier of extraFlat.keys()) {
|
|
132
140
|
const versionedModuleId2 = await (0, import_identity.getVersionedModuleId)(visitedSpecifier, moduleRegistry, runtimeParams);
|
|
133
141
|
const module2 = isBundler(defRegistry) ? await defRegistry.getModuleBundle(versionedModuleId2, runtimeEnvironment, runtimeParams) : await defRegistry.getLinkedModule(versionedModuleId2, runtimeEnvironment, runtimeParams);
|
|
134
142
|
linkedDefinitions[visitedSpecifier] = module2;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __markAsModule = (target) => __defProp(target, "__esModule", {value: true});
|
|
3
|
+
var __export = (target, all) => {
|
|
4
|
+
for (var name in all)
|
|
5
|
+
__defProp(target, name, {get: all[name], enumerable: true});
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
// packages/@lwrjs/shared-utils/src/headers.ts
|
|
9
|
+
__markAsModule(exports);
|
|
10
|
+
__export(exports, {
|
|
11
|
+
normalizeHeaders: () => normalizeHeaders
|
|
12
|
+
});
|
|
13
|
+
function normalizeHeaders(headers = {}) {
|
|
14
|
+
return Object.fromEntries(Object.entries(headers).map(([key, value]) => [key.toLowerCase(), value]));
|
|
15
|
+
}
|
package/build/cjs/html-meta.cjs
CHANGED
|
@@ -34,9 +34,8 @@ __export(exports, {
|
|
|
34
34
|
isRelative: () => isRelative,
|
|
35
35
|
isSelfUrl: () => isSelfUrl
|
|
36
36
|
});
|
|
37
|
+
var parse5 = __toModule(require("parse5"));
|
|
37
38
|
var import_identity = __toModule(require("./identity.cjs"));
|
|
38
|
-
var import_parse5_sax_parser = __toModule(require("parse5-sax-parser"));
|
|
39
|
-
var import_stream = __toModule(require("stream"));
|
|
40
39
|
function parseAssetLocation(htmlSource, tagName, attrLocation) {
|
|
41
40
|
const {startOffset, endOffset} = attrLocation;
|
|
42
41
|
const srcAttr = htmlSource.substring(startOffset, endOffset);
|
|
@@ -53,6 +52,30 @@ function parseAssetLocation(htmlSource, tagName, attrLocation) {
|
|
|
53
52
|
}
|
|
54
53
|
};
|
|
55
54
|
}
|
|
55
|
+
function parseInlineStyleImages(htmlSource, tagName, attrLocation) {
|
|
56
|
+
const imageAssets = [], urlPattern = /url\((.*?)\)/g, {startOffset, endOffset} = attrLocation, srcAttr = htmlSource.substring(startOffset, endOffset);
|
|
57
|
+
let srcAttrStart = 0, match;
|
|
58
|
+
while ((match = urlPattern.exec(srcAttr)) !== null) {
|
|
59
|
+
const currentStr = srcAttr.substring(srcAttrStart);
|
|
60
|
+
imageAssets.push({
|
|
61
|
+
url: match[1].trim().replace(/^['"]|['"]$/g, ""),
|
|
62
|
+
startOffset: startOffset + currentStr.indexOf(match[1]) + srcAttrStart,
|
|
63
|
+
endOffset: startOffset + currentStr.indexOf(match[1]) + match[1].length + srcAttrStart
|
|
64
|
+
});
|
|
65
|
+
srcAttrStart = currentStr.indexOf(match[1]) + match[1].length + srcAttrStart;
|
|
66
|
+
}
|
|
67
|
+
return imageAssets.map((asset) => {
|
|
68
|
+
return {
|
|
69
|
+
url: asset.url,
|
|
70
|
+
tagName,
|
|
71
|
+
relative: isRelative(asset.url),
|
|
72
|
+
location: {
|
|
73
|
+
startOffset: asset.startOffset,
|
|
74
|
+
endOffset: asset.endOffset
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
}
|
|
56
79
|
function isRelative(url) {
|
|
57
80
|
return !url?.match(isNotRelativeRegex);
|
|
58
81
|
}
|
|
@@ -64,23 +87,33 @@ var isSelfUrlRegex = /^\s*(data:|#)/i;
|
|
|
64
87
|
function hasHydrationDirective(attrs = {}) {
|
|
65
88
|
return Object.keys(attrs).some((attr) => attr === HYDRATE_DIRECTIVE);
|
|
66
89
|
}
|
|
67
|
-
|
|
90
|
+
function traverseHtmlTree(node, visitor) {
|
|
91
|
+
for (const child of parse5.defaultTreeAdapter.getChildNodes(node)) {
|
|
92
|
+
if (parse5.defaultTreeAdapter.isElementNode(child)) {
|
|
93
|
+
visitor.enter?.(child);
|
|
94
|
+
traverseHtmlTree(child, visitor);
|
|
95
|
+
visitor.exit?.(child);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function extractMetadataFromHtml(htmlSource, viewMetadata, appConfig) {
|
|
68
100
|
const {customElements, assetReferences} = viewMetadata;
|
|
69
101
|
const {
|
|
70
102
|
bundleConfig: {external = {}}
|
|
71
103
|
} = appConfig;
|
|
72
104
|
const externals = Object.keys(external);
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
105
|
+
const root = parse5.parse(htmlSource, {
|
|
106
|
+
sourceCodeLocationInfo: true,
|
|
107
|
+
treeAdapter: parse5.defaultTreeAdapter
|
|
108
|
+
});
|
|
109
|
+
let nestedIslands = false;
|
|
110
|
+
let styleStartOffset;
|
|
111
|
+
const openElements = new Set();
|
|
112
|
+
const ceRefStack = [];
|
|
113
|
+
traverseHtmlTree(root, {
|
|
114
|
+
enter(node) {
|
|
115
|
+
const {nodeName: tagName, attrs, sourceCodeLocation} = node;
|
|
116
|
+
if (sourceCodeLocation && tagName.includes("-") && !openElements.has(tagName) && !externals.includes((0, import_identity.kebabCaseToModuleSpecifier)(tagName))) {
|
|
84
117
|
const {startOffset, endOffset} = sourceCodeLocation;
|
|
85
118
|
const props = attrs.length ? attrs.reduce((obj, {name, value}) => {
|
|
86
119
|
obj[(0, import_identity.getPropFromAttrName)(name)] = value === "" ? "true" : value;
|
|
@@ -100,21 +133,21 @@ async function extractMetadataFromHtml(htmlSource, viewMetadata, appConfig) {
|
|
|
100
133
|
}
|
|
101
134
|
ceRefStack.push(ceRef);
|
|
102
135
|
}
|
|
103
|
-
if ((tagName === "img" || tagName === "script") && sourceCodeLocation
|
|
104
|
-
|
|
105
|
-
assetReferences.push(parseAssetLocation(htmlSource, tagName, sourceCodeLocation.attrs.src));
|
|
106
|
-
}
|
|
136
|
+
if ((tagName === "img" || tagName === "script") && sourceCodeLocation?.attrs?.src) {
|
|
137
|
+
assetReferences.push(parseAssetLocation(htmlSource, tagName, sourceCodeLocation.attrs.src));
|
|
107
138
|
}
|
|
108
|
-
if (tagName === "link" && sourceCodeLocation
|
|
109
|
-
|
|
110
|
-
assetReferences.push(parseAssetLocation(htmlSource, tagName, sourceCodeLocation.attrs.href));
|
|
111
|
-
}
|
|
139
|
+
if (tagName === "link" && sourceCodeLocation?.attrs?.href) {
|
|
140
|
+
assetReferences.push(parseAssetLocation(htmlSource, tagName, sourceCodeLocation.attrs.href));
|
|
112
141
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
sourceCodeLocation
|
|
117
|
-
|
|
142
|
+
if (tagName === "style") {
|
|
143
|
+
styleStartOffset = sourceCodeLocation?.startOffset;
|
|
144
|
+
}
|
|
145
|
+
if (sourceCodeLocation?.attrs?.style) {
|
|
146
|
+
assetReferences.push(...parseInlineStyleImages(htmlSource, tagName, sourceCodeLocation.attrs.style));
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
exit(node) {
|
|
150
|
+
const {nodeName: tagName, sourceCodeLocation} = node;
|
|
118
151
|
if (openElements.has(tagName)) {
|
|
119
152
|
const ceRef = ceRefStack.pop();
|
|
120
153
|
openElements.delete(tagName);
|
|
@@ -123,16 +156,20 @@ async function extractMetadataFromHtml(htmlSource, viewMetadata, appConfig) {
|
|
|
123
156
|
}
|
|
124
157
|
ceRef.location.endOffset = sourceCodeLocation.endOffset;
|
|
125
158
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
inputStream.pipe(parser);
|
|
159
|
+
if (tagName === "style" && styleStartOffset && sourceCodeLocation?.endOffset) {
|
|
160
|
+
assetReferences.push(...parseInlineStyleImages(htmlSource, "style", {
|
|
161
|
+
startOffset: styleStartOffset,
|
|
162
|
+
endOffset: sourceCodeLocation.endOffset
|
|
163
|
+
}));
|
|
164
|
+
styleStartOffset = void 0;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
135
167
|
});
|
|
168
|
+
return {
|
|
169
|
+
...viewMetadata,
|
|
170
|
+
customElements: customElements.filter((ce) => !nestedIslands || hasHydrationDirective(ce.props)),
|
|
171
|
+
assetReferences
|
|
172
|
+
};
|
|
136
173
|
}
|
|
137
174
|
var HYDRATE_DIRECTIVE = "lwr:hydrate";
|
|
138
175
|
var HYDRATE_LOAD_VALUE = "load";
|
package/build/cjs/identity.cjs
CHANGED
|
@@ -33,6 +33,7 @@ __export(exports, {
|
|
|
33
33
|
IMMUTABLE_ASSET_PREFIX: () => IMMUTABLE_ASSET_PREFIX,
|
|
34
34
|
LATEST_SIGNATURE: () => LATEST_SIGNATURE,
|
|
35
35
|
LOCALE_SIGIL: () => LOCALE_SIGIL,
|
|
36
|
+
SSR_SIGIL: () => SSR_SIGIL,
|
|
36
37
|
VERSION_NOT_PROVIDED: () => VERSION_NOT_PROVIDED,
|
|
37
38
|
VERSION_PREFIX: () => VERSION_PREFIX,
|
|
38
39
|
VERSION_SIGIL: () => VERSION_SIGIL,
|
|
@@ -69,6 +70,7 @@ var DEFAULT_TITLE = "LWR App";
|
|
|
69
70
|
var IMMUTABLE_ASSET_PREFIX = "/_immutable/";
|
|
70
71
|
var ASSETS_CACHE_DIR = "assetsCache";
|
|
71
72
|
var VERSION_NOT_PROVIDED = "version-not-provided";
|
|
73
|
+
var SSR_SIGIL = "ssr";
|
|
72
74
|
var DEFAULT_LOCKER_TRUSTED_CMP = ["@locker/*", "lwr/*", "@lwrjs/*", "lwc", "@lwc/*"];
|
|
73
75
|
var DEFAULT_LWR_LOCKER_CONFIG = {
|
|
74
76
|
enabled: false,
|
package/build/cjs/index.cjs
CHANGED
|
@@ -36,3 +36,5 @@ __exportStar(exports, __toModule(require("./lwr-app-observer.cjs")));
|
|
|
36
36
|
__exportStar(exports, __toModule(require("./bundle.cjs")));
|
|
37
37
|
__exportStar(exports, __toModule(require("./localization.cjs")));
|
|
38
38
|
__exportStar(exports, __toModule(require("./launch.cjs")));
|
|
39
|
+
__exportStar(exports, __toModule(require("./cookie.cjs")));
|
|
40
|
+
__exportStar(exports, __toModule(require("./headers.cjs")));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function cookieStringToObject(cookieString) {
|
|
2
|
+
return cookieString.split(';').reduce((cookies, cookie) => {
|
|
3
|
+
const [name, value] = cookie.trim().split('=');
|
|
4
|
+
if (name && value) {
|
|
5
|
+
cookies[name] = decodeURIComponent(value);
|
|
6
|
+
}
|
|
7
|
+
return cookies;
|
|
8
|
+
}, {});
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=cookie.js.map
|
package/build/es/env.d.ts
CHANGED
|
@@ -18,5 +18,5 @@ export declare function isLocalDev(): boolean;
|
|
|
18
18
|
export declare function buildEnvironmentContext(runtimeParams: RuntimeParams): EnvironmentContext;
|
|
19
19
|
export declare const REQUEST_DEPTH_HEADER = "X-SFDC-Request-Depth";
|
|
20
20
|
export declare const REQUEST_DEPTH_KEY: string;
|
|
21
|
-
export declare function
|
|
21
|
+
export declare function parseRequestDepth(headers?: Headers, query?: Record<string, string>): number;
|
|
22
22
|
//# sourceMappingURL=env.d.ts.map
|
package/build/es/env.js
CHANGED
|
@@ -2,51 +2,59 @@ if (getFeatureFlags().REEVALUATE_MODULES && !getFeatureFlags().LEGACY_LOADER) {
|
|
|
2
2
|
throw new Error('REEVALUATE_MODULES is only supported with LEGACY_LOADER');
|
|
3
3
|
}
|
|
4
4
|
export function getFeatureFlags() {
|
|
5
|
-
// Add any new feature flags here to parse from environment variables
|
|
6
5
|
return {
|
|
7
6
|
// Should we load load the assets from the lambda on MRT
|
|
8
|
-
ASSETS_ON_LAMBDA:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
// DEFAULT LEGACY_LOADER = false;
|
|
13
|
-
LEGACY_LOADER: process.env.LEGACY_LOADER !== undefined && process.env.LEGACY_LOADER.toLowerCase() === 'true'
|
|
14
|
-
? true
|
|
15
|
-
: false,
|
|
16
|
-
// SSR should concatenate bundles, default = false
|
|
17
|
-
SSR_STATIC_BUNDLES: process.env.SSR_STATIC_BUNDLES !== undefined &&
|
|
18
|
-
process.env.SSR_STATIC_BUNDLES.toLowerCase() === 'true'
|
|
19
|
-
? true
|
|
20
|
-
: false,
|
|
21
|
-
// Islands fallback to CSR if SSR fails
|
|
22
|
-
SSR_WITH_CSR_FALLBACK: process.env.SSR_WITH_CSR_FALLBACK !== undefined &&
|
|
23
|
-
process.env.SSR_WITH_CSR_FALLBACK.toLowerCase() === 'true'
|
|
24
|
-
? true
|
|
25
|
-
: false,
|
|
7
|
+
ASSETS_ON_LAMBDA: parseBooleanFlag('ASSETS_ON_LAMBDA'),
|
|
8
|
+
// Number of BundleDefinition and BundleCode instances held in memory
|
|
9
|
+
BUNDLE_CACHE_SIZE: parseStringFlag('BUNDLE_CACHE_SIZE'),
|
|
10
|
+
ENABLE_NONCE: parseBooleanFlag('ENABLE_NONCE'),
|
|
26
11
|
// AMD Module Bundles include un-versioned aliases
|
|
27
|
-
EXPERIMENTAL_UNVERSIONED_ALIASES:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
LWR_TRACING:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
ENABLE_NONCE: process.env.ENABLE_NONCE !== undefined && process.env.ENABLE_NONCE.toLowerCase() === 'true'
|
|
35
|
-
? true
|
|
36
|
-
: false,
|
|
37
|
-
// Forces SSR rendering to render only one page at a time
|
|
38
|
-
SINGLE_RENDER_MODE: process.env.SINGLE_RENDER_MODE !== undefined &&
|
|
39
|
-
process.env.SINGLE_RENDER_MODE.toLowerCase() === 'true'
|
|
40
|
-
? true
|
|
41
|
-
: false,
|
|
12
|
+
EXPERIMENTAL_UNVERSIONED_ALIASES: parseBooleanFlag('EXPERIMENTAL_UNVERSIONED_ALIASES'),
|
|
13
|
+
// DEFAULT LEGACY_LOADER = false;
|
|
14
|
+
LEGACY_LOADER: parseBooleanFlag('LEGACY_LOADER'),
|
|
15
|
+
// Enable metrics log level 'off', 'default' or 'verbose'
|
|
16
|
+
LWR_TRACING: parseTracingFlag(),
|
|
17
|
+
// Max size of ViewDefinition time to live
|
|
18
|
+
MAX_VIEW_CACHE_TTL: parseStringFlag('MAX_VIEW_CACHE_TTL'),
|
|
42
19
|
// Forces SSR to re-evaluate modules for every page render. By default, modules are evaluated only once.
|
|
43
|
-
REEVALUATE_MODULES:
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
20
|
+
REEVALUATE_MODULES: parseBooleanFlag('REEVALUATE_MODULES'),
|
|
21
|
+
// Use the LWC SSR compiler and v2 SSR API
|
|
22
|
+
SSR_COMPILER_ENABLED: parseBooleanFlag('SSR_COMPILER_ENABLED'),
|
|
23
|
+
// Create a new SSR Loader on every request
|
|
24
|
+
SSR_LOADER_PER_REQUEST: parseBooleanFlag('SSR_LOADER_PER_REQUEST'),
|
|
25
|
+
// Islands fallback to CSR if SSR fails
|
|
26
|
+
SSR_WITH_CSR_FALLBACK: parseBooleanFlag('SSR_WITH_CSR_FALLBACK'),
|
|
27
|
+
// Max number of ViewDefinitions help in memory
|
|
28
|
+
VIEW_CACHE_SIZE: parseStringFlag('VIEW_CACHE_SIZE'),
|
|
29
|
+
// Allows setting/overriding headers for non-immutable assets.
|
|
30
|
+
// Expected format is `<header_key_1>: <header_value_1>, header_value_2>; <header_key_2>: <header_value_2>`
|
|
31
|
+
// E.g., assetHeadersString Cloudflare-CDN-Cache-Control: max-age=2813308004; Cache-Tag: ABC123;
|
|
32
|
+
EXPERIMENTAL_ASSET_HEADERS: parseStringFlag('EXPERIMENTAL_ASSET_HEADERS'),
|
|
48
33
|
};
|
|
49
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Helper function to parse boolean environment variables.
|
|
37
|
+
* Returns true if the variable is set to 'true', false otherwise.
|
|
38
|
+
*/
|
|
39
|
+
function parseBooleanFlag(flag) {
|
|
40
|
+
return process.env[flag]?.toLowerCase() === 'true' || false;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Helper function to parse string environment variables.
|
|
44
|
+
* Returns the trimmed string if the variable is defined, otherwise returns undefined.
|
|
45
|
+
*/
|
|
46
|
+
function parseStringFlag(flag) {
|
|
47
|
+
const value = process.env[flag]?.trim();
|
|
48
|
+
return value || undefined;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Helper function to parse the LWR_TRACING flag.
|
|
52
|
+
* Returns the value if it's not 'off' and is defined, otherwise returns false.
|
|
53
|
+
*/
|
|
54
|
+
function parseTracingFlag() {
|
|
55
|
+
const tracingValue = process.env.LWR_TRACING?.toLowerCase();
|
|
56
|
+
return tracingValue && tracingValue !== 'off' ? process.env.LWR_TRACING : undefined;
|
|
57
|
+
}
|
|
50
58
|
/**
|
|
51
59
|
* This function is used to determine if the current environment is a lambda.
|
|
52
60
|
*
|
|
@@ -85,7 +93,7 @@ export function buildEnvironmentContext(runtimeParams) {
|
|
|
85
93
|
}
|
|
86
94
|
export const REQUEST_DEPTH_HEADER = 'X-SFDC-Request-Depth';
|
|
87
95
|
export const REQUEST_DEPTH_KEY = REQUEST_DEPTH_HEADER.toLowerCase();
|
|
88
|
-
export function
|
|
96
|
+
export function parseRequestDepth(headers = {}, query = {}) {
|
|
89
97
|
let maxDepth = 0;
|
|
90
98
|
const value = headers && headers[REQUEST_DEPTH_KEY];
|
|
91
99
|
if (value) {
|
|
@@ -106,6 +114,12 @@ export function parseRequestDepthHeader(headers = {}) {
|
|
|
106
114
|
}
|
|
107
115
|
}
|
|
108
116
|
}
|
|
117
|
+
if (query[REQUEST_DEPTH_KEY]) {
|
|
118
|
+
const queryValue = parseInt(query[REQUEST_DEPTH_KEY], 10);
|
|
119
|
+
if (!isNaN(queryValue) && queryValue > maxDepth) {
|
|
120
|
+
maxDepth = queryValue;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
109
123
|
return maxDepth;
|
|
110
124
|
}
|
|
111
125
|
//# sourceMappingURL=env.js.map
|
package/build/es/graph.js
CHANGED
|
@@ -123,9 +123,22 @@ options, moduleRegistry, defRegistry, runtimeEnvironment, runtimeParams, visited
|
|
|
123
123
|
}
|
|
124
124
|
const flattened = [];
|
|
125
125
|
await traverse(moduleDef, depth, flattened, 0, acc, defRegistry, runtimeEnvironment, runtimeParams);
|
|
126
|
+
let extraFlat = new Set();
|
|
127
|
+
if (options.includeUris || options.includeLinkedDefinitions) {
|
|
128
|
+
// Get a set of the root specifier and all dependencies
|
|
129
|
+
// DO NOT use the visited map for including URIs and linked defs because it includes
|
|
130
|
+
// entries from previous runs of getModuleGraphs() which belong to OTHER root specifiers
|
|
131
|
+
const allDeps = flattened
|
|
132
|
+
.reduce((all, node) => {
|
|
133
|
+
all.push(node.specifier, ...node.static, ...node.dynamicRefs);
|
|
134
|
+
return all;
|
|
135
|
+
}, [])
|
|
136
|
+
.filter((dep) => acc.has(dep));
|
|
137
|
+
extraFlat = new Set(allDeps);
|
|
138
|
+
}
|
|
126
139
|
const uriMap = {};
|
|
127
140
|
if (options.includeUris) {
|
|
128
|
-
for (const visitedSpecifier of
|
|
141
|
+
for (const visitedSpecifier of extraFlat.keys()) {
|
|
129
142
|
// eslint-disable-next-line no-await-in-loop
|
|
130
143
|
const moduleId = await getVersionedModuleId(visitedSpecifier, moduleRegistry, runtimeParams);
|
|
131
144
|
// eslint-disable-next-line no-await-in-loop
|
|
@@ -135,7 +148,7 @@ options, moduleRegistry, defRegistry, runtimeEnvironment, runtimeParams, visited
|
|
|
135
148
|
}
|
|
136
149
|
const linkedDefinitions = {};
|
|
137
150
|
if (options.includeLinkedDefinitions) {
|
|
138
|
-
for (const visitedSpecifier of
|
|
151
|
+
for (const visitedSpecifier of extraFlat.keys()) {
|
|
139
152
|
// eslint-disable-next-line no-await-in-loop
|
|
140
153
|
const versionedModuleId = await getVersionedModuleId(visitedSpecifier, moduleRegistry, runtimeParams);
|
|
141
154
|
const module = isBundler(defRegistry)
|
package/build/es/html-meta.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export declare function isSelfUrl(url: string): boolean;
|
|
|
5
5
|
* Pull the custom elements and img tags out of an HTML string, to use as metadata
|
|
6
6
|
* @param htmlSource - An HTML string to parse
|
|
7
7
|
*/
|
|
8
|
-
export declare function extractMetadataFromHtml(htmlSource: string, viewMetadata: RenderedViewMetadata, appConfig: NormalizedLwrGlobalConfig):
|
|
8
|
+
export declare function extractMetadataFromHtml(htmlSource: string, viewMetadata: RenderedViewMetadata, appConfig: NormalizedLwrGlobalConfig): RenderedViewMetadata;
|
|
9
9
|
export declare const HYDRATE_DIRECTIVE = "lwr:hydrate";
|
|
10
10
|
export declare const HYDRATE_LOAD_VALUE = "load";
|
|
11
11
|
export declare const HYDRATE_CLIENT_VALUE = "client-only";
|
package/build/es/html-meta.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
+
import * as parse5 from 'parse5';
|
|
1
2
|
import { getPropFromAttrName, kebabCaseToModuleSpecifier } from './identity.js';
|
|
2
|
-
import SAXParser from 'parse5-sax-parser';
|
|
3
|
-
import { Readable } from 'stream';
|
|
4
3
|
function parseAssetLocation(htmlSource, tagName, attrLocation) {
|
|
5
4
|
const { startOffset, endOffset } = attrLocation;
|
|
6
5
|
const srcAttr = htmlSource.substring(startOffset, endOffset);
|
|
@@ -19,6 +18,41 @@ function parseAssetLocation(htmlSource, tagName, attrLocation) {
|
|
|
19
18
|
},
|
|
20
19
|
};
|
|
21
20
|
}
|
|
21
|
+
function parseInlineStyleImages(htmlSource, tagName, attrLocation) {
|
|
22
|
+
const imageAssets = [],
|
|
23
|
+
// Define a regex pattern to match the 'url()' part of inline styles
|
|
24
|
+
urlPattern = /url\((.*?)\)/g, { startOffset, endOffset } = attrLocation,
|
|
25
|
+
// Extract the substring that contains the attribute (e.g., a 'style' attribute with inline CSS or <style></style> content)
|
|
26
|
+
srcAttr = htmlSource.substring(startOffset, endOffset);
|
|
27
|
+
// Initialize a variable to track the current parsing position
|
|
28
|
+
let srcAttrStart = 0, match;
|
|
29
|
+
// Loop through all matches of 'url(...)' in the inline style attribute
|
|
30
|
+
while ((match = urlPattern.exec(srcAttr)) !== null) {
|
|
31
|
+
// Extract the substring starting from the current position in srcAttr
|
|
32
|
+
const currentStr = srcAttr.substring(srcAttrStart);
|
|
33
|
+
imageAssets.push({
|
|
34
|
+
// Clean up the URL by trimming quotes and spaces
|
|
35
|
+
url: match[1].trim().replace(/^['"]|['"]$/g, ''),
|
|
36
|
+
// Calculate the starting offset of the matched URL relative to the entire HTML source
|
|
37
|
+
startOffset: startOffset + currentStr.indexOf(match[1]) + srcAttrStart,
|
|
38
|
+
// Calculate the ending offset of the matched URL
|
|
39
|
+
endOffset: startOffset + currentStr.indexOf(match[1]) + match[1].length + srcAttrStart,
|
|
40
|
+
});
|
|
41
|
+
// Move the srcAttrStart to the end of the currently matched URL to avoid picking up the already matched url
|
|
42
|
+
srcAttrStart = currentStr.indexOf(match[1]) + match[1].length + srcAttrStart;
|
|
43
|
+
}
|
|
44
|
+
return imageAssets.map((asset) => {
|
|
45
|
+
return {
|
|
46
|
+
url: asset.url,
|
|
47
|
+
tagName,
|
|
48
|
+
relative: isRelative(asset.url),
|
|
49
|
+
location: {
|
|
50
|
+
startOffset: asset.startOffset,
|
|
51
|
+
endOffset: asset.endOffset,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
}
|
|
22
56
|
// Detect if this is a relative URL
|
|
23
57
|
export function isRelative(url) {
|
|
24
58
|
return !url?.match(isNotRelativeRegex);
|
|
@@ -32,23 +66,38 @@ const isSelfUrlRegex = /^\s*(data:|#)/i;
|
|
|
32
66
|
function hasHydrationDirective(attrs = {}) {
|
|
33
67
|
return Object.keys(attrs).some((attr) => attr === HYDRATE_DIRECTIVE);
|
|
34
68
|
}
|
|
69
|
+
function traverseHtmlTree(node, visitor) {
|
|
70
|
+
for (const child of parse5.defaultTreeAdapter.getChildNodes(node)) {
|
|
71
|
+
if (parse5.defaultTreeAdapter.isElementNode(child)) {
|
|
72
|
+
visitor.enter?.(child);
|
|
73
|
+
traverseHtmlTree(child, visitor);
|
|
74
|
+
visitor.exit?.(child);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
35
78
|
/**
|
|
36
79
|
* Pull the custom elements and img tags out of an HTML string, to use as metadata
|
|
37
80
|
* @param htmlSource - An HTML string to parse
|
|
38
81
|
*/
|
|
39
|
-
export
|
|
82
|
+
export function extractMetadataFromHtml(htmlSource, viewMetadata, appConfig) {
|
|
40
83
|
const { customElements, assetReferences } = viewMetadata;
|
|
41
84
|
const { bundleConfig: { external = {} }, } = appConfig;
|
|
42
85
|
const externals = Object.keys(external);
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
86
|
+
const root = parse5.parse(htmlSource, {
|
|
87
|
+
sourceCodeLocationInfo: true,
|
|
88
|
+
treeAdapter: parse5.defaultTreeAdapter,
|
|
89
|
+
});
|
|
90
|
+
let nestedIslands = false;
|
|
91
|
+
let styleStartOffset;
|
|
92
|
+
const openElements = new Set();
|
|
93
|
+
const ceRefStack = [];
|
|
94
|
+
traverseHtmlTree(root, {
|
|
95
|
+
enter(node) {
|
|
96
|
+
// Source code location is only available if the parser is configured with preserve
|
|
97
|
+
// source location info.
|
|
98
|
+
const { nodeName: tagName, attrs, sourceCodeLocation } = node;
|
|
99
|
+
if (sourceCodeLocation &&
|
|
100
|
+
tagName.includes('-') &&
|
|
52
101
|
!openElements.has(tagName) &&
|
|
53
102
|
!externals.includes(kebabCaseToModuleSpecifier(tagName))) {
|
|
54
103
|
const { startOffset, endOffset } = sourceCodeLocation;
|
|
@@ -81,22 +130,22 @@ export async function extractMetadataFromHtml(htmlSource, viewMetadata, appConfi
|
|
|
81
130
|
}
|
|
82
131
|
// <img src="asset-url"/>
|
|
83
132
|
// <script type="text/javascript" src="asset-url"></script>
|
|
84
|
-
if ((tagName === 'img' || tagName === 'script') && sourceCodeLocation
|
|
85
|
-
|
|
86
|
-
assetReferences.push(parseAssetLocation(htmlSource, tagName, sourceCodeLocation.attrs.src));
|
|
87
|
-
}
|
|
88
|
-
// if (sourceCodeLocation.attrs.srcset) {
|
|
89
|
-
// TODO: WIP
|
|
90
|
-
// }
|
|
133
|
+
if ((tagName === 'img' || tagName === 'script') && sourceCodeLocation?.attrs?.src) {
|
|
134
|
+
assetReferences.push(parseAssetLocation(htmlSource, tagName, sourceCodeLocation.attrs.src));
|
|
91
135
|
}
|
|
92
136
|
// <link rel="stylesheet" href="asset-url">
|
|
93
|
-
if (tagName === 'link' && sourceCodeLocation
|
|
94
|
-
|
|
95
|
-
assetReferences.push(parseAssetLocation(htmlSource, tagName, sourceCodeLocation.attrs.href));
|
|
96
|
-
}
|
|
137
|
+
if (tagName === 'link' && sourceCodeLocation?.attrs?.href) {
|
|
138
|
+
assetReferences.push(parseAssetLocation(htmlSource, tagName, sourceCodeLocation.attrs.href));
|
|
97
139
|
}
|
|
98
|
-
|
|
99
|
-
|
|
140
|
+
if (tagName === 'style') {
|
|
141
|
+
styleStartOffset = sourceCodeLocation?.startOffset;
|
|
142
|
+
}
|
|
143
|
+
if (sourceCodeLocation?.attrs?.style) {
|
|
144
|
+
assetReferences.push(...parseInlineStyleImages(htmlSource, tagName, sourceCodeLocation.attrs.style));
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
exit(node) {
|
|
148
|
+
const { nodeName: tagName, sourceCodeLocation } = node;
|
|
100
149
|
if (openElements.has(tagName)) {
|
|
101
150
|
const ceRef = ceRefStack.pop();
|
|
102
151
|
openElements.delete(tagName);
|
|
@@ -106,18 +155,20 @@ export async function extractMetadataFromHtml(htmlSource, viewMetadata, appConfi
|
|
|
106
155
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
107
156
|
ceRef.location.endOffset = sourceCodeLocation.endOffset;
|
|
108
157
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}));
|
|
118
|
-
inputStream.on('error', (error) => reject(error));
|
|
119
|
-
inputStream.pipe(parser);
|
|
158
|
+
if (tagName === 'style' && styleStartOffset && sourceCodeLocation?.endOffset) {
|
|
159
|
+
assetReferences.push(...parseInlineStyleImages(htmlSource, 'style', {
|
|
160
|
+
startOffset: styleStartOffset,
|
|
161
|
+
endOffset: sourceCodeLocation.endOffset,
|
|
162
|
+
}));
|
|
163
|
+
styleStartOffset = undefined;
|
|
164
|
+
}
|
|
165
|
+
},
|
|
120
166
|
});
|
|
167
|
+
return {
|
|
168
|
+
...viewMetadata,
|
|
169
|
+
customElements: customElements.filter((ce) => !nestedIslands || hasHydrationDirective(ce.props)),
|
|
170
|
+
assetReferences,
|
|
171
|
+
};
|
|
121
172
|
}
|
|
122
173
|
export const HYDRATE_DIRECTIVE = 'lwr:hydrate';
|
|
123
174
|
export const HYDRATE_LOAD_VALUE = 'load';
|
package/build/es/identity.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export declare const DEFAULT_TITLE = "LWR App";
|
|
|
10
10
|
export declare const IMMUTABLE_ASSET_PREFIX = "/_immutable/";
|
|
11
11
|
export declare const ASSETS_CACHE_DIR = "assetsCache";
|
|
12
12
|
export declare const VERSION_NOT_PROVIDED = "version-not-provided";
|
|
13
|
+
export declare const SSR_SIGIL = "ssr";
|
|
13
14
|
export declare const DEFAULT_LOCKER_TRUSTED_CMP: string[];
|
|
14
15
|
export declare const DEFAULT_LWR_LOCKER_CONFIG: {
|
|
15
16
|
enabled: boolean;
|
package/build/es/identity.js
CHANGED
|
@@ -10,6 +10,7 @@ export const DEFAULT_TITLE = 'LWR App';
|
|
|
10
10
|
export const IMMUTABLE_ASSET_PREFIX = '/_immutable/';
|
|
11
11
|
export const ASSETS_CACHE_DIR = 'assetsCache';
|
|
12
12
|
export const VERSION_NOT_PROVIDED = 'version-not-provided';
|
|
13
|
+
export const SSR_SIGIL = 'ssr';
|
|
13
14
|
// Locker trusted components
|
|
14
15
|
export const DEFAULT_LOCKER_TRUSTED_CMP = ['@locker/*', 'lwr/*', '@lwrjs/*', 'lwc', '@lwc/*'];
|
|
15
16
|
export const DEFAULT_LWR_LOCKER_CONFIG = {
|
package/build/es/index.d.ts
CHANGED
package/build/es/index.js
CHANGED
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.15.
|
|
7
|
+
"version": "0.15.1",
|
|
8
8
|
"homepage": "https://developer.salesforce.com/docs/platform/lwr/overview",
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
@@ -37,26 +37,26 @@
|
|
|
37
37
|
"build/**/*.d.ts"
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@lwrjs/diagnostics": "0.15.
|
|
40
|
+
"@lwrjs/diagnostics": "0.15.1",
|
|
41
41
|
"es-module-lexer": "^1.5.4",
|
|
42
42
|
"fast-json-stable-stringify": "^2.1.0",
|
|
43
43
|
"magic-string": "^0.30.9",
|
|
44
44
|
"mime-types": "^2.1.33",
|
|
45
45
|
"ms": "^2.1.3",
|
|
46
|
-
"parse5
|
|
46
|
+
"parse5": "^7.2.1",
|
|
47
47
|
"path-to-regexp": "^6.2.2",
|
|
48
48
|
"resolve": "^1.22.8",
|
|
49
|
-
"rollup": "^2.
|
|
49
|
+
"rollup": "^2.79.2",
|
|
50
50
|
"slugify": "^1.4.5"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@lwrjs/types": "0.15.
|
|
53
|
+
"@lwrjs/types": "0.15.1",
|
|
54
54
|
"@types/mime-types": "2.1.4",
|
|
55
55
|
"@types/path-to-regexp": "^1.7.0",
|
|
56
|
-
"memfs": "^4.
|
|
56
|
+
"memfs": "^4.13.0"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
|
59
59
|
"node": ">=18.0.0"
|
|
60
60
|
},
|
|
61
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "9ae4002fdab4f55caea2f8de8a7139a6b64ebad1"
|
|
62
62
|
}
|