Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: receive each advisory info separatly #32

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
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),
};
};
Comment on lines +13 to 32
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the trick. Instead of returning a complete result, I returned a Promise for each key.

This allows me to add a .then to each promise, for registering a port.sendMessage at the end of each promise.

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);
});
};
Comment on lines +4 to +28
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code became a deep indentation, and also I'm struggling with the objects that passed between the events, each one requires a particular property for its use case.

I'm open to suggestions.

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.