1
0
mirror of https://github.com/sehugg/8bitworkshop.git synced 2024-07-22 05:29:11 +00:00
8bitworkshop/gen/ide/services.js

360 lines
13 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FirebaseProjectFilesystem = exports.GithubService = exports.parseGithubURL = exports.getRepos = void 0;
const util_1 = require("../common/util");
const README_md_template = "$NAME\n=====\n\n[Open this project in 8bitworkshop](http://8bitworkshop.com/redir.html?platform=$PLATFORM&githubURL=$GITHUBURL&file=$MAINFILE).\n";
function getRepos() {
var repos = {};
for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i);
if (key.startsWith('__repo__')) {
var repodata = JSON.parse(localStorage.getItem(key));
var path = key.substring('__repo__'.length);
repos[path] = repodata;
}
}
return repos;
}
exports.getRepos = getRepos;
function parseGithubURL(ghurl) {
var toks = ghurl.split('/', 8);
if (toks.length < 5)
return null;
if (toks[0] != 'https:')
return null;
if (toks[2] != 'github.com')
return null;
if (toks[5] && toks[5] != 'tree')
return null;
return { user: toks[3], repo: toks[4], repopath: toks[3] + '/' + toks[4], branch: toks[6], subtreepath: toks[7] };
}
exports.parseGithubURL = parseGithubURL;
class GithubService {
constructor(githubCons, githubToken, store, project) {
this.githubCons = githubCons;
this.githubToken = githubToken;
this.store = store;
this.project = project;
this.recreateGithub();
}
recreateGithub() {
this.github = new this.githubCons({ token: this.githubToken });
}
login() {
// already logged in? return immediately
if (this.githubToken && this.githubToken.length) {
return new Promise((yes, no) => {
yes();
});
}
// login via popup
var provider = new firebase.auth.GithubAuthProvider();
provider.addScope('repo');
return firebase.auth().signInWithPopup(provider).then((result) => {
this.githubToken = result.credential.accessToken;
var user = result.user;
this.recreateGithub();
document.cookie = "__github_key=" + this.githubToken + ";path=/;max-age=31536000";
console.log("Stored GitHub OAUTH key");
});
}
logout() {
// already logged out? return immediately
if (!(this.githubToken && this.githubToken.length)) {
return new Promise((yes, no) => {
yes();
});
}
// logout
return firebase.auth().signOut().then(() => {
document.cookie = "__github_key=;path=/;max-age=0";
this.githubToken = null;
this.recreateGithub();
});
}
isFileIgnored(s) {
s = s.toUpperCase();
if (s.startsWith("LICENSE"))
return true;
if (s.startsWith("README"))
return true;
if (s.startsWith("."))
return true;
return false;
}
async getGithubSession(ghurl) {
var urlparse = parseGithubURL(ghurl);
if (!urlparse) {
throw new Error("Please enter a valid GitHub URL.");
}
// use saved branch, or load default from rpo
var saved = getRepos()[urlparse.repopath];
var branch = urlparse.branch || (saved && saved.branch);
var repo = this.github.repos(urlparse.user, urlparse.repo);
if (1 || branch == null) {
try {
branch = (await repo.fetch()).defaultBranch || "master";
}
catch (e) {
console.log("could not fetch default branch: " + e);
branch = "main";
}
console.log("branch =", branch);
}
var sess = {
url: ghurl,
user: urlparse.user,
reponame: urlparse.repo,
repopath: urlparse.repopath,
branch: branch,
subtreepath: urlparse.subtreepath,
prefix: '',
repo: repo,
platform_id: this.project ? this.project.platform_id : (saved ? saved.platform_id : null)
};
//console.log(sess);
return sess;
}
getGithubHEADTree(ghurl) {
var sess;
return this.getGithubSession(ghurl).then((session) => {
sess = session;
return sess.repo.git.refs.heads(sess.branch).fetch();
})
.then((head) => {
sess.head = head;
sess.sha = head.object.sha;
return sess.repo.git.trees(sess.sha).fetch();
})
.then((tree) => {
if (sess.subtreepath) {
for (let subtree of tree.tree) {
if (subtree.type == 'tree' && subtree.path == sess.subtreepath && subtree.sha) {
return sess.repo.git.trees(subtree.sha).fetch();
}
}
throw Error("Cannot find subtree '" + sess.subtreepath + "' in tree " + tree.sha);
}
return tree;
})
.then((tree) => {
sess.tree = tree;
return sess;
});
}
bind(sess, dobind) {
var key = '__repo__' + sess.repopath;
if (dobind) {
var repodata = {
url: sess.url,
branch: sess.branch,
platform_id: sess.platform_id,
mainPath: sess.mainPath,
sha: sess.sha
};
console.log('storing', repodata);
localStorage.setItem(key, JSON.stringify(repodata));
}
else {
localStorage.removeItem(key);
}
}
import(ghurl) {
var sess;
return this.getGithubSession(ghurl).then((session) => {
sess = session;
// load README
return sess.repo.contents('README.md').read();
})
.catch((e) => {
console.log(e);
console.log('no README.md found');
// make user repo exists
return sess.repo.fetch().then((_repo) => {
return ''; // empty README
});
})
.then((readme) => {
var m;
// check README for main file
const re8main = /8bitworkshop.com[^)]+file=([^)&]+)/;
m = re8main.exec(readme);
if (m && m[1]) {
console.log("main path: '" + m[1] + "'");
sess.mainPath = m[1];
}
// check README for proper platform
// unless we use githubURL=
// TODO: cannot handle multiple URLs in README
const re8plat = /8bitworkshop.com[^)]+platform=([A-Za-z0-9._\-]+)/;
m = re8plat.exec(readme);
if (m) {
console.log("platform id: '" + m[1] + "'");
if (sess.platform_id && !sess.platform_id.startsWith(m[1]))
throw Error("Platform mismatch: Repository is " + m[1] + ", you have " + sess.platform_id + " selected.");
sess.platform_id = m[1];
}
// bind to repository
this.bind(sess, true);
// get head commit
return sess;
});
}
pull(ghurl, deststore) {
var sess;
return this.getGithubHEADTree(ghurl).then((session) => {
sess = session;
let blobreads = [];
sess.paths = [];
sess.tree.tree.forEach((item) => {
console.log(item.path, item.type, item.size);
sess.paths.push(item.path);
if (item.type == 'blob' && !this.isFileIgnored(item.path)) {
var read = sess.repo.git.blobs(item.sha).fetch().then((blob) => {
var path = sess.prefix + item.path;
var size = item.size;
var encoding = blob.encoding;
var data = blob.content;
if (blob.encoding == 'base64') {
var bindata = (0, util_1.stringToByteArray)(atob(data));
var isBinary = (0, util_1.isProbablyBinary)(item.path, bindata);
data = isBinary ? bindata : (0, util_1.byteArrayToUTF8)(bindata);
}
if (blob.size != data.length) {
data = data.slice(0, blob.size);
}
return (deststore || this.store).setItem(path, data);
});
blobreads.push(read);
}
else {
console.log("ignoring " + item.path);
}
});
return Promise.all(blobreads);
})
.then((blobs) => {
return sess;
});
}
importAndPull(ghurl) {
return this.import(ghurl).then((sess) => {
return this.pull(ghurl);
});
}
publish(reponame, desc, license, isprivate) {
var repo;
var platform_id = this.project.platform_id;
var mainPath = this.project.stripLocalPath(this.project.mainPath);
return this.github.user.repos.create({
name: reponame,
description: desc,
private: isprivate,
auto_init: false,
license_template: license
})
.then((_repo) => {
repo = _repo;
// create README.md
var s = README_md_template;
s = s.replace(/\$NAME/g, encodeURIComponent(reponame));
s = s.replace(/\$PLATFORM/g, encodeURIComponent(platform_id));
s = s.replace(/\$GITHUBURL/g, encodeURIComponent(repo.htmlUrl));
s = s.replace(/\$MAINFILE/g, encodeURIComponent(mainPath));
var config = {
message: '8bitworkshop: updated metadata in README.md',
content: btoa(s)
};
return repo.contents('README.md').add(config);
}).then(() => {
return this.getGithubSession(repo.htmlUrl);
});
}
commit(ghurl, message, files) {
var sess;
if (!message) {
message = "updated from 8bitworkshop.com";
}
return this.getGithubHEADTree(ghurl).then((session) => {
sess = session;
if (sess.subtreepath) {
throw Error("Sorry, right now you can only commit files to the root directory of a repository.");
}
return Promise.all(files.map((file) => {
if (typeof file.data === 'string') {
return sess.repo.git.blobs.create({
content: file.data,
encoding: 'utf-8'
});
}
else {
return sess.repo.git.blobs.create({
content: btoa((0, util_1.byteArrayToString)(file.data)),
encoding: 'base64'
});
}
}));
}).then((blobs) => {
return sess.repo.git.trees.create({
tree: files.map((file, index) => {
return {
path: file.path,
mode: '100644',
type: 'blob',
sha: blobs[index]['sha']
};
}),
base_tree: sess.tree.sha
});
}).then((newtree) => {
return sess.repo.git.commits.create({
message: message,
tree: newtree.sha,
parents: [
sess.head.object.sha
]
});
}).then((commit1) => {
return sess.repo.commits(commit1.sha).fetch();
}).then((commit) => {
sess.commit = commit;
return sess;
});
}
push(sess) {
return sess.head.update({
sha: sess.commit.sha
}).then((update) => {
return sess;
});
}
deleteRepository(ghurl) {
return this.getGithubSession(ghurl).then((session) => {
return session.repo.remove();
});
}
}
exports.GithubService = GithubService;
//
class FirebaseProjectFilesystem {
constructor(user_id, store_id) {
var database = firebase.database();
this.ref = database.ref('users/' + user_id + "/" + store_id);
}
getChildForPath(path) {
var encodedPath = encodeURIComponent(path).replace('-', '%2D').replace('.', '%2E');
return this.ref.child(encodedPath);
}
async getFileData(path) {
console.log(this.getChildForPath("test"));
var snapshot = await this.getChildForPath(path).get();
return snapshot.exists() ? snapshot.val().filedata : null;
}
async setFileData(path, data) {
return this.getChildForPath(path).set({
filedata: data
});
}
}
exports.FirebaseProjectFilesystem = FirebaseProjectFilesystem;
//# sourceMappingURL=services.js.map