feat(api): add get-slug

This commit is contained in:
41666 2020-12-15 15:29:25 -05:00
parent a85c4d5ddd
commit c55ce3b828
7 changed files with 100 additions and 38 deletions

View file

@ -51,13 +51,17 @@ class KVShim {
} }
async get(key, type = 'text') { async get(key, type = 'text') {
const result = JSON.parse(await this.level.get(key)); try {
const result = JSON.parse(await this.level.get(key));
if (!this.validate(result)) { if (!this.validate(result)) {
return null;
}
return getConversion[type](result.value);
} catch (e) {
return null; return null;
} }
return getConversion[type](result.value);
} }
async getWithMetadata(key, type) { async getWithMetadata(key, type) {

View file

@ -30,14 +30,7 @@ const context = () =>
listeners.push(fn); listeners.push(fn);
} }
}, },
Response: class { Response: fetch.Response,
constructor(body, opts = {}) {
this.body = Buffer.from(body || '');
this.headers = opts.headers || {};
this.url = opts.url || {};
this.status = opts.status || 200;
}
},
URL: URL, URL: URL,
crypto: crypto, crypto: crypto,
setTimeout: setTimeout, setTimeout: setTimeout,
@ -45,6 +38,7 @@ const context = () =>
clearInterval: clearInterval, clearInterval: clearInterval,
clearTimeout: clearTimeout, clearTimeout: clearTimeout,
fetch: fetch, fetch: fetch,
console: console,
...workerShims, ...workerShims,
}, },
{ {
@ -59,24 +53,37 @@ const server = http.createServer((req, res) => {
const event = { const event = {
respondWith: async (value) => { respondWith: async (value) => {
const timeStart = Date.now(); const timeStart = Date.now();
const response = await value; let loggedStatus = 'xxx';
try {
const response = await value;
if (!response) {
throw new Error(
`response was invalid, got ${JSON.stringify(response)}`
);
}
res.statusCode = response.status;
loggedStatus = String(response.status);
Object.entries(response.headers).forEach(([k, v]) => res.setHeader(k, v));
res.end(response.body);
} catch (e) {
console.error(e);
res.statusCode = 500;
loggedStatus = '500';
res.end(JSON.stringify({ error: 'internal server error' }));
}
const timeEnd = Date.now(); const timeEnd = Date.now();
console.log( console.log(
`${response.status} [${timeEnd - timeStart}ms] - ${req.method} ${req.url}` `${loggedStatus} [${timeEnd - timeStart}ms] - ${req.method} ${req.url}`
); );
res.statusCode = response.status;
Object.entries(response.headers).forEach(([k, v]) => res.setHeader(k, v));
res.end(response.body);
},
request: {
url: `http://${req.headers.host || 'localhost'}${req.url}`,
body: req,
headers: Object.entries(req.headers).reduce(
(acc, [k, v]) => acc.set(k, v),
new Map()
),
method: req.method,
}, },
request: new fetch.Request(
new URL(`http://${req.headers.host || 'localhost'}${req.url}`),
{
body: ['GET', 'HEAD'].includes(req.method) ? undefined : req,
headers: req.headers,
method: req.method,
}
),
}; };
event.request.headers.set('cf-client-ip', req.connection.remoteAddress); event.request.headers.set('cf-client-ip', req.connection.remoteAddress);
@ -110,6 +117,7 @@ const reload = () => {
context(), context(),
{ {
displayErrors: true, displayErrors: true,
filename: 'worker.js',
} }
) )
); );
@ -124,6 +132,11 @@ const rebuild = () =>
console.log('Compilation failed.', err); console.log('Compilation failed.', err);
reject(err); reject(err);
} else { } else {
if (stats.hasErrors()) {
console.error('Compilation errored:', stats.compilation.errors);
return;
}
console.log('Compilation done.'); console.log('Compilation done.');
resolve(); resolve();
} }

View file

@ -1,9 +1,42 @@
import { Guild } from "roleypoly/common/types"; import { GuildSlug } from 'roleypoly/common/types';
import { discordFetch } from "../utils/api-tools"; import { respond } from '../utils/api-tools';
import { getGuild } from '../utils/guild';
export const GetSlug = async (request: Request): Promise<Response> => { export const GetSlug = async (request: Request): Promise<Response> => {
const reqURL = new URL(request.url) // return respond({ hello: 'world' });
const serverID = reqURL.pathname.split('/')[2] const reqURL = new URL(request.url);
const [, , serverID] = reqURL.pathname.split('/');
const serverPayload = discordFetch<Guild> if (!serverID) {
return respond(
{
error: 'missing server ID',
},
{
status: 400,
}
);
}
const guild = await getGuild(serverID);
if (!guild) {
return respond(
{
error: 'guild not found',
},
{
status: 404,
}
);
}
const { id, name, icon } = guild;
const guildSlug: GuildSlug = {
id,
name,
icon,
permissionLevel: 0,
};
console.log({ guildSlug });
return respond(guildSlug);
}; };

View file

@ -34,7 +34,7 @@ export class Router {
this.routingTree[lowerMethod][rootPath] = handler; this.routingTree[lowerMethod][rootPath] = handler;
} }
handle(request: Request): Promise<Response> | Response { async handle(request: Request): Promise<Response> | Response {
const url = new URL(request.url); const url = new URL(request.url);
if (url.pathname === '/' || url.pathname === '') { if (url.pathname === '/' || url.pathname === '') {

View file

@ -23,7 +23,7 @@ export const resolveFailures = (
return handler(request); return handler(request);
} catch (e) { } catch (e) {
console.error(e); console.error(e);
return handleWith; return handleWith || respond({ error: 'internal server error' }, { status: 500 });
} }
}; };
@ -60,7 +60,7 @@ export const discordFetch = async <T>(
url: string, url: string,
auth: string, auth: string,
authType: 'Bearer' | 'Bot' = 'Bearer' authType: 'Bearer' | 'Bot' = 'Bearer'
): Promise<T> => { ): Promise<T | null> => {
const response = await fetch('https://discord.com/api/v8' + url, { const response = await fetch('https://discord.com/api/v8' + url, {
headers: { headers: {
authorization: `${authType} ${auth}`, authorization: `${authType} ${auth}`,
@ -69,7 +69,11 @@ export const discordFetch = async <T>(
}, },
}); });
return (await response.json()) as T; if (response.ok) {
return (await response.json()) as T;
} else {
return null;
}
}; };
export const cacheLayer = <Identity, Data>( export const cacheLayer = <Identity, Data>(
@ -86,7 +90,6 @@ export const cacheLayer = <Identity, Data>(
} }
const fallbackValue = await missHandler(identity); const fallbackValue = await missHandler(identity);
if (!fallbackValue) { if (!fallbackValue) {
return null; return null;
} }

View file

@ -26,6 +26,10 @@ export const getGuild = cacheLayer(
async (id: string) => { async (id: string) => {
const guildRaw = await discordFetch<APIGuild>(`/guilds/${id}`, botToken, 'Bot'); const guildRaw = await discordFetch<APIGuild>(`/guilds/${id}`, botToken, 'Bot');
if (!guildRaw) {
return null;
}
// Filters the raw guild data into data we actually want // Filters the raw guild data into data we actually want
const guild: Guild = { const guild: Guild = {
id: guildRaw.id, id: guildRaw.id,

View file

@ -1,4 +1,5 @@
const path = require('path'); const path = require('path');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const mode = process.env.NODE_ENV || 'production'; const mode = process.env.NODE_ENV || 'production';
@ -12,7 +13,11 @@ module.exports = {
mode, mode,
resolve: { resolve: {
extensions: ['.ts', '.tsx', '.js'], extensions: ['.ts', '.tsx', '.js'],
plugins: [], plugins: [
new TsconfigPathsPlugin({
configFile: path.resolve(__dirname, './tsconfig.json'),
}),
],
}, },
module: { module: {
rules: [ rules: [