Skip to content

Commit

Permalink
feat: add standalone mode for local scans
Browse files Browse the repository at this point in the history
  • Loading branch information
PierreDemailly committed Jan 9, 2025
1 parent 4b96608 commit 066618e
Show file tree
Hide file tree
Showing 11 changed files with 133 additions and 10 deletions.
17 changes: 16 additions & 1 deletion public/components/navigation/navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export class ViewNavigation {

const searchbar = document.getElementById("searchbar");
if (searchbar) {
searchbar.style.display = menuName === "network--view" ? "flex" : "none";
searchbar.style.display = menuName === "network--view" ? "flex" : "none";
}

this.activeMenu = selectedNav;
Expand Down Expand Up @@ -114,4 +114,19 @@ export class ViewNavigation {
this.setNewActiveMenu(selectedNav);
}
}

hideMenu(menuName, options = {}) {
const { navigateAway = false } = options;

const menu = this.menus.get(menuName);
if (!menu) {
return;
}

menu.classList.add("hidden");

if (navigateAway && this.activeMenu.isEqualNode(menu)) {
this.setNavByName("network--view");
}
}
}
2 changes: 2 additions & 0 deletions public/components/searchbar/searchbar.css
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ div.search-result-pannel .package+.package {
height: 30px;
left: 50px;
padding-left: 20px;
min-width: 455px;
max-width: calc(100vw - 70px);
box-sizing: border-box;
background: var(--primary);
Expand All @@ -227,6 +228,7 @@ div.search-result-pannel .package+.package {
display: flex;
max-width: calc(100vw - 70px - 264px);
background: var(--primary);
margin-left: auto;
}

#search-nav .packages>.package {
Expand Down
30 changes: 28 additions & 2 deletions public/core/search-nav.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@ import { createDOMElement, parseNpmSpec } from "../common/utils";
import { SearchBar } from "../components/searchbar/searchbar";

export function initSearchNav(data, options) {
const { initFromZero = true, searchOptions = null } = options;
const { initFromZero = true, searchOptions = null, initSinglePackage } = options;

const searchNavElement = document.getElementById("search-nav");
if (!searchNavElement) {
throw new Error("Unable to found search navigation");
}

if (initFromZero) {
if (initSinglePackage) {
searchNavElement.innerHTML = "";
searchNavElement.appendChild(
initSingleNavigation(initSinglePackage)
);
}
else if (initFromZero) {
searchNavElement.innerHTML = "";
searchNavElement.appendChild(
initPackagesNavigation(data)
Expand Down Expand Up @@ -122,3 +128,23 @@ function renderPackageRemoveButton(packageName, options) {

return removeButton;
}

function initSingleNavigation(packageName) {
const fragment = document.createDocumentFragment();
const container = createDOMElement("div", {
classList: ["packages"]
});

const pkgElement = createDOMElement("div", {
classList: ["package"],
childs: [
createDOMElement("p", { text: packageName })
]
});
pkgElement.dataset.name = packageName;

container.appendChild(pkgElement);
fragment.append(container);

return fragment;
}
19 changes: 17 additions & 2 deletions public/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,13 @@ document.addEventListener("DOMContentLoaded", async() => {
window.scannedPackageCache = [];
window.locker = null;
window.popup = new Popup();
window.navigation = new ViewNavigation();
window.settings = await new Settings().fetchUserConfig();
if (window.settings.config.standalone) {
console.log(`[INFO] Standalone mode activated`);
window.navigation.hideMenu("search--view", { navigateAway: true });
}
window.i18n = await new i18n().fetch();
window.navigation = new ViewNavigation();
window.wiki = new Wiki();

await init();
Expand Down Expand Up @@ -109,7 +113,18 @@ async function init(options = {}) {
window.locker = new Locker(nsn);
window.legend = new Legend({ show: window.settings.config.showFriendlyDependencies });
new HomeView(secureDataSet, nsn);
searchview ??= new SearchView(secureDataSet, nsn);
if (window.settings.config.standalone) {
window.activePackage = secureDataSet.data.rootDependencyName;
initSearchNav(void 0, {
initSinglePackage: secureDataSet.data.rootDependencyName,
searchOptions: {
nsn, secureDataSet
}
});
}
else {
searchview ??= new SearchView(secureDataSet, nsn);
}

window.addEventListener("package-info-closed", () => {
window.networkNav.currentNodeParams = null;
Expand Down
13 changes: 11 additions & 2 deletions src/commands/scanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import * as Scanner from "@nodesecure/scanner";

// Import Internal Dependencies
import * as http from "./http.js";
import { appCache } from "../http-server/cache.js";

export async function auto(spec, options) {
const { keep, ...commandOptions } = options;
Expand Down Expand Up @@ -59,7 +60,7 @@ export async function cwd(options) {
initLogger(void 0, !silent)
);

return logAndWrite(payload, output);
return logAndWrite(payload, output, { lockUi: true });
}

export async function from(spec, options) {
Expand Down Expand Up @@ -153,7 +154,11 @@ function initLogger(spec, verbose = true) {
return logger;
}

function logAndWrite(payload, output = "nsecure-result") {
function logAndWrite(payload, output = "nsecure-result", options = {}) {
const {
lockUi = false
} = options;

if (payload === null) {
console.log(i18n.getTokenSync("cli.no_dep_to_proceed"));

Expand All @@ -179,5 +184,9 @@ function logAndWrite(payload, output = "nsecure-result") {
console.log(kleur.white().bold(i18n.getTokenSync("cli.successfully_written_json", kleur.green().bold(filePath))));
console.log("");

if (lockUi) {
appCache.setStandalonePayload(payload);
}

return filePath;
}
22 changes: 22 additions & 0 deletions src/http-server/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ export const CACHE_PATH = path.join(os.tmpdir(), "nsecure-cli");
export const DEFAULT_PAYLOAD_PATH = path.join(process.cwd(), "nsecure-result.json");

class _AppCache {
/**
* - `undefined`: unknown
* - `true`: standalone
* - `false`: not standalone
*/
isStandalone;

constructor() {
fs.mkdirSync(kPayloadsPath, { recursive: true });
}
Expand Down Expand Up @@ -127,6 +134,21 @@ class _AppCache {
root
};
}

async setStandalonePayload(payload) {
await cacache.put(CACHE_PATH, "standalone", JSON.stringify(payload));
}

async getStandalonePayload() {
try {
const { data } = await cacache.get(CACHE_PATH, "standalone");

return JSON.parse(data.toString());
}
catch {
return null;
}
}
}

export const appCache = new _AppCache();
20 changes: 18 additions & 2 deletions src/http-server/config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// Import Node.js Dependencies
import fs from "node:fs";

// Import Internal Dependencies
import { appCache } from "./cache.js";
import { appCache, DEFAULT_PAYLOAD_PATH } from "./cache.js";
import { logger } from "./logger.js";

// CONSTANTS
Expand All @@ -12,14 +15,27 @@ export async function get() {
try {
const config = await appCache.getConfig();

let standalone = false;
const standalonePayload = await appCache.getStandalonePayload();
if (standalonePayload && fs.existsSync(DEFAULT_PAYLOAD_PATH)) {
const localPayload = JSON.parse(fs.readFileSync(DEFAULT_PAYLOAD_PATH, "utf-8"));
if (localPayload.id === standalonePayload.id) {
standalone = true;
}
}
appCache.isStandalone = standalone;
Object.assign(config, { standalone });

const {
defaultPackageMenu,
ignore: {
flags,
warnings
} = {}
} = config;
logger.info(`[config|get](defaultPackageMenu: ${defaultPackageMenu}|ignore-flag: ${flags}|ignore-warnings: ${warnings})`);
logger.info(
`[config|get](defaultPackageMenu: ${defaultPackageMenu}|flags: ${flags}|warnings: ${warnings}|standalone: ${standalone})`
);

return config;
}
Expand Down
8 changes: 8 additions & 0 deletions src/http-server/endpoints/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ import { logger } from "../logger.js";
const kDefaultPayloadPath = path.join(process.cwd(), "nsecure-result.json");

export async function get(req, res) {
if (appCache.isStandalone) {
logger.info("[data|get] standalone mode");
const payload = await appCache.getStandalonePayload();
send(res, 200, payload);

return;
}

try {
const { current, lru } = await appCache.payloadsList();
logger.info(`[data|get](current: ${current})`);
Expand Down
4 changes: 4 additions & 0 deletions src/http-server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import * as report from "./endpoints/report.js";
import * as middleware from "./middleware.js";
import * as wsHandlers from "./websocket/index.js";
import { logger } from "./logger.js";
import { appCache } from "./cache.js";

export function buildServer(dataFilePath, options = {}) {
const httpConfigPort = typeof options.port === "number" ? options.port : 0;
Expand Down Expand Up @@ -65,6 +66,9 @@ export function buildServer(dataFilePath, options = {}) {
if (enableWS) {
const websocket = new WebSocketServer({ port: 1338 });
websocket.on("connection", async(socket) => {
if (appCache.isStandalone) {
return;
}
socket.on("message", async(rawMessage) => {
const message = JSON.parse(rawMessage);
logger.info(`[ws](message: ${JSON.stringify(message)})`);
Expand Down
4 changes: 4 additions & 0 deletions src/http-server/websocket/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { appCache } from "../cache.js";
import { logger } from "../logger.js";

export async function init(socket, lock = false) {
if (appCache.isStandalone) {
return;
}

try {
const { current, lru, older, root } = await appCache.payloadsList();
logger.info(`[ws|init](lru: ${lru}|older: ${older}|current: ${current}|root: ${root})`);
Expand Down
4 changes: 3 additions & 1 deletion workspaces/vis-network/src/dataset.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,9 @@ export default class NodeSecureDataSet extends EventTarget {
if (author === null) {
return;
}
const contributor = contributors.find((contributor) => contributor.email === author.email && contributor.npmAvatar !== null);
const contributor = contributors.find(
(contributor) => contributor?.email === author.email && contributor?.npmAvatar !== null
);

if (this.authors.has(author.name)) {
this.authors.get(author.name).packages.add(spec);
Expand Down

0 comments on commit 066618e

Please sign in to comment.