@lwrjs/shared-utils 0.9.0-alpha.3 → 0.9.0-alpha.30

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.
@@ -0,0 +1,15 @@
1
+ import type { CompilerResult, LwrLockerConfig, ModuleCompiled } from '@lwrjs/types';
2
+ /**
3
+ * When importing these modules make sure the optional dependencies are installed:
4
+ * - 'rollup' for convertToAmd()
5
+ * - '@locker/compiler' for lockerize()
6
+ */
7
+ export declare const AMD_DEFINE = "LWR.define";
8
+ export declare function convertToAmd(source: string, { id }: {
9
+ id: string;
10
+ }, forceNamedExports?: boolean): Promise<CompilerResult>;
11
+ /** Locker
12
+ * Trusted Components can contain namespaces with wildcard or single component
13
+ */
14
+ export declare function lockerize({ compiledSource: source, specifier, moduleEntry: { entry: filename } }: ModuleCompiled, { trustedComponents }: LwrLockerConfig, sourcemap?: boolean): CompilerResult;
15
+ //# sourceMappingURL=compiler.d.ts.map
@@ -0,0 +1,65 @@
1
+ import { explodeSpecifier } from './identity.js';
2
+ import { Compiler as Locker } from '@locker/compiler';
3
+ import { rollup } from 'rollup';
4
+ /**
5
+ * When importing these modules make sure the optional dependencies are installed:
6
+ * - 'rollup' for convertToAmd()
7
+ * - '@locker/compiler' for lockerize()
8
+ */
9
+ export const AMD_DEFINE = 'LWR.define';
10
+ const AMD_ROLLUP_PLUGIN = function (rootId, source) {
11
+ return {
12
+ name: 'lwr-amd-inline',
13
+ resolveId(id) {
14
+ return rootId === id ? id : undefined;
15
+ },
16
+ load(id) {
17
+ return rootId === id ? source : undefined;
18
+ },
19
+ };
20
+ };
21
+ export async function convertToAmd(source, { id }, forceNamedExports = true) {
22
+ const bundler = await rollup({
23
+ input: id,
24
+ plugins: [AMD_ROLLUP_PLUGIN(id, source)],
25
+ onwarn(warning, warn) {
26
+ // do not print out these: 'a' is imported by b, but could not be resolved – treating it as an external dependency
27
+ if (warning.code === 'UNRESOLVED_IMPORT')
28
+ return;
29
+ warn(warning);
30
+ },
31
+ });
32
+ const { output } = await bundler.generate({
33
+ amd: { id, define: AMD_DEFINE },
34
+ exports: forceNamedExports ? 'named' : 'auto',
35
+ format: 'amd',
36
+ });
37
+ const { code } = output[0];
38
+ return { code, map: null };
39
+ }
40
+ /** Locker
41
+ * Trusted Components can contain namespaces with wildcard or single component
42
+ */
43
+ export function lockerize({ compiledSource: source, specifier, moduleEntry: { entry: filename } }, { trustedComponents }, sourcemap = false) {
44
+ const { namespace, name: rawName } = explodeSpecifier(specifier);
45
+ const [name] = rawName.split('#');
46
+ const bareSpecifier = namespace ? `${namespace}/${name}` : name;
47
+ const isJS = filename.endsWith('.js') || filename.endsWith('.mjs') || filename.endsWith('.ts');
48
+ // lockerize if component is JS and is not explicitly trusted or in a trusted namespace
49
+ if (isJS &&
50
+ trustedComponents &&
51
+ !trustedComponents.includes(`${namespace}/*`) &&
52
+ !trustedComponents.includes(bareSpecifier)) {
53
+ const { code } = Locker.compile(source, {
54
+ componentName: name,
55
+ filename,
56
+ // put non-namespaced modules in a single sandbox - this should only be non-lwc npm modules
57
+ sandboxKey: namespace || 'sandbox',
58
+ sourcemap,
59
+ remapDynamicImport: true, // support for dynamic imports
60
+ });
61
+ return { code, map: null };
62
+ }
63
+ return { code: source, map: null };
64
+ }
65
+ //# sourceMappingURL=compiler.js.map
package/build/es/env.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { FeatureFlags } from '@lwrjs/types';
1
+ import type { FeatureFlags } from '@lwrjs/types';
2
2
  export declare function getFeatureFlags(): FeatureFlags;
3
3
  //# sourceMappingURL=env.d.ts.map
package/build/es/env.js CHANGED
@@ -1,17 +1,25 @@
1
1
  export function getFeatureFlags() {
2
- let legacyLoader = process.env.LEGACY_LOADER !== undefined && process.env.LEGACY_LOADER === 'true' ? true : false;
3
- try {
4
- // Use the Shim for MRT since we don't have access to managing environment variables
5
- if (LWR) {
6
- legacyLoader = LWR.LEGACY_LOADER;
7
- }
8
- }
9
- catch (e) {
10
- // No shim, ignore error
11
- }
2
+ // Add any new feature flags here to parse from environment variables
12
3
  return {
13
4
  // DEFAULT LEGACY_LOADER = false;
14
- LEGACY_LOADER: legacyLoader,
5
+ LEGACY_LOADER: process.env.LEGACY_LOADER !== undefined && process.env.LEGACY_LOADER.toLowerCase() === 'true'
6
+ ? true
7
+ : false,
8
+ // SSR should concatenate bundles, default = false
9
+ SSR_STATIC_BUNDLES: process.env.SSR_STATIC_BUNDLES !== undefined &&
10
+ process.env.SSR_STATIC_BUNDLES.toLowerCase() === 'true'
11
+ ? true
12
+ : false,
13
+ // Should we use a js worker for SSR, sand-boxing = false (use locker for ssr sand-boxing)
14
+ SSR_SANDBOX_WORKER: process.env.SSR_SANDBOX_WORKER !== undefined &&
15
+ process.env.SSR_SANDBOX_WORKER.toLowerCase() === 'true'
16
+ ? true
17
+ : false,
18
+ // Should we load load the assets from the lambda on MRT
19
+ ASSETS_ON_LAMBDA: process.env.ASSETS_ON_LAMBDA !== undefined &&
20
+ process.env.ASSETS_ON_LAMBDA.toLowerCase() === 'true'
21
+ ? true
22
+ : false,
15
23
  };
16
24
  }
17
25
  //# sourceMappingURL=env.js.map
@@ -0,0 +1,17 @@
1
+ import type { Watcher, WatcherFactory, WatchOptions } from '@lwrjs/types';
2
+ /**
3
+ * Factory comptable with the LWR Runtime to create a file watch library for LWR dev server.
4
+ * When importing this module make sure the optional library 'chokidar' is installed.
5
+ */
6
+ export declare class WatcherFactoryImpl implements WatcherFactory {
7
+ /**
8
+ * Set up a watcher with the given options
9
+ * @param options
10
+ */
11
+ createFileWatcher(options?: WatchOptions): Watcher;
12
+ /**
13
+ * Set up file watcher
14
+ */
15
+ setupWatcher(onModuleChange: Function): Watcher;
16
+ }
17
+ //# sourceMappingURL=fs-watch.d.ts.map
@@ -0,0 +1,27 @@
1
+ import chokidar from 'chokidar';
2
+ import { debounce } from './object.js';
3
+ import { logger } from './logger.js';
4
+ /**
5
+ * Factory comptable with the LWR Runtime to create a file watch library for LWR dev server.
6
+ * When importing this module make sure the optional library 'chokidar' is installed.
7
+ */
8
+ export class WatcherFactoryImpl {
9
+ /**
10
+ * Set up a watcher with the given options
11
+ * @param options
12
+ */
13
+ createFileWatcher(options = { persistent: true, ignored: '**/node_modules/**' }) {
14
+ return chokidar.watch([], options);
15
+ }
16
+ /**
17
+ * Set up file watcher
18
+ */
19
+ setupWatcher(onModuleChange) {
20
+ const fileWatcher = this.createFileWatcher();
21
+ fileWatcher.on('change', debounce((file) => onModuleChange(file), 500));
22
+ fileWatcher.on('unlink', debounce((file) => onModuleChange(file), 500));
23
+ fileWatcher.on('add', (file) => logger.info(`Watching: ${file}`));
24
+ return fileWatcher;
25
+ }
26
+ }
27
+ //# sourceMappingURL=fs-watch.js.map
package/build/es/fs.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import { ResourcePaths, Watcher, ViewSource } from '@lwrjs/types';
2
+ import type { AssetIdentifier, ResourcePaths, ViewSource } from '@lwrjs/types';
3
3
  import { lookup } from 'mime-types';
4
4
  /**
5
5
  * Create a hash string for a source
@@ -16,15 +16,6 @@ export declare function readFile(filePath: string): string;
16
16
  * @param filePath
17
17
  */
18
18
  export declare function resolveFileExtension(filePath: string): string;
19
- /**
20
- * Set up a watcher with the given options
21
- * @param options
22
- */
23
- export declare function createFileWatcher(options?: any): Watcher;
24
- /**
25
- * Set up file watcher
26
- */
27
- export declare function setupWatcher(onModuleChange: Function): Watcher;
28
19
  /**
29
20
  * Returns if view of specific type can be resolved
30
21
  *
@@ -41,4 +32,8 @@ export declare function getViewSourceFromFile(source: string): ViewSource;
41
32
  export declare function normalizeDirectory(dir: string, rootDir: string): string;
42
33
  export declare function normalizeResourcePath(rawPath: string, { rootDir, assets, contentDir, layoutsDir }: ResourcePaths, allowUnresolvedAlias?: boolean): string;
43
34
  export { lookup as mimeLookup };
35
+ /**
36
+ * Tries to convert any URL or $aliased path into a canonical fs path
37
+ */
38
+ export declare function normalizeAssetSpecifier(assetId: AssetIdentifier, assetPathMap: Map<string, string>, resourcePaths: ResourcePaths, basePath: string): string;
44
39
  //# sourceMappingURL=fs.d.ts.map
package/build/es/fs.js CHANGED
@@ -2,8 +2,6 @@ import fs from 'fs';
2
2
  import pathLib from 'path';
3
3
  import crypto from 'crypto';
4
4
  import { slugify } from './identity.js';
5
- import { debounce } from './object.js';
6
- import chokidar from 'chokidar';
7
5
  import { LwrUnresolvableError, createSingleDiagnosticError, descriptions } from '@lwrjs/diagnostics';
8
6
  import { lookup } from 'mime-types';
9
7
  import { DEBUG, logger, VERBOSE } from './logger.js';
@@ -38,10 +36,10 @@ export function resolveFileExtension(filePath) {
38
36
  // No extension, if it exist, it can be a dir or a file
39
37
  if (fs.existsSync(filePath)) {
40
38
  if (fs.statSync(filePath).isFile()) {
41
- return filePath; // extensionless file, which is odd but...
39
+ return filePath; // extension-less file, which is odd but...
42
40
  }
43
41
  else {
44
- filePath = pathLib.join(filePath, 'index'); // if is a dir we will be tesing the extensions
42
+ filePath = pathLib.join(filePath, 'index'); // if is a dir we will be testing the extensions
45
43
  }
46
44
  }
47
45
  // At this point we have a file with no extension so we try for the default (js,ts) or fail
@@ -55,25 +53,6 @@ export function resolveFileExtension(filePath) {
55
53
  throw new Error(`Unable to find file "${filePath}"`);
56
54
  }
57
55
  }
58
- /**
59
- * Set up a watcher with the given options
60
- * @param options
61
- */
62
- export function createFileWatcher(
63
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
64
- options = { persistent: true, ignored: '**/node_modules/**' }) {
65
- return chokidar.watch([], options);
66
- }
67
- /**
68
- * Set up file watcher
69
- */
70
- export function setupWatcher(onModuleChange) {
71
- const fileWatcher = createFileWatcher();
72
- fileWatcher.on('change', debounce((file) => onModuleChange(file), 500));
73
- fileWatcher.on('unlink', debounce((file) => onModuleChange(file), 500));
74
- fileWatcher.on('add', (file) => logger.info(`Watching: ${file}`));
75
- return fileWatcher;
76
- }
77
56
  /**
78
57
  * Returns if view of specific type can be resolved
79
58
  *
@@ -153,4 +132,35 @@ function logMetrics(filePath) {
153
132
  }
154
133
  }
155
134
  }
135
+ /**
136
+ * Tries to convert any URL or $aliased path into a canonical fs path
137
+ */
138
+ export function normalizeAssetSpecifier(assetId, assetPathMap, resourcePaths, basePath) {
139
+ const { specifier, importer, type } = assetId;
140
+ if (specifier.startsWith('./') || specifier.startsWith('../')) {
141
+ if (!importer) {
142
+ throw Error(`Unable to resolve relative import "${specifier}" without an importer.`);
143
+ }
144
+ return pathLib.join(pathLib.dirname(importer), specifier);
145
+ }
146
+ if (type === 'content-asset') {
147
+ const originSpecifier = !basePath ? specifier : specifier.split(basePath)[1];
148
+ return pathLib.join(resourcePaths.contentDir, originSpecifier);
149
+ }
150
+ if (specifier[0] === '$') {
151
+ // This is a fs path containing an asset alias
152
+ return normalizeResourcePath(specifier, resourcePaths);
153
+ }
154
+ // This is an absolute path to the server
155
+ // Match in 2 ways:
156
+ // - Directories: the prefix of the asset specifier/path matches a configured assets[i].urlPath
157
+ // - Individual files: the asset specifier is equal to a configured assets[i].urlPath
158
+ for (const [urlPath, fsPath] of assetPathMap.entries()) {
159
+ const slashPath = urlPath.endsWith('/') ? urlPath : `${urlPath}/`;
160
+ if (specifier.startsWith(slashPath) || specifier === urlPath) {
161
+ return specifier.replace(urlPath, fsPath);
162
+ }
163
+ }
164
+ return specifier;
165
+ }
156
166
  //# sourceMappingURL=fs.js.map
@@ -1,9 +1,10 @@
1
- import { ModuleRegistry, RuntimeEnvironment, RuntimeParams, FlattenedModuleGraphs, GraphNode, GraphOptions, ModuleBundler } from '@lwrjs/types';
1
+ import type { ModuleRegistry, RuntimeEnvironment, RuntimeParams, FlattenedModuleGraphs, GraphNode, GraphOptions, ModuleBundler, PublicModuleRegistry, PublicModuleBundler } from '@lwrjs/types';
2
2
  export declare enum GraphDepth {
3
3
  ALL = "all",
4
4
  DIRECT = "direct",
5
5
  NONE = "none"
6
6
  }
7
+ export declare function isBundler(registry: PublicModuleRegistry | PublicModuleBundler): registry is PublicModuleBundler;
7
8
  export declare function getModuleGraphs(specifier: string, // version | un-versioned specifiers
8
9
  options: GraphOptions, moduleRegistry: ModuleRegistry, defRegistry: ModuleRegistry | ModuleBundler, runtimeEnvironment: RuntimeEnvironment, runtimeParams?: RuntimeParams, visited?: Map<string, GraphNode>): Promise<FlattenedModuleGraphs>;
9
10
  //# sourceMappingURL=graph.d.ts.map
package/build/es/graph.js CHANGED
@@ -8,7 +8,7 @@ export var GraphDepth;
8
8
  GraphDepth["NONE"] = "none";
9
9
  })(GraphDepth || (GraphDepth = {}));
10
10
  // type guard for ViewDef responses
11
- function isBundler(registry) {
11
+ export function isBundler(registry) {
12
12
  return registry.getModuleBundle !== undefined;
13
13
  }
14
14
  async function traverse(module, depth, flattened,
@@ -94,7 +94,7 @@ defRegistry, runtimeEnvironment, runtimeParams) {
94
94
  }
95
95
  async function flatten(versionedSpecifier, flattened, idx, visited) {
96
96
  const node = visited.get(versionedSpecifier);
97
- if (node) {
97
+ if (flattened[idx]?.static && node?.static) {
98
98
  node.static.forEach(async (imp) => {
99
99
  if (!flattened[idx].static.includes(imp)) {
100
100
  flattened[idx].static.push(imp);
@@ -129,7 +129,7 @@ options, moduleRegistry, defRegistry, runtimeEnvironment, runtimeParams, visited
129
129
  // eslint-disable-next-line no-await-in-loop
130
130
  const moduleId = await getVersionedModuleId(visitedSpecifier, moduleRegistry);
131
131
  // eslint-disable-next-line no-await-in-loop
132
- const uri = await moduleRegistry.resolveModuleUri(moduleId, runtimeEnvironment, runtimeParams);
132
+ const uri = await defRegistry.resolveModuleUri(moduleId, runtimeEnvironment, runtimeParams);
133
133
  uriMap[visitedSpecifier] = uri;
134
134
  }
135
135
  }
@@ -1,5 +1,5 @@
1
1
  import getCacheKeyFromJson from 'fast-json-stable-stringify';
2
- import { AbstractModuleId, AssetIdentity, BundleDefinition, MappingIdentity, MiddlewareRequest, ModuleDefinition, ModuleId, ModuleIdentity, PublicModuleRegistry, ResourceIdentity, RuntimeEnvironment, RuntimeParams } from '@lwrjs/types';
2
+ import { AbstractModuleId, AssetSource, BundleDefinition, ModuleDefinition, NormalizedLwrAppBootstrapConfig, PublicModuleRegistry, RuntimeEnvironment, RuntimeParams } from '@lwrjs/types';
3
3
  export declare const VERSION_SIGIL = "/v/";
4
4
  export declare const LOCALE_SIGIL = "l";
5
5
  export declare const ENVIRONMENT_SIGIL = "e";
@@ -13,14 +13,7 @@ export declare const DEFAULT_LWR_LOCKER_CONFIG: {
13
13
  enabled: boolean;
14
14
  trustedComponents: string[];
15
15
  };
16
- export declare const DEFAULT_LWR_BOOTSTRAP_CONFIG: {
17
- autoBoot: boolean;
18
- syntheticShadow: boolean;
19
- workers: {};
20
- services: never[];
21
- configAsSrc: boolean;
22
- ssr: boolean;
23
- };
16
+ export declare const DEFAULT_LWR_BOOTSTRAP_CONFIG: NormalizedLwrAppBootstrapConfig;
24
17
  declare type ModuleIdentifierPartial = Partial<AbstractModuleId>;
25
18
  /**
26
19
  * Turn the dots in a version into underscores
@@ -64,29 +57,9 @@ export declare function explodeSpecifiers(rawSpecifiers: string): PartialModuleI
64
57
  * @example - { namespace: '@salesforce', name: 'label/my.label', version: '1' } => '@salesforce/label/my.label/v/1'
65
58
  */
66
59
  export declare function getSpecifier({ specifier, namespace, name, version }: ModuleIdentifierPartial): string;
67
- /**
68
- * Create a versioned specifier based on the module registry
69
- *
70
- * @remarks
71
- * If the incoming specifier is already versioned, it will be returned as is.
72
- *
73
- * The returned specifier's version conforms to the format expected to be used
74
- * external to the framework (e.g. via the identity in the URL, mapping metadata,
75
- * AMD define module name). This format conforms to the `normalizeVersionToUri`
76
- * implementation (e.g. version semver format -- major_minor_patch).
77
- *
78
- * This method is analogous to `getSpecifier` but supports non-versioned `rawSpecifiers`
79
- * The inverse of this method is `explodeSpecifier`
80
-
81
- * @param specifier - the module specifier
82
- * @param moduleRegistry - the public module registry
83
- *
84
- * @returns the specifier for the latest version
85
- *
86
- * @example - 'c/form' => 'c/form/v/0_0_1'
87
- * @example - 'c/form/v/0.0.2' => 'c/form/v/0_0_2'
88
- */
89
- export declare function getVersionedSpecifier(rawSpecifier: string, moduleRegistry: PublicModuleRegistry): Promise<string>;
60
+ interface VersionedAbstractModuleId extends AbstractModuleId {
61
+ version: string;
62
+ }
90
63
  /**
91
64
  * Create a AbstractModuleId using the module registry to resolve the version
92
65
  * if a version is not provided in the `rawSpecifier`
@@ -107,7 +80,7 @@ export declare function getVersionedSpecifier(rawSpecifier: string, moduleRegist
107
80
  * @example - 'c/form/v/0.0.2' => {specifier: "c/form", version: "0.0.2"}
108
81
  * @example - 'c/form/v/0_0_2' => {specifier: "c/form", version: "0.0.2"}
109
82
  */
110
- export declare function getVersionedModuleId(rawSpecifier: string, moduleRegistry: PublicModuleRegistry): Promise<Required<Pick<ModuleId, 'specifier' | 'version'>>>;
83
+ export declare function getVersionedModuleId(rawSpecifier: string, moduleRegistry: PublicModuleRegistry): Promise<VersionedAbstractModuleId>;
111
84
  interface PackageIdentity {
112
85
  scope?: string;
113
86
  packageName: string;
@@ -131,9 +104,9 @@ export declare function parsePackageSpecifier(specifier: string): PackageIdentit
131
104
  * @param name A string in kebab case
132
105
  * @example - 'name-of-something' => 'name/ofSomething'
133
106
  */
134
- export declare function kebabCaseToModuleSpecifer(name: string): string;
107
+ export declare function kebabCaseToModuleSpecifier(name: string): string;
135
108
  /**
136
- * Clone of lwr/init, reverse of kebabCaseToModuleSpecifer, strips off versions
109
+ * Clone of lwr/init, reverse of kebabCaseToModuleSpecifier, strips off versions
137
110
  * @param specifier
138
111
  * @example - 'name/ofSomething/v/1.0.0' => 'name-of-something'
139
112
  */
@@ -164,9 +137,6 @@ export declare function getModuleUriPrefix({ apiVersion, bundle, format, compat,
164
137
  export declare function getMappingUriPrefix({ apiVersion, bundle, format, compat, basePath }: RuntimeEnvironment, { locale, environment }?: RuntimeParams): string;
165
138
  export { getCacheKeyFromJson };
166
139
  export declare function isExternalUrl(url: string): boolean;
140
+ export declare function isAssetSourceExternal(assetSource: AssetSource): boolean;
167
141
  export declare function isBundleDefinition(definition: ModuleDefinition | BundleDefinition): definition is BundleDefinition;
168
- export declare function getModuleIdentity(req: MiddlewareRequest): ModuleIdentity;
169
- export declare function getMappingIdentity(req: MiddlewareRequest): MappingIdentity;
170
- export declare function getResourceIdentity(req: MiddlewareRequest): ResourceIdentity;
171
- export declare function getAssetIdentity(req: MiddlewareRequest): AssetIdentity;
172
142
  //# sourceMappingURL=identity.d.ts.map
@@ -21,6 +21,8 @@ export const DEFAULT_LWR_BOOTSTRAP_CONFIG = {
21
21
  services: [],
22
22
  configAsSrc: false,
23
23
  ssr: false,
24
+ module: undefined,
25
+ preloadModules: [],
24
26
  };
25
27
  /**
26
28
  * Turn the dots in a version into underscores
@@ -96,37 +98,6 @@ export function getSpecifier({ specifier, namespace, name = '', version }) {
96
98
  const bareSpecifier = namespace ? `${namespace}/${name}` : name;
97
99
  return version ? `${bareSpecifier}${VERSION_SIGIL}${normalizeVersionToUri(version)}` : bareSpecifier;
98
100
  }
99
- /**
100
- * Create a versioned specifier based on the module registry
101
- *
102
- * @remarks
103
- * If the incoming specifier is already versioned, it will be returned as is.
104
- *
105
- * The returned specifier's version conforms to the format expected to be used
106
- * external to the framework (e.g. via the identity in the URL, mapping metadata,
107
- * AMD define module name). This format conforms to the `normalizeVersionToUri`
108
- * implementation (e.g. version semver format -- major_minor_patch).
109
- *
110
- * This method is analogous to `getSpecifier` but supports non-versioned `rawSpecifiers`
111
- * The inverse of this method is `explodeSpecifier`
112
-
113
- * @param specifier - the module specifier
114
- * @param moduleRegistry - the public module registry
115
- *
116
- * @returns the specifier for the latest version
117
- *
118
- * @example - 'c/form' => 'c/form/v/0_0_1'
119
- * @example - 'c/form/v/0.0.2' => 'c/form/v/0_0_2'
120
- */
121
- export async function getVersionedSpecifier(rawSpecifier, moduleRegistry) {
122
- const { specifier, namespace, name, version } = explodeSpecifier(rawSpecifier);
123
- if (version) {
124
- return normalizeVersionToUri(rawSpecifier);
125
- }
126
- // Get version from Module Registry
127
- const moduleEntry = await moduleRegistry.getModuleEntry({ specifier });
128
- return getSpecifier({ namespace, name, version: normalizeVersionToUri(moduleEntry.version) });
129
- }
130
101
  /**
131
102
  * Create a AbstractModuleId using the module registry to resolve the version
132
103
  * if a version is not provided in the `rawSpecifier`
@@ -148,13 +119,13 @@ export async function getVersionedSpecifier(rawSpecifier, moduleRegistry) {
148
119
  * @example - 'c/form/v/0_0_2' => {specifier: "c/form", version: "0.0.2"}
149
120
  */
150
121
  export async function getVersionedModuleId(rawSpecifier, moduleRegistry) {
151
- const { specifier, version } = explodeSpecifier(rawSpecifier);
152
- if (version) {
153
- return { specifier, version: normalizeVersionFromUri(version) };
122
+ const moduleId = explodeSpecifier(rawSpecifier);
123
+ if (moduleId.version) {
124
+ return { ...moduleId, version: normalizeVersionFromUri(moduleId.version) };
154
125
  }
155
126
  // Get version from Module Registry
156
- const moduleEntry = await moduleRegistry.getModuleEntry({ specifier });
157
- return { specifier, version: moduleEntry.version };
127
+ const moduleEntry = await moduleRegistry.getModuleEntry(moduleId);
128
+ return { ...moduleId, version: moduleEntry.version };
158
129
  }
159
130
  const RE_SCOPED = /^(@[^/]+\/[^/@]+)(?:\/([^@]+))?(?:@([\s\S]+))?/;
160
131
  const RE_NORMAL = /^([^/@]+)(?:\/([^@]+))?(?:@([\s\S]+))?/;
@@ -194,7 +165,7 @@ export function parsePackageSpecifier(specifier) {
194
165
  * @param name A string in kebab case
195
166
  * @example - 'name-of-something' => 'name/ofSomething'
196
167
  */
197
- export function kebabCaseToModuleSpecifer(name) {
168
+ export function kebabCaseToModuleSpecifier(name) {
198
169
  const newName = [];
199
170
  let nsFound = false;
200
171
  let upper = false;
@@ -216,7 +187,7 @@ export function kebabCaseToModuleSpecifer(name) {
216
187
  return newName.join('');
217
188
  }
218
189
  /**
219
- * Clone of lwr/init, reverse of kebabCaseToModuleSpecifer, strips off versions
190
+ * Clone of lwr/init, reverse of kebabCaseToModuleSpecifier, strips off versions
220
191
  * @param specifier
221
192
  * @example - 'name/ofSomething/v/1.0.0' => 'name-of-something'
222
193
  */
@@ -275,57 +246,11 @@ const REGEX_URL_SCHEMA_PREFIX = /^(https?|\/\/)/;
275
246
  export function isExternalUrl(url) {
276
247
  return REGEX_URL_SCHEMA_PREFIX.test(url);
277
248
  }
249
+ export function isAssetSourceExternal(assetSource) {
250
+ return assetSource.type === 'external' || (!!assetSource.uri && isExternalUrl(assetSource.uri));
251
+ }
278
252
  // type guard for ViewDef responses
279
253
  export function isBundleDefinition(definition) {
280
254
  return definition.bundleRecord !== undefined;
281
255
  }
282
- function validateSpecifier(specifer) {
283
- return specifer.indexOf('../') < 0;
284
- }
285
- export function getModuleIdentity(req) {
286
- const { specifier, signature = LATEST_SIGNATURE } = req.params;
287
- if (validateSpecifier(specifier) === false) {
288
- throw new Error('dot-dot-slash is not allowed for module specifier');
289
- }
290
- const moduleId = explodeSpecifier(specifier);
291
- return {
292
- moduleId,
293
- signature,
294
- };
295
- }
296
- export function getMappingIdentity(req) {
297
- const { specifiers } = req.params;
298
- const moduleIds = explodeSpecifiers(specifiers).map((obj) => ({
299
- ...obj,
300
- importer: req.query.importer,
301
- }));
302
- return {
303
- moduleIds,
304
- };
305
- }
306
- export function getResourceIdentity(req) {
307
- const { specifier, signature = LATEST_SIGNATURE } = req.params;
308
- if (validateSpecifier(specifier) === false) {
309
- throw new Error('dot-dot-slash is not allowed for resource specifier');
310
- }
311
- const resourceId = explodeSpecifier(specifier);
312
- return {
313
- resourceId,
314
- signature,
315
- };
316
- }
317
- export function getAssetIdentity(req) {
318
- const { signature = LATEST_SIGNATURE, assetType: type } = req.params;
319
- const [specifier] = req.originalUrl.split('?');
320
- if (validateSpecifier(specifier) === false) {
321
- throw new Error('dot-dot-slash is not allowed for asset specifier');
322
- }
323
- return {
324
- assetId: {
325
- specifier,
326
- type,
327
- },
328
- signature,
329
- };
330
- }
331
256
  //# sourceMappingURL=identity.js.map
@@ -6,7 +6,6 @@ export * from './link.js';
6
6
  export * from './object.js';
7
7
  export * from './serialize.js';
8
8
  export * from './tasks.js';
9
- export * from './typescript.js';
10
9
  export * from './import-metadata.js';
11
10
  export * from './graph.js';
12
11
  export * from './mappings.js';
@@ -14,4 +13,5 @@ export * from './urls.js';
14
13
  export * from './env.js';
15
14
  export * from './logger.js';
16
15
  export * from './lwr-app-observer.js';
16
+ export * from './site-metadata.js';
17
17
  //# sourceMappingURL=index.d.ts.map
package/build/es/index.js CHANGED
@@ -6,7 +6,6 @@ export * from './link.js';
6
6
  export * from './object.js';
7
7
  export * from './serialize.js';
8
8
  export * from './tasks.js';
9
- export * from './typescript.js';
10
9
  export * from './import-metadata.js';
11
10
  export * from './graph.js';
12
11
  export * from './mappings.js';
@@ -14,4 +13,5 @@ export * from './urls.js';
14
13
  export * from './env.js';
15
14
  export * from './logger.js';
16
15
  export * from './lwr-app-observer.js';
16
+ export * from './site-metadata.js';
17
17
  //# sourceMappingURL=index.js.map
@@ -11,7 +11,7 @@ import { InterchangeableModuleRecord, LwcConfig, ResolverModuleRecord, Interchan
11
11
  * @returns {map} a map of all possible interchangeable modules
12
12
  *
13
13
  */
14
- export declare function discoverInterchangeableModules(modules: ResolverModuleRecord[], interchangeableModules?: InterchangeableModuleMap): InterchangeableModuleMap;
14
+ export declare function discoverInterchangeableModules(modules: ResolverModuleRecord[], interchangeableModules?: InterchangeableModuleMap, visitedModules?: Set<string>): InterchangeableModuleMap;
15
15
  /**
16
16
  * Locate the LWC config for the package and resolve custom properties
17
17
  *
@@ -24,10 +24,13 @@ function isNpmModuleRecord(module) {
24
24
  * @returns {map} a map of all possible interchangeable modules
25
25
  *
26
26
  */
27
- export function discoverInterchangeableModules(modules, interchangeableModules) {
27
+ export function discoverInterchangeableModules(modules, interchangeableModules, visitedModules) {
28
28
  if (!interchangeableModules) {
29
29
  interchangeableModules = new Map();
30
30
  }
31
+ if (!visitedModules) {
32
+ visitedModules = new Set();
33
+ }
31
34
  if (modules.length === 0) {
32
35
  return interchangeableModules;
33
36
  }
@@ -37,6 +40,10 @@ export function discoverInterchangeableModules(modules, interchangeableModules)
37
40
  if (!isNpmModuleRecord(module)) {
38
41
  continue;
39
42
  }
43
+ if (visitedModules?.has(module.npm)) {
44
+ continue;
45
+ }
46
+ visitedModules.add(module.npm);
40
47
  // resolve module path and package.json
41
48
  const packageJsonPath = resolve.sync(`${module.npm}/package.json`);
42
49
  const packageJson = JSON.parse(readFile(packageJsonPath));
@@ -55,7 +62,7 @@ export function discoverInterchangeableModules(modules, interchangeableModules)
55
62
  interchangeableModules = normalizeInterchangeableModuleConfig(lwcConfig.interchangeableModules, interchangeableModules);
56
63
  }
57
64
  }
58
- return discoverInterchangeableModules(nestedModules, interchangeableModules);
65
+ return discoverInterchangeableModules(nestedModules, interchangeableModules, visitedModules);
59
66
  }
60
67
  /**
61
68
  * Locate the LWC config for the package and resolve custom properties