cccdbe26c736b04249bed38ea1e9893ed181a30f
[sketchy-heroes.git] / src / public / app / api.ts
1 import {Player} from '@prisma/client';
2 import axios from 'axios';
3 import { Events } from './events';
4 import { LoginOutputType, AccountCreateType, MoveOutputType } from 'src/routes';
5 import {actionLog} from './components';
6
7 type ApiResponse<T> = {
8   status: 'ok' | 'error',
9   statusCode: number
10   meta: {
11     gameTime: number;
12     id: string;
13     processingTime: number
14   },
15   payload: T
16 }
17
18 export class Api extends Events {
19   base: string;
20   headers: Record<string, string>;
21   player: Player | null;
22
23   constructor(root: string) {
24     super();
25     this.base = root;
26
27     // we use the headers for auth data
28     this.headers = {};
29     this.player = null;
30   }
31
32
33   async get<T>(endpoint: string, params: Record<string, string> = {}): Promise<ApiResponse<T>> {
34     const res = await axios({
35       method: 'get',
36       url: endpoint,
37       baseURL: this.base,
38       params: params,
39       headers: this.headers
40     });
41
42     if(res.data.status !== 'ok') {
43       throw new Error(res.data.payload.toString());
44     }
45
46     return res.data;
47   }
48
49   async post<T>(endpoint: string, data: any = {}): Promise<ApiResponse<T>> {
50     const res = await axios({
51       method: 'post',
52       url: endpoint,
53       baseURL: this.base,
54       data: data,
55       headers: this.headers
56     });
57
58     if(res.data.status !== 'ok') {
59       throw new Error(res.data.payload.toString());
60     }
61
62     return res.data;
63   }
64
65   async signup(username: string, password: string, confirmation: string): Promise<AccountCreateType> {
66     const res = await this.post<AccountCreateType>('/v1/accounts', {
67       username: username,
68       password: password,
69       confirmation: confirmation
70     });
71
72     return res.payload;
73   }
74
75   async login(username: string, password: string): Promise<LoginOutputType> {
76     const res = await this.post<LoginOutputType>('/v1/accounts/auth', { 
77       username: username,
78       password: password
79     });
80
81     this.headers['x-auth-token'] = res.payload.token;
82     this.player = res.payload.player;
83
84     this.emit('player', this.player);
85
86     return res.payload;
87   }
88
89   async move(): Promise<MoveOutputType> {
90     if(this.player === null) {
91       throw new Error('Not authenicated');
92     }
93     const res = await this.post<MoveOutputType>(`/v1/accounts/${this.player.id}/move`);
94
95     this.player = res.payload.player;
96
97     this.emit('player', this.player);
98
99     actionLog(res.payload.displayText, true);
100
101     return res.payload;
102   }
103 }