// @flow import fetch from 'isomorphic-unfetch'; import cookie from 'cookie'; import { getValidUser } from '../utils/validation'; import { auth } from '../actions/global'; import type { Store } from 'redux'; // eslint-disable-line import/named import type { User, GameId, Game, Stats, State } from 'shared/types/state'; import type { Action } from 'shared/types/actions'; import type { BackfillRequest, BackfillResponse } from 'shared/types/api'; // NOTE: This method is strictly called on the server side export async function addCurUserToState( req: http$IncomingMessage, store: Store<State, Action> ) { const { sessionId } = cookie.parse(req.headers.cookie || ''); if (sessionId) { try { const res = await fetchJson('/auth', { headers: { cookie: `sessionId=${sessionId}` } }); const user = getValidUser(res); store.dispatch(auth(user)); } catch (err) { // Nothing to do, user is guest } } } export async function createUserSession(userName: string): Promise<User> { return fetchPost('/auth', { userName }); } export async function getDashboard(): Promise<{ games: Array<Game>, stats: Stats }> { return fetchJson(`/dashboard`); } export async function getGame(gameId: GameId): Promise<Game> { return fetchJson(`/game/${gameId}`); } export async function createGame(): Promise<Game> { return fetchPost('/game'); } export async function backfillGameActions( req: BackfillRequest ): Promise<BackfillResponse> { return fetchPost(`/backfill`, req); } export function getApiUrl(path?: string) { const baseUrl = process.env.NODE_ENV === 'production' ? getProdBaseUrl() : 'http://localhost:4000'; return path ? `${baseUrl}${path}` : `${baseUrl}/`; } export function Unauthorized() { this.name = 'Unauthorized'; this.message = 'Invalid user session'; } function getProdBaseUrl() { // Relative paths allow us to serve the prod app from any proxy address (eg. // via ngrok), but server-side requests need to contain the host address return typeof window === 'undefined' ? 'http://localhost:3000' : ''; } function fetchJson(urlPath: string, options?: Object): Promise<any> { return fetch(getApiUrl(urlPath), options).then(parseResponse); } function fetchPost(urlPath: string, body: Object = {}): Promise<any> { return fetchJson(urlPath, { method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }); } function parseResponse(response) { if (response.status >= 200 && response.status < 300) { return response.json(); } else { if (response.status === 401) { throw new Unauthorized(); } // TODO: Forward server error if response is parsable // return response.json().then( // response => { // throw new Error(response.error); // }, // () => { // throw new Error('Server error'); // } // ); throw new Error('Server error'); } }