You're Invited: Meet the Socket team at BSidesSF and RSAC - April 27 - May 1.RSVP
Socket
Sign inDemoInstall
Socket

@lwrjs/client-modules

Package Overview
Dependencies
Maintainers
7
Versions
538
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@lwrjs/client-modules - npm Package Compare versions

Comparing version

to
0.0.2-alpha30

build/modules/lwr/hmr/util/swap.js

4

build/index.d.ts

@@ -1,2 +0,2 @@

import { ProviderContext, ResourceDefinition, ResourceIdentifier, ResourceProvider, RuntimeContext } from '@lwrjs/types';
import { ProviderContext, ResourceDefinition, ResourceIdentifier, ResourceProvider, RuntimeEnvironment } from '@lwrjs/types';
export default class ClientModuleService implements ResourceProvider {

@@ -8,4 +8,4 @@ name: string;

constructor(context: ProviderContext);
getResource<T extends ResourceIdentifier, R extends RuntimeContext>(resource: T, context: R): Promise<ResourceDefinition | undefined>;
getResource<T extends ResourceIdentifier, R extends RuntimeEnvironment>(resource: T, environment: R): Promise<ResourceDefinition | undefined>;
}
//# sourceMappingURL=index.d.ts.map

@@ -18,3 +18,3 @@ "use strict";

}
async getResource(resource, context) {
async getResource(resource, environment) {
const { specifier, version = this.version } = resource;

@@ -30,5 +30,5 @@ // Check that the resource is the correct version

specifier,
path: absFilepath,
type: 'text/javascript',
src: this.context.resourceRegistry.resolveResourceUri(resource, context),
type: 'application/javascript',
stream: fs_1.default.createReadStream(absFilepath),
src: this.context.resourceRegistry.resolveResourceUri(resource, environment),
};

@@ -35,0 +35,0 @@ }

@@ -1,35 +0,51 @@

// @ts-nocheck
import { registerTemplateSwap, registerStyleSwap, registerComponentSwap } from 'lwc';
import { updateStaleModule } from './util/swap';
export function initHMR() {
// eslint-disable-next-line no-undef
const isDevMode = globalThis.process.env.NODE_ENV === 'dev';
// This is a workaround until we don't change the way HMR works
// The server will always return the same canonical "latest URL"
// So we need to track the last new URI instead
const URI_MAPPING = new Map();
if (isDevMode) {
const socket = new WebSocket(`ws://${location.host}`);
async function moduleUpdate(payload) {
const {
oldUri,
newUri,
module: { specifier },
} = payload;
socket.addEventListener('message', async ({ data }) => {
const event = JSON.parse(data);
const lastEvalutedUri = URI_MAPPING.get(oldUri) || oldUri;
const oldModule = await import(lastEvalutedUri);
const newModule = await import(newUri);
URI_MAPPING.set(oldUri, newUri);
if (event.eventType === 'moduleUpdate') {
const {
oldUri,
newUri,
module: { namespace, name },
} = event.payload;
updateStaleModule({
oldModule,
newModule,
specifier,
});
}
const oldModule = await import(oldUri);
const newModule = await import(newUri);
async function viewUpdate(payload) {
const pathName = window.location.pathname;
const requestPath = payload.viewId.requestPath;
if (name.endsWith('html') && newModule.default) {
console.log(`Swapping html template for module "${namespace}/${name}"`);
registerTemplateSwap(oldModule.default, newModule.default);
} else if (name.endsWith('css') && newModule.default) {
registerStyleSwap(oldModule.default[0], newModule.default[0]);
} else {
registerComponentSwap(oldModule.default, newModule.default);
}
}
});
if (requestPath === pathName) {
window.location.reload();
}
}
export function initHMR(serverURI = '') {
// {apiVersion}/hmr/{format}/{compat}?debug
const socket = new WebSocket(`ws://${location.host}/${serverURI}`);
socket.addEventListener('message', async ({ data }) => {
const { eventType, payload } = JSON.parse(data);
switch (eventType) {
case 'moduleUpdate':
return moduleUpdate(payload);
case 'viewUpdate':
return viewUpdate(payload);
default:
return;
}
});
}

@@ -16,29 +16,34 @@ /**

* Import any requested static application dependencies, define the root
* application component into the CustomElement registry, and inject it.
* @param rootAppSpecifier - The bare specifier for the component, eg: 'x/appRoot'
* @param rootApp - A reference to the Constructor (extended from LightningElement)
* application component(s) into the CustomElement registry, and inject them.
* @param rootModules - An array of arrays, each one holding a pair of
* bare specifier and corresponding LightningElement constructor
* @example - [['x/appRoot', appCtor], ['x/nav', navCtor]]
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function init(rootAppSpecifier, rootApp) {
export function init(rootModules) {
if (typeof customElements !== 'undefined' && typeof document !== 'undefined') {
const elementName = toKebabCase(rootAppSpecifier); // Add the root to the CustomElementRegistry
const container = document.querySelector('[lwr-root]');
rootModules.forEach(([moduleSpecifier, ctor]) => {
// Kebab-case the specifier
const elementName = toKebabCase(moduleSpecifier); // Add the root to the CustomElementRegistry
customElements.define(elementName, rootApp.CustomElementConstructor); // Append the root element to the DOM, if it does not exist
customElements.define(elementName, ctor.CustomElementConstructor); // Append the root element to the DOM, if it does not exist
const rootEl = document.body.querySelector(elementName);
let el = document.body.querySelector(elementName);
if (!rootEl) {
const el = document.createElement(elementName);
const container = document.querySelector('[lwr-root]');
if (!el) {
el = document.createElement(elementName);
if (container) {
// Append to a node with the "lwr-root" attribute
container.appendChild(el);
} else {
// Otherwise, add the root to the <body>
document.body.appendChild(el);
if (container) {
// Append to a node with the "lwr-root" attribute
container.appendChild(el);
} else {
// Otherwise, add the root to the <body>
document.body.appendChild(el);
}
}
}
});
}
}

@@ -6,5 +6,5 @@ # Lightning Web Runtime :: Application Initialization

- importing static application dependencies
- defining the _root application component_ into the [`CustomElementRegistry`](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry)
- defining the _root application component(s)_ into the [`CustomElementRegistry`](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry)
This results in the _root application component_ being renderable by the DOM on first page load.
This results in the _root application component(s)_ being renderable by the DOM on first page load.

@@ -15,3 +15,3 @@ ## Definition

interface InitAPI {
init(rootAppSpecifier: string, rootApp: LightningElement): void;
init(rootModules: [string, LightningElement][]): void;
}

@@ -25,4 +25,8 @@ ```

import xAppRoot from 'x/appRoot';
import xNav from 'x/nav';
init('x/appRoot', xAppRoot);
init([
['x/appRoot', xAppRoot],
['x/nav', xNav],
]);
```

@@ -38,9 +42,11 @@

// src/modules/example/init/init.js
export function init(rootAppSpecifier, rootApp) {
const elementName = rootAppSpecifier.replace(/\//, '-');
customElements.define(elementName, rootApp.CustomElementConstructor);
export function init(rootModules) {
rootModules.forEach(([moduleSpecifier, ctor]) => {
const elementName = toKebabCase(moduleSpecifier);
customElements.define(elementName, ctor.CustomElementConstructor);
});
}
```
2. Configure the module specifier in _lwr.config.json_:
2. Configure the `init` module specifier in _lwr.config.json_:

@@ -47,0 +53,0 @@ ```json

@@ -1,35 +0,51 @@

// @ts-nocheck
import { registerTemplateSwap, registerStyleSwap, registerComponentSwap } from 'lwc';
import { updateStaleModule } from './util/swap';
export function initHMR() {
// eslint-disable-next-line no-undef
const isDevMode = globalThis.process.env.NODE_ENV === 'dev';
// This is a workaround until we don't change the way HMR works
// The server will always return the same canonical "latest URL"
// So we need to track the last new URI instead
const URI_MAPPING = new Map();
if (isDevMode) {
const socket = new WebSocket(`ws://${location.host}`);
async function moduleUpdate(payload) {
const {
oldUri,
newUri,
module: { specifier },
} = payload;
socket.addEventListener('message', async ({ data }) => {
const event = JSON.parse(data);
const lastEvalutedUri = URI_MAPPING.get(oldUri) || oldUri;
const oldModule = await import(lastEvalutedUri);
const newModule = await import(newUri);
URI_MAPPING.set(oldUri, newUri);
if (event.eventType === 'moduleUpdate') {
const {
oldUri,
newUri,
module: { namespace, name },
} = event.payload;
updateStaleModule({
oldModule,
newModule,
specifier,
});
}
const oldModule = await import(oldUri);
const newModule = await import(newUri);
async function viewUpdate(payload) {
const pathName = window.location.pathname;
const requestPath = payload.viewId.requestPath;
if (name.endsWith('html') && newModule.default) {
console.log(`Swapping html template for module "${namespace}/${name}"`);
registerTemplateSwap(oldModule.default, newModule.default);
} else if (name.endsWith('css') && newModule.default) {
registerStyleSwap(oldModule.default[0], newModule.default[0]);
} else {
registerComponentSwap(oldModule.default, newModule.default);
}
}
});
if (requestPath === pathName) {
window.location.reload();
}
}
export function initHMR(serverURI = '') {
// {apiVersion}/hmr/{format}/{compat}?debug
const socket = new WebSocket(`ws://${location.host}/${serverURI}`);
socket.addEventListener('message', async ({ data }) => {
const { eventType, payload } = JSON.parse(data);
switch (eventType) {
case 'moduleUpdate':
return moduleUpdate(payload);
case 'viewUpdate':
return viewUpdate(payload);
default:
return;
}
});
}

@@ -12,7 +12,14 @@ import { init } from '../init';

};
const TestCmp4 = {
CustomElementConstructor: class Fake extends HTMLElement {},
};
const TestCmp5 = {
CustomElementConstructor: class Fake extends HTMLElement {},
};
describe('LWR init', () => {
it('initializes and append root element to <body>', () => {
init('generated/lauraHomePage', TestCmp);
it('initializes and appends root element to <body>', () => {
init([['generated/lauraHomePage', TestCmp]]);
expect(customElements.get('generated-laura-home-page')).toBeDefined();
expect(document.body.querySelector('generated-laura-home-page')).not.toBeNull();
});

@@ -23,14 +30,25 @@ it('initializes and append root element to lwr-root node', () => {

document.body.appendChild(container);
init('c/darrell', TestCmp2);
init([['c/darrell', TestCmp2]]);
expect(customElements.get('c-darrell')).toBeDefined();
expect(document.body.querySelector('[lwr-root] c-darrell')).not.toBeNull();
});
it('initializes and skips appending the root element', () => {
document.body.appendChild(document.createElement('c-diego'));
init('c/diego', TestCmp3);
init([['c/diego', TestCmp3]]);
expect(customElements.get('c-diego')).toBeDefined();
});
it('initializes and appends multiple root elements to <body>', () => {
init([
['c/hunter', TestCmp4],
['c/brian', TestCmp5],
]);
expect(customElements.get('c-hunter')).toBeDefined();
expect(customElements.get('c-brian')).toBeDefined();
expect(document.body.querySelector('c-hunter')).not.toBeNull();
expect(document.body.querySelector('c-brian')).not.toBeNull();
});
it('initializes in a headless environment', () => {
const oldCustomElements = customElements;
delete globalThis.customElements;
init('c/khang', TestCmp);
init([['c/khang', TestCmp]]);
globalThis.customElements = oldCustomElements;

@@ -37,0 +55,0 @@ expect(customElements.get('c-khang')).toBeUndefined();

@@ -0,1 +1,3 @@

import type { LightningElement } from 'lwc/types';
/**

@@ -20,27 +22,33 @@ * Convert a module specifier into a valid CustomElement registry name:

* Import any requested static application dependencies, define the root
* application component into the CustomElement registry, and inject it.
* @param rootAppSpecifier - The bare specifier for the component, eg: 'x/appRoot'
* @param rootApp - A reference to the Constructor (extended from LightningElement)
* application component(s) into the CustomElement registry, and inject them.
* @param rootModules - An array of arrays, each one holding a pair of
* bare specifier and corresponding LightningElement constructor
* @example - [['x/appRoot', appCtor], ['x/nav', navCtor]]
*/
export function init(rootAppSpecifier: string, rootApp): void {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function init(rootModules: [string, LightningElement][]): void {
if (typeof customElements !== 'undefined' && typeof document !== 'undefined') {
const elementName = toKebabCase(rootAppSpecifier);
const container = document.querySelector('[lwr-root]');
// Add the root to the CustomElementRegistry
customElements.define(elementName, rootApp.CustomElementConstructor);
rootModules.forEach(([moduleSpecifier, ctor]) => {
// Kebab-case the specifier
const elementName = toKebabCase(moduleSpecifier);
// Append the root element to the DOM, if it does not exist
const rootEl = document.body.querySelector(elementName);
if (!rootEl) {
const el = document.createElement(elementName);
const container = document.querySelector('[lwr-root]');
if (container) {
// Append to a node with the "lwr-root" attribute
container.appendChild(el);
} else {
// Otherwise, add the root to the <body>
document.body.appendChild(el);
// Add the root to the CustomElementRegistry
customElements.define(elementName, ctor.CustomElementConstructor);
// Append the root element to the DOM, if it does not exist
let el = document.body.querySelector(elementName);
if (!el) {
el = document.createElement(elementName);
if (container) {
// Append to a node with the "lwr-root" attribute
container.appendChild(el);
} else {
// Otherwise, add the root to the <body>
document.body.appendChild(el);
}
}
}
});
}
}

@@ -6,5 +6,5 @@ # Lightning Web Runtime :: Application Initialization

- importing static application dependencies
- defining the _root application component_ into the [`CustomElementRegistry`](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry)
- defining the _root application component(s)_ into the [`CustomElementRegistry`](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry)
This results in the _root application component_ being renderable by the DOM on first page load.
This results in the _root application component(s)_ being renderable by the DOM on first page load.

@@ -15,3 +15,3 @@ ## Definition

interface InitAPI {
init(rootAppSpecifier: string, rootApp: LightningElement): void;
init(rootModules: [string, LightningElement][]): void;
}

@@ -25,4 +25,8 @@ ```

import xAppRoot from 'x/appRoot';
import xNav from 'x/nav';
init('x/appRoot', xAppRoot);
init([
['x/appRoot', xAppRoot],
['x/nav', xNav],
]);
```

@@ -38,9 +42,11 @@

// src/modules/example/init/init.js
export function init(rootAppSpecifier, rootApp) {
const elementName = rootAppSpecifier.replace(/\//, '-');
customElements.define(elementName, rootApp.CustomElementConstructor);
export function init(rootModules) {
rootModules.forEach(([moduleSpecifier, ctor]) => {
const elementName = toKebabCase(moduleSpecifier);
customElements.define(elementName, ctor.CustomElementConstructor);
});
}
```
2. Configure the module specifier in _lwr.config.json_:
2. Configure the `init` module specifier in _lwr.config.json_:

@@ -47,0 +53,0 @@ ```json

@@ -7,3 +7,3 @@ {

},
"version": "0.0.2-alpha3",
"version": "0.0.2-alpha30",
"homepage": "https://lwr.dev/",

@@ -23,16 +23,15 @@ "repository": {

"build/**/*.d.ts",
"modules",
"assets"
"modules"
],
"scripts": {
"build": "node ../../../bin/pack-lwc --dir modules build/modules"
"build": "node ../../../bin/pack-lwc --dir modules build/modules && yarn build:locker",
"build:locker": "rollup --config ./scripts/rollup.config.locker.js"
},
"dependencies": {
"@locker/sandbox": "^0.11.11",
"@lwrjs/shared-utils": "0.0.2-alpha30"
},
"lwc": {
"modules": [
{
"name": "lwc",
"path": "assets/lwc/engine.js",
"description": "Temporal Hack: We need to fix the lwc package to make npm: 'lwc' work"
},
{
"dir": "modules"

@@ -42,8 +41,9 @@ }

"expose": [
"lwc",
"lwr/hmr",
"lwr/init"
"lwr/init",
"lwr/servicesESM",
"lwr/lockerDefine"
]
},
"gitHead": "0a3ec38ad674e502f5dae4d232de8975fb0e4d76"
"gitHead": "ec31eb8e6e809d9afc95f63c0428e04a5830451d"
}