Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions public/components/views/search/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,8 @@ export class SearchView {
}

fetchPackage(packageName, version) {
const pkg = `${packageName}@${version}`;

window.socket.commands.search(pkg);
const spec = `${packageName}@${version}`;
window.socket.commands.search(spec);
}

async fetchPackageVersions(packageName) {
Expand All @@ -259,7 +258,7 @@ export class SearchView {
return versions.reverse();
}

onScan(pkg) {
onScan(spec) {
const searchViewForm = document.querySelector("#search--view form");
searchViewForm?.remove();
const containerResult = document.querySelector("#search--view .result-container");
Expand All @@ -268,7 +267,7 @@ export class SearchView {
const searchViewContainer = document.querySelector("#search--view .container");
const scanInfo = document.createElement("div");
scanInfo.classList.add("scan-info");
scanInfo.textContent = `Scanning ${pkg}.`;
scanInfo.textContent = `Scanning ${spec}`;
const spinner = document.createElement("div");
spinner.classList.add("spinner");
searchViewContainer.appendChild(scanInfo);
Expand Down
14 changes: 8 additions & 6 deletions public/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ document.addEventListener("DOMContentLoaded", async() => {
socket.addEventListener("SCAN", (event) => {
const data = event.detail;

searchview.onScan(data.pkg);
searchview.onScan(data.spec);
});
});

Expand All @@ -73,9 +73,10 @@ async function onSocketPayload(event) {

async function onSocketInitOrReload(event) {
const data = event.detail;
const { cache } = data;

window.scannedPackageCache = data.availables;
window.recentPackageCache = data.lru;
window.scannedPackageCache = cache.availables;
window.recentPackageCache = cache.lru;
console.log(
"[INFO] Older packages are loaded!",
window.scannedPackageCache
Expand All @@ -85,7 +86,7 @@ async function onSocketInitOrReload(event) {
window.recentPackageCache
);

initSearchNav(data, {
initSearchNav(cache, {
searchOptions: {
nsn,
secureDataSet
Expand All @@ -107,9 +108,10 @@ async function onSocketInitOrReload(event) {
await init();

// FIXME: initSearchNav is called twice, we need to fix this
initSearchNav(data, {
initSearchNav(cache, {
searchOptions: {
nsn, secureDataSet
nsn,
secureDataSet
}
});
}
Expand Down
4 changes: 2 additions & 2 deletions public/websocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ export class WebSocketClient extends EventTarget {
this.client = new WebSocket(url);
this.client.addEventListener("message", this.#messageHandler.bind(this));
this.commands = {
search: (pkg) => this.send({ action: "SEARCH", pkg }),
remove: (pkg) => this.send({ action: "REMOVE", pkg })
search: (spec) => this.send({ commandName: "SEARCH", spec }),
remove: (spec) => this.send({ commandName: "REMOVE", spec })
};

window.socket = this;
Expand Down
14 changes: 7 additions & 7 deletions workspaces/server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ All static files (UI, assets, etc.) are served from the project root directory.
> [!NOTE]
> For more details on each endpoint, see the corresponding files in /src/endpoints.

## Websocket actions
## Websocket commands

The `WebSocketServerInstanciator` class sets up and manages a WebSocket server for real-time communication with NodeSecure clients. It provides live updates and cache management features for package analysis.

Expand All @@ -183,27 +183,27 @@ new WebSocketServerInstanciator();
- Initializes a WebSocket server on port 1338.
- Listens for client connections and incoming messages.

- `SEARCH`:
### SEARCH

**Request**:
```json
{
"action": "SEARCH",
"pkg": "<package-name>"
"commandName": "SEARCH",
"spec": "<package-name>@<package-version>"
}
```

**Response**:

Streams scan progress, payload data, and cache state updates.

- `REMOVE`:
### REMOVE

**Request**:
```json
{
"action": "REMOVE",
"pkg": "<package-name>"
"commandName": "REMOVE",
"spec": "<package-name>@<package-version>"
}
```

Expand Down
178 changes: 84 additions & 94 deletions workspaces/server/src/websocket/commands/remove.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,111 +8,101 @@ import type {
} from "../websocket.types.js";

export async function* remove(
pkg: string,
spec: string,
context: WebSocketContext
): AsyncGenerator<WebSocketResponse, void, unknown> {
const { cache, logger } = context;

logger.info(`[ws|remove](pkg: ${pkg})`);

try {
const { mru, lru, current, lastUsed, root, availables } = await cache.payloadsList();
delete lastUsed[pkg];
if (availables.includes(pkg)) {
logger.info("[ws|remove] remove from availables");
cache.removePayload(pkg);
const updatedList: PayloadsList = {
mru,
current,
lru,
lastUsed: {
...lastUsed
},
root,
availables: availables.filter((pkgName) => pkgName !== pkg)
};
await cache.updatePayloadsList(updatedList);

yield {
status: "RELOAD",
...updatedList
};

return;
}

logger.debug(`[ws|remove](lru: ${lru}|current: ${current})`);

if (mru.length === 1 && lru.length === 0) {
throw new Error("Cannot remove the last package.");
}

const mruIndex = mru.findIndex((pkgName) => pkgName === pkg);
const lruIndex = lru.findIndex((pkgName) => pkgName === pkg);

if (mruIndex === -1 && lruIndex === -1) {
throw new Error("Package not found in cache.");
}
const { mru, lru, current, lastUsed, root, availables } = await cache.payloadsList();
delete lastUsed[spec];
if (availables.includes(spec)) {
logger.info("[ws|command.remove] remove from availables");
cache.removePayload(spec);
const updatedList: PayloadsList = {
mru,
current,
lru,
lastUsed: {
...lastUsed
},
root,
availables: availables.filter((iterSpec) => iterSpec !== spec)
};
await cache.updatePayloadsList(updatedList);

yield {
status: "RELOAD",
cache: updatedList
};

return;
}

if (mruIndex > -1) {
logger.info("[ws|remove](remove from lru)");
const updatedMru = mru.filter((pkgName) => pkgName !== pkg);
if (lru.length > 0) {
// We need to move the first lru package to the mru list
const olderLruPkg = lru.sort((a, b) => {
const aDate = lastUsed[a];
const bDate = lastUsed[b];
logger.debug(`[ws|command.remove](lru: ${lru}|current: ${current})`);

return aDate - bDate;
});
updatedMru.push(olderLruPkg[0]);
lru.splice(lru.indexOf(olderLruPkg[0]), 1);
}
if (mru.length === 1 && lru.length === 0) {
throw new Error("Cannot remove the last package.");
}

const updatedList: PayloadsList = {
mru: updatedMru,
lru,
lastUsed: {
...lastUsed
},
current: current === pkg ? updatedMru[0] : current,
root,
availables
};
await cache.updatePayloadsList(updatedList);
const mruIndex = mru.findIndex((iterSpec) => iterSpec === spec);
const lruIndex = lru.findIndex((iterSpec) => iterSpec === spec);

yield {
status: "RELOAD",
...updatedList
};
}
else {
logger.info("[ws|remove](remove from lru)");
const updatedLru = lru.filter((pkgName) => pkgName !== pkg);
const updatedList: PayloadsList = {
mru,
lru: updatedLru,
availables,
lastUsed: {
...lastUsed
},
current,
root
};
await cache.updatePayloadsList(updatedList);
if (mruIndex === -1 && lruIndex === -1) {
throw new Error("Package not found in cache.");
}

yield {
status: "RELOAD",
...updatedList
};
if (mruIndex > -1) {
logger.info("[ws|command.remove] removed from mru");
const updatedMru = mru.filter((iterSpec) => iterSpec !== spec);
if (lru.length > 0) {
// We need to move the first lru package to the mru list
const olderLruPkg = lru.sort((a, b) => {
const aDate = lastUsed[a];
const bDate = lastUsed[b];

return aDate - bDate;
});
updatedMru.push(olderLruPkg[0]);
lru.splice(lru.indexOf(olderLruPkg[0]), 1);
}

cache.removePayload(pkg);
const updatedList: PayloadsList = {
mru: updatedMru,
lru,
lastUsed: {
...lastUsed
},
current: current === spec ? updatedMru[0] : current,
root,
availables
};
await cache.updatePayloadsList(updatedList);

yield {
status: "RELOAD",
cache: updatedList
};
}
catch (error: any) {
logger.error(`[ws|remove](error: ${error.message})`);
logger.debug(error);

throw error;
else {
logger.info("[ws|command.remove] removed from lru");
const updatedLru = lru.filter((iterSpec) => iterSpec !== spec);
const updatedList: PayloadsList = {
mru,
lru: updatedLru,
availables,
lastUsed: {
...lastUsed
},
current,
root
};
await cache.updatePayloadsList(updatedList);

yield {
status: "RELOAD",
cache: updatedList
};
}

cache.removePayload(spec);
}
Loading