@lwrjs/shared-utils 0.11.0-alpha.1 → 0.11.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/env.cjs CHANGED
@@ -8,6 +8,7 @@ var __export = (target, all) => {
8
8
  // packages/@lwrjs/shared-utils/src/env.ts
9
9
  __markAsModule(exports);
10
10
  __export(exports, {
11
+ buildEnvironmentContext: () => buildEnvironmentContext,
11
12
  getFeatureFlags: () => getFeatureFlags
12
13
  });
13
14
  function getFeatureFlags() {
@@ -16,7 +17,20 @@ function getFeatureFlags() {
16
17
  LEGACY_LOADER: process.env.LEGACY_LOADER !== void 0 && process.env.LEGACY_LOADER.toLowerCase() === "true" ? true : false,
17
18
  SSR_SANDBOX_WORKER: process.env.SSR_SANDBOX_WORKER !== void 0 && process.env.SSR_SANDBOX_WORKER.toLowerCase() === "true" ? true : false,
18
19
  SSR_STATIC_BUNDLES: process.env.SSR_STATIC_BUNDLES !== void 0 && process.env.SSR_STATIC_BUNDLES.toLowerCase() === "true" ? true : false,
20
+ SSR_WITH_CSR_FALLBACK: process.env.SSR_WITH_CSR_FALLBACK !== void 0 && process.env.SSR_WITH_CSR_FALLBACK.toLowerCase() === "true" ? true : false,
19
21
  EXPERIMENTAL_UNVERSIONED_ALIASES: process.env.EXPERIMENTAL_UNVERSIONED_ALIASES !== void 0 && process.env.EXPERIMENTAL_UNVERSIONED_ALIASES.toLowerCase() === "true" ? true : false,
20
22
  LWR_TRACING: process.env.LWR_TRACING !== void 0 && process.env.LWR_TRACING.toLowerCase() !== "off" ? true : false
21
23
  };
22
24
  }
25
+ function buildEnvironmentContext(runtimeParams) {
26
+ const basePath = runtimeParams.basePath;
27
+ const locale = runtimeParams.locale;
28
+ const assetBasePath = runtimeParams.assetBasePath;
29
+ const uiBasePath = runtimeParams.uiBasePath;
30
+ return {
31
+ basePath,
32
+ locale,
33
+ assetBasePath,
34
+ uiBasePath
35
+ };
36
+ }
@@ -28,7 +28,7 @@ __export(exports, {
28
28
  });
29
29
  var import_chokidar = __toModule(require("chokidar"));
30
30
  var import_object = __toModule(require("./object.cjs"));
31
- var import_logger = __toModule(require("./logger.cjs"));
31
+ var import_diagnostics = __toModule(require("@lwrjs/diagnostics"));
32
32
  var WatcherFactoryImpl = class {
33
33
  createFileWatcher(options = {persistent: true, ignored: "**/node_modules/**"}) {
34
34
  return import_chokidar.default.watch([], options);
@@ -37,7 +37,7 @@ var WatcherFactoryImpl = class {
37
37
  const fileWatcher = this.createFileWatcher();
38
38
  fileWatcher.on("change", (0, import_object.debounce)((file) => onModuleChange(file), 500));
39
39
  fileWatcher.on("unlink", (0, import_object.debounce)((file) => onModuleChange(file), 500));
40
- fileWatcher.on("add", (file) => import_logger.logger.info(`Watching: ${file}`));
40
+ fileWatcher.on("add", (file) => import_diagnostics.logger.info(`Watching: ${file}`));
41
41
  return fileWatcher;
42
42
  }
43
43
  };
package/build/cjs/fs.cjs CHANGED
@@ -43,7 +43,7 @@ var import_identity = __toModule(require("./identity.cjs"));
43
43
  var import_diagnostics = __toModule(require("@lwrjs/diagnostics"));
44
44
  var import_mime_types = __toModule(require("mime-types"));
45
45
  var import_stream = __toModule(require("stream"));
46
- var import_logger = __toModule(require("./logger.cjs"));
46
+ var import_diagnostics2 = __toModule(require("@lwrjs/diagnostics"));
47
47
  var fileCount = 0;
48
48
  var files = new Map();
49
49
  function hashContent(source) {
@@ -75,6 +75,9 @@ function resolveFileExtension(filePath) {
75
75
  }
76
76
  }
77
77
  function canResolveView(source, type) {
78
+ if (typeof source !== "string") {
79
+ return false;
80
+ }
78
81
  if (!source.endsWith(`.${type}`)) {
79
82
  return false;
80
83
  }
@@ -119,14 +122,14 @@ function normalizeResourcePath(rawPath, {rootDir, assets, contentDir, layoutsDir
119
122
  });
120
123
  }
121
124
  function logMetrics(filePath) {
122
- if (import_logger.logger.currentLevel == import_logger.DEBUG || import_logger.logger.currentLevel == import_logger.VERBOSE) {
125
+ if (import_diagnostics2.logger.currentLevel == import_diagnostics2.DEBUG || import_diagnostics2.logger.currentLevel == import_diagnostics2.VERBOSE) {
123
126
  let count = files.get(filePath) || 0;
124
127
  if (++count % 100 === 0) {
125
- import_logger.logger.debug(`[${count}] Repeat Read ${filePath}`);
128
+ import_diagnostics2.logger.debug(`[${count}] Repeat Read ${filePath}`);
126
129
  }
127
130
  files.set(filePath, count);
128
131
  if (++fileCount % 1e3 === 0) {
129
- import_logger.logger.debug(`Open file count [${fileCount}]`);
132
+ import_diagnostics2.logger.debug(`Open file count [${fileCount}]`);
130
133
  }
131
134
  }
132
135
  }
@@ -61,13 +61,16 @@ function isSelfUrl(url) {
61
61
  return !url || !!url.match(isSelfUrlRegex);
62
62
  }
63
63
  var isSelfUrlRegex = /^\s*(data:|#)/i;
64
- async function extractMetadataFromHtml(htmlSource) {
64
+ function hasHydrationDirective(attrs = {}) {
65
+ return Object.keys(attrs).some((attr) => attr === HYDRATE_DIRECTIVE);
66
+ }
67
+ async function extractMetadataFromHtml(htmlSource, viewMetadata) {
68
+ const {customElements, assetReferences, serverData} = viewMetadata;
65
69
  return new Promise((resolve, reject) => {
66
- const customElements = [];
67
70
  const openElements = new Set();
68
- const assetReferences = [];
69
71
  const parser = new import_parse5_sax_parser.default({sourceCodeLocationInfo: true});
70
72
  const ceRefStack = [];
73
+ let nestedIslands = false;
71
74
  parser.on("startTag", ({
72
75
  tagName,
73
76
  attrs,
@@ -75,23 +78,23 @@ async function extractMetadataFromHtml(htmlSource) {
75
78
  }) => {
76
79
  if (tagName.includes("-") && !openElements.has(tagName)) {
77
80
  const {startOffset, endOffset} = sourceCodeLocation;
78
- const ceRef = {
79
- tagName,
80
- location: {startOffset, endOffset},
81
- props: attrs.length ? attrs.reduce((obj, {name, value}) => {
82
- obj[(0, import_identity.getPropFromAttrName)(name)] = value === "" ? "true" : value;
83
- return obj;
84
- }, {}) : void 0
85
- };
81
+ const props = attrs.length ? attrs.reduce((obj, {name, value}) => {
82
+ obj[(0, import_identity.getPropFromAttrName)(name)] = value === "" ? "true" : value;
83
+ return obj;
84
+ }, {}) : void 0;
85
+ const ceRef = {tagName, location: {startOffset, endOffset}, props};
86
86
  openElements.add(tagName);
87
87
  if (ceRefStack.length) {
88
88
  const last = ceRefStack[ceRefStack.length - 1];
89
89
  last.children = last.children ? [...last.children, ceRef] : [ceRef];
90
- ceRefStack.push(ceRef);
90
+ if (hasHydrationDirective(props)) {
91
+ customElements.push(ceRef);
92
+ nestedIslands = true;
93
+ }
91
94
  } else {
92
95
  customElements.push(ceRef);
93
- ceRefStack.push(ceRef);
94
96
  }
97
+ ceRefStack.push(ceRef);
95
98
  }
96
99
  if ((tagName === "img" || tagName === "script") && sourceCodeLocation.attrs) {
97
100
  if (sourceCodeLocation.attrs.src) {
@@ -118,7 +121,11 @@ async function extractMetadataFromHtml(htmlSource) {
118
121
  }
119
122
  });
120
123
  const inputStream = import_stream.Readable.from(htmlSource);
121
- inputStream.on("end", () => resolve({customElements, assetReferences}));
124
+ inputStream.on("end", () => resolve({
125
+ customElements: customElements.filter((ce) => !nestedIslands || hasHydrationDirective(ce.props)),
126
+ assetReferences,
127
+ serverData
128
+ }));
122
129
  inputStream.on("error", (error) => reject(error));
123
130
  inputStream.pipe(parser);
124
131
  });
@@ -47,13 +47,15 @@ __export(exports, {
47
47
  isAssetSourceExternal: () => isAssetSourceExternal,
48
48
  isBundleDefinition: () => isBundleDefinition,
49
49
  isExternalUrl: () => isExternalUrl,
50
+ isSpecifier: () => isSpecifier,
50
51
  kebabCaseToModuleSpecifier: () => kebabCaseToModuleSpecifier,
51
52
  moduleSpecifierToKebabCase: () => moduleSpecifierToKebabCase,
52
53
  normalizeVersionFromUri: () => normalizeVersionFromUri,
53
54
  normalizeVersionToUri: () => normalizeVersionToUri,
54
55
  parsePackageSpecifier: () => parsePackageSpecifier,
55
56
  prettyModuleUriSuffix: () => prettyModuleUriSuffix,
56
- slugify: () => slugify
57
+ slugify: () => slugify,
58
+ stringToVariableName: () => stringToVariableName
57
59
  });
58
60
  var import_slugify = __toModule(require("slugify"));
59
61
  var import_fast_json_stable_stringify = __toModule(require("fast-json-stable-stringify"));
@@ -132,6 +134,9 @@ async function getVersionedModuleId(rawSpecifier, moduleRegistry, runtimeParams)
132
134
  const moduleEntry = await moduleRegistry.getModuleEntry(moduleId, runtimeParams);
133
135
  return {...moduleId, version: moduleEntry.version};
134
136
  }
137
+ function isSpecifier(specifier) {
138
+ return !!specifier && /^@?[\w-]+(\/[\w-]+)*$/.test(specifier);
139
+ }
135
140
  var RE_SCOPED = /^(@[^/]+\/[^/@]+)(?:\/([^@]+))?(?:@([\s\S]+))?/;
136
141
  var RE_NORMAL = /^([^/@]+)(?:\/([^@]+))?(?:@([\s\S]+))?/;
137
142
  function parsePackageSpecifier(specifier) {
@@ -208,3 +213,10 @@ function isAssetSourceExternal(assetSource) {
208
213
  function isBundleDefinition(definition) {
209
214
  return definition.bundleRecord !== void 0;
210
215
  }
216
+ function stringToVariableName(inputString) {
217
+ const cleanedString = inputString.replace(/@/g, "").replace(/[^a-zA-Z0-9_$]/g, "_");
218
+ if (!cleanedString || /^[0-9$]+/.test(cleanedString)) {
219
+ return `_${cleanedString}`;
220
+ }
221
+ return cleanedString;
222
+ }
@@ -28,7 +28,7 @@ __export(exports, {
28
28
  getImportMetadata: () => getImportMetadata
29
29
  });
30
30
  var import_es_module_lexer = __toModule(require("es-module-lexer"));
31
- var import_logger = __toModule(require("./logger.cjs"));
31
+ var import_diagnostics = __toModule(require("@lwrjs/diagnostics"));
32
32
  var IMPORT_META_REGEX = /^import\.meta(\.\w+)+/;
33
33
  var ModuleNameType;
34
34
  (function(ModuleNameType2) {
@@ -53,8 +53,8 @@ async function getImportMetadata(compiledSource) {
53
53
  const isStringLiteral = moduleSpecifier.startsWith("'") || moduleSpecifier.startsWith('"');
54
54
  const moduleNameType = isStringLiteral ? ModuleNameType.string : ModuleNameType.unresolved;
55
55
  moduleSpecifier = isStringLiteral ? moduleSpecifier.slice(1, -1) : moduleSpecifier;
56
- if (import_logger.logger.currentLevel === import_logger.DEBUG || import_logger.logger.currentLevel === import_logger.VERBOSE) {
57
- import_logger.logger.debug(`[import-metadata] Import from dynamic import ${compiledSource.slice(moduleImportLocation.ss, moduleImportLocation.se)} -> ${compiledSource.slice(moduleImportLocation.ss, moduleImportLocation.s)}`);
56
+ if (import_diagnostics.logger.currentLevel === import_diagnostics.DEBUG || import_diagnostics.logger.currentLevel === import_diagnostics.VERBOSE) {
57
+ import_diagnostics.logger.debug(`[import-metadata] Import from dynamic import ${compiledSource.slice(moduleImportLocation.ss, moduleImportLocation.se)} -> ${compiledSource.slice(moduleImportLocation.ss, moduleImportLocation.s)}`);
58
58
  }
59
59
  dynamicImports.push({
60
60
  moduleSpecifier,
@@ -32,7 +32,6 @@ __exportStar(exports, __toModule(require("./graph.cjs")));
32
32
  __exportStar(exports, __toModule(require("./mappings.cjs")));
33
33
  __exportStar(exports, __toModule(require("./urls.cjs")));
34
34
  __exportStar(exports, __toModule(require("./env.cjs")));
35
- __exportStar(exports, __toModule(require("./logger.cjs")));
36
35
  __exportStar(exports, __toModule(require("./lwr-app-observer.cjs")));
37
36
  __exportStar(exports, __toModule(require("./bundle.cjs")));
38
37
  __exportStar(exports, __toModule(require("./localization.cjs")));
@@ -1,54 +1,34 @@
1
- var __create = Object.create;
2
1
  var __defProp = Object.defineProperty;
3
- var __getProtoOf = Object.getPrototypeOf;
4
- var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
2
  var __markAsModule = (target) => __defProp(target, "__esModule", {value: true});
8
3
  var __export = (target, all) => {
9
4
  for (var name in all)
10
5
  __defProp(target, name, {get: all[name], enumerable: true});
11
6
  };
12
- var __exportStar = (target, module2, desc) => {
13
- if (module2 && typeof module2 === "object" || typeof module2 === "function") {
14
- for (let key of __getOwnPropNames(module2))
15
- if (!__hasOwnProp.call(target, key) && key !== "default")
16
- __defProp(target, key, {get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable});
17
- }
18
- return target;
19
- };
20
- var __toModule = (module2) => {
21
- return __exportStar(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? {get: () => module2.default, enumerable: true} : {value: module2, enumerable: true})), module2);
22
- };
23
7
 
24
8
  // packages/@lwrjs/shared-utils/src/localization.ts
25
9
  __markAsModule(exports);
26
10
  __export(exports, {
27
- hasCountryCode: () => hasCountryCode,
28
- stripCountryCode: () => stripCountryCode
11
+ getFallbackLocale: () => getFallbackLocale,
12
+ walkLocaleFallbacks: () => walkLocaleFallbacks
29
13
  });
30
- var import_logger = __toModule(require("./logger.cjs"));
31
- function hasCountryCode(locale) {
32
- try {
33
- const parsedLocale = new Intl.Locale(resolveLocaleId(locale));
34
- return typeof parsedLocale.region === "string";
35
- } catch (error) {
36
- import_logger.logger.debug(`[static-util] Failed to parse country code from locale: ${locale}`, error);
37
- return false;
38
- }
14
+ function getFallbackLocale(localeId, i18n) {
15
+ const locale = i18n.locales.find((l) => l.id === localeId);
16
+ return locale?.fallback;
39
17
  }
40
- function stripCountryCode(locale) {
41
- try {
42
- const parsedLocale = new Intl.Locale(resolveLocaleId(locale));
43
- return parsedLocale.language;
44
- } catch (error) {
45
- import_logger.logger.debug(`[static-util] Failed to strip country code from locale: ${locale}`, error);
18
+ async function walkLocaleFallbacks(initialLocale, i18n, test) {
19
+ const visited = new Set();
20
+ let localeId = initialLocale;
21
+ while (localeId && !visited.has(localeId)) {
22
+ const result = await test(localeId);
23
+ if (result) {
24
+ return result;
25
+ }
26
+ visited.add(localeId);
27
+ const config = i18n.locales.find((l) => l.id === localeId);
28
+ localeId = config && config.fallback;
46
29
  }
47
- }
48
- function resolveLocaleId(locale) {
49
- const asLocalObj = locale;
50
- if (asLocalObj.id !== void 0) {
51
- return asLocalObj.id;
30
+ if (!visited.has(i18n.defaultLocale)) {
31
+ return test(i18n.defaultLocale);
52
32
  }
53
- return locale;
33
+ return void 0;
54
34
  }
@@ -23,7 +23,10 @@ function _deepFreeze(obj, maxDepth, depth) {
23
23
  }
24
24
  }
25
25
  function deepFreeze(obj, maxDepth = 5) {
26
- const objClone = JSON.parse(JSON.stringify(obj));
26
+ let objClone = obj;
27
+ if (process.env.UNSAFE_IGNORE_CONFIG_VALIDATION !== "true") {
28
+ objClone = JSON.parse(JSON.stringify(obj));
29
+ }
27
30
  return _deepFreeze(objClone, maxDepth, 0);
28
31
  }
29
32
  var debounce = (func, waitFor) => {
@@ -29,10 +29,13 @@ __export(exports, {
29
29
  getClientBootstrapConfigurationRoutes: () => getClientBootstrapConfigurationRoutes,
30
30
  getClientBootstrapConfigurationUri: () => getClientBootstrapConfigurationUri,
31
31
  getClientBootstrapConfigurationUriPrefix: () => getClientBootstrapConfigurationUriPrefix,
32
+ getViewUri: () => getViewUri,
32
33
  isModuleOrBundleUrl: () => isModuleOrBundleUrl,
34
+ isURL: () => isURL,
33
35
  removeClientBootstrapConfigurationSuffix: () => removeClientBootstrapConfigurationSuffix
34
36
  });
35
37
  var import_path_to_regexp = __toModule(require("path-to-regexp"));
38
+ var import_path = __toModule(require("path"));
36
39
  var CONFIG_SUFFIX = "/config.js";
37
40
  var SIGNATURE_SIGIL = "s";
38
41
  function getClientBootstrapConfigurationUri(routeInfo, runtimeEnvironment, runtimeParams, signature) {
@@ -100,3 +103,25 @@ var isModuleOrBundleRegEx = /^\/.*\/(module|bundle)\//i;
100
103
  function isModuleOrBundleUrl(url) {
101
104
  return isModuleOrBundleRegEx.test(url);
102
105
  }
106
+ function getViewUri(routePath, basePath, locale, i18n) {
107
+ if (isURL(routePath)) {
108
+ return routePath;
109
+ }
110
+ let url = basePath;
111
+ if (i18n.uriPattern === "path-prefix" && locale !== i18n.defaultLocale) {
112
+ url = import_path.default.join(url, `/${locale}`);
113
+ }
114
+ url = import_path.default.join(url, routePath);
115
+ if (i18n.uriPattern === "query-param" && locale !== i18n.defaultLocale) {
116
+ url = addQueryParamToAbsoluteURI(url, "locale", locale);
117
+ }
118
+ return url;
119
+ }
120
+ function isURL(uri) {
121
+ return /^https?:\/\//i.test(uri);
122
+ }
123
+ function addQueryParamToAbsoluteURI(absoluteURI, paramName, paramValue) {
124
+ const url = new URL(absoluteURI, "http://example.com");
125
+ url.searchParams.set(paramName, paramValue);
126
+ return url.pathname + url.search;
127
+ }
package/build/es/env.d.ts CHANGED
@@ -1,3 +1,7 @@
1
- import type { FeatureFlags } from '@lwrjs/types';
1
+ import type { EnvironmentContext, FeatureFlags, RuntimeParams } from '@lwrjs/types';
2
2
  export declare function getFeatureFlags(): FeatureFlags;
3
+ /**
4
+ * Create a serializable context for the lwr/environment variable
5
+ */
6
+ export declare function buildEnvironmentContext(runtimeParams: RuntimeParams): EnvironmentContext;
3
7
  //# sourceMappingURL=env.d.ts.map
package/build/es/env.js CHANGED
@@ -20,6 +20,11 @@ export function getFeatureFlags() {
20
20
  process.env.SSR_STATIC_BUNDLES.toLowerCase() === 'true'
21
21
  ? true
22
22
  : false,
23
+ // Islands fallback to CSR if SSR fails
24
+ SSR_WITH_CSR_FALLBACK: process.env.SSR_WITH_CSR_FALLBACK !== undefined &&
25
+ process.env.SSR_WITH_CSR_FALLBACK.toLowerCase() === 'true'
26
+ ? true
27
+ : false,
23
28
  // AMD Module Bundles include un-versioned aliases
24
29
  EXPERIMENTAL_UNVERSIONED_ALIASES: process.env.EXPERIMENTAL_UNVERSIONED_ALIASES !== undefined &&
25
30
  process.env.EXPERIMENTAL_UNVERSIONED_ALIASES.toLowerCase() === 'true'
@@ -30,4 +35,23 @@ export function getFeatureFlags() {
30
35
  : false,
31
36
  };
32
37
  }
38
+ /**
39
+ * Create a serializable context for the lwr/environment variable
40
+ */
41
+ export function buildEnvironmentContext(runtimeParams) {
42
+ // The baseBath form the config or set from the request (e.g. /shop)
43
+ const basePath = runtimeParams.basePath;
44
+ // The locale set from the request or the defaultLocale from the config (e.g. en-US)
45
+ const locale = runtimeParams.locale;
46
+ // Root base path for static assets (e.g. /shop/mobify/bundle/1234/site)
47
+ const assetBasePath = runtimeParams.assetBasePath;
48
+ // Base path for UI routing (e.g. /shop/en-US)
49
+ const uiBasePath = runtimeParams.uiBasePath;
50
+ return {
51
+ basePath,
52
+ locale,
53
+ assetBasePath,
54
+ uiBasePath,
55
+ };
56
+ }
33
57
  //# sourceMappingURL=env.js.map
@@ -1,6 +1,6 @@
1
1
  import chokidar from 'chokidar';
2
2
  import { debounce } from './object.js';
3
- import { logger } from './logger.js';
3
+ import { logger } from '@lwrjs/diagnostics';
4
4
  /**
5
5
  * Factory comptable with the LWR Runtime to create a file watch library for LWR dev server.
6
6
  * When importing this module make sure the optional library 'chokidar' is installed.
package/build/es/fs.d.ts CHANGED
@@ -21,10 +21,10 @@ export declare function resolveFileExtension(filePath: string): string;
21
21
  /**
22
22
  * Returns if view of specific type can be resolved
23
23
  *
24
- * @param source - path to view
24
+ * @param source - possible path to view
25
25
  * @param type - extension of file that should be expected, i.e. 'html'
26
26
  */
27
- export declare function canResolveView(source: string, type: string): boolean;
27
+ export declare function canResolveView(source: unknown, type: string): boolean;
28
28
  /**
29
29
  * Construct a ViewSource from the associated file on the fs
30
30
  * @param source - Filepath with the source (source can be an absolute or relative path)
package/build/es/fs.js CHANGED
@@ -5,7 +5,7 @@ import { slugify } from './identity.js';
5
5
  import { LwrUnresolvableError, createSingleDiagnosticError, descriptions } from '@lwrjs/diagnostics';
6
6
  import { lookup } from 'mime-types';
7
7
  import { Readable } from 'stream';
8
- import { DEBUG, logger, VERBOSE } from './logger.js';
8
+ import { DEBUG, logger, VERBOSE } from '@lwrjs/diagnostics';
9
9
  let fileCount = 0;
10
10
  const files = new Map();
11
11
  /**
@@ -57,10 +57,13 @@ export function resolveFileExtension(filePath) {
57
57
  /**
58
58
  * Returns if view of specific type can be resolved
59
59
  *
60
- * @param source - path to view
60
+ * @param source - possible path to view
61
61
  * @param type - extension of file that should be expected, i.e. 'html'
62
62
  */
63
63
  export function canResolveView(source, type) {
64
+ if (typeof source !== 'string') {
65
+ return false;
66
+ }
64
67
  if (!source.endsWith(`.${type}`)) {
65
68
  return false;
66
69
  }
@@ -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): Promise<RenderedViewMetadata>;
8
+ export declare function extractMetadataFromHtml(htmlSource: string, viewMetadata: RenderedViewMetadata): Promise<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";
@@ -29,46 +29,51 @@ export function isSelfUrl(url) {
29
29
  return !url || !!url.match(isSelfUrlRegex);
30
30
  }
31
31
  const isSelfUrlRegex = /^\s*(data:|#)/i;
32
+ function hasHydrationDirective(attrs = {}) {
33
+ return Object.keys(attrs).some((attr) => attr === HYDRATE_DIRECTIVE);
34
+ }
32
35
  /**
33
36
  * Pull the custom elements and img tags out of an HTML string, to use as metadata
34
37
  * @param htmlSource - An HTML string to parse
35
38
  */
36
- export async function extractMetadataFromHtml(htmlSource) {
39
+ export async function extractMetadataFromHtml(htmlSource, viewMetadata) {
40
+ const { customElements, assetReferences, serverData } = viewMetadata;
37
41
  return new Promise((resolve, reject) => {
38
- const customElements = [];
39
42
  const openElements = new Set();
40
- const assetReferences = [];
41
43
  const parser = new SAXParser({ sourceCodeLocationInfo: true }); // TODO: Would we need this in the future?
42
44
  const ceRefStack = [];
45
+ let nestedIslands = false;
43
46
  parser.on('startTag', ({ tagName, attrs, // attributes are passed into SSR
44
47
  sourceCodeLocation, }) => {
45
48
  // custom elements
46
49
  if (tagName.includes('-') && !openElements.has(tagName)) {
47
50
  const { startOffset, endOffset } = sourceCodeLocation;
48
- const ceRef = {
49
- tagName,
50
- location: { startOffset, endOffset },
51
- // transform attributes [{ name: 'some-attr', value: 'the value' }] into properties { someAttr: 'the value' }
52
- // leave props as undefined if there are no attributes
53
- // set boolean attribute values to "true", or lwc will see them as falsy
54
- props: attrs.length
55
- ? attrs.reduce((obj, { name, value }) => {
56
- obj[getPropFromAttrName(name)] = value === '' ? 'true' : value;
57
- return obj;
58
- }, {})
59
- : undefined,
60
- };
51
+ // transform attributes [{ name: 'some-attr', value: 'the value' }] into properties { someAttr: 'the value' }
52
+ // leave props as undefined if there are no attributes
53
+ // set boolean attribute values to "true", or lwc will see them as falsy
54
+ const props = attrs.length
55
+ ? attrs.reduce((obj, { name, value }) => {
56
+ obj[getPropFromAttrName(name)] = value === '' ? 'true' : value;
57
+ return obj;
58
+ }, {})
59
+ : undefined;
60
+ const ceRef = { tagName, location: { startOffset, endOffset }, props };
61
61
  openElements.add(tagName);
62
62
  if (ceRefStack.length) {
63
63
  // nested CE
64
64
  const last = ceRefStack[ceRefStack.length - 1];
65
65
  last.children = last.children ? [...last.children, ceRef] : [ceRef];
66
- ceRefStack.push(ceRef);
66
+ // nested CEs are collected if they have a hydration directive
67
+ if (hasHydrationDirective(props)) {
68
+ customElements.push(ceRef);
69
+ nestedIslands = true;
70
+ }
67
71
  }
68
72
  else {
73
+ // collect all top-level CEs
69
74
  customElements.push(ceRef);
70
- ceRefStack.push(ceRef);
71
75
  }
76
+ ceRefStack.push(ceRef);
72
77
  }
73
78
  // <img src="asset-url"/>
74
79
  // <script type="text/javascript" src="asset-url"></script>
@@ -99,8 +104,13 @@ export async function extractMetadataFromHtml(htmlSource) {
99
104
  }
100
105
  });
101
106
  const inputStream = Readable.from(htmlSource);
102
- // dedupe custom element references
103
- inputStream.on('end', () => resolve({ customElements, assetReferences }));
107
+ // If nested islands are found, ONLY collect custom elements with the hydration directive
108
+ // Otherwise, just collect top-level custom elements (ie: root components) as usual
109
+ inputStream.on('end', () => resolve({
110
+ customElements: customElements.filter((ce) => !nestedIslands || hasHydrationDirective(ce.props)),
111
+ assetReferences,
112
+ serverData,
113
+ }));
104
114
  inputStream.on('error', (error) => reject(error));
105
115
  inputStream.pipe(parser);
106
116
  });
@@ -82,6 +82,7 @@ interface VersionedAbstractModuleId extends AbstractModuleId {
82
82
  * @example - 'c/form/v/0_0_2' => {specifier: "c/form", version: "0.0.2"}
83
83
  */
84
84
  export declare function getVersionedModuleId(rawSpecifier: string, moduleRegistry: PublicModuleRegistry, runtimeParams: RuntimeParams): Promise<VersionedAbstractModuleId>;
85
+ export declare function isSpecifier(specifier?: string): boolean;
85
86
  interface PackageIdentity {
86
87
  scope?: string;
87
88
  packageName: string;
@@ -140,4 +141,9 @@ export { getCacheKeyFromJson };
140
141
  export declare function isExternalUrl(url: string): boolean;
141
142
  export declare function isAssetSourceExternal(assetSource: AssetSource): boolean;
142
143
  export declare function isBundleDefinition(definition: ModuleDefinition | BundleDefinition): definition is BundleDefinition;
144
+ /**
145
+ * Create a js safe variable name
146
+ * @param name - Proposed name
147
+ */
148
+ export declare function stringToVariableName(inputString: string): string;
143
149
  //# sourceMappingURL=identity.d.ts.map
@@ -129,6 +129,9 @@ export async function getVersionedModuleId(rawSpecifier, moduleRegistry, runtime
129
129
  const moduleEntry = await moduleRegistry.getModuleEntry(moduleId, runtimeParams);
130
130
  return { ...moduleId, version: moduleEntry.version };
131
131
  }
132
+ export function isSpecifier(specifier) {
133
+ return !!specifier && /^@?[\w-]+(\/[\w-]+)*$/.test(specifier);
134
+ }
132
135
  const RE_SCOPED = /^(@[^/]+\/[^/@]+)(?:\/([^@]+))?(?:@([\s\S]+))?/;
133
136
  const RE_NORMAL = /^([^/@]+)(?:\/([^@]+))?(?:@([\s\S]+))?/;
134
137
  /**
@@ -255,4 +258,18 @@ export function isAssetSourceExternal(assetSource) {
255
258
  export function isBundleDefinition(definition) {
256
259
  return definition.bundleRecord !== undefined;
257
260
  }
261
+ /**
262
+ * Create a js safe variable name
263
+ * @param name - Proposed name
264
+ */
265
+ export function stringToVariableName(inputString) {
266
+ // Remove at symbols (@)
267
+ // Remove non-alphanumeric characters except for underscore (_) and dollar sign ($)
268
+ const cleanedString = inputString.replace(/@/g, '').replace(/[^a-zA-Z0-9_$]/g, '_');
269
+ // Prepend an underscore if the resulting name is empty or starts with a number, underscore (_) and dollar sign ($)
270
+ if (!cleanedString || /^[0-9$]+/.test(cleanedString)) {
271
+ return `_${cleanedString}`;
272
+ }
273
+ return cleanedString;
274
+ }
258
275
  //# sourceMappingURL=identity.js.map
@@ -1,5 +1,5 @@
1
1
  import { parse as parseImports } from 'es-module-lexer';
2
- import { DEBUG, logger, VERBOSE } from './logger.js';
2
+ import { DEBUG, logger, VERBOSE } from '@lwrjs/diagnostics';
3
3
  const IMPORT_META_REGEX = /^import\.meta(\.\w+)+/;
4
4
  export var ModuleNameType;
5
5
  (function (ModuleNameType) {
@@ -11,7 +11,6 @@ export * from './graph.js';
11
11
  export * from './mappings.js';
12
12
  export * from './urls.js';
13
13
  export * from './env.js';
14
- export * from './logger.js';
15
14
  export * from './lwr-app-observer.js';
16
15
  export * from './bundle.js';
17
16
  export * from './localization.js';
package/build/es/index.js CHANGED
@@ -11,7 +11,6 @@ export * from './graph.js';
11
11
  export * from './mappings.js';
12
12
  export * from './urls.js';
13
13
  export * from './env.js';
14
- export * from './logger.js';
15
14
  export * from './lwr-app-observer.js';
16
15
  export * from './bundle.js';
17
16
  export * from './localization.js';
@@ -1,4 +1,4 @@
1
- import type { Locale } from '@lwrjs/types';
2
- export declare function hasCountryCode(locale: Locale | string): boolean;
3
- export declare function stripCountryCode(locale: Locale | string): string | undefined;
1
+ import type { I18NConfig } from '@lwrjs/types';
2
+ export declare function getFallbackLocale(localeId: string, i18n: I18NConfig): string | undefined;
3
+ export declare function walkLocaleFallbacks<R>(initialLocale: string, i18n: I18NConfig, test: (locale: string) => Promise<R | undefined>): Promise<R | undefined>;
4
4
  //# sourceMappingURL=localization.d.ts.map
@@ -1,29 +1,28 @@
1
- import { logger } from './logger.js';
2
1
  // Utilities for working with localized content
3
- export function hasCountryCode(locale) {
4
- try {
5
- const parsedLocale = new Intl.Locale(resolveLocaleId(locale));
6
- return typeof parsedLocale.region === 'string';
7
- }
8
- catch (error) {
9
- logger.debug(`[static-util] Failed to parse country code from locale: ${locale}`, error);
10
- return false; // Invalid locale format
11
- }
2
+ export function getFallbackLocale(localeId, i18n) {
3
+ const locale = i18n.locales.find((l) => l.id === localeId);
4
+ return locale?.fallback;
12
5
  }
13
- export function stripCountryCode(locale) {
14
- try {
15
- const parsedLocale = new Intl.Locale(resolveLocaleId(locale));
16
- return parsedLocale.language;
6
+ // Utilities to walk locale fallback logic
7
+ export async function walkLocaleFallbacks(initialLocale, i18n, test) {
8
+ // Walk the locales
9
+ const visited = new Set();
10
+ let localeId = initialLocale;
11
+ while (localeId && !visited.has(localeId)) {
12
+ // eslint-disable-next-line no-await-in-loop
13
+ const result = await test(localeId);
14
+ if (result) {
15
+ return result;
16
+ }
17
+ visited.add(localeId);
18
+ const config = i18n.locales.find((l) => l.id === localeId);
19
+ localeId = config && config.fallback;
17
20
  }
18
- catch (error) {
19
- logger.debug(`[static-util] Failed to strip country code from locale: ${locale}`, error);
20
- }
21
- }
22
- function resolveLocaleId(locale) {
23
- const asLocalObj = locale;
24
- if (asLocalObj.id !== undefined) {
25
- return asLocalObj.id;
21
+ // If we did not already visit the default locale give that a try
22
+ if (!visited.has(i18n.defaultLocale)) {
23
+ return test(i18n.defaultLocale);
26
24
  }
27
- return locale;
25
+ // Did not find what we were looking for
26
+ return undefined;
28
27
  }
29
28
  //# sourceMappingURL=localization.js.map
@@ -18,7 +18,12 @@ function _deepFreeze(obj, maxDepth, depth) {
18
18
  */
19
19
  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
20
20
  export function deepFreeze(obj, maxDepth = 5) {
21
- const objClone = JSON.parse(JSON.stringify(obj));
21
+ let objClone = obj;
22
+ // Temporary fix for W-13723739 to prevent out of memory exceptions
23
+ // Only clone the object if we don't have the env variable set
24
+ if (process.env.UNSAFE_IGNORE_CONFIG_VALIDATION !== 'true') {
25
+ objClone = JSON.parse(JSON.stringify(obj));
26
+ }
22
27
  return _deepFreeze(objClone, maxDepth, 0);
23
28
  }
24
29
  /**
@@ -1,4 +1,4 @@
1
- import type { RuntimeEnvironment, RuntimeParams } from '@lwrjs/types';
1
+ import type { I18NConfig, RuntimeEnvironment, RuntimeParams } from '@lwrjs/types';
2
2
  export declare function getClientBootstrapConfigurationUri(routeInfo: {
3
3
  id: string;
4
4
  url: string;
@@ -28,4 +28,12 @@ export declare function getClientBootstrapConfigurationRoutes(): string[];
28
28
  */
29
29
  export declare function extractRequestParams(parameterizedRoute: string, resolvedUrl: string, existingParams?: Record<string, string>): Record<string, string>;
30
30
  export declare function isModuleOrBundleUrl(url: string): boolean;
31
+ /**
32
+ * Return a view route URL considering the basePath and the i18N config
33
+ */
34
+ export declare function getViewUri(routePath: string, basePath: string, locale: string, i18n: I18NConfig): string;
35
+ /**
36
+ * Returns true is the URI starts with http:// or https://
37
+ */
38
+ export declare function isURL(uri: string): boolean;
31
39
  //# sourceMappingURL=urls.d.ts.map
package/build/es/urls.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { pathToRegexp } from 'path-to-regexp';
2
+ import path from 'path';
2
3
  const CONFIG_SUFFIX = '/config.js';
3
4
  const SIGNATURE_SIGIL = 's';
4
5
  export function getClientBootstrapConfigurationUri(routeInfo, runtimeEnvironment, runtimeParams, signature) {
@@ -91,4 +92,36 @@ const isModuleOrBundleRegEx = /^\/.*\/(module|bundle)\//i;
91
92
  export function isModuleOrBundleUrl(url) {
92
93
  return isModuleOrBundleRegEx.test(url);
93
94
  }
95
+ /**
96
+ * Return a view route URL considering the basePath and the i18N config
97
+ */
98
+ export function getViewUri(routePath, basePath, locale, i18n) {
99
+ // Use a regular expression to check if the URI has a domain
100
+ if (isURL(routePath)) {
101
+ return routePath;
102
+ }
103
+ let url = basePath;
104
+ if (i18n.uriPattern === 'path-prefix' && locale !== i18n.defaultLocale) {
105
+ url = path.join(url, `/${locale}`);
106
+ }
107
+ url = path.join(url, routePath);
108
+ if (i18n.uriPattern === 'query-param' && locale !== i18n.defaultLocale) {
109
+ url = addQueryParamToAbsoluteURI(url, 'locale', locale);
110
+ }
111
+ return url;
112
+ }
113
+ /**
114
+ * Returns true is the URI starts with http:// or https://
115
+ */
116
+ export function isURL(uri) {
117
+ return /^https?:\/\//i.test(uri);
118
+ }
119
+ function addQueryParamToAbsoluteURI(absoluteURI, paramName, paramValue) {
120
+ // Use a dummy domain for parsing
121
+ const url = new URL(absoluteURI, 'http://example.com');
122
+ // Add the query parameter
123
+ url.searchParams.set(paramName, paramValue);
124
+ // Get the modified URI with the query parameter
125
+ return url.pathname + url.search;
126
+ }
94
127
  //# sourceMappingURL=urls.js.map
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "version": "0.11.0-alpha.1",
7
+ "version": "0.11.0-alpha.10",
8
8
  "homepage": "https://developer.salesforce.com/docs/platform/lwr/overview",
9
9
  "repository": {
10
10
  "type": "git",
@@ -45,6 +45,7 @@
45
45
  "build/**/*.d.ts"
46
46
  ],
47
47
  "dependencies": {
48
+ "@lwrjs/diagnostics": "0.11.0-alpha.10",
48
49
  "es-module-lexer": "^1.3.0",
49
50
  "fast-json-stable-stringify": "^2.1.0",
50
51
  "magic-string": "^0.30.0",
@@ -61,13 +62,12 @@
61
62
  "rollup": "^2.78.0"
62
63
  },
63
64
  "devDependencies": {
64
- "@lwrjs/diagnostics": "0.11.0-alpha.1",
65
- "@lwrjs/types": "0.11.0-alpha.1",
65
+ "@lwrjs/types": "0.11.0-alpha.10",
66
66
  "@types/mime-types": "2.1.1",
67
67
  "@types/path-to-regexp": "^1.7.0"
68
68
  },
69
69
  "engines": {
70
70
  "node": ">=16.0.0"
71
71
  },
72
- "gitHead": "6a840d4694fac9f0be5c3a21707015379cbadad7"
72
+ "gitHead": "34b1e289e8de12531f5624b64512e870157195d4"
73
73
  }
@@ -1,146 +0,0 @@
1
- var __create = Object.create;
2
- var __defProp = Object.defineProperty;
3
- var __getProtoOf = Object.getPrototypeOf;
4
- var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
- var __markAsModule = (target) => __defProp(target, "__esModule", {value: true});
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, {get: all[name], enumerable: true});
11
- };
12
- var __exportStar = (target, module2, desc) => {
13
- if (module2 && typeof module2 === "object" || typeof module2 === "function") {
14
- for (let key of __getOwnPropNames(module2))
15
- if (!__hasOwnProp.call(target, key) && key !== "default")
16
- __defProp(target, key, {get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable});
17
- }
18
- return target;
19
- };
20
- var __toModule = (module2) => {
21
- return __exportStar(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? {get: () => module2.default, enumerable: true} : {value: module2, enumerable: true})), module2);
22
- };
23
-
24
- // packages/@lwrjs/shared-utils/src/logger.ts
25
- __markAsModule(exports);
26
- __export(exports, {
27
- DEBUG: () => DEBUG,
28
- ERROR: () => ERROR,
29
- INFO: () => INFO,
30
- VERBOSE: () => VERBOSE,
31
- WARN: () => WARN,
32
- logger: () => logger,
33
- stringifyError: () => stringifyError
34
- });
35
- var import_diagnostics = __toModule(require("@lwrjs/diagnostics"));
36
- var VERBOSE = "verbose";
37
- var DEBUG = "debug";
38
- var INFO = "info";
39
- var WARN = "warn";
40
- var ERROR = "error";
41
- var options = {};
42
- var DUPES = new Set();
43
- var currentLevel = process.env.LOG_LEVEL || INFO;
44
- function log(level, message, additionalInfo) {
45
- const LOG_LEVEL = process.env.LOG_LEVEL || INFO;
46
- if (currentLevel !== LOG_LEVEL) {
47
- currentLevel = LOG_LEVEL;
48
- console.log(`LOG_LEVEL: ${LOG_LEVEL}`);
49
- }
50
- let shouldLog = false;
51
- switch (level) {
52
- case VERBOSE:
53
- shouldLog = LOG_LEVEL == VERBOSE;
54
- break;
55
- case DEBUG:
56
- shouldLog = LOG_LEVEL == VERBOSE || LOG_LEVEL == DEBUG;
57
- break;
58
- case INFO:
59
- shouldLog = LOG_LEVEL == VERBOSE || LOG_LEVEL == DEBUG || LOG_LEVEL == INFO;
60
- break;
61
- case WARN:
62
- shouldLog = LOG_LEVEL == VERBOSE || LOG_LEVEL == DEBUG || LOG_LEVEL == INFO || LOG_LEVEL == WARN;
63
- break;
64
- case ERROR:
65
- shouldLog = true;
66
- break;
67
- }
68
- if (shouldLog && options.dedupe && options.dedupe.has(level)) {
69
- const key = `[${level}] : ${message}`;
70
- if (DUPES.has(key)) {
71
- shouldLog = false;
72
- } else {
73
- DUPES.add(key);
74
- }
75
- }
76
- if (shouldLog) {
77
- const logMessage = `[${level}]${gap(message)}${message}`;
78
- const additionalMessage = additionalInfo ? `Additional Info: ${JSON.stringify(additionalInfo)}` : void 0;
79
- if (level == ERROR) {
80
- console.error("%s", logMessage);
81
- if (additionalInfo) {
82
- console.error("\n%s", additionalMessage);
83
- }
84
- } else if (level == WARN) {
85
- console.warn("%s", logMessage);
86
- if (additionalInfo) {
87
- console.warn("\n%s", additionalMessage);
88
- }
89
- } else if (level == DEBUG || level == VERBOSE) {
90
- console.log("%s", logMessage);
91
- if (additionalInfo) {
92
- console.log("\n%s", additionalMessage);
93
- }
94
- } else {
95
- console.log(logMessage);
96
- if (additionalInfo) {
97
- console.log(`
98
- ${additionalMessage}`);
99
- }
100
- }
101
- }
102
- }
103
- var stringifyError = (error) => {
104
- if (error instanceof import_diagnostics.DiagnosticsError) {
105
- return JSON.stringify({
106
- message: error.message,
107
- diagnostics: error.diagnostics,
108
- stack: error.stack
109
- });
110
- } else if (typeof error === "string" || error instanceof String) {
111
- return error;
112
- } else {
113
- const propertyNames = Object.getOwnPropertyNames(error);
114
- const retObj = {};
115
- for (let property, i = 0, len = propertyNames.length; i < len; ++i) {
116
- property = propertyNames[i];
117
- const descriptor = Object.getOwnPropertyDescriptor(error, property);
118
- retObj[property] = descriptor?.value;
119
- }
120
- return JSON.stringify(retObj);
121
- }
122
- };
123
- function gap(message) {
124
- return String(message)?.indexOf("[") === 0 ? "" : " ";
125
- }
126
- function logError(err, additionalInfo) {
127
- if (err instanceof import_diagnostics.DiagnosticsError || !err || !err.message) {
128
- log(ERROR, stringifyError(err), additionalInfo);
129
- }
130
- if (err && err.message) {
131
- console.error("%s", `[${ERROR}]${gap(err.message)}${err.message}`);
132
- console.error("%s", err);
133
- }
134
- }
135
- var logger = {
136
- verbose: (message, additionalInfo) => log(VERBOSE, message, additionalInfo),
137
- debug: (message, additionalInfo) => log(DEBUG, message, additionalInfo),
138
- info: (message, additionalInfo) => log(INFO, message, additionalInfo),
139
- warn: (message, additionalInfo) => log(WARN, message, additionalInfo),
140
- error: (error, additionalInfo) => logError(error, additionalInfo),
141
- log,
142
- setOptions: (opts) => {
143
- options = opts;
144
- },
145
- currentLevel
146
- };
@@ -1,23 +0,0 @@
1
- type LEVEL = 'verbose' | 'debug' | 'info' | 'warn' | 'error';
2
- export declare const VERBOSE: LEVEL;
3
- export declare const DEBUG: LEVEL;
4
- export declare const INFO: LEVEL;
5
- export declare const WARN: LEVEL;
6
- export declare const ERROR: LEVEL;
7
- type LoggerOptions = {
8
- dedupe?: Set<string>;
9
- };
10
- declare function log(level: string, message: string, additionalInfo?: any): void;
11
- export declare const stringifyError: (error: any) => string;
12
- export declare const logger: {
13
- verbose: (message: string, additionalInfo?: any) => void;
14
- debug: (message: string, additionalInfo?: any) => void;
15
- info: (message: string, additionalInfo?: any) => void;
16
- warn: (message: string, additionalInfo?: any) => void;
17
- error: (error: any, additionalInfo?: any) => void;
18
- log: typeof log;
19
- setOptions: (opts: LoggerOptions) => void;
20
- currentLevel: string;
21
- };
22
- export {};
23
- //# sourceMappingURL=logger.d.ts.map
@@ -1,124 +0,0 @@
1
- import { DiagnosticsError } from '@lwrjs/diagnostics';
2
- export const VERBOSE = 'verbose';
3
- export const DEBUG = 'debug';
4
- export const INFO = 'info';
5
- export const WARN = 'warn';
6
- export const ERROR = 'error';
7
- let options = {};
8
- const DUPES = new Set();
9
- let currentLevel = process.env.LOG_LEVEL || INFO;
10
- function log(level, message, additionalInfo) {
11
- const LOG_LEVEL = process.env.LOG_LEVEL || INFO;
12
- if (currentLevel !== LOG_LEVEL) {
13
- currentLevel = LOG_LEVEL;
14
- console.log(`LOG_LEVEL: ${LOG_LEVEL}`);
15
- }
16
- let shouldLog = false;
17
- switch (level) {
18
- case VERBOSE:
19
- shouldLog = LOG_LEVEL == VERBOSE;
20
- break;
21
- case DEBUG:
22
- shouldLog = LOG_LEVEL == VERBOSE || LOG_LEVEL == DEBUG;
23
- break;
24
- case INFO:
25
- shouldLog = LOG_LEVEL == VERBOSE || LOG_LEVEL == DEBUG || LOG_LEVEL == INFO;
26
- break;
27
- case WARN:
28
- shouldLog = LOG_LEVEL == VERBOSE || LOG_LEVEL == DEBUG || LOG_LEVEL == INFO || LOG_LEVEL == WARN;
29
- break;
30
- case ERROR:
31
- shouldLog = true;
32
- break;
33
- }
34
- // Check if we should suppress dupes and we have already logged this message
35
- if (shouldLog && options.dedupe && options.dedupe.has(level)) {
36
- const key = `[${level}] : ${message}`;
37
- if (DUPES.has(key)) {
38
- shouldLog = false;
39
- }
40
- else {
41
- // add key to de-duplicate cache
42
- DUPES.add(key);
43
- }
44
- }
45
- if (shouldLog) {
46
- const logMessage = `[${level}]${gap(message)}${message}`;
47
- const additionalMessage = additionalInfo
48
- ? `Additional Info: ${JSON.stringify(additionalInfo)}`
49
- : undefined;
50
- if (level == ERROR) {
51
- console.error('\x1b[31m%s\x1b[0m', logMessage); // red
52
- if (additionalInfo) {
53
- console.error('\n\x1b[31m%s\x1b[0m', additionalMessage); // red
54
- }
55
- }
56
- else if (level == WARN) {
57
- console.warn('\x1b[33m%s\x1b[0m', logMessage); // yellow
58
- if (additionalInfo) {
59
- console.warn('\n\x1b[33m%s\x1b[0m', additionalMessage); // yellow
60
- }
61
- }
62
- else if (level == DEBUG || level == VERBOSE) {
63
- console.log('\x1b[2m%s\x1b[0m', logMessage); // dim
64
- if (additionalInfo) {
65
- console.log('\n\x1b[2m%s\x1b[0m', additionalMessage); // dim
66
- }
67
- }
68
- else {
69
- console.log(logMessage);
70
- if (additionalInfo) {
71
- console.log(`\n${additionalMessage}`);
72
- }
73
- }
74
- }
75
- }
76
- export const stringifyError = (error) => {
77
- if (error instanceof DiagnosticsError) {
78
- return JSON.stringify({
79
- message: error.message,
80
- diagnostics: error.diagnostics,
81
- stack: error.stack,
82
- });
83
- }
84
- else if (typeof error === 'string' || error instanceof String) {
85
- return error;
86
- }
87
- else {
88
- const propertyNames = Object.getOwnPropertyNames(error);
89
- const retObj = {};
90
- for (let property, i = 0, len = propertyNames.length; i < len; ++i) {
91
- property = propertyNames[i];
92
- const descriptor = Object.getOwnPropertyDescriptor(error, property);
93
- retObj[property] = descriptor?.value;
94
- }
95
- return JSON.stringify(retObj);
96
- }
97
- };
98
- // Return a space if there should be a space between the message and the level
99
- function gap(message) {
100
- return String(message)?.indexOf('[') === 0 ? '' : ' ';
101
- }
102
- function logError(err, additionalInfo) {
103
- if (err instanceof DiagnosticsError || !err || !err.message) {
104
- log(ERROR, stringifyError(err), additionalInfo);
105
- }
106
- // If this is an error with a message update the message header and log as is...
107
- if (err && err.message) {
108
- console.error('\x1b[31m%s\x1b[0m', `[${ERROR}]${gap(err.message)}${err.message}`);
109
- console.error('\x1b[90m%s\x1b[0m', err);
110
- }
111
- }
112
- export const logger = {
113
- verbose: (message, additionalInfo) => log(VERBOSE, message, additionalInfo),
114
- debug: (message, additionalInfo) => log(DEBUG, message, additionalInfo),
115
- info: (message, additionalInfo) => log(INFO, message, additionalInfo),
116
- warn: (message, additionalInfo) => log(WARN, message, additionalInfo),
117
- error: (error, additionalInfo) => logError(error, additionalInfo),
118
- log,
119
- setOptions: (opts) => {
120
- options = opts;
121
- },
122
- currentLevel,
123
- };
124
- //# sourceMappingURL=logger.js.map