generated from DimitarNestorov/RepoOnVercel
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- yulkari0.0.1-0.0.3
- ytnoshortsbutton1.0
- streaknotifications0.1-0.3
- notfinical1.0.3
- notfinical0.0.1-1.0.2
- kumquat1.1
- kumquat1.0
- isponsorblocklegacy1.0-13
- isponsorblocklegacy1.0-13b2
- isponsorblocklegacy1.0-13b1
- isponsorblock1.0-15
- isponsorblock1.0-14
- isponsorblock1.0-13
- isponsorblock1.0-12
- isponsorblock1.0-11
- isponsorblock1.0-10
- isponsorblock1.0-9
- isponsorblock0.0.1-1.0-8
- bigytminiplayer1.0
- bigytminiplayer0.1
- bigytminiplaye1.0-1
- 14pip1.0
0 parents
commit ed6b5ec
Showing
39 changed files
with
1,228 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# local env files | ||
.env.local | ||
.env.development.local | ||
.env.test.local | ||
.env.production.local | ||
|
||
.vercel | ||
|
||
# TODO: Generated files | ||
# ./public/Packages | ||
# ./public/Packages.bz2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"semi": false, | ||
"trailingComma": "all", | ||
"tabWidth": 4, | ||
"printWidth": 120, | ||
"singleQuote": true, | ||
"useTabs": true | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"recommendations": ["esbenp.prettier-vscode", "andrewrazumovsky.vscode-styled-jsx-languageserver"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"editor.tabSize": 4, | ||
"editor.insertSpaces": false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2020 Dimitar Nestorov | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# Repo on Vercel | ||
|
||
This is a Cydia/APT repository template built for the [Vercel platform](https://vercel.com/). This is a [Next.js](https://nextjs.org/) project. | ||
|
||
## Why Repo on Vercel? | ||
|
||
Repo on Vercel is aimed to make possible downloading packages directly from GitHub Releases which has a download counter unlike GitHub Pages. | ||
|
||
## Getting Started | ||
|
||
<p align="center"><a href="https://github.com/dimitarnestorov/RepoOnVercel/generate"><img width="200" src=".vscode/Button.png" alt="Use this template"></a></p> | ||
|
||
### Run the development server | ||
|
||
#### Install Node.js | ||
|
||
To build and run this repo locally you need Node.js: https://nodejs.org/ | ||
|
||
You can install it using [Homebrew](https://brew.sh/) on macOS: `brew install node` | ||
|
||
You can install it using [Chocolatey](https://chocolatey.org/) on Windows: `choco install nodejs` | ||
|
||
#### Install the dependencies | ||
|
||
Run the following in the root folder of your repo: | ||
|
||
```sh | ||
npm install | ||
``` | ||
|
||
#### Run the server | ||
|
||
```bash | ||
npm run dev | ||
``` | ||
|
||
### Edit the repository metadata | ||
|
||
Edit the `exports.name` and `exports.description` strings in the `repo.js` file. | ||
|
||
### Replace `CydiaIcon.png` and `favicon.ico` with your own | ||
|
||
Icons are located in the `public` folder. They are visible in package managers and on the web. | ||
|
||
### Add your packages | ||
|
||
Insert your GitHub Releases package URLs in the `exports.packages` array in the `repo.js` file. | ||
|
||
### Add your depictions | ||
|
||
Depictions live in the `pages` folder. The format for the file name is `name.js` where `name` is the name of your package. To view your depictions before deploying run the development server and visit `http://localhost:3000/name` where `name` is the name of your package. | ||
|
||
If your package name has spaces in it replace those with `-` for the depiction file. | ||
|
||
### Add your package icons | ||
|
||
Put your icons in the public folder and then edit the `exports.icons` object in the `repo.js` file. The key is the name of your package, the value is the path of the icon without `public`. | ||
|
||
### Modify the home page | ||
|
||
Modify `index.js` in the `pages` folder, [run the development server](#run-the-development-server), and open [http://localhost:3000](http://localhost:3000) in your browser to see the result. | ||
|
||
### Deploy on Vercel | ||
|
||
After you've created your repo click [here to import](https://vercel.com/import) your repo on Vercel. Choose "Import Git Repository" and enter the URL of your Git repository. | ||
|
||
## Increase rate limit (fix "Error: rate limit exceeded") | ||
|
||
This template uses the GitHub API to cache requests. The GitHub API is limited to 60 unauthenticated requests per IP address per hour. To increase this limit you need to specify a GitHub token as an environment variable (`GITHUB_TOKEN`) when running `npm run dev`. To get a token go to [Settings -> Developer settings -> Personal access tokens](https://github.com/settings/tokens) and click "Generate new token". If you experience `rate limit exceeded` when deploying to Vercel you need to specify a GitHub token as an environment variable in your project settings. | ||
|
||
```sh | ||
GITHUB_TOKEN=d107d6aaf3a6b550ebeead351a3974cb8b262b74 npm run dev | ||
``` | ||
|
||
## Disable Vercel comments | ||
|
||
<p align="center"><img src=".vscode/VercelComment.png" width="836" alt="Vercel comment example"></p> | ||
|
||
By default Vercel for GitHub will comment on commits and pull requests when it successfully deploys your repo. This can be disabled by setting `github.silent` to `true` in your Vercel configuration (add `vercel.json` in the root of your repository). [Reference](https://vercel.com/docs/configuration#git-integrations/github-silent). | ||
|
||
## Notes | ||
|
||
- If you reupload a package with the same name and tag (resulting with a URL that is already in `repo.js`) you will need to redeploy your repo or restart your development server | ||
|
||
## Join [The Community Repo](https://repo.community/) | ||
|
||
To become a part of The Community Repo add a file in the `public` folder called `repo_community_validation.txt` with the following contents: | ||
|
||
``` | ||
community.repo.access: allow_forwarding_all | ||
``` | ||
|
||
Visit the [Add Your Repo](https://repo.community/add) page, fill out the form at the bottom of the page, and click Submit. | ||
|
||
## Repositories using this template | ||
|
||
- [https://dimitarnestorov.com/](https://dimitarnestorov.com/) ([Source code](https://github.com/dimitarnestorov/website)) | ||
- [https://yulkytulky.com/](https://yulkytulky.com/) ([Source code](https://github.com/YulkyTulky/Repo)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import Links from './Links' | ||
import Page from './Page' | ||
import Section, { SectionPadding } from './Section' | ||
|
||
import { icons } from '../loader!../repo' | ||
|
||
export default function Depiction({ children, name, subtitle, github }) { | ||
return ( | ||
<Page title={name}> | ||
<style jsx>{` | ||
.title { | ||
margin: 16px 0; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
} | ||
.title > img { | ||
width: 48px; | ||
height: 48px; | ||
} | ||
.titles { | ||
margin: 0 0 0 8px; | ||
text-align: center; | ||
} | ||
.titles > h1 { | ||
font-size: 24px; | ||
margin: 0; | ||
} | ||
.titles > h2 { | ||
font-size: 12px; | ||
margin: 0; | ||
font-weight: 400; | ||
} | ||
`}</style> | ||
<div className="title"> | ||
<img src={icons[name]} alt={`${name} icon`} /> | ||
<div className="titles"> | ||
<h1>{name}</h1> | ||
{subtitle && <h2>{subtitle}</h2>} | ||
</div> | ||
</div> | ||
<Section> | ||
<SectionPadding>{children}</SectionPadding> | ||
</Section> | ||
<Links> | ||
{[ | ||
{ icon: '/assets/link-icons/PayPal.png', label: 'PayPal', href: 'https://www.paypal.me/' }, | ||
{ icon: '/assets/link-icons/Discord.png', label: 'Discord', href: 'https://discord.gg/' }, | ||
{ icon: '/assets/link-icons/Twitter.png', label: 'Twitter', href: 'https://twitter.com/' }, | ||
{ icon: '/assets/link-icons/GitHub.png', label: 'GitHub', href: github }, | ||
]} | ||
</Links> | ||
</Page> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import Section from './Section' | ||
|
||
export default function Links({ children }) { | ||
return ( | ||
<Section> | ||
<div className="links"> | ||
<style jsx>{` | ||
.links > a { | ||
height: 44px; | ||
padding: 0 12px; | ||
display: flex; | ||
align-items: center; | ||
border-bottom: 1px solid #333; | ||
font-size: 16px; | ||
font-weight: 300; | ||
} | ||
.links > a:last-child { | ||
border-bottom: 0 none; | ||
} | ||
.links > a > img { | ||
width: 29px; | ||
height: 29px; | ||
margin-right: 8px; | ||
} | ||
`}</style> | ||
{children.map( | ||
(link, i) => | ||
link.href && ( | ||
<a href={link.href} key={i} target="_blank"> | ||
<img src={link.icon} alt={`${link.label} icon`} /> | ||
<span>{link.label}</span> | ||
</a> | ||
), | ||
)} | ||
</div> | ||
</Section> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import Head from 'next/head' | ||
|
||
import { name as repoName } from '../loader!../repo' | ||
|
||
export default function Page({ children, title }) { | ||
return ( | ||
<> | ||
<Head> | ||
<title>{title ? `${title} - ${repoName}` : repoName}</title> | ||
<link rel="icon" href="/favicon.ico" /> | ||
</Head> | ||
<style jsx global>{` | ||
* { | ||
box-sizing: border-box; | ||
} | ||
html { | ||
background-color: black; | ||
color: white; | ||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, | ||
'Open Sans', 'Helvetica Neue', sans-serif; | ||
} | ||
body { | ||
margin: 0; | ||
} | ||
a { | ||
color: #1687e9; | ||
} | ||
.container { | ||
max-width: 400px; | ||
width: 90%; | ||
margin: 0 auto; | ||
} | ||
`}</style> | ||
<div className="container">{children}</div> | ||
</> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
export default function Section({ children }) { | ||
return ( | ||
<div className="section"> | ||
<style jsx>{` | ||
.section { | ||
background-color: #222222; | ||
margin: 16px 0; | ||
border-radius: 8px; | ||
} | ||
`}</style> | ||
{children} | ||
</div> | ||
) | ||
} | ||
|
||
export function SectionPadding({ children }) { | ||
return ( | ||
<div className="padding"> | ||
<style jsx>{` | ||
.padding { | ||
padding: 12px; | ||
} | ||
`}</style> | ||
{children} | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
const crypto = require('crypto') | ||
const fs = require('fs') | ||
const path = require('path') | ||
const stream = require('stream') | ||
|
||
const ar = require('ar') | ||
const axios = require('axios') | ||
const gunzipMaybe = require('gunzip-maybe') | ||
const tar = require('tar-stream') | ||
|
||
const { urlRegexp } = require('./utils') | ||
|
||
// Create node_modules/.cache folder | ||
const cacheFolder = path.join(__dirname, 'node_modules', '.cache') | ||
if (!fs.existsSync(cacheFolder)) { | ||
fs.mkdirSync(cacheFolder) | ||
} | ||
|
||
// Load node_modules/.cache/urlsLoader.json | ||
const cacheVersion = 2 | ||
const cacheFile = path.join(__dirname, 'node_modules', '.cache', 'urlsLoader.json') | ||
function getCacheFileContents() { | ||
const emptyCache = { | ||
version: cacheVersion, | ||
cache: {}, | ||
} | ||
|
||
if (fs.existsSync(cacheFile)) { | ||
try { | ||
const cacheFileContents = require(cacheFile) | ||
if (cacheFileContents.version !== cacheVersion) return emptyCache | ||
if (typeof cacheFileContents.cache !== 'object') return emptyCache | ||
|
||
return cacheFileContents | ||
} catch (error) { | ||
return emptyCache | ||
} | ||
} else { | ||
return emptyCache | ||
} | ||
} | ||
const cache = getCacheFileContents().cache | ||
let lastWrittenCache = JSON.stringify(cache) | ||
|
||
const urlsToAssetId = {} | ||
|
||
function getAssetIdForURL(url) { | ||
const result = url.match(urlRegexp) | ||
if (!result) throw new Error(`Bad URL: ${url}`) | ||
const [, owner, repo, tag] = result | ||
const options = {} | ||
if (process.env.GITHUB_TOKEN) options.headers = { Authorization: `token ${process.env.GITHUB_TOKEN}` } | ||
return axios | ||
.get(`https://api.github.com/repos/${owner}/${repo}/releases/tags/${tag}`, options) | ||
.then(({ data }) => (data.assets.filter((asset) => asset.browser_download_url === url)[0] || {}).id) | ||
.catch(({ response }) => { | ||
throw new Error(response.statusText) | ||
}) | ||
} | ||
|
||
function extractControlTarGunzipMaybe(data) { | ||
return new Promise((resolve, reject) => { | ||
const readableStream = new stream.Readable({ | ||
read() { | ||
this.push(data) | ||
this.push(null) | ||
}, | ||
}) | ||
|
||
const extract = tar.extract() | ||
|
||
extract.on('entry', function (header, stream, next) { | ||
if (header.name === './control') { | ||
const data = [] | ||
stream.on('data', (chunk) => { | ||
data.push(chunk) | ||
}) | ||
stream.on('end', function () { | ||
resolve(Buffer.concat(data).toString()) | ||
}) | ||
stream.resume() | ||
} else { | ||
next() | ||
} | ||
}) | ||
|
||
extract.on('finish', function () { | ||
reject(new Error('control file missing')) | ||
}) | ||
|
||
readableStream.pipe(gunzipMaybe()).pipe(extract) | ||
}) | ||
} | ||
|
||
function convertControlToObject(control) { | ||
const controlRegExp = /^([A-Za-z-]+): (.*)$/gm | ||
const meta = {} | ||
|
||
let result | ||
while ((result = controlRegExp.exec(control))) { | ||
meta[result[1]] = result[2] | ||
} | ||
|
||
delete meta.Icon | ||
return meta | ||
} | ||
|
||
async function getMetaForURL(url) { | ||
const { data } = await axios.get(url, { responseType: 'arraybuffer' }) | ||
|
||
const archive = new ar.Archive(data) | ||
|
||
const meta = {} | ||
|
||
for (const file of archive.getFiles()) { | ||
const fileName = file.name() | ||
if (fileName.startsWith('control.tar')) { | ||
Object.assign(meta, convertControlToObject(await extractControlTarGunzipMaybe(file.fileData()))) | ||
} else if (fileName.startsWith('data.tar') || fileName === 'debian-binary') { | ||
// Skip | ||
} else { | ||
console.warn('File', fileName, 'not supported; skipping') | ||
} | ||
} | ||
|
||
delete meta.Depiction | ||
delete meta.Icon | ||
|
||
// Calculate Size [size of package] | ||
meta.Size = data.length | ||
|
||
// Calculate MD5sum of package | ||
meta.MD5sum = crypto.createHash('md5').update(data).digest('hex') | ||
|
||
meta.Filename = `api/deb/${meta.MD5sum}.deb` | ||
|
||
// Calculate SHA1 of package | ||
meta.SHA1 = crypto.createHash('sha1').update(data).digest('hex') | ||
|
||
// Calculate SHA256 of package | ||
meta.SHA256 = crypto.createHash('sha256').update(data).digest('hex') | ||
|
||
return meta | ||
} | ||
|
||
module.exports = async function () { | ||
const repo = require(this.resourcePath) | ||
|
||
const packages = await Promise.all( | ||
repo.packages.map(async (url) => { | ||
const assetId = urlsToAssetId[url] || (urlsToAssetId[url] = await getAssetIdForURL(url)) | ||
if (!assetId) throw new Error(`Asset with URL ${url} not found`) | ||
const meta = cache[assetId] || (cache[assetId] = await getMetaForURL(url)) | ||
return { meta, url } | ||
}), | ||
) | ||
|
||
const currentCacheSerialized = JSON.stringify({ version: cacheVersion, cache }) | ||
if (lastWrittenCache !== currentCacheSerialized) { | ||
fs.writeFileSync(cacheFile, currentCacheSerialized) | ||
lastWrittenCache = currentCacheSerialized | ||
} | ||
|
||
const restructuredPackages = {} | ||
const md5Table = {} | ||
|
||
for (const p of packages) { | ||
// package is a reserved variable name | ||
if (!restructuredPackages[p.meta.Name]) restructuredPackages[p.meta.Name] = {} | ||
restructuredPackages[p.meta.Name][p.meta.Version] = p | ||
md5Table[p.meta.MD5sum] = p.url | ||
} | ||
|
||
return `export const packages = ${JSON.stringify(restructuredPackages)}; | ||
export const md5Table = ${JSON.stringify(md5Table)}; | ||
export const name = ${JSON.stringify(repo.name)}; | ||
export const description = ${JSON.stringify(repo.description)}; | ||
export const icons = ${JSON.stringify(repo.icons)};` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
module.exports = { | ||
async rewrites() { | ||
return [ | ||
{ source: '/Release', destination: '/api/Release' }, | ||
{ source: '/./Release', destination: '/api/Release' }, | ||
{ source: '/./Packages', destination: '/api/Packages' }, | ||
{ source: '/./Packages.gz', destination: '/api/Packages.gz' }, | ||
{ source: '/Packages', destination: '/api/Packages' }, | ||
{ source: '/Packages.gz', destination: '/api/Packages.gz' }, | ||
{ source: '/./CydiaIcon.png', destination: '/CydiaIcon.png' }, | ||
{ source: '/./api/(.*)', destination: '/api/$1' }, | ||
] | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
{ | ||
"name": "repo", | ||
"version": "0.0.0", | ||
"private": true, | ||
"license": "MIT", | ||
"scripts": { | ||
"dev": "next dev", | ||
"build": "next build", | ||
"start": "next start" | ||
}, | ||
"dependencies": { | ||
"@apollo/react-hooks": "^3.1.5", | ||
"apollo-cache-inmemory": "^1.6.6", | ||
"apollo-client": "^2.6.10", | ||
"apollo-link-http": "^1.5.17", | ||
"graphql": "^15.3.0", | ||
"graphql-tag": "^2.10.4", | ||
"next": "^9.5.1", | ||
"nookies": "^2.3.2", | ||
"react": "^16.13.1", | ||
"react-dom": "^16.13.1", | ||
"timeago-react": "^3.0.0" | ||
}, | ||
"devDependencies": { | ||
"ar": "^0.0.1", | ||
"axios": "^0.19.2", | ||
"gunzip-maybe": "^1.4.2", | ||
"tar-stream": "^2.1.2" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import Depiction from '../components/Depiction' | ||
|
||
export default function Blue() { | ||
return ( | ||
<Depiction name="Blue" github="https://github.com/dimitarnestorov/RepoOnVercel/tree/example-tweak-blue"> | ||
Blue is a <span style={{ color: 'blue' }}>blue</span> package. | ||
</Depiction> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import Depiction from '../components/Depiction' | ||
|
||
export default function Green() { | ||
return ( | ||
<Depiction name="Green" subtitle="Green like lettuce"> | ||
Green is a <span style={{ color: 'green' }}>green</span> package. | ||
</Depiction> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import Depiction from '../components/Depiction' | ||
|
||
export default function Red() { | ||
return ( | ||
<Depiction | ||
name="Red" | ||
github="https://github.com/dimitarnestorov/RepoOnVercel/tree/example-tweak-red" | ||
subtitle="Reddest of them all" | ||
> | ||
Red is a <span style={{ color: 'red' }}>red</span> package. | ||
</Depiction> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { gzipSync } from 'zlib' | ||
|
||
import Packages from './Packages' | ||
|
||
export default (req, res) => { | ||
const fakeRes = { | ||
setHeader() {}, | ||
end(end) { | ||
this.end = end | ||
}, | ||
} | ||
Packages(req, fakeRes) | ||
res.setHeader('Cache-Control', 's-maxage=31536000') | ||
res.end(gzipSync(Buffer.from(fakeRes.end))) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { packages, icons } from '../../loader!../../repo' | ||
import { getRepoUrl } from '../../utils' | ||
|
||
const spaceRegExp = /\s/g | ||
|
||
export default (req, res) => { | ||
const url = getRepoUrl(req) | ||
const result = [] | ||
for (const name in packages) { | ||
const versions = packages[name] | ||
for (const version in versions) { | ||
const p = versions[version] // package is a reserved variable name | ||
const strings = [] | ||
for (const entry in p.meta) { | ||
strings.push(`${entry}: ${p.meta[entry]}`) | ||
} | ||
|
||
icons[name] && strings.push(`Icon: ${url}${icons[name]}`) | ||
strings.push(`Depiction: ${url}${name.replace(spaceRegExp, '-')}`) | ||
|
||
result.push(strings.join('\n')) | ||
} | ||
} | ||
|
||
res.setHeader('Cache-Control', 's-maxage=31536000') | ||
res.end(result.join('\n\n')) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { name, description } from '../../loader!../../repo' | ||
|
||
export default (req, res) => { | ||
res.setHeader('Cache-Control', 's-maxage=31536000') | ||
res.end(`Origin: ${name} | ||
Label: ${name} | ||
Suite: stable | ||
Version: 1.0 | ||
Codename: ios | ||
Architectures: iphoneos-arm | ||
Components: main | ||
Description: ${description} | ||
`) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { md5Table } from '../../../loader!../../../repo' | ||
|
||
export default (req, res) => { | ||
if (req.method === 'HEAD') { | ||
res.status(200) | ||
res.end() | ||
return | ||
} | ||
|
||
const query = req.query['md5.deb'] | ||
const md5 = query.substr(0, query.length - 4) | ||
const url = md5Table[md5] | ||
if (!url) { | ||
res.status(404) | ||
} else { | ||
res.setHeader('Location', url) | ||
res.status(302) | ||
} | ||
res.end() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
import { useRef } from 'react' | ||
|
||
import { name as repoName } from '../loader!../repo' | ||
import Page from '../components/Page' | ||
import { getRepoUrl } from '../utils' | ||
|
||
export default function Home({ repoURL }) { | ||
const inputRef = useRef() | ||
return ( | ||
<Page> | ||
<style jsx>{` | ||
h1 { | ||
text-align: center; | ||
margin-bottom: 100px; | ||
} | ||
.package-manager { | ||
display: flex; | ||
align-items: center; | ||
color: white; | ||
text-align: center; | ||
background-color: #000000; | ||
border: 1px solid rgba(255, 255, 255, 0.5); | ||
margin: 10px auto; | ||
width: 200px; | ||
border-radius: 14px; | ||
font-size: 20px; | ||
text-decoration: none; | ||
} | ||
.package-manager > span { | ||
flex-grow: 1; | ||
margin-right: 8px; | ||
} | ||
.package-manager::before { | ||
content: ''; | ||
background-repeat: no-repeat; | ||
width: 36px; | ||
height: 36px; | ||
margin: 6px 0 6px 6px; | ||
background-size: contain; | ||
} | ||
.package-manager.cydia::before { | ||
background-image: url('/assets/package-managers/Cydia.png'); | ||
} | ||
.package-manager.zebra::before { | ||
background-image: url('/assets/package-managers/Zebra.png'); | ||
} | ||
.package-manager.sileo::before { | ||
background-image: url('/assets/package-managers/Sileo.png'); | ||
} | ||
.input-container { | ||
width: 320px; | ||
max-width: 90%; | ||
position: relative; | ||
margin: 32px auto; | ||
} | ||
.input-container > input { | ||
border: 0 none; | ||
padding: 0 68px 0 12px; | ||
font-size: 18px; | ||
height: 50px; | ||
width: 100%; | ||
border-radius: 12px; | ||
flex-grow: 1; | ||
background-color: #333333; | ||
color: #ffffff; | ||
} | ||
.input-container > button { | ||
font-size: 16px; | ||
position: absolute; | ||
height: 30px; | ||
right: 10px; | ||
top: 10px; | ||
padding: 6px 8px; | ||
border-radius: 6px; | ||
background-color: #1e90ff; | ||
color: #ffffff; | ||
border: 0 none; | ||
line-height: 16px; | ||
} | ||
`}</style> | ||
|
||
<h1>{repoName}</h1> | ||
|
||
<a | ||
href={`cydia://url/https://cydia.saurik.com/api/share#?source=${repoURL}`} | ||
className="package-manager cydia" | ||
> | ||
<span>Add to Cydia</span> | ||
</a> | ||
<a href={`zbra://sources/add/${repoURL}`} className="package-manager zebra"> | ||
<span>Add to Zebra</span> | ||
</a> | ||
<a href={`sileo://source/${repoURL}`} className="package-manager sileo"> | ||
<span>Add to Sileo</span> | ||
</a> | ||
{/* <a href={`installer://add/repo=${repoURL}`}>Add to Installer</a> */} | ||
|
||
<div className="input-container"> | ||
<input | ||
value={repoURL} | ||
readOnly | ||
ref={inputRef} | ||
onClick={() => { | ||
inputRef.current.select() | ||
inputRef.current.setSelectionRange(0, repoURL.length) | ||
}} | ||
/> | ||
<button | ||
onClick={() => { | ||
if (navigator.clipboard && navigator.clipboard.writeText) { | ||
navigator.clipboard.writeText(repoURL) | ||
} else { | ||
inputRef.current.select() | ||
inputRef.current.setSelectionRange(0, repoURL.length) | ||
document.execCommand('copy') | ||
} | ||
}} | ||
> | ||
Copy | ||
</button> | ||
</div> | ||
</Page> | ||
) | ||
} | ||
|
||
Home.getInitialProps = ({ req }) => ({ | ||
repoURL: getRepoUrl(req), | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,394 @@ | ||
import { ApolloProvider, useQuery } from '@apollo/react-hooks' | ||
import { ApolloClient } from 'apollo-client' | ||
import { InMemoryCache } from 'apollo-cache-inmemory' | ||
import { HttpLink } from 'apollo-link-http' | ||
import gql from 'graphql-tag' | ||
import { setCookie, parseCookies, destroyCookie } from 'nookies' | ||
import { useMemo, useRef, useState, createContext, useContext, useEffect } from 'react' | ||
import TimeAgo from 'timeago-react' | ||
|
||
import Page from '../components/Page' | ||
|
||
import { packages, icons } from '../loader!../repo' | ||
import { urlRegexp } from '../utils' | ||
|
||
let apolloClient | ||
|
||
function createApolloClient(token) { | ||
return new ApolloClient({ | ||
ssrMode: typeof window === 'undefined', | ||
link: new HttpLink({ | ||
uri: 'https://api.github.com/graphql', // Server URL (must be absolute) | ||
// credentials: 'same-origin', // Additional fetch() options like `credentials` or `headers` | ||
headers: { | ||
authorization: `bearer ${token}`, | ||
}, | ||
}), | ||
cache: new InMemoryCache(), | ||
shouldBatch: true, | ||
}) | ||
} | ||
|
||
function initializeApollo(token, initialState = null) { | ||
const _apolloClient = apolloClient ?? createApolloClient(token) | ||
|
||
if (initialState) { | ||
_apolloClient.cache.restore(initialState) | ||
} | ||
// For SSG and SSR always create a new Apollo Client | ||
if (typeof window === 'undefined') return _apolloClient | ||
// Create the Apollo Client once in the client | ||
if (!apolloClient) apolloClient = _apolloClient | ||
|
||
return _apolloClient | ||
} | ||
|
||
function useApollo(token, initialState) { | ||
return useMemo(() => initializeApollo(token, initialState), [token, initialState]) | ||
} | ||
|
||
function hashCode(string) { | ||
var hash = 0, | ||
i, | ||
chr | ||
for (i = 0; i < string.length; i++) { | ||
chr = string.charCodeAt(i) | ||
hash = (hash << 5) - hash + chr | ||
hash |= 0 // Convert to 32bit integer | ||
} | ||
return ('a' + hash).replace('a-', 'az') | ||
} | ||
|
||
function setObjectIfNotSet(object, key) { | ||
const currentValue = object[key] | ||
if (currentValue) return currentValue | ||
return (object[key] = {}) | ||
} | ||
|
||
// owner -> repo -> tag -> asset | ||
const resources = {} | ||
const nodes = [] | ||
for (const i in packages) { | ||
const p = packages[i] | ||
|
||
for (const version in p) { | ||
const url = p[version].url | ||
const matches = url.match(urlRegexp) | ||
if (!matches) throw new Error(`Bad URL: ${url}`) | ||
|
||
const [, owner, repoName, tagName, assetName] = matches | ||
|
||
const ownerObject = setObjectIfNotSet(resources, owner) | ||
const repoObject = setObjectIfNotSet(ownerObject, repoName) | ||
const tagObject = setObjectIfNotSet(repoObject, tagName) | ||
tagObject[assetName] = hashCode(url) | ||
} | ||
|
||
nodes.push(<Package key={i} name={i} package={p} />) | ||
} | ||
|
||
const buildReleaseQuery = (hash, tagName, assetName) => | ||
`${hash}: release(tagName: "${tagName}") { | ||
releaseAssets(name: "${assetName}", first: 1) { | ||
nodes { | ||
downloadCount | ||
} | ||
} | ||
}` | ||
|
||
const queryParts = [] | ||
for (const owner in resources) { | ||
const ownerObject = resources[owner] | ||
for (const repoName in ownerObject) { | ||
const repoObject = ownerObject[repoName] | ||
queryParts.push(`${hashCode(`${owner}/${repoName}`)}: repository(owner: "${owner}", name: "${repoName}") {`) | ||
for (const tagName in repoObject) { | ||
const tagObject = repoObject[tagName] | ||
for (const assetName in tagObject) { | ||
const hash = tagObject[assetName] | ||
queryParts.push(buildReleaseQuery(hash, tagName, assetName)) | ||
} | ||
} | ||
queryParts.push(`}`) | ||
} | ||
} | ||
|
||
const query = gql` | ||
query GetDownloads { | ||
${queryParts.join('')} | ||
rateLimit { | ||
limit | ||
cost | ||
remaining | ||
resetAt | ||
} | ||
} | ||
` | ||
|
||
const DataContext = createContext() | ||
|
||
function Version({ version, url }) { | ||
const data = useContext(DataContext) | ||
|
||
return ( | ||
<li> | ||
Version {version} has {data[hashCode(url)].releaseAssets.nodes[0].downloadCount} downloads | ||
</li> | ||
) | ||
} | ||
|
||
function Package({ package: p, name }) { | ||
const versions = [] | ||
for (const i in p) { | ||
versions.push(<Version key={i} version={i} url={p[i].url} />) | ||
} | ||
|
||
return ( | ||
<div className="tweak"> | ||
<style jsx>{` | ||
.tweak { | ||
background-color: #272727; | ||
padding: 12px; | ||
margin: 10px 0; | ||
border-radius: 10px; | ||
} | ||
.tweakName { | ||
display: flex; | ||
align-items: center; | ||
} | ||
.tweakName > img { | ||
margin-right: 8px; | ||
} | ||
.tweakName > h3 { | ||
margin: 0; | ||
} | ||
ul { | ||
margin: 8px 0 0; | ||
padding-left: 20px; | ||
font-size: 18px; | ||
} | ||
`}</style> | ||
<div className="tweakName"> | ||
{icons[name] && <img src={icons[name]} alt={`${name} icon`} width="40" height="40" />} | ||
<h3>{name}</h3> | ||
</div> | ||
<ul>{versions}</ul> | ||
</div> | ||
) | ||
} | ||
|
||
function Stats({ setState }) { | ||
const { loading, error, data } = useQuery(query) | ||
|
||
const flatData = useMemo(() => { | ||
const object = {} | ||
for (const i in data) { | ||
if (i === 'rateLimit') continue | ||
Object.assign(object, data[i]) | ||
} | ||
return object | ||
}, [data]) | ||
|
||
return ( | ||
<> | ||
<style jsx>{` | ||
h1 { | ||
text-align: center; | ||
} | ||
details { | ||
opacity: 0.8; | ||
} | ||
details > ul { | ||
margin-top: 6px; | ||
} | ||
details > summary { | ||
cursor: pointer; | ||
padding: 4px; | ||
user-select: none; | ||
} | ||
`}</style> | ||
<h1>Statistics</h1> | ||
|
||
{error ? ( | ||
<> | ||
<p style={{ color: 'red' }}>Error: {error.message}</p> | ||
<button | ||
onClick={() => { | ||
setState({ token: '' }) | ||
destroyCookie(undefined, 'token') | ||
}} | ||
> | ||
Delete saved token | ||
</button> | ||
</> | ||
) : loading ? ( | ||
'Loading…' | ||
) : ( | ||
<DataContext.Provider value={flatData}> | ||
{nodes} | ||
<details> | ||
<summary>Rate limit</summary> | ||
<ul> | ||
<li>Limit: {data.rateLimit.limit}</li> | ||
<li>Cost: {data.rateLimit.cost}</li> | ||
<li>Remaining: {data.rateLimit.remaining}</li> | ||
<li> | ||
Remaining resets <TimeAgo datetime={data.rateLimit.resetAt} /> | ||
</li> | ||
</ul> | ||
</details> | ||
</DataContext.Provider> | ||
)} | ||
</> | ||
) | ||
} | ||
|
||
function Provider({ state, children }) { | ||
const apolloClient = useApollo(state.token, state.initialState) | ||
return <ApolloProvider client={apolloClient}>{children}</ApolloProvider> | ||
} | ||
|
||
export default function GetToken({ token, initialState }) { | ||
const [state, setState] = useState({ token, initialState }) | ||
const inputRef = useRef() | ||
|
||
const [isMounted, setIsMounted] = useState(false) | ||
useEffect(() => { | ||
setIsMounted(true) | ||
}, [setIsMounted]) | ||
|
||
return ( | ||
<Page title="Statistics"> | ||
{state.token ? ( | ||
<Provider state={state}> | ||
<Stats setState={setState} /> | ||
</Provider> | ||
) : ( | ||
<div> | ||
<style jsx>{` | ||
div { | ||
text-align: center; | ||
font-size: 18px; | ||
} | ||
div > * { | ||
margin: 8px 0; | ||
} | ||
a { | ||
display: block; | ||
margin: 32px 0 !important; | ||
} | ||
form { | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
} | ||
input { | ||
border-radius: 16px; | ||
border: 0; | ||
padding: 0 | ||
${typeof window !== 'undefined' && isMounted && navigator.clipboard ? '68px' : '16px'} 0 | ||
12px; | ||
font-size: 16px; | ||
height: 32px; | ||
background-color: #222222; | ||
color: #ffffff; | ||
width: 248px; | ||
font-family: monospace; | ||
} | ||
button[type='button'] { | ||
height: 26px; | ||
border-radius: 13px; | ||
border: 0; | ||
padding: 0; | ||
width: 60px; | ||
font-size: 15px; | ||
margin-left: -63px; | ||
text-align: center; | ||
background-color: #000000; | ||
border: 1px solid #666666; | ||
color: #ffffff; | ||
} | ||
button[type='submit'] { | ||
height: 32px; | ||
border-radius: 16px; | ||
border: 0; | ||
padding: 0 16px; | ||
font-size: 16px; | ||
margin-left: 8px; | ||
background-color: #1e90ff; | ||
color: #ffffff; | ||
} | ||
`}</style> | ||
<a href="https://github.com/settings/tokens" target="_blank"> | ||
Get a GitHub personal access token | ||
</a> | ||
<div>Enter your GitHub personal access token:</div> | ||
<form | ||
onSubmit={(event) => { | ||
event.preventDefault() | ||
const token = inputRef.current.value | ||
setCookie(undefined, 'token', token, { maxAge: 500000000 }) | ||
setState({ token, initialState: state.initialState }) | ||
}} | ||
> | ||
<input | ||
type="text" | ||
ref={inputRef} | ||
placeholder="76d80224611fc919a5d54f0ff9fba446cdec93ec" | ||
autoCorrect="off" | ||
autoComplete="off" | ||
autoCapitalize="off" | ||
/> | ||
{typeof window !== 'undefined' && isMounted && navigator.clipboard && ( | ||
<button | ||
type="button" | ||
onClick={() => | ||
navigator.clipboard | ||
.readText() | ||
.then((text) => (inputRef.current.value = text)) | ||
.catch(() => | ||
alert( | ||
'Please allow access to your clipboard in order for the paste button to work', | ||
), | ||
) | ||
} | ||
> | ||
Paste | ||
</button> | ||
)} | ||
<button type="submit">Save</button> | ||
</form> | ||
</div> | ||
)} | ||
</Page> | ||
) | ||
} | ||
|
||
GetToken.getInitialProps = async (ctx) => { | ||
const token = parseCookies(ctx).token | ||
const apolloClient = initializeApollo(token) | ||
|
||
try { | ||
if (token) { | ||
await apolloClient.query({ | ||
query, | ||
}) | ||
} | ||
} catch (error) { | ||
console.error(error) | ||
} | ||
|
||
return { token, initialState: apolloClient.cache.extract() } | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
User-agent: * | ||
Allow: / |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
exports.name = 'Repo on Vercel' | ||
exports.description = "Repo on Vercel's example repository" | ||
|
||
exports.packages = [ | ||
'https://github.com/dimitarnestorov/RepoOnVercel/releases/download/red-1.0.1/example.red_1.0.1_iphoneos-arm.deb', | ||
'https://github.com/dimitarnestorov/RepoOnVercel/releases/download/red-1.0.0/example.red_1.0.0_iphoneos-arm.deb', | ||
'https://github.com/dimitarnestorov/RepoOnVercel/releases/download/green-1.0.0/example.green_1.0.0_iphoneos-arm.deb', | ||
'https://github.com/dimitarnestorov/RepoOnVercel/releases/download/blue-1.0.0/example.blue_1.0.0_iphoneos-arm.deb', | ||
] | ||
|
||
exports.icons = { | ||
Red: 'assets/red/icon.png', | ||
Blue: 'assets/blue/icon.png', | ||
Green: 'assets/green/icon.png', | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
exports.urlRegexp = /^https:\/\/github.com\/([^\/]+)\/([^\/]+)\/releases\/download\/([^\/]+)\/([^\/]+)$/ | ||
|
||
exports.getRepoUrl = function getRepoUrl(req) { | ||
if (req) { | ||
return `${ | ||
req.headers['x-forwarded-proto'] | ||
? req.headers['x-forwarded-proto'] | ||
: process.env.NODE_ENV === 'production' | ||
? 'https' | ||
: 'http' | ||
}://${req.headers['x-forwarded-host'] ? req.headers['x-forwarded-host'] : req.headers.host}/` | ||
} | ||
|
||
return `${window.location.protocol}//${window.locations.host}/` | ||
} |