@lwrjs/core 0.15.4-alpha.0 → 0.15.5

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.
@@ -24,7 +24,8 @@ var __toModule = (module2) => {
24
24
  // packages/@lwrjs/core/src/middleware/asset-middleware.ts
25
25
  __markAsModule(exports);
26
26
  __export(exports, {
27
- assetMiddleware: () => assetMiddleware
27
+ assetMiddleware: () => assetMiddleware,
28
+ parseHeaderStringToObject: () => parseHeaderStringToObject
28
29
  });
29
30
  var import_shared_utils = __toModule(require("@lwrjs/shared-utils"));
30
31
  var import_path = __toModule(require("path"));
@@ -119,7 +120,25 @@ function sendRedirect(res, assetUri) {
119
120
  res.sendStatus(302);
120
121
  }
121
122
  function parseHeaderStringToObject(assetHeadersString) {
122
- if (typeof assetHeadersString === "string") {
123
- return Object.fromEntries(assetHeadersString.split(";").filter(Boolean).map((e) => e.split(":").map((s) => s.trim())).filter((pair) => pair.length === 2 && pair[0]));
123
+ if (typeof assetHeadersString !== "string") {
124
+ return void 0;
124
125
  }
126
+ const headersObject = {};
127
+ const errors = [];
128
+ const pairs = assetHeadersString.split(";").filter(Boolean);
129
+ pairs.forEach((pair, index) => {
130
+ const [key, value] = pair.split(":").map((s) => s.trim());
131
+ if (!key || !value) {
132
+ errors.push(`Error at Header ${index + 1}: Malformed Header "${pair.trim()}"`);
133
+ } else {
134
+ headersObject[key] = value;
135
+ }
136
+ });
137
+ if (errors.length > 0) {
138
+ import_diagnostics.logger.error({
139
+ label: "asset-middleware",
140
+ message: "Parse Errors:" + errors.join("\n")
141
+ });
142
+ }
143
+ return headersObject;
125
144
  }
@@ -69,7 +69,7 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
69
69
  params: viewRequest.params,
70
70
  query: viewRequest.query,
71
71
  cookie: req.headers?.cookie,
72
- trueClientIP: req.headers && req.headers["True-Client-IP"],
72
+ trueClientIP: req.headers && req.headers["true-client-ip"],
73
73
  coreProxy: req.getCoreProxy(appConfig.coreProxy ?? void 0, route.bootstrap?.proxyForSSR)
74
74
  };
75
75
  const resolve = req.isJsonRequest() ? viewHandler.getViewJson : viewHandler.getViewContent;
@@ -142,15 +142,17 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
142
142
  } else if (viewDefinitionStatus && viewDefinitionStatus.code) {
143
143
  const origStatus = status;
144
144
  const {code, location} = viewDefinitionStatus;
145
- const isRedirect = code === 301 || code == 302;
145
+ const isRedirect = code === 301 || code === 302;
146
146
  status = code;
147
- if (isRedirect && location && (0, import_shared_utils.isURL)(location) || location?.startsWith("/")) {
148
- res.set({
149
- location: addRedirectQueryParam(location, (0, import_shared_utils.parseRequestDepth)(req.headers, req.query))
150
- });
151
- } else {
152
- status = origStatus;
153
- import_diagnostics.logger.warn(`[view-middleware] Ignoring invalid location header: "${location}"`);
147
+ if (isRedirect) {
148
+ if (location && (0, import_shared_utils.isURL)(location) || location?.startsWith("/")) {
149
+ res.set({
150
+ location: addRedirectQueryParam(location, (0, import_shared_utils.parseRequestDepth)(req.headers, req.query))
151
+ });
152
+ } else {
153
+ status = origStatus;
154
+ import_diagnostics.logger.warn(`[view-middleware] Ignoring invalid location header: "${location}"`);
155
+ }
154
156
  }
155
157
  }
156
158
  res.status(status);
@@ -1,3 +1,33 @@
1
1
  import type { InternalAppServer, ServerContext, ServerTypes } from '@lwrjs/types';
2
2
  export declare function assetMiddleware<T extends ServerTypes>(app: InternalAppServer<T>, context: ServerContext): void;
3
+ /**
4
+ * Parses a semicolon-separated string of key-value pairs into an object.
5
+ *
6
+ * The input string must contain key-value pairs in the format `key:value;key2:value2`.
7
+ * This function validates the format of each pair and logs errors for malformed entries.
8
+ * If no errors are encountered, the function returns an object representing the parsed pairs.
9
+ * Otherwise, errors are logged, and only valid pairs are included in the result.
10
+ *
11
+ * @param {string | undefined} assetHeadersString - The semicolon-separated string to parse. Can be undefined.
12
+ * @returns {Record<string, string> | undefined} - A key-value pair object if valid pairs are found,
13
+ * or `undefined` if the input is invalid or empty.
14
+ *
15
+ * ### Example Usage:
16
+ * ```typescript
17
+ * const input = "key1:value1;key2:value2";
18
+ * const result = parseHeaderStringToObject(input);
19
+ * console.log(result);
20
+ * // Output: { key1: "value1", key2: "value2" }
21
+ * ```
22
+ *
23
+ * ### Error Logging Example:
24
+ * For an input like `key1:value1;invalidpair;key3:`, the function logs:
25
+ * ```
26
+ * {
27
+ * label: 'asset-middleware',
28
+ * message: 'Parse Errors: Error at Header 2: Malformed Header "invalidpair"\nError at Header 3: Malformed Header "key3:"'
29
+ * }
30
+ * ```
31
+ */
32
+ export declare function parseHeaderStringToObject(assetHeadersString: string | undefined): Record<string, string> | undefined;
3
33
  //# sourceMappingURL=asset-middleware.d.ts.map
@@ -1,6 +1,6 @@
1
1
  import { getFeatureFlags } from '@lwrjs/shared-utils';
2
2
  import path from 'path';
3
- import { DiagnosticsError } from '@lwrjs/diagnostics';
3
+ import { DiagnosticsError, logger } from '@lwrjs/diagnostics';
4
4
  import { RequestHandlerSpan, getTracer } from '@lwrjs/instrumentation';
5
5
  import { getAssetIdentity } from './utils/identity.js';
6
6
  import { handleErrors } from './utils/error-handling.js';
@@ -112,14 +112,58 @@ function sendRedirect(res, assetUri) {
112
112
  });
113
113
  res.sendStatus(302);
114
114
  }
115
- function parseHeaderStringToObject(assetHeadersString) {
116
- if (typeof assetHeadersString === 'string') {
117
- // convert to cache sring header:value to object
118
- return Object.fromEntries(assetHeadersString
119
- .split(';')
120
- .filter(Boolean)
121
- .map((e) => e.split(':').map((s) => s.trim()))
122
- .filter((pair) => pair.length === 2 && pair[0]));
115
+ /**
116
+ * Parses a semicolon-separated string of key-value pairs into an object.
117
+ *
118
+ * The input string must contain key-value pairs in the format `key:value;key2:value2`.
119
+ * This function validates the format of each pair and logs errors for malformed entries.
120
+ * If no errors are encountered, the function returns an object representing the parsed pairs.
121
+ * Otherwise, errors are logged, and only valid pairs are included in the result.
122
+ *
123
+ * @param {string | undefined} assetHeadersString - The semicolon-separated string to parse. Can be undefined.
124
+ * @returns {Record<string, string> | undefined} - A key-value pair object if valid pairs are found,
125
+ * or `undefined` if the input is invalid or empty.
126
+ *
127
+ * ### Example Usage:
128
+ * ```typescript
129
+ * const input = "key1:value1;key2:value2";
130
+ * const result = parseHeaderStringToObject(input);
131
+ * console.log(result);
132
+ * // Output: { key1: "value1", key2: "value2" }
133
+ * ```
134
+ *
135
+ * ### Error Logging Example:
136
+ * For an input like `key1:value1;invalidpair;key3:`, the function logs:
137
+ * ```
138
+ * {
139
+ * label: 'asset-middleware',
140
+ * message: 'Parse Errors: Error at Header 2: Malformed Header "invalidpair"\nError at Header 3: Malformed Header "key3:"'
141
+ * }
142
+ * ```
143
+ */
144
+ export function parseHeaderStringToObject(assetHeadersString) {
145
+ if (typeof assetHeadersString !== 'string') {
146
+ return undefined;
147
+ }
148
+ const headersObject = {};
149
+ const errors = [];
150
+ // Split the string into key-value pairs by semicolon
151
+ const pairs = assetHeadersString.split(';').filter(Boolean); // Remove empty segments
152
+ pairs.forEach((pair, index) => {
153
+ const [key, value] = pair.split(':').map((s) => s.trim()); // Split by colon and trim spaces
154
+ if (!key || !value) {
155
+ errors.push(`Error at Header ${index + 1}: Malformed Header "${pair.trim()}"`);
156
+ }
157
+ else {
158
+ headersObject[key] = value;
159
+ }
160
+ });
161
+ if (errors.length > 0) {
162
+ logger.error({
163
+ label: 'asset-middleware',
164
+ message: 'Parse Errors:' + errors.join('\n'),
165
+ });
123
166
  }
167
+ return headersObject;
124
168
  }
125
169
  //# sourceMappingURL=asset-middleware.js.map
@@ -43,7 +43,7 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
43
43
  params: viewRequest.params,
44
44
  query: viewRequest.query,
45
45
  cookie: req.headers?.cookie,
46
- trueClientIP: req.headers && req.headers['True-Client-IP'],
46
+ trueClientIP: req.headers && req.headers['true-client-ip'],
47
47
  coreProxy: req.getCoreProxy(appConfig.coreProxy ?? undefined, route.bootstrap?.proxyForSSR),
48
48
  };
49
49
  const resolve = req.isJsonRequest() ? viewHandler.getViewJson : viewHandler.getViewContent;
@@ -127,17 +127,19 @@ function createViewMiddleware(route, errorRoutes, context, viewHandler) {
127
127
  else if (viewDefinitionStatus && viewDefinitionStatus.code) {
128
128
  const origStatus = status;
129
129
  const { code, location } = viewDefinitionStatus;
130
- const isRedirect = code === 301 || code == 302;
130
+ const isRedirect = code === 301 || code === 302;
131
131
  status = code;
132
- if ((isRedirect && location && isURL(location)) || location?.startsWith('/')) {
133
- res.set({
134
- location: addRedirectQueryParam(location, parseRequestDepth(req.headers, req.query)),
135
- });
136
- }
137
- else {
138
- // reset the status in the event of an ivalid location when redirecting
139
- status = origStatus;
140
- logger.warn(`[view-middleware] Ignoring invalid location header: "${location}"`);
132
+ if (isRedirect) {
133
+ if ((location && isURL(location)) || location?.startsWith('/')) {
134
+ res.set({
135
+ location: addRedirectQueryParam(location, parseRequestDepth(req.headers, req.query)),
136
+ });
137
+ }
138
+ else {
139
+ // reset the status in the event of an invalid location when redirecting
140
+ status = origStatus;
141
+ logger.warn(`[view-middleware] Ignoring invalid location header: "${location}"`);
142
+ }
141
143
  }
142
144
  }
143
145
  res.status(status);
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "version": "0.15.4-alpha.0",
7
+ "version": "0.15.5",
8
8
  "homepage": "https://developer.salesforce.com/docs/platform/lwr/overview",
9
9
  "repository": {
10
10
  "type": "git",
@@ -43,34 +43,34 @@
43
43
  "build": "tsc -b"
44
44
  },
45
45
  "dependencies": {
46
- "@lwrjs/app-service": "0.15.4-alpha.0",
47
- "@lwrjs/asset-registry": "0.15.4-alpha.0",
48
- "@lwrjs/asset-transformer": "0.15.4-alpha.0",
49
- "@lwrjs/base-view-provider": "0.15.4-alpha.0",
50
- "@lwrjs/base-view-transformer": "0.15.4-alpha.0",
51
- "@lwrjs/client-modules": "0.15.4-alpha.0",
52
- "@lwrjs/config": "0.15.4-alpha.0",
53
- "@lwrjs/diagnostics": "0.15.4-alpha.0",
54
- "@lwrjs/esbuild": "0.15.4-alpha.0",
55
- "@lwrjs/fs-asset-provider": "0.15.4-alpha.0",
56
- "@lwrjs/fs-watch": "0.15.4-alpha.0",
57
- "@lwrjs/html-view-provider": "0.15.4-alpha.0",
58
- "@lwrjs/instrumentation": "0.15.4-alpha.0",
59
- "@lwrjs/loader": "0.15.4-alpha.0",
60
- "@lwrjs/lwc-module-provider": "0.15.4-alpha.0",
61
- "@lwrjs/lwc-ssr": "0.15.4-alpha.0",
62
- "@lwrjs/markdown-view-provider": "0.15.4-alpha.0",
63
- "@lwrjs/module-bundler": "0.15.4-alpha.0",
64
- "@lwrjs/module-registry": "0.15.4-alpha.0",
65
- "@lwrjs/npm-module-provider": "0.15.4-alpha.0",
66
- "@lwrjs/nunjucks-view-provider": "0.15.4-alpha.0",
67
- "@lwrjs/o11y": "0.15.4-alpha.0",
68
- "@lwrjs/resource-registry": "0.15.4-alpha.0",
69
- "@lwrjs/router": "0.15.4-alpha.0",
70
- "@lwrjs/server": "0.15.4-alpha.0",
71
- "@lwrjs/shared-utils": "0.15.4-alpha.0",
72
- "@lwrjs/static": "0.15.4-alpha.0",
73
- "@lwrjs/view-registry": "0.15.4-alpha.0",
46
+ "@lwrjs/app-service": "0.15.5",
47
+ "@lwrjs/asset-registry": "0.15.5",
48
+ "@lwrjs/asset-transformer": "0.15.5",
49
+ "@lwrjs/base-view-provider": "0.15.5",
50
+ "@lwrjs/base-view-transformer": "0.15.5",
51
+ "@lwrjs/client-modules": "0.15.5",
52
+ "@lwrjs/config": "0.15.5",
53
+ "@lwrjs/diagnostics": "0.15.5",
54
+ "@lwrjs/esbuild": "0.15.5",
55
+ "@lwrjs/fs-asset-provider": "0.15.5",
56
+ "@lwrjs/fs-watch": "0.15.5",
57
+ "@lwrjs/html-view-provider": "0.15.5",
58
+ "@lwrjs/instrumentation": "0.15.5",
59
+ "@lwrjs/loader": "0.15.5",
60
+ "@lwrjs/lwc-module-provider": "0.15.5",
61
+ "@lwrjs/lwc-ssr": "0.15.5",
62
+ "@lwrjs/markdown-view-provider": "0.15.5",
63
+ "@lwrjs/module-bundler": "0.15.5",
64
+ "@lwrjs/module-registry": "0.15.5",
65
+ "@lwrjs/npm-module-provider": "0.15.5",
66
+ "@lwrjs/nunjucks-view-provider": "0.15.5",
67
+ "@lwrjs/o11y": "0.15.5",
68
+ "@lwrjs/resource-registry": "0.15.5",
69
+ "@lwrjs/router": "0.15.5",
70
+ "@lwrjs/server": "0.15.5",
71
+ "@lwrjs/shared-utils": "0.15.5",
72
+ "@lwrjs/static": "0.15.5",
73
+ "@lwrjs/view-registry": "0.15.5",
74
74
  "chokidar": "^3.6.0",
75
75
  "esbuild": "^0.9.7",
76
76
  "fs-extra": "^11.2.0",
@@ -80,7 +80,7 @@
80
80
  "ws": "^8.18.0"
81
81
  },
82
82
  "devDependencies": {
83
- "@lwrjs/types": "0.15.4-alpha.0",
83
+ "@lwrjs/types": "0.15.5",
84
84
  "@types/ws": "^8.5.12",
85
85
  "memfs": "^4.13.0"
86
86
  },
@@ -93,5 +93,5 @@
93
93
  "volta": {
94
94
  "extends": "../../../package.json"
95
95
  },
96
- "gitHead": "aa3192e18d79d1793325852e15ede56fd5f34dcd"
96
+ "gitHead": "edbc1ac9de986855c6b68c941f84a309e5792889"
97
97
  }