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: 7 additions & 2 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ The extension will expect you to pass in 2 parameters at flight time, otherwise
# Custom flight repos
You can host a custom flight repo and point the extension to it. This will allow you to define standard and logical flights without contributing to this project.

An example repo doc is here: `https://apollorion.com/flight_repo.json`
An example repo doc is here: `https://apollorion.com/flight_repo_named.json`

The custom flight repo has 2 requirements.
1. The `Access-Control-Allow-Origin: *` header is present (this is a chrome requirement)
Expand All @@ -83,7 +83,12 @@ interface CustomFlightRepo {
}
```

To use the custom flight repo, just run `fly set repo $url`. You can unset this repo at anytime via `fly unset repo`.
To use the custom flight repo, just run `fly repo set $name $url` then `fly repo update`. You can unset this repo at anytime via `fly repo unset $name`.
`fly repo update` will fetch the contents of the repository.

ex:
1. `fly repo set apollorion https://apollorion.com/flight_repo_named.json`
2. `fly repo update`

# Devving this repo

Expand Down
88 changes: 88 additions & 0 deletions extension/helpers.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { repoManagement } from './helpers';
import {setLocalStorage, getLocalStorage} from "./localstorage.js";

function mockGetLocalStorageWithResult() {
// @ts-ignore
getLocalStorage = jest.fn(async (key) => {
return new Promise((resolve, reject) => {
resolve("{}");
});
});
}

function mockGetLocalStorageWithoutResult() {
// @ts-ignore
getLocalStorage = jest.fn(async (key) => {
return new Promise((resolve, reject) => {
reject();
});
});
}

function mockSetLocalStorage() {
// @ts-ignore
setLocalStorage = jest.fn();
}

test("repo can set", async () => {
mockGetLocalStorageWithResult();
mockSetLocalStorage();

const result = await repoManagement(["repo", "set", "apollorion", "https://apollorion.com/flight_repo.json"]);
expect(result).toBe("set apollorion https://apollorion.com/flight_repo.json");
});

test("repo can unset", async () => {
mockGetLocalStorageWithResult();
mockSetLocalStorage();

const result = await repoManagement(["repo", "unset", "apollorion"]);
expect(result).toBe("unset apollorion");
});

test("repo can update", async () => {
mockGetLocalStorageWithResult();
mockSetLocalStorage();

const result = await repoManagement(["repo", "update"]);
expect(result).toBe("repos updated");
});

test("repo set no local storage", async () => {
mockGetLocalStorageWithoutResult();
mockSetLocalStorage();

const result = await repoManagement(["repo", "set", "apollorion", "https://apollorion.com/flight_repo.json"]);
expect(result).toBe("set apollorion https://apollorion.com/flight_repo.json");
});

test("repo unset no local storage", async () => {
mockGetLocalStorageWithoutResult();
mockSetLocalStorage();

const result = await repoManagement(["repo", "unset", "apollorion"]);
expect(result).toBe("unset apollorion");
});

test("repo update no local storage", async () => {
mockGetLocalStorageWithoutResult();
mockSetLocalStorage();

const result = await repoManagement(["repo", "update"]);
expect(result).toBe("repos updated");
});

test("repo management bad query", async () => {
const result = await repoManagement(["repo", "broken-query"]);
expect(result).toBe("Attempted to run broken-query, but that is not a valid action.");
});

test("repo management set called incorrectly", async () => {
const result = await repoManagement(["repo", "set", "apollorion"]);
expect(result).toBe("set called with missing parameter");
});

test("repo management unset called incorrectly", async () => {
const result = await repoManagement(["repo", "unset"]);
expect(result).toBe("unset called with missing parameter");
});
120 changes: 70 additions & 50 deletions extension/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {Flight, FlightType, LogicalFlightDefinition, StandardFlightDefinition, RepoFlightsResponse} from "./types.js";
import {logicalFlights, standardFlights} from "./flights.js";
import {setLocalStorage, getLocalStorage, unsetLocalStorage} from "./localstorage.js";

export async function getFlightFromQuery(query: string[], repoFlightResponse: RepoFlightsResponse | undefined): Promise<Flight> {
// Remove null items from values
Expand Down Expand Up @@ -66,25 +67,13 @@ export function getNewFlightResponseSynchronous(repoFlightResponse: RepoFlightsR
}

export async function checkRepoFlights(): Promise<RepoFlightsResponse | undefined>{
let response;
try {
const repoUrl = await getLocalStorage("repo");
const jsonString = await requestJson(repoUrl);
response = JSON.parse(jsonString);
const jsonString = await getLocalStorage("updated-repos");
return JSON.parse(jsonString);
} catch (e) {
console.log("No custom repo set", e);
return undefined;
}

if(response.version === "1" && Object.keys(response).includes("logical") && Object.keys(response).includes("standard")){
return {
standard: response.standard,
logical: response.logical
}
}

return undefined;

}

async function requestJson(url: string): Promise<string> {
Expand All @@ -95,6 +84,73 @@ async function requestJson(url: string): Promise<string> {
});
}

export async function repoManagement(query: string[]): Promise<string> {
query.shift();
const action = query[0];
query.shift();

if(!["set", "unset", "update"].includes(action)){
return `Attempted to run ${action}, but that is not a valid action.`;
}

if((action === "set" && query.length !== 2) || (action === "unset" && query.length !== 1)){
return `${action} called with missing parameter`;
}

let repos;
let repoResult;
switch(action){
case "set":
try {
repoResult = await getLocalStorage("repos");
} catch {
repoResult = "{}";
}
repos = JSON.parse(repoResult);

repos[query[0]] = query[1];
await setLocalStorage("repos", JSON.stringify(repos));
return `set ${query[0]} ${query[1]}`;
case "unset":
try {
repoResult = await getLocalStorage("repos");
} catch {
repoResult = "{}";
}
repos = JSON.parse(repoResult);

if(Object.keys(repos).includes(query[0])){
delete repos[query[0]];
}
await setLocalStorage("repos", JSON.stringify(repos));
return `unset ${query[0]}`;
case "update":
try {
repoResult = await getLocalStorage("repos");
} catch {
repoResult = "{}";
}
repos = JSON.parse(repoResult);

let newRepoContent = {standard: {}, logical: {}};
for(let name in repos){
try {
let json = JSON.parse(await requestJson(repos[name]));
if(json.version === "1" && Object.keys(json).includes("logical") && Object.keys(json).includes("standard")){
newRepoContent.standard = {...newRepoContent.standard, ...json.standard};
newRepoContent.logical = {...newRepoContent.logical, ...json.logical};
}
} catch {
console.log(`Failed to fetch repo ${name}`);
}
}
await setLocalStorage("updated-repos", JSON.stringify(newRepoContent));
return "repos updated";
default:
throw new Error("Incorrect repo action");
}
}


export async function setCalled(query: string[]){
if(query.length === 3){
Expand All @@ -107,20 +163,6 @@ export async function unsetCalled(query: string[]){
}
}

export async function getLocalStorage(key: string): Promise<string>{
return new Promise((resolve, reject) => {
console.log("get", key);
// @ts-ignore
chrome.storage.local.get([key], async function (items: { [x: string]: string; }) {
if(key in items){
resolve(items[key]);
} else {
reject();
}
});
});
}

export async function redirect(message: string, link: string){
const dev = false;
console.log(message, link);
Expand All @@ -129,26 +171,4 @@ export async function redirect(message: string, link: string){
// @ts-ignore
await chrome.tabs.update({url: link});
}
}

async function setLocalStorage(key: string, value: string){
return new Promise((resolve, reject) => {
console.log("set", key, value);
let obj: any = {};
obj[key] = value;
// @ts-ignore
chrome.storage.local.set(obj, function () {
resolve(undefined);
});
});
}

async function unsetLocalStorage(key: string){
return new Promise((resolve, reject) => {
console.log("unset", key);
// @ts-ignore
chrome.storage.local.remove(key, function () {
resolve(undefined);
});
});
}
35 changes: 35 additions & 0 deletions extension/localstorage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
export async function getLocalStorage(key: string): Promise<string>{
return new Promise((resolve, reject) => {
console.log("get", key);
// @ts-ignore
chrome.storage.local.get([key], async function (items: { [x: string]: string; }) {
if(key in items){
resolve(items[key]);
} else {
reject();
}
});
});
}

export async function setLocalStorage(key: string, value: string){
return new Promise((resolve, reject) => {
console.log("set", key, value);
let obj: any = {};
obj[key] = value;
// @ts-ignore
chrome.storage.local.set(obj, function () {
resolve(undefined);
});
});
}

export async function unsetLocalStorage(key: string){
return new Promise((resolve, reject) => {
console.log("unset", key);
// @ts-ignore
chrome.storage.local.remove(key, function () {
resolve(undefined);
});
});
}
3 changes: 2 additions & 1 deletion extension/main.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { handleFlight } from './main';
import { Flight, FlightType } from './types';
import { redirect, getLocalStorage } from './helpers';
import { redirect } from './helpers';
import { getLocalStorage } from "./localstorage.js";

beforeEach(() => {
jest.clearAllMocks();
Expand Down
16 changes: 10 additions & 6 deletions extension/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import {
getFlightFromQuery,
setCalled,
unsetCalled,
getLocalStorage,
redirect,
checkRepoFlights, getNewFlightResponseSynchronous
checkRepoFlights,
getNewFlightResponseSynchronous,
repoManagement
} from "./helpers.js";

const repoFlightResponsePromise = checkRepoFlights();
import {getLocalStorage } from "./localstorage.js";

export async function main() {
// @ts-ignore
Expand All @@ -22,16 +23,19 @@ export async function main() {
await setCalled(query);
} else if (query[0] === "unset") {
await unsetCalled(query);
} else if (query[0] === "repo") {
let resp = await repoManagement(query);
console.log(resp);
} else {
const repoFlightResponse = await repoFlightResponsePromise;
const repoFlightResponse = await checkRepoFlights();
const flight = await getFlightFromQuery(query, repoFlightResponse);
await handleFlight(flight);
}
});
}

export async function handleStandardFlight(flight: Flight){
const repoFlightResponse = await repoFlightResponsePromise;
const repoFlightResponse = await checkRepoFlights();
let newFlights = getNewFlightResponseSynchronous(repoFlightResponse);
const newStandardFlights = newFlights.standard;

Expand All @@ -47,7 +51,7 @@ export async function handleStandardFlight(flight: Flight){
}

export async function handleFlight(flight: Flight){
const repoFlightResponse = await repoFlightResponsePromise;
const repoFlightResponse = await checkRepoFlights();
let newFlights = getNewFlightResponseSynchronous(repoFlightResponse);
const newLogicalFlights = newFlights.logical;

Expand Down