Skip to content

Commit a3a9f40

Browse files
committed
Write initial github backend
1 parent 9c54a70 commit a3a9f40

File tree

5 files changed

+104
-16
lines changed

5 files changed

+104
-16
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
"json-stable-stringify": "^1.0.1",
7272
"module-alias": "^2.1.0",
7373
"original-require": "^1.0.1",
74+
"request-promise": "^4.2.4",
7475
"source-map-support": "^0.5.9",
7576
"web3": "^1.0.0-beta.36"
7677
},

src/storage/github/index.ts

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,40 @@
44

55
import * as config from "ethpm/config";
66
import * as storage from "ethpm/storage";
7+
import * as t from "io-ts";
8+
import { Maybe } from "ethpm/types";
9+
import { URL } from "url";
10+
import { isValidGithubUri } from "./validation";
11+
12+
import request = require("request-promise");
13+
export { isValidGithubUri } from "./validation";
14+
15+
async function makeGithubRequest(blobUri: URL): Promise<string> {
16+
let response: any = {};
17+
const options = {
18+
uri: blobUri,
19+
json: true,
20+
headers: { "user-agent": "node.js" }
21+
};
22+
23+
await request
24+
.get(options)
25+
.then(body => {
26+
const decoded = new Buffer(body.content, "base64");
27+
response = decoded.toString("ascii");
28+
})
29+
.catch(err => {
30+
response = err.toString();
31+
});
32+
return response;
33+
}
734

835
export class GithubService implements storage.Service {
936
async read(uri: URL): Promise<Maybe<string>> {
10-
11-
// validate uri
12-
// fetch contents
13-
// validate fetched contents
37+
if (!isValidGithubUri(uri)) {
38+
throw new TypeError(uri + "is not a valid content addressed Github uri.");
39+
}
40+
let base64Contents = await makeGithubRequest(uri);
41+
return base64Contents;
1442
}
1543
}
16-
17-
export default class GithubConnector extends config.Connector<storage.Service> {
18-
/**
19-
* Construct GithubService and load with specified contents
20-
*/
21-
async init(): Promise<GithubService> {
22-
const service = new GithubService();
23-
return service;
24-
}
25-
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { GithubService } from "ethpm/storage/github";
2+
import { URL } from "url";
3+
import examples from "test/examples/manifests";
4+
5+
describe("Github service returns URI contents", () => {
6+
it("with valid blob URI", async () => {
7+
const ownedBlobUri = new URL(
8+
"https://api.github.com/repos/ethpm/ethpm-spec/git/blobs/8f9dc767d4c8b31fec4a08d9c0858d4f37b83180"
9+
);
10+
const service = new GithubService();
11+
const actualContents = await service.read(ownedBlobUri);
12+
expect(actualContents).toBe(examples.owned);
13+
});
14+
});
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { isValidGithubUri } from "ethpm/storage/github";
2+
import { URL } from "url";
3+
4+
const invalidUris = [
5+
// http is not valid protocol
6+
"http://api.github.com/repos/ethpm/ethpm-spec/git/blobs/123",
7+
// www.github.com is not valid hostname
8+
"https://www.github.com/repos/ethpm/ethpm-spec/git/blobs/123",
9+
// path doesn't contain 'repos' & 'git' & 'blobs'
10+
"https://api.github.com/ethpm/ethpm-spec/git/blobs/123",
11+
"https://api.github.com/repos/ethpm/ethpm-spec/blobs/123",
12+
"https://api.github.com/repos/ethpm/ethpm-spec/git/123"
13+
];
14+
15+
const validUris = [
16+
"https://api.github.com/repos/ethpm/ethpm-spec/git/blobs/123",
17+
"https://api.github.com/repos/other/repository/git/blobs/123"
18+
];
19+
20+
invalidUris.forEach(uri => {
21+
describe("Github uri validator invalidates", () => {
22+
it(uri, () => {
23+
const result = isValidGithubUri(new URL(uri));
24+
expect(result).toBe(false);
25+
});
26+
});
27+
});
28+
29+
validUris.forEach(uri => {
30+
describe("Github uri validator validates", () => {
31+
it(uri, () => {
32+
const result = isValidGithubUri(new URL(uri));
33+
expect(result).toBe(true);
34+
});
35+
});
36+
});

src/storage/github/validation.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,26 @@
11
/**
2-
* @module "ethpm/storage/github"
2+
* @module "ethpm/storage/github/validation"
33
*/
44

5-
export default function isValidGithubUri(uri: URL): boolean {
5+
import { URL } from "url";
66

7+
/**
8+
* Returns a bool indicating whether the given uri conforms to this scheme.
9+
* https://api.github.com/repos/:owner/:repo/git/blobs/:file_sha
10+
*/
11+
export function isValidGithubUri(uri: URL): boolean {
12+
if (uri.hostname != "api.github.com") {
13+
return false;
14+
}
15+
if (uri.protocol != "https:") {
16+
return false;
17+
}
18+
if (
19+
!uri.pathname.includes("/repos/") ||
20+
!uri.pathname.includes("/git/") ||
21+
!uri.pathname.includes("/blobs/")
22+
) {
23+
return false;
24+
}
25+
return true;
726
}

0 commit comments

Comments
 (0)