@lwrjs/app-service
Advanced tools
Comparing version 0.0.2-alpha30 to 0.0.2-alpha31
@@ -1,2 +0,2 @@ | ||
import { ModuleFormat } from '@lwrjs/types'; | ||
import { ModuleFormat, NormalizedLwrRoute, PublicViewRegistry } from '@lwrjs/types'; | ||
export declare const APP_BOOTSTRAP_PACKAGE_NAME = "@lwrjs/app-service"; | ||
@@ -31,4 +31,4 @@ export declare const SUPPORTED_MODULE_FORMATS: string[]; | ||
export declare function getAppSpecifer(appIdentity: AppResourceId): string; | ||
export declare function isValidFormat(format: string): format is ModuleFormat; | ||
export declare function isValidResourceType(resourceType: string): resourceType is AppResourceType; | ||
export declare function getRootComponents({ subResource }: AppResourceIdentity, route: NormalizedLwrRoute, viewRegistry: PublicViewRegistry): Promise<string[]>; | ||
export declare function isValidResourceIdentity(appIdentity: AppResourceIdentity, resourceType: string): boolean; | ||
//# sourceMappingURL=identity.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.isValidResourceType = exports.isValidFormat = exports.getAppSpecifer = exports.parseAppIdentity = exports.AppResourceEnum = exports.SUPPORTED_MODULE_FORMATS = exports.APP_BOOTSTRAP_PACKAGE_NAME = void 0; | ||
exports.isValidResourceIdentity = exports.getRootComponents = exports.getAppSpecifer = exports.parseAppIdentity = exports.AppResourceEnum = exports.SUPPORTED_MODULE_FORMATS = exports.APP_BOOTSTRAP_PACKAGE_NAME = void 0; | ||
const shared_utils_1 = require("@lwrjs/shared-utils"); | ||
@@ -119,3 +119,3 @@ /* | ||
} | ||
else if (/^(config|mapping|json|module)/.test(appResource)) { | ||
else if (/^(config|mapping|json|module)/.test(appResourceId)) { | ||
// app = {id: "app", name: "app"} | ||
@@ -143,2 +143,21 @@ return { | ||
} | ||
// Return an array of all root components on the page | ||
async function getRootComponents({ subResource }, route, viewRegistry) { | ||
// Pull the custom element root components from the View Registry | ||
const requestPath = subResource ? subResource.requestPath : '/'; | ||
const { customElements } = await viewRegistry.getRenderedViewMetadata({ | ||
...route, | ||
requestPath, | ||
}, {}); | ||
// Convert all module names to be HTML friendly | ||
const rootComponents = customElements.map(shared_utils_1.kebabcaseToCamelcase); | ||
// If the root SPA component is not included in the root module array, add it | ||
// This happens when the 'lwr-root' HTML property is used for root insertion (see init.ts) | ||
const { rootComponent } = route; | ||
if (rootComponent && !rootComponents.includes(rootComponent)) { | ||
rootComponents.unshift(rootComponent); | ||
} | ||
return rootComponents; | ||
} | ||
exports.getRootComponents = getRootComponents; | ||
/* validation methods */ | ||
@@ -149,3 +168,2 @@ function isValidFormat(format) { | ||
} | ||
exports.isValidFormat = isValidFormat; | ||
function isValidResourceType(resourceType) { | ||
@@ -158,3 +176,9 @@ return (resourceType !== undefined && | ||
} | ||
exports.isValidResourceType = isValidResourceType; | ||
function isValidResourceIdentity(appIdentity, resourceType) { | ||
return (appIdentity.packageName === exports.APP_BOOTSTRAP_PACKAGE_NAME && | ||
isValidResourceType(resourceType) && | ||
appIdentity.resourceType === resourceType && | ||
isValidFormat(appIdentity.format)); | ||
} | ||
exports.isValidResourceIdentity = isValidResourceIdentity; | ||
//# sourceMappingURL=identity.js.map |
@@ -9,4 +9,5 @@ import { BootstrapRuntimeEnvironment, ProviderContext, ResourceDefinition, ResourceIdentifier, ResourceProvider } from '@lwrjs/types'; | ||
name: string; | ||
private appConfig; | ||
private registry; | ||
private routesConfig; | ||
private moduleRegistry; | ||
private viewRegistry; | ||
constructor(providerContext: ProviderContext); | ||
@@ -13,0 +14,0 @@ getResource<T extends ResourceIdentifier>({ specifier }: T, environment: BootstrapRuntimeEnvironment): Promise<ResourceDefinition | undefined>; |
@@ -5,11 +5,2 @@ "use strict"; | ||
const identity_1 = require("../identity"); | ||
// Validation gating methods | ||
function isValidMappingIdentity(appIdentity) { | ||
if (appIdentity.packageName === identity_1.APP_BOOTSTRAP_PACKAGE_NAME && | ||
appIdentity.resourceType === identity_1.AppResourceEnum.MAPPING && | ||
identity_1.SUPPORTED_MODULE_FORMATS.includes(appIdentity.format)) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
/** | ||
@@ -24,12 +15,13 @@ * The Mapping Resource Provider | ||
// LWR framework references | ||
this.appConfig = providerContext.config.application; | ||
this.registry = providerContext.moduleRegistry; | ||
this.routesConfig = providerContext.config.routes; | ||
this.moduleRegistry = providerContext.moduleRegistry; | ||
this.viewRegistry = providerContext.viewRegistry; | ||
} | ||
// Get a JSON mapping resource | ||
async getResource({ specifier }, environment) { | ||
const { name: configuredAppName, root: appRoot } = this.appConfig; | ||
// Check for a valid App ID and corresponding route config object | ||
const appIdentity = identity_1.parseAppIdentity(specifier); | ||
if (!appIdentity || | ||
!isValidMappingIdentity(appIdentity) || | ||
appIdentity.appName !== configuredAppName) { | ||
const route = this.routesConfig.find((r) => r.id === appIdentity?.appName); | ||
// Reject the request if there is no matching route (from config) | ||
if (!appIdentity || !route || !identity_1.isValidResourceIdentity(appIdentity, identity_1.AppResourceEnum.MAPPING)) { | ||
return; | ||
@@ -39,9 +31,9 @@ } | ||
const bootstrapImports = environment.bootstrapImports || [ | ||
identity_1.getAppSpecifer({ ...appIdentity, resourceType: identity_1.AppResourceEnum.MAPPING }), | ||
identity_1.getAppSpecifer({ ...appIdentity, resourceType: identity_1.AppResourceEnum.MODULE }), | ||
]; | ||
const rootComponents = await identity_1.getRootComponents(appIdentity, route, this.viewRegistry); | ||
const content = await utils_1.createJsonSource( | ||
// The import metadata crawls the dependencies of | ||
// the root app component and the app bootstrap module | ||
// TODO240: Crawl dependencies of ALL root modules from requestPath | ||
[appRoot, ...bootstrapImports], environment, this.registry); | ||
// the root app component(s) and the app bootstrap module | ||
[...rootComponents, ...bootstrapImports], environment, this.moduleRegistry); | ||
return { | ||
@@ -48,0 +40,0 @@ specifier, |
@@ -1,11 +0,10 @@ | ||
import { ModuleCompiled, ModuleEntry, ModuleProvider, ModuleSource, NormalizedLwrApplicationConfig, ProviderContext, PublicViewRegistry, AbstractModuleId } from '@lwrjs/types'; | ||
export default class AppService implements ModuleProvider { | ||
import { ModuleCompiled, ModuleEntry, ModuleProvider, ModuleSource, NormalizedLwrRoute, ProviderContext, AbstractModuleId } from '@lwrjs/types'; | ||
export default class AppModuleProvider implements ModuleProvider { | ||
name: string; | ||
version: string; | ||
appContext: NormalizedLwrApplicationConfig; | ||
viewRegistry: PublicViewRegistry; | ||
routesConfig: NormalizedLwrRoute[]; | ||
private viewRegistry; | ||
private compiler; | ||
private moduleRegistry; | ||
private hmrEnabled; | ||
constructor({ compiler, moduleRegistry, viewRegistry, config: { application }, runtimeEnvironment: { hmrEnabled }, }: ProviderContext); | ||
constructor({ compiler, viewRegistry, config: { routes }, runtimeEnvironment: { hmrEnabled }, }: ProviderContext); | ||
getModuleEntry({ specifier }: AbstractModuleId): Promise<ModuleEntry | undefined>; | ||
@@ -12,0 +11,0 @@ getModuleSource<R extends AbstractModuleId>({ specifier, namespace, name, }: R): Promise<ModuleSource | undefined>; |
@@ -14,23 +14,11 @@ "use strict"; | ||
const appIdentity = identity_1.parseAppIdentity(specifier); | ||
if (appIdentity && isValidModuleIdentity(appIdentity)) { | ||
return true; | ||
} | ||
return false; | ||
return !!appIdentity && identity_1.isValidResourceIdentity(appIdentity, identity_1.AppResourceEnum.MODULE); | ||
} | ||
function isValidModuleIdentity(appIdentity) { | ||
if (appIdentity.packageName === identity_1.APP_BOOTSTRAP_PACKAGE_NAME && | ||
appIdentity.resourceType === identity_1.AppResourceEnum.MODULE && | ||
identity_1.SUPPORTED_MODULE_FORMATS.includes(appIdentity.format)) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
class AppService { | ||
constructor({ compiler, moduleRegistry, viewRegistry, config: { application }, runtimeEnvironment: { hmrEnabled }, }) { | ||
class AppModuleProvider { | ||
constructor({ compiler, viewRegistry, config: { routes }, runtimeEnvironment: { hmrEnabled }, }) { | ||
this.name = 'app-provider'; | ||
this.hmrEnabled = false; | ||
this.appContext = application; | ||
this.routesConfig = routes; | ||
this.viewRegistry = viewRegistry; | ||
this.compiler = compiler; | ||
this.moduleRegistry = moduleRegistry; | ||
this.hmrEnabled = hmrEnabled; | ||
@@ -42,8 +30,5 @@ // Get version of this Provider from package.json | ||
async getModuleEntry({ specifier }) { | ||
const appIdentity = identity_1.parseAppIdentity(specifier); | ||
// Validate the root app module specifier | ||
// expected format: @lwrjs/app-service/{appName}/module/{format}[/path/{requestPath}] | ||
if (appIdentity && | ||
isValidModuleIdentity(appIdentity) && | ||
appIdentity.appName === this.appContext.name) { | ||
if (validateSpecifier(specifier)) { | ||
const normalizedSpecifier = specifier.endsWith('/') ? `${specifier}index` : specifier; | ||
@@ -62,28 +47,15 @@ const virtualId = `<virtual>/${normalizedSpecifier}`; | ||
const appIdentity = identity_1.parseAppIdentity(specifier); | ||
if (!appIdentity || !isValidModuleIdentity(appIdentity)) { | ||
if (!appIdentity || !identity_1.isValidResourceIdentity(appIdentity, identity_1.AppResourceEnum.MODULE)) { | ||
return; | ||
} | ||
const { subResource, format } = appIdentity; | ||
const requestPath = subResource ? subResource.requestPath : '/'; | ||
// Parse information from various contexts and fetch Module Entry | ||
// Fetch the Module Entry and corresponding route config object | ||
const moduleEntry = await this.getModuleEntry({ specifier }); | ||
if (!moduleEntry) { | ||
const route = this.routesConfig.find((r) => r.id === appIdentity.appName); | ||
if (!moduleEntry || !route) { | ||
throw new Error(`Bootstrap module entry not found: ${specifier}`); | ||
} | ||
// Get the array of root components in the view by request path | ||
// The ABS specifier is in form: "@lwrjs/app-service/{appName}/module/{format}[/path/{requestPath}]" | ||
// TODO240: If missing, pull the path from config (by appName) | ||
const { customElements } = await this.viewRegistry.getRenderedViewMetadata({ | ||
path: requestPath, | ||
requestPath, | ||
}, {}); | ||
const rootModules = customElements.map(shared_utils_1.kebabcaseToCamelcase); | ||
if (requestPath === '/' && !rootModules.includes(this.appContext.root)) { | ||
// If the root application module is not included in the root module array, add it | ||
// This happens when the 'lwr-root' HTML property is used for root insertion (see init.ts) | ||
// TODO240: Pull "root" component (if it exists) from config (by appName) | ||
rootModules.unshift(this.appContext.root); | ||
} | ||
// Get the array of root components for this route | ||
const rootComponents = await identity_1.getRootComponents(appIdentity, route, this.viewRegistry); | ||
// Generate ABS module | ||
const originalSource = await utils_1.createVirtualSource(format, this.hmrEnabled, rootModules, this.appContext, this.moduleRegistry); | ||
const originalSource = await utils_1.createVirtualSource(appIdentity.format, this.hmrEnabled, rootComponents, route.bootstrap); | ||
return { | ||
@@ -120,3 +92,3 @@ id: moduleEntry.id, | ||
} | ||
exports.default = AppService; | ||
exports.default = AppModuleProvider; | ||
//# sourceMappingURL=index.js.map |
@@ -1,2 +0,2 @@ | ||
import { PublicModuleRegistry, NormalizedLwrApplicationConfig, ModuleFormat } from '@lwrjs/types'; | ||
import { NormalizedLwrAppBootstrapConfig, ModuleFormat } from '@lwrjs/types'; | ||
/** | ||
@@ -12,3 +12,3 @@ * Create the virtual source for the application module | ||
*/ | ||
export declare function createVirtualSource(format: ModuleFormat, hmrEnabled: boolean, rootComponents: string[], { init: initModule, locker, services, syntheticShadow }: NormalizedLwrApplicationConfig, moduleRegistry: PublicModuleRegistry): Promise<string>; | ||
export declare function createVirtualSource(format: ModuleFormat, hmrEnabled: boolean, rootComponents: string[], { init: initModule, locker, services, syntheticShadow, workers }: NormalizedLwrAppBootstrapConfig): Promise<string>; | ||
//# sourceMappingURL=utils.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.createVirtualSource = void 0; | ||
const shared_utils_1 = require("@lwrjs/shared-utils"); | ||
function getDefaultImportName(service) { | ||
@@ -29,8 +28,8 @@ return `loaderService_${service.replace(/\//gi, '_').replace(/@/gi, '')}`; | ||
*/ | ||
async function createVirtualSource(format, hmrEnabled, rootComponents, { init: initModule, locker, services, syntheticShadow }, moduleRegistry) { | ||
async function createVirtualSource(format, hmrEnabled, rootComponents, { init: initModule, locker, services, syntheticShadow, workers }) { | ||
const isAMD = format === 'amd'; | ||
const isESM = format === 'esm'; | ||
const servicesSource = services && createServicesSource(services); | ||
const versionedRootCmps = isAMD && (await Promise.all(rootComponents.map((s) => shared_utils_1.getVersionedSpecifier(s, moduleRegistry)))); | ||
const importRootModules = rootComponents.map((wc, index) => `import Ctor${index} from '${wc}'`); | ||
const workerCmps = Object.values(workers); | ||
return [ | ||
@@ -41,3 +40,3 @@ '/* This module is generated */', | ||
// import the loader and services for AMD | ||
isAMD && `import { load ${services && services.length ? ', services' : ''}} from 'lwr/loader';`, | ||
isAMD && services && services.length && `import { services } from 'lwr/loader';`, | ||
// import ESM version of ServiceAPI | ||
@@ -59,8 +58,17 @@ !isAMD && services && services.length && `import { services } from 'lwr/servicesESM';`, | ||
// initialize root components | ||
isESM | ||
? `init([${rootComponents.map((r, i) => `["${r}", Ctor${i}]`)}]); ${hmrEnabled ? `initHMR(globalThis.LWR.hmrServerURI);` : ''}` | ||
: `const rootCmps = ${JSON.stringify(versionedRootCmps)}; | ||
const appRoot = globalThis.LWR.rootComponent; | ||
appRoot && !rootCmps.includes(appRoot) && rootCmps.push(appRoot); | ||
rootCmps.forEach(c => load(c).then(({ default: Ctor }) => { init([[c, Ctor]]); }));`, | ||
isESM && | ||
`init([${rootComponents.map((r, i) => `["${r}", Ctor${i}]`)}]); ${hmrEnabled ? `initHMR(globalThis.LWR.hmrServerURI);` : ''}`, | ||
isAMD && | ||
`const rootCmps = ${JSON.stringify(rootComponents)}; | ||
const appRoot = globalThis.LWR.rootComponent; | ||
if (!appRoot || rootCmps.includes(appRoot)) { | ||
${rootComponents | ||
.map((cmp) => `import('${cmp}').then(({ default: Ctor }) => { init([['${cmp}', Ctor]]); });`) | ||
.join('\n')} | ||
}`, | ||
// OR initialize worker components | ||
isAMD && | ||
`${workerCmps.map((cmp) => `else if (appRoot === "${cmp}") { | ||
import('${cmp}').then(({ default: Ctor }) => { init([['${cmp}', Ctor]]); }); | ||
}`)}`, | ||
] | ||
@@ -67,0 +75,0 @@ .filter(Boolean) |
// TODO: We won't need this anymore once we upgrade to Node 14 | ||
throw new Error( | ||
'This package its only resolvable via: ' + | ||
'@lwrjs/app-service/cjs/moduleProvider' + | ||
'@lwrjs/app-service/cjs/configProvider' + | ||
' or' + | ||
'@lwrjs/app-service/cjs/resourceProvider', | ||
'@lwrjs/app-service/cjs/jsonProvider' + | ||
' or' + | ||
'@lwrjs/app-service/cjs/mappingProvider' + | ||
' or' + | ||
'@lwrjs/app-service/cjs/moduleProvider', | ||
); |
@@ -7,3 +7,3 @@ { | ||
}, | ||
"version": "0.0.2-alpha30", | ||
"version": "0.0.2-alpha31", | ||
"homepage": "https://lwr.dev/", | ||
@@ -27,5 +27,4 @@ "repository": { | ||
"dependencies": { | ||
"@lwrjs/shared-utils": "0.0.2-alpha30" | ||
}, | ||
"gitHead": "ec31eb8e6e809d9afc95f63c0428e04a5830451d" | ||
"@lwrjs/shared-utils": "0.0.2-alpha31" | ||
} | ||
} |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
41676
20
890
- Removed@lwrjs/shared-utils@0.0.2-alpha30(transitive)
- Removedanymatch@3.1.3(transitive)
- Removedbinary-extensions@2.3.0(transitive)
- Removedbraces@3.0.3(transitive)
- Removedchokidar@3.6.0(transitive)
- Removedfast-json-stable-stringify@2.1.0(transitive)
- Removedfill-range@7.1.1(transitive)
- Removedfsevents@2.3.3(transitive)
- Removedglob-parent@5.1.2(transitive)
- Removedis-binary-path@2.1.0(transitive)
- Removedis-extglob@2.1.1(transitive)
- Removedis-glob@4.0.3(transitive)
- Removedis-number@7.0.0(transitive)
- Removednormalize-path@3.0.0(transitive)
- Removedparse5@6.0.1(transitive)
- Removedparse5-sax-parser@6.0.1(transitive)
- Removedpicomatch@2.3.1(transitive)
- Removedreaddirp@3.6.0(transitive)
- Removedslugify@1.6.6(transitive)
- Removedto-regex-range@5.0.1(transitive)