Skip to content

Commit

Permalink
feat: receive each advisory info separatly (#32)
Browse files Browse the repository at this point in the history
fixes #26 
depends on #30 

First, I moved from `message` communication to `port` communication, as
described
[here](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#choosing_between_one-off_messages_and_connection-based_messaging).

Then, I split the advisories fetching to send a message when each
advisory info is fetched, instead of aggregating them all together.

---------

Co-authored-by: jossef <jossef12@gmail.com>
  • Loading branch information
baruchiro and jossef committed Mar 19, 2023
1 parent 360af54 commit cebdb97
Show file tree
Hide file tree
Showing 13 changed files with 107 additions and 109 deletions.
2 changes: 1 addition & 1 deletion src/background.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { listen } from './background/bridge';
import { listen } from './background/background-events';

listen();
27 changes: 18 additions & 9 deletions src/background/advisory/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,23 @@ const handleAsyncError = (func, ...args) =>
return null;
});

export default async (packageID) => {
const [debricked, depsDev, openbase, snyk, socket] = await Promise.all([
handleAsyncError(fetchDebricked, packageID),
handleAsyncError(fetchDepsDev, packageID),
handleAsyncError(fetchOpenbase, packageID),
handleAsyncError(fetchSnyk, packageID),
handleAsyncError(fetchSocket, packageID),
]);
export default (packageID) => {
const depsDev = handleAsyncError(fetchDepsDev, packageID);
const info = depsDev.then((depsDevInfo) => {
const { latestVersion, licenses, stars } = depsDevInfo.data;
return {
latest: latestVersion,
licenses,
stars,
};
});

return { debricked, depsDev, openbase, snyk, socket };
return {
debricked: handleAsyncError(fetchDebricked, packageID),
depsDev,
info,
openbase: handleAsyncError(fetchOpenbase, packageID),
snyk: handleAsyncError(fetchSnyk, packageID),
socket: handleAsyncError(fetchSocket, packageID),
};
};
20 changes: 11 additions & 9 deletions src/background/advisory/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ import advisory from '.';

describe('advisory', () => {
it(`should contain shared properties in each advisory`, async () => {
const results = await advisory({ type: 'npm', name: 'react' });
const { info, ...advisories } = advisory({ type: 'npm', name: 'react' });

Object.entries(results).forEach(([_name, advisor]) => {
expect(advisor).toEqual(
expect.objectContaining({
issues: expect.any(Number),
data: expect.any(Object),
})
);
});
const { latest, licenses, stars } = await info;
expect(latest).toEqual(expect.any(String));
expect(licenses).toEqual(expect.any(Array));
expect(stars).toEqual(expect.any(Number));

for (const name in advisories) {
const { issues, data } = await advisories[name];
expect(issues).toEqual(expect.any(Number));
expect(data).toEqual(expect.any(Object));
}
});
});
28 changes: 28 additions & 0 deletions src/background/background-events.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { REQUEST_PACKAGE_INFO_EVENT, RESPONSE_PACKAGE_INFO_EVENT } from '../events-shared';
import advisories from './advisory/index';

const listener = async ({ type, detail }, port) => {
if (type === REQUEST_PACKAGE_INFO_EVENT) {
const promises = await advisories(detail);
Object.entries(promises).forEach(([part, promise]) => {
promise.then((info) => {
port.postMessage({
type: RESPONSE_PACKAGE_INFO_EVENT,
detail: {
packageId: detail,
part,
info,
},
});
});
});
}

return true;
};

export const listen = () => {
chrome.runtime.onConnect.addListener((port) => {
port.onMessage.addListener(listener);
});
};
30 changes: 0 additions & 30 deletions src/background/bridge.js

This file was deleted.

22 changes: 11 additions & 11 deletions src/content.stackoverflow.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { mountContentScript } from './content';
import { getPackageInfo } from './content/bridge';
import { sendPackageInfoToWebapp } from './content/content-events';
import { fetchPackageInfo } from './content/content-events';
import { findRanges } from './content/stackoverflow/finder';
import { addIndicator } from './content/stackoverflow/indicator';

mountContentScript(async () => {
const findings = findRanges(document.body);
console.debug({ findings });

findings.reduce((acc, current) => {
const { type, name } = current;
if (acc[type + '_' + name]) return acc;
let processed = {};
findings.forEach(({ range, ...packageId }) => {
addIndicator(range, packageId);
let packageKey = `${packageId.type}/${packageId.name}`;
if (processed[packageKey]) {
return;
}

getPackageInfo(find).then(sendPackageInfoToWebapp);
acc[type + '_' + name] = true;
return acc;
}, {});

findings.forEach(addIndicator);
processed[packageKey] = true;
fetchPackageInfo(packageId);
});
});
13 changes: 0 additions & 13 deletions src/content/bridge.js

This file was deleted.

23 changes: 20 additions & 3 deletions src/content/content-events.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,23 @@
import { dispatchEvent, READY_EVENT, RESPONSE_PACKAGE_INFO_EVENT } from '../events-shared';
import {
CONTENT_PORT_CONNECTION,
dispatchEvent,
READY_EVENT,
REQUEST_PACKAGE_INFO_EVENT,
RESPONSE_PACKAGE_INFO_EVENT,
} from '../events-shared';

const sendPackageInfoToWebapp = (info) => dispatchEvent(RESPONSE_PACKAGE_INFO_EVENT, info);

const backgroundConnection = chrome.runtime.connect({ name: CONTENT_PORT_CONNECTION });
backgroundConnection.onMessage.addListener((message) => {
if (message.type === RESPONSE_PACKAGE_INFO_EVENT) {
sendPackageInfoToWebapp(message.detail);
}
});

export const fetchPackageInfo = (packageId) => {
backgroundConnection.postMessage({ type: REQUEST_PACKAGE_INFO_EVENT, detail: packageId });
};

let isWebappReady = false;
export const onScriptLoaded = (timeout = 5000, interval = 100) => {
Expand All @@ -24,5 +43,3 @@ export const listen = () => {
isWebappReady = true;
});
};

export const sendPackageInfoToWebapp = (info) => dispatchEvent(RESPONSE_PACKAGE_INFO_EVENT, info);
4 changes: 1 addition & 3 deletions src/content/stackoverflow/indicator.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
export const addIndicator = async ({ range, ...packageID }) => {
export const addIndicator = async (range, packageID) => {
console.debug('Adding indicator for', packageID);

const indicator = document.createElement('overlay-indicator');
indicator.setAttribute('overlay-indicator-package-type', packageID.type);
indicator.setAttribute('overlay-indicator-package-name', packageID.name);
indicator.appendChild(range.extractContents());
range.insertNode(indicator);

// TODO: handle info for package, from inside the component or from store
};
14 changes: 12 additions & 2 deletions src/custom-elements/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,21 @@ import { reactive } from 'vue';
const store = reactive({ packages: {} });
window.__overlay_global_store = store;

export const updatePackageInfo = ({ type, name, ...info }) => {
export const updatePackageInfo = ({ type, name }, part, info) => {
if (!store.packages[type]) {
store.packages[type] = {};
}
store.packages[type][name] = info;
if (!store.packages[type][name]) {
store.packages[type][name] = {
sources: {},
};
}

if (part === 'info') {
store.packages[type][name] = { ...store.packages[type][name], ...info };
return;
}
store.packages[type][name].sources[part] = info;
};

export default store;
5 changes: 3 additions & 2 deletions src/custom-elements/webapp-events.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import * as store from './store.js';
export const initEventListenersAndStore = () => {
console.debug('Store initialized by referencing to the store', store);

window.addEventListener(RESPONSE_PACKAGE_INFO_EVENT, (event) => {
store.updatePackageInfo(event.detail);
window.addEventListener(RESPONSE_PACKAGE_INFO_EVENT, ({ detail }) => {
const { packageId, part, info } = detail;
store.updatePackageInfo(packageId, part, info);
});

dispatchEvent(READY_EVENT);
Expand Down
4 changes: 2 additions & 2 deletions src/events-shared.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export const PACKAGE_INFO_ACTION = 'PACKAGE_INFO_ACTION';

const overlayPrefix = 'overlay-';
export const REQUEST_PACKAGE_INFO_EVENT = overlayPrefix + 'REQUEST_PACKAGE_INFO_EVENT';
export const RESPONSE_PACKAGE_INFO_EVENT = overlayPrefix + 'RESPONSE_PACKAGE_INFO_EVENT';
export const READY_EVENT = overlayPrefix + 'READY_EVENT';
export const CONTENT_PORT_CONNECTION = overlayPrefix + 'content-script';

export const dispatchEvent = (type, detail) => {
const event = new CustomEvent(type, { detail });
Expand Down
24 changes: 0 additions & 24 deletions src/indicator.css

This file was deleted.

0 comments on commit cebdb97

Please sign in to comment.