Skip to content

Commit

Permalink
Remove axios from the dependency list
Browse files Browse the repository at this point in the history
  • Loading branch information
marcomontalbano committed Feb 26, 2024
1 parent bfe7ea3 commit 72641f4
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 25 deletions.
1 change: 0 additions & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"dependencies": {
"@figma-export/core": "^5.0.1",
"@figma-export/types": "^5.0.1",
"axios": "^1.4.0",
"ora": "~5.4.1",
"sade": "~1.8.1"
},
Expand Down
48 changes: 32 additions & 16 deletions packages/cli/src/commands/login.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import crypto from 'crypto';
import { Ora } from 'ora';
import { Sade } from 'sade';
import axios from 'axios';

import readline from 'readline';
import { jsonFetch } from '../jsonFetch';

type Auth = {
user_id: number
Expand All @@ -10,16 +12,8 @@ type Auth = {
expires_in: number
}

function check(state: string): Promise<Auth> {
const result = axios.get<Auth>(`http://localhost:3000/api/check/${state}`).then((response) => {
return response.data;
}).catch(() => {
return new Promise<Auth>((resolve) => {
setTimeout(() => resolve(check(state)), 2000);
});
});

return result;
function check(state: string): Promise<Auth | undefined> {
return jsonFetch<Auth>(`http://127.0.0.1:3000/api/check/${state}`).then((response) => response.data).catch(() => undefined);
}

export const addLogin = (prog: Sade, spinner: Ora) => prog
Expand All @@ -32,12 +26,34 @@ export const addLogin = (prog: Sade, spinner: Ora) => prog
spinner.info('Log in on https://figma.com');
console.log(`
Login at:
http://localhost:3000/api/login/${state}
http://127.0.0.1:3000/api/login/${state}
`);
spinner.start('waiting');
check(state).then((response) => {
spinner.info(response.access_token);
spinner.succeed('Logged in on https://figma.com.');

const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});

rl.question('PIN: ', (pin) => {
check(`${state}:${pin}`).then((response) => {
if (response == null) {
spinner.fail('Failed to login!');
return;
}

spinner.info(JSON.stringify(response, undefined, 2));
spinner.succeed('Logged in on https://figma.com.');
}).catch((error) => {
spinner.fail(error);
});
rl.close();
});

// spinner.start('waiting');

// check(state).then((response) => {
// spinner.info(JSON.stringify(response, undefined, 2));
// spinner.succeed('Logged in on https://figma.com.');
// });
},
);
62 changes: 62 additions & 0 deletions packages/cli/src/jsonFetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import http from 'http';
import https from 'https';

type Response<Data> = {
status?: number
statusText?: string
headers: http.IncomingHttpHeaders
body: string
data: Data
}

export const jsonFetch = <Data>(url: string): Promise<Response<Data>> => {
return new Promise((resolve, reject) => {
// Parse the URL
const parsedUrl = new URL(url);

// Determine the protocol module (http or https)
const protocol = parsedUrl.protocol === 'https:' ? https : http;

// Prepare the request options
const options = {
hostname: parsedUrl.hostname,
port: parsedUrl.port,
path: parsedUrl.pathname + parsedUrl.search,
method: 'GET',
};

// Send the request
const req = protocol.request(options, (res) => {
let body = '';

// Accumulate the response data
res.on('data', (chunk) => {
body += chunk;
});

// Resolve the promise when the response ends
res.on('end', () => {
try {
const data = JSON.parse(body);
resolve({
status: res.statusCode,
statusText: res.statusMessage,
headers: res.headers,
body,
data,
});
} catch (error) {
reject(error);
}
});
});

// Handle request errors
req.on('error', (error) => {
reject(error);
});

// End the request
req.end();
});
};
2 changes: 1 addition & 1 deletion packages/website/.env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
FIGMA_APP_CLIENT_SECRET=
FIGMA_APP_CLIENT_ID=
FIGMA_APP_REDIRECT_URI=http://localhost:3000/api/auth
FIGMA_APP_REDIRECT_URI=http://127.0.0.1:3000/api/auth
2 changes: 1 addition & 1 deletion packages/website/lib/auth-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export function setItem(key: string, value: Auth): void {

setTimeout(() => {
removeItem(key)
}, 10 * 1000)
}, 30 * 1000)
}

export function getItem(key: string): Auth | undefined {
Expand Down
11 changes: 9 additions & 2 deletions packages/website/pages/api/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ function isValid(cookieState: unknown, queryState: unknown): cookieState is stri
&& cookieState === queryState
}

function rnd(length: number) {
let min = Math.pow(10, length - 1)
let max = Math.pow(10, length) - 1
return Math.floor(Math.random() * (max - min + 1)) + min
}

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const state = req.query.state
const cookieState = req.cookies.state
Expand All @@ -26,8 +32,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
)
.then(r => r.json())

setItem(state, auth)
res.status(307).redirect('/auth/success')
const pin = rnd(6)
setItem(`${state}:${pin}`, auth)
res.status(307).redirect(`/auth/success#${pin}`)
} else {
res.status(443).json({ message: 'Access denied!' })
}
Expand Down
62 changes: 59 additions & 3 deletions packages/website/pages/auth/success.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,57 @@
import Link from 'next/link'
import GitHubLink from '../../src/GitHubLink'
import { useEffect, useRef, useState } from 'react'

export default function HomePage() {
const [pin, setPin] = useState<number>(NaN)
const [timer, setTimer] = useState<number>(30)
const interval = useRef<NodeJS.Timer>()

useEffect(function handleTimer() {
if (interval.current == null && !isNaN(pin)) {
const endTimeString = window.sessionStorage.getItem(pin.toString())
if (endTimeString == null) {
window.sessionStorage.setItem(pin.toString(), (Date.now() + 30 * 1000).toString())
} else {
const endTime = parseInt(endTimeString ?? '0')
setTimer(Math.round((endTime - Date.now()) / 1000))
}

interval.current = setInterval(() => setTimer((t) => t - 1), 1000);
}

() => clearInterval(interval.current)
}, [pin])

useEffect(function clearTimer() {
if (timer < 0) {
clearInterval(interval.current)
setTimer(0)
}
}, [timer])


useEffect(function readPin() {
setPin(parseInt(window.location.hash.slice(1)))
}, [])

if (isNaN(pin)) {
return (
<>
<div className="container hero figma-gradient with-opacity-05">
<section>
<h1 className="title">
<Link href="/"><a className="figma-gradient text">
@figma-export
</a></Link>
</h1>
</section>
</div>
<GitHubLink />
</>
)
}

return (
<>
<div className="container hero figma-gradient with-opacity-05">
Expand All @@ -12,12 +62,18 @@ export default function HomePage() {
</a></Link>
</h1>
<p>
<code className="figma-gradient with-opacity-10">authentication complete</code>
<code className="figma-gradient with-opacity-10" style={{ fontSize: '36px', textDecoration: timer > 0 ? undefined : 'line-through' }}>{pin}</code>
</p>
<p>You may now close this window</p>
{
timer > 0 ? (
<p>Copy this <code>pin</code> in your terminal window in {timer} seconds.</p>
) : (
<p>This <code>pin</code> expired.</p>
)
}
</section>
</div>
<GitHubLink />
</>
);
)
}
1 change: 0 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,6 @@ __metadata:
dependencies:
"@figma-export/core": ^5.0.1
"@figma-export/types": ^5.0.1
axios: ^1.4.0
ora: ~5.4.1
sade: ~1.8.1
bin:
Expand Down

0 comments on commit 72641f4

Please sign in to comment.