Comparing version 0.0.6 to 0.0.7
@@ -34,6 +34,6 @@ (function (global, factory) { | ||
const plugins = new Set(); | ||
function use(plugin) { | ||
function use(plugin, ...args) { | ||
if (!plugins.has(plugin)) { | ||
plugins.add(plugin); | ||
plugin(); | ||
plugin(args); | ||
} | ||
@@ -62,38 +62,118 @@ } | ||
const isArr = (x) => Array.isArray(x); | ||
const isObj = (x) => Object.prototype.toString.call(x) === '[object Object]'; | ||
function proxy(base, onWirte) { | ||
const copy = isArr(base) ? [] : getCleanCopy(base); | ||
let map = Object.create(null); | ||
let draft = { | ||
base, | ||
copy, | ||
onWirte | ||
}; | ||
return new Proxy(base, { | ||
get(target, key) { | ||
if (key === 'IS_BERIAL_SANDBOX') | ||
return true; | ||
if (key in map) | ||
return map[key]; | ||
if (isObj(base[key]) || isArr(base[key])) { | ||
map[key] = proxy(base[key], (obj) => (copy[key] = obj)); | ||
return map[key]; | ||
function run(code, options = {}) { | ||
try { | ||
if (checkSyntax(code)) { | ||
const handler = { | ||
get(obj, prop) { | ||
return Reflect.has(obj, prop) ? obj[prop] : null; | ||
}, | ||
set(obj, prop, value) { | ||
Reflect.set(obj, prop, value); | ||
return true; | ||
}, | ||
has(obj, prop) { | ||
return obj && Reflect.has(obj, prop); | ||
} | ||
}; | ||
const captureHandler = { | ||
get(obj, prop) { | ||
return Reflect.get(obj, prop); | ||
}, | ||
set() { | ||
return true; | ||
}, | ||
has() { | ||
return true; | ||
} | ||
}; | ||
const allowList = Object.assign({ IS_BERIAL_SANDBOX: true, __proto__: null, console, | ||
String, | ||
Number, | ||
Array, | ||
Symbol, | ||
Math, | ||
Object, | ||
Promise, | ||
RegExp, | ||
JSON, | ||
Date, | ||
Function, | ||
parseInt, | ||
document, | ||
navigator, | ||
location, | ||
performance, | ||
MessageChannel, | ||
SVGElement, | ||
HTMLElement, | ||
HTMLIFrameElement, | ||
history, | ||
Map, | ||
Set, | ||
WeakMap, | ||
WeakSet, | ||
Error, | ||
localStorage, | ||
decodeURI, | ||
encodeURI, | ||
decodeURIComponent, | ||
encodeURIComponent, fetch: fetch.bind(window), setTimeout: setTimeout.bind(window), clearTimeout: clearTimeout.bind(window), setInterval: setInterval.bind(window), clearInterval: clearInterval.bind(window), requestAnimationFrame: requestAnimationFrame.bind(window), cancelAnimationFrame: cancelAnimationFrame.bind(window), addEventListener: addEventListener.bind(window), removeEventListener: removeEventListener.bind(window), eval: function (code) { | ||
return run('return ' + code, null); | ||
}, alert: function () { | ||
alert('Sandboxed alert:' + arguments[0]); | ||
}, innerHeight, | ||
innerWidth, | ||
outerHeight, | ||
outerWidth, | ||
pageXOffset, | ||
pageYOffset, | ||
screen, | ||
screenLeft, | ||
screenTop, | ||
screenX, | ||
screenY, | ||
scrollBy, | ||
scrollTo, | ||
scrollX, | ||
scrollY }, (options.allowList || {})); | ||
if (!Object.isFrozen(String.prototype)) { | ||
for (const k in allowList) { | ||
const fn = allowList[k]; | ||
if (typeof fn === 'object' && fn.prototype) { | ||
Object.freeze(fn.prototype); | ||
} | ||
if (typeof fn === 'function') { | ||
Object.freeze(fn); | ||
} | ||
} | ||
} | ||
else { | ||
return copy[key] || target[key]; | ||
} | ||
}, | ||
set(target, key, value) { | ||
if (isObj(base[key]) || isArr(base[key])) { | ||
map[key] = proxy(value, (obj) => (copy[key] = obj)); | ||
} | ||
onWirte && onWirte(draft.onWirte); | ||
copy[key] = value; | ||
return true; | ||
const proxy = new Proxy(allowList, handler); | ||
const capture = new Proxy({ | ||
__proto__: null, | ||
proxy, | ||
globalThis: new Proxy(allowList, handler), | ||
window: new Proxy(allowList, handler), | ||
self: new Proxy(allowList, handler) | ||
}, captureHandler); | ||
return Function('proxy', 'capture', `with(capture) { | ||
with(proxy) { | ||
return (function(){ | ||
"use strict"; | ||
${code}; | ||
return window | ||
})(); | ||
} | ||
}); | ||
}`)(proxy, capture); | ||
} | ||
} | ||
catch (e) { | ||
throw e; | ||
} | ||
} | ||
function getCleanCopy(obj) { | ||
return Object.create(Object.getPrototypeOf(obj)); | ||
function checkSyntax(code) { | ||
Function(code); | ||
if (/\bimport\s*(?:[(]|\/[*]|\/\/|<!--|-->)/.test(code)) { | ||
throw new Error('Dynamic imports are blocked'); | ||
} | ||
return true; | ||
} | ||
@@ -109,2 +189,3 @@ | ||
function request(url, option) { | ||
console.log(url); | ||
if (!window.fetch) { | ||
@@ -152,8 +233,7 @@ error("It looks like that your browser doesn't support fetch. Polyfill is needed before you use it."); | ||
const bodyNode = loadBody(template); | ||
const fake = proxy(window, null); | ||
const lifecycle = yield loadScript(template, fake, app.name); | ||
const lifecycle = yield loadScript(template, app.name); | ||
return { lifecycle, styleNodes, bodyNode }; | ||
}); | ||
} | ||
function loadScript(template, global, name) { | ||
function loadScript(template, name) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
@@ -167,3 +247,3 @@ const { scriptURLs, scripts } = parseScript(template); | ||
scriptsToLoad.forEach((script) => { | ||
const lifecycles = runScript(script, global, name); | ||
const lifecycles = run(script, {})[name]; | ||
bootstrap = [...bootstrap, lifecycles.bootstrap]; | ||
@@ -201,16 +281,2 @@ mount = [...mount, lifecycles.mount]; | ||
} | ||
function runScript(script, global, umdName) { | ||
const resolver = new Function('window', ` | ||
with(window.IS_BERIAL_SANDBOX) { | ||
try { | ||
${script} | ||
return window['${umdName}'] | ||
} | ||
catch(e) { | ||
console.log(e) | ||
} | ||
} | ||
`); | ||
return resolver.call(global, global); | ||
} | ||
function loadCSS(template) { | ||
@@ -449,10 +515,8 @@ return __awaiter(this, void 0, void 0, function* () { | ||
}; | ||
function polyfillRoute(updateState) { | ||
function polyfillHistory(fn) { | ||
return function () { | ||
const urlBefore = window.location.href; | ||
// @ts-ignore | ||
updateState.apply(this, arguments); | ||
const urlAfter = window.location.href; | ||
if (urlBefore !== urlAfter) { | ||
// @ts-ignore | ||
const before = window.location.href; | ||
fn.apply(this, arguments); | ||
const after = window.location.href; | ||
if (before !== after) { | ||
reroute(new PopStateEvent('popstate')); | ||
@@ -462,4 +526,4 @@ } | ||
} | ||
window.history.pushState = polyfillRoute(window.history.pushState); | ||
window.history.replaceState = polyfillRoute(window.history.replaceState); | ||
window.history.pushState = polyfillHistory(window.history.pushState); | ||
window.history.replaceState = polyfillHistory(window.history.replaceState); | ||
@@ -469,5 +533,4 @@ const Berial = { | ||
register, | ||
loadScript, | ||
importHtml, | ||
proxy, | ||
run, | ||
mixin, | ||
@@ -480,6 +543,5 @@ use | ||
exports.importHtml = importHtml; | ||
exports.loadScript = loadScript; | ||
exports.mixin = mixin; | ||
exports.proxy = proxy; | ||
exports.register = register; | ||
exports.run = run; | ||
exports.start = start; | ||
@@ -486,0 +548,0 @@ exports.use = use; |
@@ -1,2 +0,2 @@ | ||
import type { App, Lifecycles, ProxyType } from './types'; | ||
import type { App, Lifecycles } from './types'; | ||
export declare function importHtml(app: App): Promise<{ | ||
@@ -7,2 +7,2 @@ lifecycle: Lifecycles; | ||
}>; | ||
export declare function loadScript(template: string, global: ProxyType, name: string): Promise<Lifecycles>; | ||
export declare function loadScript(template: string, name: string): Promise<Lifecycles>; |
import { start, register } from './app'; | ||
import { mixin, use } from './mixin'; | ||
import { loadScript, importHtml } from './html-loader'; | ||
import { proxy } from './proxy'; | ||
import { importHtml } from './html-loader'; | ||
import { run } from './sandbox'; | ||
export declare const Berial: { | ||
start: typeof start; | ||
register: typeof register; | ||
loadScript: typeof loadScript; | ||
importHtml: typeof importHtml; | ||
proxy: typeof proxy; | ||
run: typeof run; | ||
mixin: typeof mixin; | ||
@@ -15,2 +14,2 @@ use: typeof use; | ||
export default Berial; | ||
export { start, register, loadScript, importHtml, proxy, mixin, use }; | ||
export { start, register, importHtml, run, mixin, use }; |
import type { Lifecycles } from './types'; | ||
export declare function use(plugin: () => any): void; | ||
export declare function use(plugin: (args: any) => any, ...args: any): void; | ||
export declare function mixin(mix: any): void; | ||
export declare function mapMixin(): Lifecycles; |
@@ -8,2 +8,2 @@ import type { Lifecycle, Lifecycles } from './types'; | ||
export declare function lifecycleCheck(lifecycle: Lifecycle | Lifecycles): void; | ||
export declare function reverse(arr: any[]): any[]; | ||
export declare function reverse<T>(arr: T[]): T[]; |
@@ -1,4 +0,7 @@ | ||
import { h, render } from 'fre' | ||
import { h, render,useEffect } from 'fre' | ||
function App() { | ||
useEffect(()=>{ | ||
document.title = '111' | ||
}) | ||
return <div> | ||
@@ -5,0 +8,0 @@ <h1 style={{ color: 'rgb(242, 35, 101)' }}>Hello Fre!!</h1> |
@@ -61,4 +61,6 @@ const path = require('path') | ||
historyApiFallback: true, | ||
hot: true | ||
hot: true, | ||
inline: false, | ||
// lazy: true, | ||
} | ||
} |
@@ -1,2 +0,3 @@ | ||
import React from 'react' | ||
import React, { Fragment } from 'react' | ||
import { BrowserRouter as Router, Switch, Route, Link } from 'react-router-dom' | ||
@@ -12,9 +13,41 @@ class App extends React.Component { | ||
return ( | ||
<div> | ||
<h1 style={{ color: '#61dafb' }} onClick={()=>this.setState({count:this.state.count+1})}>Hello React:{this.state.count}!</h1> | ||
<img | ||
height="300" | ||
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii0xMS41IC0xMC4yMzE3NCAyMyAyMC40NjM0OCI+CiAgPHRpdGxlPlJlYWN0IExvZ288L3RpdGxlPgogIDxjaXJjbGUgY3g9IjAiIGN5PSIwIiByPSIyLjA1IiBmaWxsPSIjNjFkYWZiIi8+CiAgPGcgc3Ryb2tlPSIjNjFkYWZiIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiPgogICAgPGVsbGlwc2Ugcng9IjExIiByeT0iNC4yIi8+CiAgICA8ZWxsaXBzZSByeD0iMTEiIHJ5PSI0LjIiIHRyYW5zZm9ybT0icm90YXRlKDYwKSIvPgogICAgPGVsbGlwc2Ugcng9IjExIiByeT0iNC4yIiB0cmFuc2Zvcm09InJvdGF0ZSgxMjApIi8+CiAgPC9nPgo8L3N2Zz4K" | ||
/> | ||
</div> | ||
<Router> | ||
<div> | ||
<h1 | ||
style={{ color: '#61dafb' }} | ||
onClick={() => this.setState({ count: this.state.count + 1 })} | ||
> | ||
Hello React:{this.state.count}! | ||
</h1> | ||
<img | ||
height="300" | ||
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii0xMS41IC0xMC4yMzE3NCAyMyAyMC40NjM0OCI+CiAgPHRpdGxlPlJlYWN0IExvZ288L3RpdGxlPgogIDxjaXJjbGUgY3g9IjAiIGN5PSIwIiByPSIyLjA1IiBmaWxsPSIjNjFkYWZiIi8+CiAgPGcgc3Ryb2tlPSIjNjFkYWZiIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiPgogICAgPGVsbGlwc2Ugcng9IjExIiByeT0iNC4yIi8+CiAgICA8ZWxsaXBzZSByeD0iMTEiIHJ5PSI0LjIiIHRyYW5zZm9ybT0icm90YXRlKDYwKSIvPgogICAgPGVsbGlwc2Ugcng9IjExIiByeT0iNC4yIiB0cmFuc2Zvcm09InJvdGF0ZSgxMjApIi8+CiAgPC9nPgo8L3N2Zz4K" | ||
/> | ||
<h1>React Router Test</h1> | ||
<nav> | ||
<ul> | ||
<li> | ||
<Link to="/react">Home</Link> | ||
</li> | ||
<li> | ||
<Link to="/react/about">About</Link> | ||
</li> | ||
<li> | ||
<Link to="/react/users">Users</Link> | ||
</li> | ||
</ul> | ||
</nav> | ||
<Switch> | ||
<Route path="/react/about"> | ||
<About /> | ||
</Route> | ||
<Route path="/react/users"> | ||
<Users /> | ||
</Route> | ||
<Route path="/react"> | ||
<Home /> | ||
</Route> | ||
</Switch> | ||
</div> | ||
</Router> | ||
) | ||
@@ -24,2 +57,12 @@ } | ||
function Home() { | ||
return <h2>Home</h2> | ||
} | ||
function About() { | ||
return <h2>About</h2> | ||
} | ||
function Users() { | ||
return <h2>Users</h2> | ||
} | ||
export default App |
@@ -23,4 +23,3 @@ import React from 'react' | ||
const root = host.shadowRoot.getElementById('root') | ||
// 从 DOM 中卸载组件 | ||
ReactDOM.unmountComponentAtNode(root) | ||
} |
@@ -19,2 +19,3 @@ { | ||
"react-dom": "^17.0.0-rc.0", | ||
"react-router-dom": "^5.2.0", | ||
"regenerator-runtime": "^0.13.7" | ||
@@ -21,0 +22,0 @@ }, |
@@ -25,3 +25,3 @@ const path = require('path') | ||
options: { | ||
presets: ['@babel/preset-env', '@babel/preset-react'] | ||
presets: ['@babel/preset-react'] | ||
} | ||
@@ -55,4 +55,5 @@ } | ||
historyApiFallback: true, | ||
hot: true | ||
hot: true, | ||
inline: false | ||
} | ||
} |
import Vue from 'vue' | ||
import App from './App.vue' | ||
import router from './router' | ||
@@ -14,2 +15,3 @@ let mountEl = null | ||
el: appNode, | ||
router, | ||
render: h => h(App) | ||
@@ -32,2 +34,3 @@ }) | ||
el: appNode, | ||
router, | ||
render: h => h(App) | ||
@@ -34,0 +37,0 @@ }) |
@@ -17,3 +17,4 @@ { | ||
"dependencies": { | ||
"vue": "^2.6.11" | ||
"vue": "^2.6.11", | ||
"vue-router": "^3.4.3" | ||
}, | ||
@@ -20,0 +21,0 @@ "devDependencies": { |
@@ -64,4 +64,5 @@ const path = require('path') | ||
historyApiFallback: true, | ||
hot: true | ||
hot: true, | ||
inline: false | ||
} | ||
} |
{ | ||
"scripts": { | ||
"build": "cross-env NODE_ENV=production webpack --mode production", | ||
"start": "concurrently \"npm run start:parent\" \"npm run start:child-fre\" \"npm run start:child-react\" \"npm run start:child-vue\"", | ||
"start:parent": "cross-env NODE_ENV=development webpack-dev-server --mode development", | ||
"build:berial": "cd ../../ && npm run build && cd example/parent", | ||
"start": "npm run build:berial && concurrently \"npm run start:parent\" \"npm run start:child-fre\" \"npm run start:child-react\" \"npm run start:child-vue\"", | ||
"start:parent": "cross-env NODE_ENV=development webpack-dev-server --mode production", | ||
"start:child-fre": "cd ../child-fre && npm start", | ||
@@ -7,0 +8,0 @@ "start:child-react": "cd ../child-react && npm start", |
{ | ||
"name": "berial", | ||
"version": "0.0.6", | ||
"version": "0.0.7", | ||
"description": "micro frontend", | ||
@@ -17,3 +17,4 @@ "main": "dist/berial.js", | ||
"serve": "serve ./demo/", | ||
"type": "tsc --project tsconfig.json --skipLibCheck --noEmit" | ||
"type": "tsc --project tsconfig.json --skipLibCheck --noEmit", | ||
"test": "karma start karma.conf.js" | ||
}, | ||
@@ -33,6 +34,9 @@ "repository": { | ||
"@rollup/plugin-replace": "^2.3.3", | ||
"@types/jest": "^24.0.18", | ||
"@types/chai": "^4.2.12", | ||
"@types/mocha": "^8.0.3", | ||
"@types/node": "^10.12.24", | ||
"@types/sinon": "^9.0.5", | ||
"@typescript-eslint/eslint-plugin": "^3.7.0", | ||
"@typescript-eslint/parser": "^3.7.0", | ||
"chai": "^4.2.0", | ||
"eslint": "^7.5.0", | ||
@@ -43,9 +47,15 @@ "eslint-config-prettier": "^6.11.0", | ||
"husky": "^4.2.5", | ||
"jest": "^24.1.0", | ||
"karma": "^5.1.1", | ||
"karma-chrome-launcher": "^3.1.0", | ||
"karma-mocha": "^2.0.1", | ||
"karma-spec-reporter": "0.0.32", | ||
"karma-typescript": "^5.1.0", | ||
"mocha": "^8.1.1", | ||
"npm-run-all": "^4.1.5", | ||
"prettier": "^2.0.5", | ||
"puppeteer": "^5.2.1", | ||
"rollup": "^2.23.0", | ||
"rollup-plugin-typescript2": "^0.27.1", | ||
"serve": "^11.3.2", | ||
"ts-jest": "^26.1.4", | ||
"sinon": "^9.0.3", | ||
"tslib": "^2.0.0", | ||
@@ -56,5 +66,5 @@ "typescript": "^3.9.7" | ||
"hooks": { | ||
"pre-commit": "run-p fmt fix; git add ." | ||
"pre-commit": "run-p fmt fix;" | ||
} | ||
} | ||
} |
@@ -27,5 +27,5 @@ import typescript from 'rollup-plugin-typescript2' | ||
removeComments: true, | ||
useTsconfigDeclarationDir: true, | ||
}), | ||
useTsconfigDeclarationDir: true | ||
}) | ||
] | ||
} |
@@ -197,10 +197,9 @@ import type { App } from './types' | ||
function polyfillRoute(updateState: any): () => void { | ||
function polyfillHistory(fn: any): () => void { | ||
return function (): void { | ||
const urlBefore = window.location.href | ||
const before = window.location.href | ||
// @ts-ignore | ||
updateState.apply(this, arguments) | ||
const urlAfter = window.location.href | ||
if (urlBefore !== urlAfter) { | ||
fn.apply(this, arguments) | ||
const after = window.location.href | ||
if (before !== after) { | ||
// @ts-ignore | ||
@@ -212,3 +211,3 @@ reroute(new PopStateEvent('popstate')) | ||
window.history.pushState = polyfillRoute(window.history.pushState) | ||
window.history.replaceState = polyfillRoute(window.history.replaceState) | ||
window.history.pushState = polyfillHistory(window.history.pushState) | ||
window.history.replaceState = polyfillHistory(window.history.replaceState) |
@@ -1,4 +0,4 @@ | ||
import type { App, PromiseFn, Lifecycles, Lifecycle, ProxyType } from './types' | ||
import type { App, PromiseFn, Lifecycles, ProxyType } from './types' | ||
import { proxy } from './proxy' | ||
import { run } from './sandbox' | ||
import { request } from './util' | ||
@@ -50,4 +50,3 @@ | ||
const bodyNode = loadBody(template) | ||
const fake = proxy(window as any, null) | ||
const lifecycle = await loadScript(template, fake, app.name) | ||
const lifecycle = await loadScript(template, app.name) | ||
return { lifecycle, styleNodes, bodyNode } | ||
@@ -58,3 +57,2 @@ } | ||
template: string, | ||
global: ProxyType, | ||
name: string | ||
@@ -72,3 +70,3 @@ ): Promise<Lifecycles> { | ||
scriptsToLoad.forEach((script) => { | ||
const lifecycles = runScript(script, global, name) | ||
const lifecycles = run(script, {})[name] | ||
bootstrap = [...bootstrap, lifecycles.bootstrap] | ||
@@ -111,24 +109,2 @@ mount = [...mount, lifecycles.mount] | ||
function runScript( | ||
script: string, | ||
global: ProxyType, | ||
umdName: string | ||
): Lifecycle { | ||
const resolver = new Function( | ||
'window', | ||
` | ||
with(window.IS_BERIAL_SANDBOX) { | ||
try { | ||
${script} | ||
return window['${umdName}'] | ||
} | ||
catch(e) { | ||
console.log(e) | ||
} | ||
} | ||
` | ||
) | ||
return resolver.call(global, global) | ||
} | ||
async function loadCSS(template: string): Promise<HTMLStyleElement[]> { | ||
@@ -135,0 +111,0 @@ const { cssURLs, styles } = parseCSS(template) |
import { start, register } from './app' | ||
import { mixin, use } from './mixin' | ||
import { loadScript, importHtml } from './html-loader' | ||
import { proxy } from './proxy' | ||
import { importHtml } from './html-loader' | ||
import { run } from './sandbox' | ||
@@ -9,5 +9,4 @@ export const Berial = { | ||
register, | ||
loadScript, | ||
importHtml, | ||
proxy, | ||
run, | ||
mixin, | ||
@@ -19,2 +18,2 @@ use | ||
export { start, register, loadScript, importHtml, proxy, mixin, use } | ||
export { start, register, importHtml, run, mixin, use } |
@@ -6,6 +6,6 @@ import type { Lifecycles } from './types' | ||
export function use(plugin: () => any): void { | ||
export function use(plugin: (args: any) => any, ...args: any): void { | ||
if (!plugins.has(plugin)) { | ||
plugins.add(plugin) | ||
plugin() | ||
plugin(args) | ||
} | ||
@@ -12,0 +12,0 @@ } |
@@ -20,2 +20,3 @@ import type { Lifecycle, Lifecycles } from './types' | ||
export function request(url: string, option?: RequestInit): Promise<string> { | ||
console.log(url) | ||
if (!window.fetch) { | ||
@@ -44,9 +45,4 @@ error( | ||
export function reverse(arr: any[]): any[] { | ||
let last: any | ||
const reversed: any[] = [] | ||
while ((last = arr.pop())) { | ||
reversed.push(last) | ||
} | ||
return reversed | ||
export function reverse<T>(arr: T[]): T[] { | ||
return Array.from(arr).reverse() | ||
} |
@@ -8,2 +8,3 @@ { | ||
"noImplicitAny": true, | ||
"removeComments":true, | ||
"target": "es6", | ||
@@ -20,4 +21,4 @@ "module": "es6", | ||
}, | ||
"include": ["src/**/*", "types"], | ||
"exclude": ["**/__tests__", "node_modules"] | ||
"include": ["src/**/*"], | ||
"exclude": ["test/*", "node_modules"] | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
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 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
98966
55
1881
28
6
2