Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

single-spa

Package Overview
Dependencies
Maintainers
1
Versions
139
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

single-spa - npm Package Compare versions

Comparing version 1.0.0 to 1.1.0

examples/apps/bower-angular-phonecat/.bowerrc

204

dist/single-spa.js

@@ -15,3 +15,3 @@ 'use strict';

var nativeSystemGlobal = window.System;
var requiredLifeCycleFuncs = ['entryWillBeInstalled', 'entryWasInstalled', 'applicationWillMount', 'mountApplication', 'applicationWasMounted', 'applicationWillUnmount', 'unmountApplication', 'activeApplicationSourceWillUpdate', 'activeApplicationSourceWillUpdate'];
var requiredLifeCycleFuncs = ['scriptsWillBeLoaded', 'scriptsWereLoaded', 'applicationWillMount', 'applicationWasMounted', 'applicationWillUnmount', 'applicationWasUnmounted', 'activeApplicationSourceWillUpdate', 'activeApplicationSourceWillUpdate'];

@@ -88,25 +88,17 @@ window.singlespa = function (element) {

if (newApp !== mountedApp) {
var appWillUnmountPromise = mountedApp ? callLifecycleFunction(mountedApp, 'applicationWillUnmount') : new Promise(function (resolve) {
(mountedApp ? callLifecycleFunction(mountedApp, 'applicationWillUnmount') : new Promise(function (resolve) {
return resolve();
});
appWillUnmountPromise.then(function () {
return new Promise(function (resolve) {
if (mountedApp) {
callLifecycleFunction(mountedApp, 'unmountApplication', mountedApp.containerEl).then(function () {
finishUnmountingApp(mountedApp);
resolve();
});
} else {
resolve();
}
})).then(function () {
return cleanupDom();
}).then(function () {
return finishUnmountingApp(mountedApp);
}).then(function () {
return mountedApp ? callLifecycleFunction(mountedApp, 'applicationWasUnmounted') : new Promise(function (resolve) {
return resolve();
});
}).then(function () {
if (newApp.entryURI) {
return new Promise(function (resolve) {
return resolve();
});
} else {
return loadAppForFirstTime(newApp.appLocation);
}
return newApp.scriptsLoaded ? new Promise(function (resolve) {
return resolve();
}) : loadAppForFirstTime(newApp.appLocation);
}).then(function () {

@@ -117,4 +109,6 @@ return callLifecycleFunction(newApp, 'applicationWillMount');

}).then(function () {
return callLifecycleFunction(newApp, 'mountApplication', newApp.containerEl);
return insertDomFrom(newApp);
}).then(function () {
return callLifecycleFunction(newApp, 'applicationWasMounted');
}).then(function () {
return mountedApp = newApp;

@@ -125,2 +119,39 @@ });

function cleanupDom() {
return new Promise(function (resolve) {
while (document.head.childNodes.length > 0) {
document.head.removeChild(document.head.childNodes[0]);
}
while (document.body.childNodes.length > 0) {
document.body.removeChild(document.body.childNodes[0]);
}
resolve();
});
}
function insertDomFrom(app) {
return new Promise(function (resolve) {
var deepClone = true;
var clonedAppDom = app.parsedDom.cloneNode(deepClone);
for (var i = 0; i < clonedAppDom.attributes.length; i++) {
var attr = clonedAppDom.attributes[i];
document.documentElement.setAttribute(attr.name, attr.value);
}
var appHead = app.parsedDom.querySelector('head');
while (appHead.childNodes.length > 0) {
document.head.appendChild(appHead.childNodes[0]);
}
var appBody = app.parsedDom.querySelector('body');
while (appBody.childNodes.length > 0) {
document.body.appendChild(appBody.childNodes[0]);
}
app.parsedDom = clonedAppDom;
resolve();
});
}
function loadAppForFirstTime(appLocation) {

@@ -131,9 +162,9 @@ return new Promise(function (resolve, reject) {

nativeSystemGlobal['import'](appLocation).then(function (restOfApp) {
registerApplication(appLocation, restOfApp.entryURI, restOfApp.lifecycles);
registerApplication(appLocation, restOfApp.publicRoot, restOfApp.pathToIndex, restOfApp.lifecycles);
var app = appLocationToApp[appLocation];
window.System = currentAppSystemGlobal;
callLifecycleFunction(app, 'entryWillBeInstalled').then(function () {
return window.System['import'](app.entryURI);
callLifecycleFunction(app, 'scriptsWillBeLoaded').then(function () {
return loadIndex(app);
}).then(function () {
return callLifecycleFunction(app, 'entryWasInstalled');
return callLifecycleFunction(app, 'scriptsWereLoaded');
}).then(function () {

@@ -146,7 +177,98 @@ return resolve();

function registerApplication(appLocation, entryURI, lifecycles) {
function loadIndex(app) {
return new Promise(function (resolve) {
var request = new XMLHttpRequest();
request.addEventListener('load', htmlLoaded);
request.open('GET', window.location.protocol + '//' + window.location.hostname + ':' + window.location.port + '/' + app.publicRoot + '/' + app.pathToIndex);
request.send();
function htmlLoaded() {
var parser = new DOMParser();
var dom = parser.parseFromString(this.responseText, 'text/html');
var isLoadingScript = false;
var scriptsToBeLoaded = [];
traverseNode(dom);
app.parsedDom = dom.documentElement;
if (app.scriptsLoaded) {
setTimeout(function () {
resolve();
}, 10);
}
function traverseNode(node) {
for (var i = 0; i < node.childNodes.length; i++) {
var child = node.childNodes[i];
if (child.tagName === 'SCRIPT') {
if (child.getAttribute('src')) {
child.setAttribute('src', prependURL(child.getAttribute('src'), app.publicRoot));
}
//we put the scripts onto the page as part of the scriptsLoaded lifecycle
scriptsToBeLoaded.push(child);
appendScriptTag();
} else if (child.tagName === 'LINK' && child.getAttribute('href')) {
child.setAttribute('href', prependURL(child.getAttribute('href'), app.publicRoot));
} else if (child.tagName === 'IMG' && child.getAttribute('src')) {
child.setAttribute('src', prependURL(child.getAttribute('src'), app.publicRoot));
}
traverseNode(child);
}
}
function prependURL(url, prefix) {
var parsedURL = document.createElement('a');
parsedURL.href = url;
var result = parsedURL.protocol + '//' + (parsedURL.hostname + ':' + parsedURL.port + '/' + prefix + '/' + parsedURL.pathname + parsedURL.search + parsedURL.hash).replace(/[\/]+/g, '/');
return result;
}
function appendScriptTag() {
if (isLoadingScript) {
return;
}
if (scriptsToBeLoaded.length === 0) {
app.scriptsLoaded = true;
if (app.parsedDom) {
//loading a script was the last thing we were waiting on
setTimeout(function () {
resolve();
}, 10);
}
return;
}
var originalScriptTag = scriptsToBeLoaded.splice(0, 1)[0];
//one does not simply append script tags to the dom
var scriptTag = document.createElement('script');
for (var i = 0; i < originalScriptTag.attributes.length; i++) {
scriptTag.setAttribute(originalScriptTag.attributes[i].nodeName, originalScriptTag.getAttribute(originalScriptTag.attributes[i].nodeName));
}
if (!scriptTag.src) {
scriptTag.text = originalScriptTag.text;
}
isLoadingScript = true;
document.head.appendChild(scriptTag);
if (scriptTag.src) {
scriptTag.onload = function () {
isLoadingScript = false;
appendScriptTag();
};
} else {
isLoadingScript = false;
appendScriptTag();
}
//normally when you appendChild, the old parent no longer has the child anymore. We have to simulate that since we're not really appending the child
originalScriptTag.remove();
}
}
});
}
function registerApplication(appLocation, publicRoot, pathToIndex, lifecycles) {
//validate
if (typeof entryURI !== 'string') {
throw new Error('App ' + appLocation + ' must export an entryURI string');
if (typeof publicRoot !== 'string') {
throw new Error('App ' + appLocation + ' must export a publicRoot string');
}
if (typeof pathToIndex !== 'string') {
throw new Error('App ' + appLocation + ' must export a pathToIndex string');
}
if (typeof lifecycles !== 'object' && typeof lifecycles !== 'function') {

@@ -173,3 +295,4 @@ throw new Error('App ' + appLocation + ' must export a \'lifecycles\' object or array of objects');

var app = appLocationToApp[appLocation];
app.entryURI = entryURI;
app.publicRoot = publicRoot;
app.pathToIndex = pathToIndex;
app.hashChangeFunctions = [];

@@ -211,5 +334,2 @@ app.popStateFunctions = [];

});
app.containerEl = document.createElement('div');
app.containerEl.setAttribute('single-spa-active-app', app.appLocation);
document.body.appendChild(app.containerEl);
resolve();

@@ -220,9 +340,15 @@ });

function finishUnmountingApp(app) {
app.hashChangeFunctions.forEach(function (hashChangeFunction) {
window.removeEventListener('hashchange', hashChangeFunction);
return new Promise(function (resolve) {
if (!app) {
resolve();
return;
}
app.hashChangeFunctions.forEach(function (hashChangeFunction) {
window.removeEventListener('hashchange', hashChangeFunction);
});
app.popStateFunctions.forEach(function (popStateFunction) {
window.removeEventListener('popstate', popStateFunction);
});
resolve();
});
app.popStateFunctions.forEach(function (popStateFunction) {
window.removeEventListener('popstate', popStateFunction);
});
document.body.removeChild(app.containerEl);
}

@@ -229,0 +355,0 @@

5

examples/bootstrap.js
import { declareChildApplication } from "single-spa";
declareChildApplication('/apps/jspm-with-angular-1.3.0/app.js', () => window.location.pathname.startsWith('/legacy'));
declareChildApplication('/apps/jspm-with-angular-1.4.6/app.js', () => window.location.pathname.startsWith('/v2'));
declareChildApplication('/apps/jspm-with-angular-1.3.0/single-spa.config.js', () => window.location.pathname.startsWith('/legacy'));
declareChildApplication('/apps/jspm-with-angular-1.4.6/single-spa.config.js', () => window.location.pathname.startsWith('/v2'));
declareChildApplication('/apps/bower-angular-phonecat/single-spa.config.js', () => window.location.pathname.startsWith('/phonecat'));

@@ -17,9 +17,8 @@ System.config({

map: {
"angular": "github:angular/bower-angular@1.2.0",
"babel": "npm:babel-core@5.8.25",
"babel-runtime": "npm:babel-runtime@5.8.24",
"core-js": "npm:core-js@1.1.4",
"single-spa": "github:single-spa@1.0.0",
"single-spa-angular1": "npm:single-spa-angular1@1.0.1",
"single-spa-jspm": "npm:single-spa-jspm@1.0.1",
"single-spa": "github:single-spa@1.1.0",
"single-spa-angular1": "npm:single-spa-angular1@1.1.0",
"single-spa-jspm": "npm:single-spa-jspm@1.1.0",
"github:jspm/nodelibs-process@0.1.1": {

@@ -26,0 +25,0 @@ "process": "npm:process@0.10.1"

@@ -9,5 +9,4 @@ {

"dependencies": {
"angular": "github:angular/bower-angular@1.2.0",
"single-spa-angular1": "npm:single-spa-angular1@1.0.1",
"single-spa-jspm": "npm:single-spa-jspm@^1.0.1"
"single-spa-angular1": "npm:single-spa-angular1@1.1.0",
"single-spa-jspm": "npm:single-spa-jspm@1.1.0"
},

@@ -14,0 +13,0 @@ "devDependencies": {

{
"name": "single-spa",
"version": "1.0.0",
"version": "1.1.0",
"description": "Multiple applications, one page",

@@ -23,4 +23,4 @@ "main": "src/single-spa.js",

"devDependencies": {
"babel": "^5.8.23"
"babel": "5.8.23"
}
}

@@ -8,9 +8,8 @@ let appLocationToApp = {};

const requiredLifeCycleFuncs = [
'entryWillBeInstalled',
'entryWasInstalled',
'scriptsWillBeLoaded',
'scriptsWereLoaded',
'applicationWillMount',
'mountApplication',
'applicationWasMounted',
'applicationWillUnmount',
'unmountApplication',
'applicationWasUnmounted',
'activeApplicationSourceWillUpdate',

@@ -90,28 +89,12 @@ 'activeApplicationSourceWillUpdate'

if (newApp !== mountedApp) {
let appWillUnmountPromise = mountedApp ? callLifecycleFunction(mountedApp, 'applicationWillUnmount') : new Promise((resolve) => resolve());
appWillUnmountPromise
.then(() => {
return new Promise(function(resolve) {
if (mountedApp) {
callLifecycleFunction(mountedApp, 'unmountApplication', mountedApp.containerEl)
.then(() => {
finishUnmountingApp(mountedApp);
resolve();
});
} else {
resolve();
}
});
})
.then(() => {
if (newApp.entryURI) {
return new Promise((resolve) => resolve());
} else {
return loadAppForFirstTime(newApp.appLocation);
}
})
(mountedApp ? callLifecycleFunction(mountedApp, 'applicationWillUnmount') : new Promise((resolve) => resolve()))
.then(() => cleanupDom())
.then(() => finishUnmountingApp(mountedApp))
.then(() => (mountedApp ? callLifecycleFunction(mountedApp, 'applicationWasUnmounted') : new Promise((resolve) => resolve())))
.then(() => (newApp.scriptsLoaded ? new Promise((resolve) => resolve()) : loadAppForFirstTime(newApp.appLocation)))
.then(() => callLifecycleFunction(newApp, 'applicationWillMount'))
.then(() => appWillBeMounted(newApp))
.then(() => callLifecycleFunction(newApp, 'mountApplication', newApp.containerEl))
.then(() => insertDomFrom(newApp))
.then(() => callLifecycleFunction(newApp, 'applicationWasMounted'))
.then(() => mountedApp = newApp)

@@ -121,2 +104,39 @@ }

function cleanupDom() {
return new Promise((resolve) => {
while (document.head.childNodes.length > 0) {
document.head.removeChild(document.head.childNodes[0]);
}
while (document.body.childNodes.length > 0) {
document.body.removeChild(document.body.childNodes[0]);
}
resolve();
})
}
function insertDomFrom(app) {
return new Promise((resolve) => {
const deepClone = true;
let clonedAppDom = app.parsedDom.cloneNode(deepClone);
for (let i=0; i<clonedAppDom.attributes.length; i++) {
const attr = clonedAppDom.attributes[i];
document.documentElement.setAttribute(attr.name, attr.value);
}
let appHead = app.parsedDom.querySelector('head');
while (appHead.childNodes.length > 0) {
document.head.appendChild(appHead.childNodes[0]);
}
let appBody = app.parsedDom.querySelector('body');
while (appBody.childNodes.length > 0) {
document.body.appendChild(appBody.childNodes[0]);
}
app.parsedDom = clonedAppDom;
resolve();
})
}
function loadAppForFirstTime(appLocation) {

@@ -127,8 +147,8 @@ return new Promise(function(resolve, reject) {

nativeSystemGlobal.import(appLocation).then(function(restOfApp) {
registerApplication(appLocation, restOfApp.entryURI, restOfApp.lifecycles);
registerApplication(appLocation, restOfApp.publicRoot, restOfApp.pathToIndex, restOfApp.lifecycles);
let app = appLocationToApp[appLocation];
window.System = currentAppSystemGlobal;
callLifecycleFunction(app, 'entryWillBeInstalled')
.then(() => window.System.import(app.entryURI))
.then(() => callLifecycleFunction(app, 'entryWasInstalled'))
callLifecycleFunction(app, 'scriptsWillBeLoaded')
.then(() => loadIndex(app))
.then(() => callLifecycleFunction(app, 'scriptsWereLoaded'))
.then(() => resolve())

@@ -139,7 +159,98 @@ })

function registerApplication(appLocation, entryURI, lifecycles) {
function loadIndex(app) {
return new Promise((resolve) => {
let request = new XMLHttpRequest();
request.addEventListener('load', htmlLoaded);
request.open('GET', `${window.location.protocol}//${window.location.hostname}:${window.location.port}/${app.publicRoot}/${app.pathToIndex}`);
request.send();
function htmlLoaded() {
let parser = new DOMParser();
let dom = parser.parseFromString(this.responseText, 'text/html');
let isLoadingScript = false;
let scriptsToBeLoaded = [];
traverseNode(dom);
app.parsedDom = dom.documentElement;
if (app.scriptsLoaded) {
setTimeout(function() {
resolve();
}, 10)
}
function traverseNode(node) {
for (let i=0; i<node.childNodes.length; i++) {
const child = node.childNodes[i];
if (child.tagName === 'SCRIPT') {
if (child.getAttribute('src')) {
child.setAttribute('src', prependURL(child.getAttribute('src'), app.publicRoot));
}
//we put the scripts onto the page as part of the scriptsLoaded lifecycle
scriptsToBeLoaded.push(child);
appendScriptTag();
} else if (child.tagName === 'LINK' && child.getAttribute('href')) {
child.setAttribute('href', prependURL(child.getAttribute('href'), app.publicRoot));
} else if (child.tagName === 'IMG' && child.getAttribute('src')) {
child.setAttribute('src', prependURL(child.getAttribute('src'), app.publicRoot));
}
traverseNode(child);
}
}
function prependURL(url, prefix) {
let parsedURL = document.createElement('a');
parsedURL.href = url;
let result = `${parsedURL.protocol}//` + `${parsedURL.hostname}:${parsedURL.port}/${prefix}/${parsedURL.pathname}${parsedURL.search}${parsedURL.hash}`.replace(/[\/]+/g, '/');
return result;
}
function appendScriptTag() {
if (isLoadingScript) {
return;
}
if (scriptsToBeLoaded.length === 0) {
app.scriptsLoaded = true;
if (app.parsedDom) {
//loading a script was the last thing we were waiting on
setTimeout(function() {
resolve();
}, 10)
}
return;
}
let originalScriptTag = scriptsToBeLoaded.splice(0, 1)[0];
//one does not simply append script tags to the dom
let scriptTag = document.createElement('script');
for (let i=0; i<originalScriptTag.attributes.length; i++) {
scriptTag.setAttribute(originalScriptTag.attributes[i].nodeName, originalScriptTag.getAttribute(originalScriptTag.attributes[i].nodeName));
}
if (!scriptTag.src) {
scriptTag.text = originalScriptTag.text;
}
isLoadingScript = true;
document.head.appendChild(scriptTag);
if (scriptTag.src) {
scriptTag.onload = () => {
isLoadingScript = false;
appendScriptTag();
}
} else {
isLoadingScript = false;
appendScriptTag();
}
//normally when you appendChild, the old parent no longer has the child anymore. We have to simulate that since we're not really appending the child
originalScriptTag.remove();
}
}
});
}
function registerApplication(appLocation, publicRoot, pathToIndex, lifecycles) {
//validate
if (typeof entryURI !== 'string') {
throw new Error(`App ${appLocation} must export an entryURI string`);
if (typeof publicRoot !== 'string') {
throw new Error(`App ${appLocation} must export a publicRoot string`);
}
if (typeof pathToIndex !== 'string') {
throw new Error(`App ${appLocation} must export a pathToIndex string`);
}
if (typeof lifecycles !== 'object' && typeof lifecycles !== 'function') {

@@ -161,3 +272,4 @@ throw new Error(`App ${appLocation} must export a 'lifecycles' object or array of objects`);

let app = appLocationToApp[appLocation];
app.entryURI = entryURI;
app.publicRoot = publicRoot;
app.pathToIndex = pathToIndex;
app.hashChangeFunctions = [];

@@ -198,5 +310,2 @@ app.popStateFunctions = [];

});
app.containerEl = document.createElement('div');
app.containerEl.setAttribute('single-spa-active-app', app.appLocation);
document.body.appendChild(app.containerEl);
resolve();

@@ -207,9 +316,15 @@ })

function finishUnmountingApp(app) {
app.hashChangeFunctions.forEach((hashChangeFunction) => {
window.removeEventListener('hashchange', hashChangeFunction);
});
app.popStateFunctions.forEach((popStateFunction) => {
window.removeEventListener('popstate', popStateFunction);
});
document.body.removeChild(app.containerEl);
return new Promise((resolve) => {
if (!app) {
resolve()
return;
}
app.hashChangeFunctions.forEach((hashChangeFunction) => {
window.removeEventListener('hashchange', hashChangeFunction);
});
app.popStateFunctions.forEach((popStateFunction) => {
window.removeEventListener('popstate', popStateFunction);
});
resolve();
})
}

@@ -216,0 +331,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc