Skip to content

Commit

Permalink
feat: updater for Xplorer
Browse files Browse the repository at this point in the history
  • Loading branch information
kimlimjustin committed Dec 22, 2021
1 parent 24501a4 commit c46dd92
Show file tree
Hide file tree
Showing 19 changed files with 3,312 additions and 2 deletions.
5 changes: 5 additions & 0 deletions api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Home for Xplorer API.

# /api/updater

An API to check if there is an update available and to download it.
3 changes: 3 additions & 0 deletions api/updater/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}
39 changes: 39 additions & 0 deletions api/updater/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# 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
*.pem

# 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
.vercel

# typescript
*.tsbuildinfo

.vercel
4 changes: 4 additions & 0 deletions api/updater/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
## This is Xplorer's automatic updater API.

Nothing much here, just an [API](https://updater.xplorer.space) to check if there is an update available and to download it.
Go back to the [Xplorer website](https://xplorer.space) for Xplorer's docs.
5 changes: 5 additions & 0 deletions api/updater/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
4 changes: 4 additions & 0 deletions api/updater/next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/** @type {import('next').NextConfig} */
module.exports = {
reactStrictMode: true,
}
24 changes: 24 additions & 0 deletions api/updater/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "updater",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"next": "12.0.7",
"react": "17.0.2",
"react-dom": "17.0.2",
"semver": "^7.3.5"
},
"devDependencies": {
"@types/node": "17.0.2",
"@types/react": "17.0.37",
"@types/semver": "^7.3.9",
"eslint": "8.5.0",
"eslint-config-next": "12.0.7",
"typescript": "4.5.4"
}
}
8 changes: 8 additions & 0 deletions api/updater/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import '../styles/globals.css'
import type { AppProps } from 'next/app'

function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}

export default MyApp
96 changes: 96 additions & 0 deletions api/updater/pages/api/[...slug].ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { AVAILABLE_PLATFORMS, validatePlatform } from '../../util/platform';
import semver from 'semver';
import { GITHUB_TOKEN } from '../../util/constant';

export default async function handler(req: any, res: any) {
const { slug } = req.query;
const platform = slug[0];
const version = slug[1];

if (!platform || !validatePlatform(platform)) {
res.status(400).send('Invalid platform');
return;
}

if (!version || !semver.valid(version)) {
res.status(400).send('Invalid version');
return;
}
const reqUrl = new URL(`https://api.github.com/repos/kimlimjustin/xplorer/releases`);
// Headers
const headers: HeadersInit = { Accept: 'application/vnd.github.preview' };
if (GITHUB_TOKEN && GITHUB_TOKEN.length > 0) {
headers.Authorization = `token ${GITHUB_TOKEN}`;
}
const release = await (await fetch(reqUrl.toString(), { method: 'GET', headers })).json();

// Get the latest release but only the ones that is not draft
let index = 0;
let latest_release = release[index];
while (latest_release.draft) {
index++;
latest_release = release[index];
}
const latest_version = sanitizeVersion(latest_release.tag_name);
const should_update = semver.gt(latest_version, version);
if (!should_update) {
res.status(204).send('');
return;
}
for (const asset of latest_release.assets) {
const { name, browser_download_url } = asset;
const findPlatform = checkPlatform(platform, name);
if (!findPlatform) continue;

res.status(200).json({
name: latest_release.tag_name,
notes: `Please visit ${latest_release.html_url} to see the detailed changelog.`,
pub_date: latest_release.published_at,
signature: '',
url: browser_download_url,
});
return;
}
res.status(204).send('');
}

function sanitizeVersion(version: string): string {
// if it start with v1.0.0 remove the `v`
if (version.charAt(0) === 'v') {
return version.substring(1);
}

return version;
}

function extname(filename: string) {
return filename.split('.').pop() || '';
}

function checkPlatform(platform: string, fileName: string) {
const extension = extname(fileName);

// OSX we should have our .app tar.gz
if (
(fileName.includes('.app') || fileName.includes('darwin') || fileName.includes('osx')) &&
extension === 'gz' &&
platform === AVAILABLE_PLATFORMS.MacOS
) {
return 'darwin';
}

// Windows 64 bits
if ((fileName.includes('x64') || fileName.includes('win64')) && extension === 'zip' && platform === AVAILABLE_PLATFORMS.Win64) {
return 'win64';
}

// Windows 32 bits
if ((fileName.includes('x32') || fileName.includes('win32')) && extension === 'zip' && platform === AVAILABLE_PLATFORMS.Win32) {
return 'win32';
}

// Linux app image
if (fileName.includes('AppImage') && extension === 'gz' && platform === AVAILABLE_PLATFORMS.Linux) {
return 'linux';
}
}
30 changes: 30 additions & 0 deletions api/updater/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type { NextPage } from 'next';
import Head from 'next/head';
import styles from '../styles/Home.module.css';

const Home: NextPage = () => {
return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>

<main className={styles.main}>
<h1 className={styles.title}>Hello World.</h1>

<p className={styles.description}>Actually there{"'"}s nothing here, just an auto updater API for Xplorer. </p>

<div className={styles.grid}>
<a href="https://xplorer.space" className={styles.card}>
<h2>Xplorer Documentation &rarr;</h2>
<p>Go to Xplorer home page instead</p>
</a>
</div>
</main>
</div>
);
};

export default Home;
Binary file added api/updater/public/favicon.ico
Binary file not shown.
116 changes: 116 additions & 0 deletions api/updater/styles/Home.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
.container {
padding: 0 2rem;
}

.main {
min-height: 100vh;
padding: 4rem 0;
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}

.footer {
display: flex;
flex: 1;
padding: 2rem 0;
border-top: 1px solid #eaeaea;
justify-content: center;
align-items: center;
}

.footer a {
display: flex;
justify-content: center;
align-items: center;
flex-grow: 1;
}

.title a {
color: #0070f3;
text-decoration: none;
}

.title a:hover,
.title a:focus,
.title a:active {
text-decoration: underline;
}

.title {
margin: 0;
line-height: 1.15;
font-size: 4rem;
}

.title,
.description {
text-align: center;
}

.description {
margin: 4rem 0;
line-height: 1.5;
font-size: 1.5rem;
}

.code {
background: #fafafa;
border-radius: 5px;
padding: 0.75rem;
font-size: 1.1rem;
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
Bitstream Vera Sans Mono, Courier New, monospace;
}

.grid {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
max-width: 800px;
}

.card {
margin: 1rem;
padding: 1.5rem;
text-align: left;
color: inherit;
text-decoration: none;
border: 1px solid #eaeaea;
border-radius: 10px;
transition: color 0.15s ease, border-color 0.15s ease;
max-width: 300px;
}

.card:hover,
.card:focus,
.card:active {
color: #0070f3;
border-color: #0070f3;
}

.card h2 {
margin: 0 0 1rem 0;
font-size: 1.5rem;
}

.card p {
margin: 0;
font-size: 1.25rem;
line-height: 1.5;
}

.logo {
height: 1em;
margin-left: 0.5rem;
}

@media (max-width: 600px) {
.grid {
width: 100%;
flex-direction: column;
}
}
16 changes: 16 additions & 0 deletions api/updater/styles/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
html,
body {
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}

a {
color: inherit;
text-decoration: none;
}

* {
box-sizing: border-box;
}
20 changes: 20 additions & 0 deletions api/updater/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}
1 change: 1 addition & 0 deletions api/updater/util/constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
Loading

2 comments on commit c46dd92

@vercel
Copy link

@vercel vercel bot commented on c46dd92 Dec 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on c46dd92 Dec 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

updater – ./api/updater

updater-git-master-kimlimjustin.vercel.app
updater-five.vercel.app
updater-kimlimjustin.vercel.app

Please sign in to comment.