├── .gitignore ├── browser-client ├── dev ├── .gitignore ├── entries │ ├── appShellDev.html │ ├── index.html │ ├── appShellSource.js │ ├── service-worker.js │ ├── index.js │ └── appShell.js ├── public │ ├── favicon.ico │ ├── apple-touch-icon.png │ ├── favicon-16x16-manifest-17206.png │ ├── favicon-32x32-manifest-17206.png │ ├── favicon-96x96-manifest-17206.png │ ├── apple-icon-57x57-manifest-17206.png │ ├── apple-icon-60x60-manifest-17206.png │ ├── apple-icon-72x72-manifest-17206.png │ ├── apple-icon-76x76-manifest-17206.png │ ├── android-icon-192x192-manifest-17206.png │ ├── apple-icon-114x114-manifest-17206.png │ ├── apple-icon-120x120-manifest-17206.png │ ├── apple-icon-144x144-manifest-17206.png │ ├── apple-icon-152x152-manifest-17206.png │ ├── apple-icon-180x180-manifest-17206.png │ └── manifest.webmanifest ├── lib │ ├── shims │ │ └── React.js │ └── copyToClipboard.js ├── .eslintrc.json ├── components │ ├── NetworkTab │ │ ├── MeshState.jsx │ │ ├── Progressbar.jsx │ │ ├── Tabs.jsx │ │ ├── Step2Join.jsx │ │ ├── Step1.jsx │ │ ├── Step3Join.jsx │ │ ├── PeersTab.jsx │ │ ├── Step3Invite.jsx │ │ ├── index.jsx │ │ ├── Step2Invite.jsx │ │ └── ConnectTab.jsx │ ├── RunningAppTab │ │ ├── index.jsx │ │ ├── Iframe.jsx │ │ └── AppShell.jsx │ ├── AppsTab │ │ ├── index.jsx │ │ ├── CreateAppForm.jsx │ │ └── Apps.jsx │ ├── useWgOs │ │ ├── useJustWgOs.jsx │ │ └── log.js │ ├── AboutTab │ │ ├── font.txt │ │ ├── logo.txt │ │ └── index.jsx │ ├── Navbar.jsx │ ├── SettingsTab │ │ └── index.jsx │ └── App.jsx ├── scripts │ └── build ├── config │ └── index.js └── package.json ├── node-bridge ├── .gitignore ├── config │ └── index.js ├── lib │ ├── dummyClient.js │ ├── connectServer.js │ └── connectWgOs.js ├── package.json └── index.js ├── apps ├── WeSharedState │ ├── .gitignore │ ├── index.jsx │ ├── package.json │ └── components │ │ └── App.jsx ├── WeGit │ ├── .gitignore │ ├── components │ │ ├── Main │ │ │ ├── Preview.jsx │ │ │ ├── index.jsx │ │ │ ├── Repo.jsx │ │ │ ├── Files.jsx │ │ │ └── NoRepo.jsx │ │ ├── PullRequests │ │ │ ├── Main.jsx │ │ │ ├── Show.jsx │ │ │ ├── index.jsx │ │ │ └── Create.jsx │ │ ├── Progressbar.jsx │ │ ├── Settings │ │ │ └── index.jsx │ │ ├── Tabs.jsx │ │ ├── lib │ │ │ ├── gitHelpers.js │ │ │ ├── sharedStateTransportMiddleware.js │ │ │ └── transportMiddleware.js │ │ ├── App.jsx │ │ ├── useFs.jsx │ │ └── CiCd │ │ │ └── testsPage.html │ ├── index.jsx │ └── package.json ├── WeBox │ ├── package-lock.json │ └── package.json └── WeWeWeChat │ ├── package.json │ └── index.jsx ├── git-remote-wegit ├── .gitignore ├── .eslintrc.json ├── package.json └── lib │ ├── findAgentMiddleware.js │ ├── parser.js │ └── transportMiddleware.js ├── lib ├── .gitignore ├── version.js ├── browser │ └── utils │ │ ├── addStyles.js │ │ └── addScript.js ├── utils │ ├── atobtoa.js │ ├── wgKey.js │ ├── parseAppSource.js │ ├── receiveInChunksMiddleware.js │ ├── sendInChunksMiddleware.js │ └── sharedSimpleStateMiddleware.js ├── package.json └── WgOs │ └── index.js ├── signalling ├── firebase │ ├── .gitignore │ ├── package.json │ └── index.js ├── https │ ├── .gitignore │ ├── package-lock.json │ ├── index.js │ └── package.json └── https-server │ ├── .gitignore │ ├── package.json │ └── index.js ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | config.json 2 | -------------------------------------------------------------------------------- /browser-client/dev: -------------------------------------------------------------------------------- 1 | ../apps/WeBox -------------------------------------------------------------------------------- /node-bridge/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /apps/WeSharedState/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /git-remote-wegit/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /lib/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | -------------------------------------------------------------------------------- /signalling/firebase/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /signalling/https/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /signalling/https-server/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /apps/WeGit/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .cache 4 | -------------------------------------------------------------------------------- /browser-client/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .cache 3 | dist 4 | -------------------------------------------------------------------------------- /lib/version.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./package.json').version; 2 | -------------------------------------------------------------------------------- /browser-client/entries/appShellDev.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /browser-client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welldan97/WeGit/HEAD/browser-client/public/favicon.ico -------------------------------------------------------------------------------- /apps/WeBox/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wewewechat-app", 3 | "version": "0.0.1", 4 | "lockfileVersion": 1 5 | } 6 | -------------------------------------------------------------------------------- /browser-client/public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welldan97/WeGit/HEAD/browser-client/public/apple-touch-icon.png -------------------------------------------------------------------------------- /browser-client/public/favicon-16x16-manifest-17206.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welldan97/WeGit/HEAD/browser-client/public/favicon-16x16-manifest-17206.png -------------------------------------------------------------------------------- /browser-client/public/favicon-32x32-manifest-17206.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welldan97/WeGit/HEAD/browser-client/public/favicon-32x32-manifest-17206.png -------------------------------------------------------------------------------- /browser-client/public/favicon-96x96-manifest-17206.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welldan97/WeGit/HEAD/browser-client/public/favicon-96x96-manifest-17206.png -------------------------------------------------------------------------------- /browser-client/public/apple-icon-57x57-manifest-17206.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welldan97/WeGit/HEAD/browser-client/public/apple-icon-57x57-manifest-17206.png -------------------------------------------------------------------------------- /browser-client/public/apple-icon-60x60-manifest-17206.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welldan97/WeGit/HEAD/browser-client/public/apple-icon-60x60-manifest-17206.png -------------------------------------------------------------------------------- /browser-client/public/apple-icon-72x72-manifest-17206.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welldan97/WeGit/HEAD/browser-client/public/apple-icon-72x72-manifest-17206.png -------------------------------------------------------------------------------- /browser-client/public/apple-icon-76x76-manifest-17206.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welldan97/WeGit/HEAD/browser-client/public/apple-icon-76x76-manifest-17206.png -------------------------------------------------------------------------------- /browser-client/public/android-icon-192x192-manifest-17206.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welldan97/WeGit/HEAD/browser-client/public/android-icon-192x192-manifest-17206.png -------------------------------------------------------------------------------- /browser-client/public/apple-icon-114x114-manifest-17206.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welldan97/WeGit/HEAD/browser-client/public/apple-icon-114x114-manifest-17206.png -------------------------------------------------------------------------------- /browser-client/public/apple-icon-120x120-manifest-17206.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welldan97/WeGit/HEAD/browser-client/public/apple-icon-120x120-manifest-17206.png -------------------------------------------------------------------------------- /browser-client/public/apple-icon-144x144-manifest-17206.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welldan97/WeGit/HEAD/browser-client/public/apple-icon-144x144-manifest-17206.png -------------------------------------------------------------------------------- /browser-client/public/apple-icon-152x152-manifest-17206.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welldan97/WeGit/HEAD/browser-client/public/apple-icon-152x152-manifest-17206.png -------------------------------------------------------------------------------- /browser-client/public/apple-icon-180x180-manifest-17206.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/welldan97/WeGit/HEAD/browser-client/public/apple-icon-180x180-manifest-17206.png -------------------------------------------------------------------------------- /lib/browser/utils/addStyles.js: -------------------------------------------------------------------------------- 1 | export default styles => { 2 | const $link = document.createElement('style'); 3 | $link.innerHTML = styles; 4 | document.head.appendChild($link); 5 | }; 6 | -------------------------------------------------------------------------------- /browser-client/lib/shims/React.js: -------------------------------------------------------------------------------- 1 | export default React; 2 | export const useCallback = React.useCallback; 3 | export const useEffect = React.useEffect; 4 | export const useMemo = React.useMemo; 5 | export const useRef = React.useRef; 6 | export const useState = React.useState; 7 | -------------------------------------------------------------------------------- /lib/browser/utils/addScript.js: -------------------------------------------------------------------------------- 1 | export default async src => 2 | new Promise(resolve => { 3 | const $script = document.createElement('script'); 4 | $script.setAttribute('src', src); 5 | document.body.appendChild($script); 6 | $script.addEventListener('load', () => resolve()); 7 | }); 8 | -------------------------------------------------------------------------------- /node-bridge/config/index.js: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | // Main 5 | // ============================================================================= 6 | 7 | module.exports = () => ({ 8 | iceServers: [{ urls: ['stun:stun.l.google.com:19302'] }], 9 | signalling: undefined, 10 | }); 11 | -------------------------------------------------------------------------------- /git-remote-wegit/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "commonjs": true, 4 | "es6": true, 5 | "node": true 6 | }, 7 | "extends": "eslint:recommended", 8 | "globals": { 9 | "Atomics": "readonly", 10 | "SharedArrayBuffer": "readonly" 11 | }, 12 | "parserOptions": { 13 | "ecmaVersion": 2018 14 | }, 15 | "rules": { 16 | } 17 | } -------------------------------------------------------------------------------- /signalling/https/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wegit-signalling-https", 3 | "version": "0.0.1", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "node-fetch": { 8 | "version": "2.6.0", 9 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", 10 | "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /browser-client/entries/index.html: -------------------------------------------------------------------------------- 1 | Loading… 2 | 3 | -------------------------------------------------------------------------------- /lib/utils/atobtoa.js: -------------------------------------------------------------------------------- 1 | // NOTE: universal atob/btoa helpers 2 | 3 | // Imports 4 | // ============================================================================= 5 | 6 | // Main 7 | // ============================================================================= 8 | 9 | module.exports = { 10 | btoa: 11 | typeof btoa !== 'undefined' 12 | ? btoa 13 | : string => Buffer.from(string).toString('base64'), 14 | 15 | atob: 16 | typeof atob !== 'undefined' 17 | ? atob 18 | : string => Buffer.from(string, 'base64').toString(), 19 | }; 20 | -------------------------------------------------------------------------------- /browser-client/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true, 5 | "node": true 6 | }, 7 | "extends": [ 8 | "eslint:recommended", 9 | "plugin:react/recommended" 10 | ], 11 | "globals": { 12 | "Atomics": "readonly", 13 | "SharedArrayBuffer": "readonly" 14 | }, 15 | "parserOptions": { 16 | "ecmaFeatures": { 17 | "jsx": true 18 | }, 19 | "ecmaVersion": 2018, 20 | "sourceType": "module" 21 | }, 22 | "plugins": [ 23 | "react" 24 | ], 25 | "rules": { 26 | "react/prop-types": ["off"] 27 | } 28 | } -------------------------------------------------------------------------------- /browser-client/entries/appShellSource.js: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | import { readFileSync } from 'fs'; 5 | 6 | // Main 7 | // ============================================================================= 8 | 9 | // NOTE: Build it before using it, even in dev! npm run build:appShell 10 | // NOTE: parcel builder loads it and replace it with contents automatically 11 | // https://github.com/parcel-bundler/parcel/issues/970#issuecomment-381403710 12 | 13 | export default readFileSync(__dirname + '../../dist/appShell.js', 'utf-8'); 14 | -------------------------------------------------------------------------------- /node-bridge/lib/dummyClient.js: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | const net = require('net'); 5 | 6 | // Main 7 | // ============================================================================= 8 | 9 | const port = process.env.PORT || 1996; 10 | 11 | const connection = net.connect({ port }, () => { 12 | connection.on('data', data => { 13 | const parsedData = JSON.parse(data.toString()); 14 | console.log(JSON.stringify(parsedData, undefined, 2)); 15 | }); 16 | 17 | connection.on('end', () => console.log('disconnected from server')); 18 | }); 19 | -------------------------------------------------------------------------------- /lib/utils/wgKey.js: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | const VERSION = require('../version'); 5 | 6 | const { atob, btoa } = require('./atobtoa'); 7 | 8 | // Main 9 | // ============================================================================= 10 | 11 | module.exports = { 12 | toWgKey: prefix => obj => { 13 | return `${prefix}("${VERSION}","${btoa(JSON.stringify(obj))}")`; 14 | }, 15 | 16 | fromWgKey: wgKey => { 17 | const { prefix, version, key } = wgKey.match( 18 | /(?.*)\("(?.*)","(?.*)"\)/, 19 | ).groups; 20 | 21 | return JSON.parse(atob(key)); 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | WeGit 2 | ===== 3 | 4 | Distributed P2P Git Hosting Network 5 | 6 | Checkout video: https://www.youtube.com/watch?v=7EQDqoBrzT0 7 | 8 | Running app: https://wegit.network/ 9 | 10 | - Can manage repository. Works with regular git CLI commands i.e. push/pull/clone 11 | - Has minimal CI/CD for testing & building apps 12 | - Runs in the browser, so it could work on your computer, phone & may be microwave 13 | - Doesn't need server, and can work from single html file 14 | - Doesn't require internet connection if used on local network 15 | - Can run different apps, not only git 16 | - Easy to develop new p2p apps, it's all JS 17 | - Doesn't require signalling server but can be used with one to automate connection 18 | - PWA 19 | -------------------------------------------------------------------------------- /signalling/https/index.js: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | const doFetch = typeof fetch === 'undefined' ? require('node-fetch') : fetch; 5 | 6 | // Main 7 | // ============================================================================= 8 | 9 | module.exports = ({ url }) => ({ 10 | init: async wgOs => { 11 | const { wgOffer } = await wgOs.invite(); 12 | const response = await doFetch(url, { 13 | method: 'POST', 14 | headers: { 15 | 'Content-Type': 'application/json', 16 | }, 17 | body: JSON.stringify({ wgOffer }), 18 | }); 19 | const { wgAnswer } = await response.json(); 20 | await wgOs.establish(wgAnswer); 21 | }, 22 | }); 23 | -------------------------------------------------------------------------------- /browser-client/components/NetworkTab/MeshState.jsx: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | import React from 'react'; 5 | 6 | // Main 7 | // ============================================================================= 8 | 9 | export default function MeshState({ state }) { 10 | return ( 11 |

12 | {state === 'connected' && ( 13 | {'\u{2705}'} connected 14 | )} 15 | {state === 'connecting' && ( 16 | {'\u{23f3}'} connecting 17 | )} 18 | {state === 'disconnected' && ( 19 | {'\u{274c}'} disconnected 20 | )} 21 |

22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /apps/WeBox/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webox-app", 3 | "version": "0.0.1", 4 | "description": "Distributed P2P Git Hosting Provider Network", 5 | "main": "index.jsx", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": { 10 | "name": "Dmitry Yakimov", 11 | "url": "http://welldan97.com" 12 | }, 13 | "keywords": [ 14 | "WeGit", 15 | "p2p", 16 | "peer", 17 | "webrtc", 18 | "git", 19 | "git hosting", 20 | "network" 21 | ], 22 | "repository": { 23 | "type": "git", 24 | "url": "git://github.com/welldan97/WeGit.git" 25 | }, 26 | "bugs": { 27 | "url": "https://github.com/welldan97/WeGit/issues" 28 | }, 29 | "homepage": "https://github.com/welldan97/WeGit", 30 | "license": "MIT" 31 | } -------------------------------------------------------------------------------- /apps/WeWeWeChat/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wewewechat-app", 3 | "version": "0.0.1", 4 | "description": "Distributed P2P Git Hosting Provider Network", 5 | "main": "index.jsx", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": { 10 | "name": "Dmitry Yakimov", 11 | "url": "http://welldan97.com" 12 | }, 13 | "keywords": [ 14 | "WeGit", 15 | "p2p", 16 | "peer", 17 | "webrtc", 18 | "git", 19 | "git hosting", 20 | "network" 21 | ], 22 | "repository": { 23 | "type": "git", 24 | "url": "git://github.com/welldan97/WeGit.git" 25 | }, 26 | "bugs": { 27 | "url": "https://github.com/welldan97/WeGit/issues" 28 | }, 29 | "homepage": "https://github.com/welldan97/WeGit", 30 | "license": "MIT" 31 | } -------------------------------------------------------------------------------- /browser-client/scripts/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | export NODE_ENV=production; 6 | 7 | # build wegit app 8 | ( 9 | cd ../apps/WeGit 10 | rm -rf ./dist 11 | npx parcel build --no-source-maps --no-content-hash index.jsx 12 | head -n 7 < index.jsx | cat - ./dist/index.js > ./dist/next.js && mv ./dist/next.js ./dist/index.js 13 | ) 14 | 15 | #rm -rf .cache 16 | rm -rf ./dist 17 | # NOTE: build:appShell is needed for development 18 | npm run build:appShell 19 | # NOTE: build:appShell creates some dev file, remove it 20 | rm ./dist/dev.*.js 21 | 22 | parcel build --no-source-maps --no-content-hash entries/index.js 23 | 24 | { 25 | head -n 1 < ./entries/index.html 26 | echo '' 29 | } > ./dist/index.html 30 | cp ./public/* dist 31 | -------------------------------------------------------------------------------- /lib/utils/parseAppSource.js: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | const nanoid = require('nanoid'); 5 | 6 | // Main 7 | // ============================================================================= 8 | 9 | module.exports = (appSource, options) => { 10 | const { groups: rawApp } = new RegExp( 11 | `// ==WgApp== 12 | // @id (?.*) 13 | // @name (?.*) 14 | // @description (?.*) 15 | // @icon (?.*) 16 | // @user (?.*)`, 17 | ).exec(appSource); 18 | return { 19 | id: rawApp.id || nanoid(), 20 | name: rawApp.name, 21 | description: rawApp.description, 22 | // TODO: dangerous, eval! 23 | icon: eval(rawApp.rawIcon), 24 | user: JSON.parse(rawApp.rawUser), 25 | source: appSource, 26 | ...options, 27 | }; 28 | }; 29 | -------------------------------------------------------------------------------- /signalling/https/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wegit-signalling-https", 3 | "version": "0.0.1", 4 | "description": "Distributed P2P Git Hosting Provider Network", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": { 10 | "name": "Dmitry Yakimov", 11 | "url": "http://welldan97.com" 12 | }, 13 | "keywords": [ 14 | "WeGit", 15 | "p2p", 16 | "peer", 17 | "webrtc", 18 | "git", 19 | "git hosting", 20 | "network" 21 | ], 22 | "repository": { 23 | "type": "git", 24 | "url": "git://github.com/welldan97/WeGit.git" 25 | }, 26 | "bugs": { 27 | "url": "https://github.com/welldan97/WeGit/issues" 28 | }, 29 | "homepage": "https://github.com/welldan97/WeGit", 30 | "license": "MIT", 31 | "dependencies": { 32 | "node-fetch": "^2.6.0" 33 | } 34 | } -------------------------------------------------------------------------------- /apps/WeSharedState/index.jsx: -------------------------------------------------------------------------------- 1 | // ==WgApp== 2 | // @name WeSharedState 3 | // @description Example of shared state 4 | // @icon '\u{1F916}' 5 | // @user { "userName": "welldan97" } 6 | // ==/WgApp== 7 | 8 | // Imports 9 | // ============================================================================= 10 | import React from 'react'; 11 | import ReactDOM from 'react-dom'; 12 | // NOTE: necessary for async/await 13 | import 'regenerator-runtime/runtime'; 14 | 15 | import App from './components/App'; 16 | 17 | // Main 18 | // ============================================================================= 19 | const main = () => { 20 | document.body.innerHTML = '
'; 21 | ReactDOM.render( 22 | , 23 | document.getElementsByTagName('div')[0], 24 | ); 25 | }; 26 | 27 | if (typeof module !== 'undefined') module.exports = main; 28 | else main(); 29 | -------------------------------------------------------------------------------- /signalling/firebase/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wegit-signalling-firebase", 3 | "version": "0.0.1", 4 | "description": "Distributed P2P Git Hosting Provider Network", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": { 10 | "name": "Dmitry Yakimov", 11 | "url": "http://welldan97.com" 12 | }, 13 | "keywords": [ 14 | "WeGit", 15 | "p2p", 16 | "peer", 17 | "webrtc", 18 | "git", 19 | "git hosting", 20 | "network" 21 | ], 22 | "repository": { 23 | "type": "git", 24 | "url": "git://github.com/welldan97/WeGit.git" 25 | }, 26 | "bugs": { 27 | "url": "https://github.com/welldan97/WeGit/issues" 28 | }, 29 | "homepage": "https://github.com/welldan97/WeGit", 30 | "license": "MIT", 31 | "dependencies": { 32 | "firebase": "^7.14.1", 33 | "nanoid": "^2.1.11" 34 | } 35 | } -------------------------------------------------------------------------------- /apps/WeGit/components/Main/Preview.jsx: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | import React from 'react'; 5 | import ReactMarkdown from 'react-markdown'; 6 | 7 | // Main 8 | // ============================================================================= 9 | 10 | export default function Preview({ previewFile }) { 11 | const isMarkdown = previewFile.name.toLowerCase().endsWith('.md'); 12 | return ( 13 |
14 |
15 | {'\u{1F4C4} '} 16 | {previewFile.name} 17 |
18 |
19 | {!isMarkdown && ( 20 |
21 |             {previewFile.contents}
22 |           
23 | )} 24 | {isMarkdown && } 25 |
26 |
27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /apps/WeGit/index.jsx: -------------------------------------------------------------------------------- 1 | // ==WgApp== 2 | // @id WE-WE-WE-WE-WE-WE-GIT 3 | // @name WeGit 4 | // @description P2P hub for git users 5 | // @icon '\u{1F46F}' 6 | // @user { "userName": "welldan97" } 7 | // ==/WgApp== 8 | 9 | // Imports 10 | // ============================================================================= 11 | import React from 'react'; 12 | import ReactDOM from 'react-dom'; 13 | // NOTE: necessary for async/await 14 | import 'regenerator-runtime/runtime'; 15 | 16 | import App from './components/App'; 17 | 18 | // Main 19 | // ============================================================================= 20 | const main = () => { 21 | document.body.innerHTML = '
'; 22 | ReactDOM.render( 23 | , 24 | document.getElementsByTagName('div')[0], 25 | ); 26 | }; 27 | main(); 28 | // module.exports = main; 29 | 30 | /* 31 | if (typeof module !== 'undefined') module.exports = main; 32 | else main(); 33 | */ 34 | -------------------------------------------------------------------------------- /lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wegit-lib", 3 | "version": "0.0.1", 4 | "description": "Distributed P2P Git Hosting Provider Network", 5 | "main": "WgOs/index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": { 10 | "name": "Dmitry Yakimov", 11 | "url": "http://welldan97.com" 12 | }, 13 | "keywords": [ 14 | "WeGit", 15 | "p2p", 16 | "peer", 17 | "webrtc", 18 | "git", 19 | "git hosting", 20 | "network" 21 | ], 22 | "repository": { 23 | "type": "git", 24 | "url": "git://github.com/welldan97/WeGit.git" 25 | }, 26 | "bugs": { 27 | "url": "https://github.com/welldan97/WeGit/issues" 28 | }, 29 | "homepage": "https://github.com/welldan97/WeGit", 30 | "license": "MIT", 31 | "dependencies": { 32 | "eventemitter3": "^4.0.0", 33 | "nanoid": "^2.1.11", 34 | "simple-peer": "welldan97/simple-peer", 35 | "wrtc": "^0.4.4" 36 | } 37 | } -------------------------------------------------------------------------------- /signalling/https-server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wegit-signalling-https-server", 3 | "version": "0.0.1", 4 | "description": "Distributed P2P Git Hosting Provider Network", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": { 10 | "name": "Dmitry Yakimov", 11 | "url": "http://welldan97.com" 12 | }, 13 | "keywords": [ 14 | "WeGit", 15 | "p2p", 16 | "peer", 17 | "webrtc", 18 | "git", 19 | "git hosting", 20 | "network" 21 | ], 22 | "repository": { 23 | "type": "git", 24 | "url": "git://github.com/welldan97/WeGit.git" 25 | }, 26 | "bugs": { 27 | "url": "https://github.com/welldan97/WeGit/issues" 28 | }, 29 | "homepage": "https://github.com/welldan97/WeGit", 30 | "dependencies": { 31 | "body-parser": "^1.19.0", 32 | "cors": "^2.8.5", 33 | "express": "^4.17.1", 34 | "wegit-lib": "0.0.1" 35 | }, 36 | "author": "", 37 | "license": "MIT" 38 | } -------------------------------------------------------------------------------- /apps/WeSharedState/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wesharedstate-app", 3 | "version": "0.0.1", 4 | "description": "Distributed P2P Git Hosting Provider Network", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": { 10 | "name": "Dmitry Yakimov", 11 | "url": "http://welldan97.com" 12 | }, 13 | "keywords": [ 14 | "WeGit", 15 | "p2p", 16 | "peer", 17 | "webrtc", 18 | "git", 19 | "git hosting", 20 | "network" 21 | ], 22 | "repository": { 23 | "type": "git", 24 | "url": "git://github.com/welldan97/WeGit.git" 25 | }, 26 | "bugs": { 27 | "url": "https://github.com/welldan97/WeGit/issues" 28 | }, 29 | "homepage": "https://github.com/welldan97/WeGit", 30 | "license": "MIT", 31 | "dependencies": { 32 | "lodash": "^4.17.15", 33 | "react": "^16.13.1", 34 | "react-dom": "^16.13.1", 35 | "regenerator-runtime": "^0.13.5", 36 | "wegit-lib": "0.0.1" 37 | } 38 | } -------------------------------------------------------------------------------- /browser-client/components/NetworkTab/Progressbar.jsx: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | import React from 'react'; 5 | 6 | // Main 7 | // ============================================================================= 8 | 9 | export default function Progressbar({ progress }) { 10 | return ( 11 |
19 |
20 |
21 |
29 |
30 |
31 |
32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /browser-client/components/RunningAppTab/index.jsx: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | import React, { memo } from 'react'; 5 | 6 | import AppShell from './AppShell'; 7 | 8 | // Main 9 | // ============================================================================= 10 | 11 | export default memo(function RunningAppTab({ 12 | runningApp, 13 | currentUser, 14 | users, 15 | transport, 16 | utils, 17 | isShown, 18 | config, 19 | onCreateApp, 20 | }) { 21 | const style = { 22 | width: '100%', 23 | 24 | maxHeight: 'calc(100% - 48px)', 25 | height: '100%', 26 | }; 27 | return ( 28 | 39 | ); 40 | }); 41 | -------------------------------------------------------------------------------- /browser-client/entries/service-worker.js: -------------------------------------------------------------------------------- 1 | const CACHE = 'wegit-v1'; 2 | 3 | const AUTO_CACHE = ['/', '/service-worker.js']; 4 | 5 | self.addEventListener('install', event => { 6 | event.waitUntil( 7 | caches 8 | .open(CACHE) 9 | .then(cache => cache.addAll(AUTO_CACHE)) 10 | .then(self.skipWaiting()), 11 | ); 12 | }); 13 | 14 | self.addEventListener('activate', event => { 15 | event.waitUntil( 16 | caches 17 | .keys() 18 | .then(cacheNames => { 19 | return cacheNames.filter(cacheName => CACHE !== cacheName); 20 | }) 21 | .then(unusedCaches => { 22 | return Promise.all( 23 | unusedCaches.map(unusedCache => { 24 | return caches.delete(unusedCache); 25 | }), 26 | ); 27 | }) 28 | .then(() => self.clients.claim()), 29 | ); 30 | }); 31 | 32 | self.addEventListener('fetch', event => { 33 | event.respondWith( 34 | caches.match(event.request).then(function(response) { 35 | return response || fetch(event.request); 36 | }), 37 | ); 38 | }); 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Dmitry Yakimov 2 | Permission is hereby granted, free of charge, to any person obtaining a copy 3 | of this software and associated documentation files (the "Software"), to deal 4 | in the Software without restriction, including without limitation the rights 5 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 6 | copies of the Software, and to permit persons to whom the Software is 7 | furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all 10 | copies or substantial portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 18 | SOFTWARE. 19 | -------------------------------------------------------------------------------- /node-bridge/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wegit-node-bridge", 3 | "version": "0.0.1", 4 | "description": "Distributed P2P Git Hosting Provider Network", 5 | "main": "index.js", 6 | "bin": { 7 | "wegit-node-bridge": "./index.js" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "author": { 13 | "name": "Dmitry Yakimov", 14 | "url": "http://welldan97.com" 15 | }, 16 | "keywords": [ 17 | "WeGit", 18 | "p2p", 19 | "peer", 20 | "webrtc", 21 | "git", 22 | "git hosting", 23 | "network" 24 | ], 25 | "repository": { 26 | "type": "git", 27 | "url": "git://github.com/welldan97/WeGit.git" 28 | }, 29 | "bugs": { 30 | "url": "https://github.com/welldan97/WeGit/issues" 31 | }, 32 | "homepage": "https://github.com/welldan97/WeGit", 33 | "license": "MIT", 34 | "dependencies": { 35 | "chalk": "^4.0.0", 36 | "clipboardy": "^2.3.0", 37 | "inquirer": "^7.1.0", 38 | "ora": "^4.0.4", 39 | "wegit-lib": "0.0.1", 40 | "wegit-signalling-firebase": "0.0.1", 41 | "wegit-signalling-https": "0.0.1" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /apps/WeGit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wegit-app", 3 | "version": "0.0.1", 4 | "description": "Distributed P2P Git Hosting Provider Network", 5 | "main": "index.jsx", 6 | "dependencies": { 7 | "browserfs": "^1.4.3", 8 | "eventemitter3": "^4.0.0", 9 | "isomorphic-git": "^0.78.5", 10 | "nanoid": "^3.1.10", 11 | "parcel-bundler": "^1.12.4", 12 | "react": "^16.12.0", 13 | "react-dom": "^16.12.0", 14 | "react-markdown": "^4.3.1", 15 | "regenerator-runtime": "^0.13.3", 16 | "wegit-lib": "0.0.1" 17 | }, 18 | "devDependencies": {}, 19 | "scripts": { 20 | "test": "echo \"Error: no test specified\" && exit 1" 21 | }, 22 | "author": { 23 | "name": "Dmitry Yakimov", 24 | "url": "http://welldan97.com" 25 | }, 26 | "keywords": [ 27 | "WeGit", 28 | "p2p", 29 | "peer", 30 | "webrtc", 31 | "git", 32 | "git hosting", 33 | "network" 34 | ], 35 | "repository": { 36 | "type": "git", 37 | "url": "git://github.com/welldan97/WeGit.git" 38 | }, 39 | "bugs": { 40 | "url": "https://github.com/welldan97/WeGit/issues" 41 | }, 42 | "homepage": "https://github.com/welldan97/WeGit", 43 | "license": "MIT" 44 | } -------------------------------------------------------------------------------- /apps/WeGit/components/Main/index.jsx: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | import React, { memo, useCallback, useState } from 'react'; 5 | 6 | import NoRepo from './NoRepo'; 7 | import Repo from './Repo'; 8 | 9 | // Main 10 | // ============================================================================= 11 | 12 | export default function Main({ 13 | repoName, 14 | currentBranch, 15 | branches, 16 | onChangeBranch, 17 | lastCommitHolder, 18 | 19 | path, 20 | onPathChange, 21 | files, 22 | previewFile, 23 | currentFile, 24 | // 25 | hasRepo, 26 | progress, 27 | onClone, 28 | }) { 29 | return ( 30 | <> 31 | {hasRepo || } 32 | {hasRepo && ( 33 | 48 | )} 49 | 50 | ); 51 | } 52 | -------------------------------------------------------------------------------- /git-remote-wegit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "git-remote-wegit", 3 | "version": "0.0.1", 4 | "description": "Distributed P2P Git Hosting Provider Network", 5 | "main": "index.js", 6 | "bin": { 7 | "git-remote-wegit": "./index.js" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "author": { 13 | "name": "Dmitry Yakimov", 14 | "url": "http://welldan97.com" 15 | }, 16 | "keywords": [ 17 | "WeGit", 18 | "p2p", 19 | "peer", 20 | "webrtc", 21 | "git", 22 | "git hosting", 23 | "network" 24 | ], 25 | "repository": { 26 | "type": "git", 27 | "url": "git://github.com/welldan97/WeGit.git" 28 | }, 29 | "bugs": { 30 | "url": "https://github.com/welldan97/WeGit/issues" 31 | }, 32 | "homepage": "https://github.com/welldan97/WeGit", 33 | "license": "MIT", 34 | "dependencies": { 35 | "@ungap/event": "^0.1.4", 36 | "@ungap/event-target": "^0.1.0", 37 | "clipboardy": "^2.1.0", 38 | "inquirer": "^7.0.1", 39 | "isomorphic-git": "^0.78.5", 40 | "ora": "^4.0.4", 41 | "wegit-lib": "0.0.1", 42 | "wrtc": "^0.4.2" 43 | }, 44 | "devDependencies": { 45 | "eslint": "^6.8.0" 46 | } 47 | } -------------------------------------------------------------------------------- /apps/WeGit/components/PullRequests/Main.jsx: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | import React, { useState } from 'react'; 5 | 6 | // Main 7 | // ============================================================================= 8 | 9 | export default function Main({ pullRequests, onCreate, onShow }) { 10 | return ( 11 |
12 |
13 |
    14 | {pullRequests.map(p => ( 15 |
  • onShow(p)} 21 | style={{ cursor: 'pointer' }} 22 | > 23 | {'\u{21A9}'}  {p.title} 24 |
  • 25 | ))} 26 |
27 | 34 |
35 |
36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /node-bridge/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // Imports 4 | // ============================================================================= 5 | 6 | const fs = require('fs'); 7 | 8 | const connectUi = require('./lib/connectUi'); 9 | const connectWgOs = require('./lib/connectWgOs'); 10 | const connectServer = require('./lib/connectServer'); 11 | 12 | const getConfig = require('./config/index.js'); 13 | 14 | // Main 15 | // ============================================================================= 16 | const port = process.env.PORT || 1996; 17 | const userName = process.env.USER || undefined; 18 | 19 | const main = async () => { 20 | let config = getConfig(); 21 | if (process.argv[2] === '--config') { 22 | const file = fs.readFileSync(process.argv[3]); 23 | config = JSON.parse(file.toString()); 24 | } 25 | 26 | const ui = connectUi({ userName }); 27 | const serverTransport = connectServer({ port }); 28 | const wgOsTransport = connectWgOs({ config, userName }); 29 | 30 | serverTransport.onMessage((userId, message) => { 31 | wgOsTransport.send(userId, message); 32 | }); 33 | 34 | serverTransport.onChange(state => { 35 | ui.clientChange(state); 36 | }); 37 | 38 | serverTransport.onConnect(({ port }) => { 39 | ui.ready({ port, wgOs: wgOsTransport.wgOs }); 40 | }); 41 | 42 | wgOsTransport.onMessage(message => { 43 | serverTransport.send(message); 44 | }); 45 | 46 | wgOsTransport.onChange(({ meshState }) => { 47 | serverTransport.change({ meshState }); 48 | ui.change({ meshState }); 49 | }); 50 | }; 51 | 52 | main(); 53 | -------------------------------------------------------------------------------- /browser-client/components/AppsTab/index.jsx: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | import React, { useState } from 'react'; 5 | 6 | import Apps from './Apps'; 7 | import CreateAppForm from './CreateAppForm'; 8 | 9 | // Main 10 | // ============================================================================= 11 | 12 | export default function AppsTab({ 13 | apps, 14 | runningApp, 15 | onCreate, 16 | onRun, 17 | onStop, 18 | onDelete, 19 | }) { 20 | const [isCreating, setIsCreating] = useState(false); 21 | 22 | return ( 23 | <> 24 |
25 |
26 |

Apps

27 |
28 |
29 | 36 | {isCreating && ( 37 | { 39 | setIsCreating(false); 40 | }} 41 | onSubmit={app => { 42 | setIsCreating(false); 43 | onCreate(app); 44 | }} 45 | /> 46 | )} 47 | 48 | {!isCreating && ( 49 |
50 |
51 | 58 |
59 |
60 | )} 61 | 62 | ); 63 | } 64 | -------------------------------------------------------------------------------- /git-remote-wegit/lib/findAgentMiddleware.js: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | // Main 5 | // ============================================================================= 6 | 7 | module.exports = ({ isReadyPromise }) => ({ send, onMessage, ...args }) => { 8 | let isAgentFound = false; 9 | let findAgentResolve; 10 | let userIdsToProcess; 11 | const findAgent = new Promise( 12 | resolve => (findAgentResolve = (...args) => resolve(...args)), 13 | ); 14 | 15 | const nextOnMessage = async (message, options = {}) => { 16 | const { type: rawType } = message; 17 | 18 | if (rawType !== 'transport:statusResponse') 19 | return onMessage(message, options); 20 | 21 | if (isAgentFound) return; 22 | if (message.payload.isReady) { 23 | findAgentResolve(message.path[0]); 24 | } else { 25 | userIdsToProcess--; 26 | if (userIdsToProcess === 0) findAgentResolve(undefined); 27 | } 28 | }; 29 | 30 | isReadyPromise.then(meshState => { 31 | // NOTE: for now due locks, just ask first user 32 | const userIds = [ 33 | meshState.connections 34 | .filter(c => c.state === 'connected') 35 | .filter(c => c.user && c.user.type === 'browser') 36 | .map(c => c.user.id)[0], 37 | ]; 38 | 39 | userIdsToProcess = userIds.length; 40 | if (!userIds.length) return findAgentResolve(undefined); 41 | 42 | userIds.forEach(userId => { 43 | send(userId, { 44 | type: 'transport:status', 45 | payload: {}, 46 | }); 47 | }); 48 | }); 49 | return { ...args, send: send, onMessage: nextOnMessage, findAgent }; 50 | }; 51 | -------------------------------------------------------------------------------- /browser-client/entries/index.js: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | import React from 'react'; 5 | import ReactDOM from 'react-dom'; 6 | // NOTE: necessary for async/await 7 | import 'regenerator-runtime/runtime'; 8 | 9 | import addStyles from 'wegit-lib/browser/utils/addStyles'; 10 | import styles from 'wegit-lib/browser/bootstrap.min.css'; 11 | 12 | import App from '../components/App'; 13 | 14 | // NOTE: using source to avoid extra code with iframe 15 | // may be parcel handles it though 16 | import appShellSource from './appShellSource'; 17 | 18 | // Utils 19 | // ============================================================================= 20 | 21 | const isIframe = () => { 22 | try { 23 | return window.self !== window.top; 24 | } catch (e) { 25 | return true; 26 | } 27 | }; 28 | 29 | // Main 30 | // ============================================================================= 31 | 32 | const main = async () => { 33 | const source = document.body.innerHTML.trim() + '\n'; 34 | document.documentElement.innerHTML = 35 | '
'; 36 | addStyles(styles); 37 | 38 | ReactDOM.render( 39 | , 40 | document.getElementsByTagName('div')[0], 41 | ); 42 | }; 43 | 44 | const appShell = () => { 45 | document.documentElement.innerHTML = '
'; 46 | 47 | const evaluate = new Function(appShellSource); 48 | evaluate(); 49 | }; 50 | 51 | if (isIframe()) appShell(); 52 | else main(); 53 | -------------------------------------------------------------------------------- /signalling/https-server/index.js: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | const express = require('express'); 5 | const bodyParser = require('body-parser'); 6 | const cors = require('cors'); 7 | 8 | const WgOs = require('wegit-lib/WgOs'); 9 | 10 | // Main 11 | // ============================================================================= 12 | 13 | const config = JSON.parse(process.env.WG_CONFIG || '{}'); 14 | const currentUser = { 15 | userName: 'HTTPS Signalling Server', 16 | type: 'signalling', 17 | }; 18 | const apps = []; 19 | 20 | let wgOs; 21 | 22 | const reset = () => { 23 | if (wgOs) wgOs.disconnnect(); 24 | wgOs = new WgOs({ 25 | config, 26 | currentUser, 27 | apps, 28 | }); 29 | }; 30 | 31 | reset(); 32 | 33 | const app = express(); 34 | const port = process.env.PORT || 1993; 35 | app.use(cors()); 36 | app.use(bodyParser.json()); 37 | 38 | app.get('/', (req, res) => res.send('It works!')); 39 | app.get('/state', (req, res) => { 40 | const baseMeshState = wgOs.getMeshState(); 41 | const meshState = { 42 | connections: baseMeshState.connections.map(c => ({ 43 | ...c, 44 | user: wgOs.users.find(u => u.id === c.peer), 45 | })), 46 | globalState: baseMeshState.globalState, 47 | }; 48 | 49 | res.send(`
${JSON.stringify(meshState, undefined, 2)}
`); 50 | }); 51 | 52 | app.delete('/', (req, res) => reset()); 53 | 54 | app.post('/', async (req, res) => { 55 | const { wgOffer } = req.body; 56 | const { wgAnswer } = await wgOs.join(wgOffer); 57 | if (wgAnswer) return res.json({ wgAnswer }); 58 | res.status(409); 59 | res.send(); 60 | }); 61 | 62 | app.listen(port, () => console.log(`Listening on port ${port}!`)); 63 | -------------------------------------------------------------------------------- /browser-client/config/index.js: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | import parseAppSource from 'wegit-lib/utils/parseAppSource'; 5 | 6 | import { readFileSync, existsSync } from 'fs'; 7 | 8 | const WeWeWeChatSource = readFileSync( 9 | __dirname + '../../../apps/WeWeWeChat/index.jsx', 10 | 'utf-8', 11 | ); 12 | 13 | const WeBoxSource = readFileSync( 14 | __dirname + '../../../apps/WeBox/index.jsx', 15 | 'utf-8', 16 | ); 17 | 18 | const WeGitSource = readFileSync( 19 | //__dirname + '../../../apps/WeGit/index.jsx', 20 | __dirname + '../../../apps/WeGit/dist/index.js', 21 | 'utf-8', 22 | ); 23 | 24 | let baseConfig = {}; 25 | 26 | if (process.env.NODE_ENV === 'development') 27 | baseConfig = JSON.parse( 28 | readFileSync(__dirname + '../../../config.json', 'utf-8'), 29 | ); 30 | 31 | // Utils 32 | // ============================================================================= 33 | 34 | const isFile = () => window.location.protocol === 'file:'; 35 | 36 | // Main 37 | // ============================================================================= 38 | export default () => ({ 39 | tab: 'network', 40 | iceServers: [{ urls: ['stun:stun.l.google.com:19302'] }], 41 | signalling: undefined, 42 | //runApp: 'WE-WE-WE-WE-WE-WECHAT', 43 | runApp: false, 44 | iframeMode: { 45 | // NOTE: crossOrigin doesn't work yet 46 | type: 'sameOrigin', 47 | }, 48 | serviceWorkers: !isFile(), 49 | appShellLocalApp: false, 50 | alwaysDefaultConfig: false, 51 | ...baseConfig, 52 | initialApps: [ 53 | parseAppSource(WeWeWeChatSource), 54 | parseAppSource(WeBoxSource), 55 | parseAppSource(WeGitSource), 56 | ...(baseConfig.initialApps || []), 57 | ], 58 | }); 59 | -------------------------------------------------------------------------------- /lib/utils/receiveInChunksMiddleware.js: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | const nanoid = require('nanoid'); 5 | 6 | // Main 7 | // ============================================================================= 8 | 9 | const MAX_SIZE = 10000; 10 | 11 | module.exports = ({ send, onMessage, ...args }) => { 12 | const receivedChunks = {}; 13 | 14 | const receiveChunk = (message, { onProgress = () => {}, ...options }) => { 15 | const { 16 | path: [userId], 17 | payload: { id, chunkBody, chunkNo, chunksCount }, 18 | } = message; 19 | if (!receivedChunks[id]) receivedChunks[id] = ''; 20 | receivedChunks[id] += chunkBody; 21 | onProgress({ 22 | phase: 'Receiving', 23 | loaded: chunkNo, 24 | total: chunksCount - 1, 25 | lengthComputable: true, 26 | }); 27 | 28 | if (chunkNo !== chunksCount - 1) 29 | send(userId, { type: 'nextChunk', payload: { id } }); 30 | else { 31 | const parsedMessage = JSON.parse(receivedChunks[id]); 32 | onMessage({ ...message, ...parsedMessage }, options); 33 | delete receivedChunks[id]; 34 | } 35 | }; 36 | 37 | //---------------------------------------------------------------------------- 38 | 39 | const nextSend = (userId, message, options = {}) => { 40 | if (message.type === 'chunks') return; // TODO 41 | if (message.type === 'nextChunk') return; // TODO 42 | return send(userId, message, options); 43 | }; 44 | 45 | const nextOnMessage = (message, options = {}) => { 46 | if (message.type === 'chunks') return receiveChunk(message, options); 47 | else return onMessage(message, options); 48 | }; 49 | 50 | return { ...args, send: nextSend, onMessage: nextOnMessage }; 51 | }; 52 | -------------------------------------------------------------------------------- /browser-client/components/NetworkTab/Tabs.jsx: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | import React from 'react'; 5 | 6 | // Main 7 | // ============================================================================= 8 | 9 | export default function Tabs({ 10 | active, 11 | onActivate, 12 | connectingPeersCount, 13 | connectedPeersCount, 14 | }) { 15 | return ( 16 | 54 | ); 55 | } 56 | -------------------------------------------------------------------------------- /apps/WeGit/components/PullRequests/Show.jsx: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | import React, { useEffect, useState } from 'react'; 5 | import { nanoid } from 'nanoid'; 6 | 7 | // Main 8 | // ============================================================================= 9 | 10 | export default function Create({ pullRequest, onCancel, onDelete, onMerge }) { 11 | return ( 12 | <> 13 |
14 |
15 |

{pullRequest.title}

16 | 17 |
18 |
19 | From: {'\u{1F500} '} {pullRequest.from} 20 |
21 | {'\u{279e} '} 22 |
23 | To: {'\u{1F500} '} {pullRequest.to} 24 |
25 |
26 | 27 |

{pullRequest.comment}

28 | 29 |
30 | 37 | 44 | 51 |
52 |
53 |
54 | 55 | ); 56 | } 57 | -------------------------------------------------------------------------------- /browser-client/components/NetworkTab/Step2Join.jsx: -------------------------------------------------------------------------------- 1 | // Imports 2 | // ============================================================================= 3 | 4 | import React, { useState } from 'react'; 5 | 6 | // Main 7 | // ============================================================================= 8 | 9 | export default function Step2Join({ join, cancelConnection }) { 10 | const [wgOfferKey, setWgOfferKey] = useState(''); 11 | 12 | return ( 13 | <> 14 |
15 |
16 |
17 | 📋 Paste the Offer from your peer here and go to the next step 18 |
19 |
20 |
21 |
{ 24 | e.preventDefault(); 25 | join(wgOfferKey); 26 | }} 27 | > 28 |
29 | 30 |