single-spa
Advanced tools
Comparing version 1.0.0 to 1.1.0
@@ -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 @@ |
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
Install scripts
Supply chain riskInstall scripts are run when the package is installed. The majority of malware in npm is hidden in install scripts.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
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
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
7094987
396
97146
1
16
11