-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.ts
167 lines (152 loc) · 3.85 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
type RequestInfo = Request | string;
type HeadersInit = Headers | string[][] | Record<string, string>;
export interface FunReq extends RequestInit {
url: RequestInfo;
}
export interface FunQLResponse<T> {
success: boolean;
code?: number;
body: string | T;
}
type RequestSchema = {
schema: {
contents: {
[key: string]: {
models: {
[key: string]: {
doits: {
[key: string]: {
details: { get?: unknown; set?: unknown } | never;
};
};
};
};
};
};
};
};
type ResponseSchema = {
schema: {
contents: {
[key: string]: {
models: {
[key: string]: {
doits: {
[key: string]: {
details: { response: unknown };
};
};
};
};
};
};
};
};
export const throwErr = (msg: string) => {
throw new Error(msg);
};
export const funreq = <
Req extends RequestSchema,
Res extends ResponseSchema
>() => {
let setting: FunReq = {
url: "http://localhost:3000/funql",
method: "POST", // *GET, POST, PUT, DELETE, etc.
mode: "cors", // no-cors, *cors, same-origin
cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
credentials: "same-origin", // include, *same-origin, omit
headers: {
"Content-Type": "application/json",
// ...data.headers,
},
redirect: "follow", // manual, *follow, error
referrerPolicy: "no-referrer", // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
// return response.json();
};
const setup = (data: FunReq) => {
setting = {
...setting,
...data,
};
};
const api = async <
SCHEMA extends Req & Res,
CONTENTS extends SCHEMA["schema"]["contents"],
CONTENTSK extends keyof CONTENTS,
MODEL extends CONTENTS[CONTENTSK]["models"],
MODELK extends keyof MODEL,
DOIT extends MODEL[MODELK]["doits"],
DOITK extends keyof DOIT,
RESPONSE extends DOIT[DOITK]["details"]["response"]
>(
body: DOIT[DOITK] extends { details: never }
? {
contents: CONTENTSK;
wants: {
model: MODELK;
doit: DOITK;
};
}
: {
contents: CONTENTSK;
wants: {
model: MODELK;
doit: DOITK;
};
details: {
set: DOIT[DOITK]["details"]["set"];
get: DOIT[DOITK]["details"]["get"];
};
},
headers?: HeadersInit
) => {
try {
const response = await fetch(setting.url, {
...setting,
headers: {
...setting.headers,
...headers,
},
body: JSON.stringify(body),
});
if (!response.ok) {
throw new Error(response.statusText);
}
// may error if there is no body
const parsedBody: FunQLResponse<RESPONSE> = await response.json();
if (parsedBody.success === false) {
throw new Error(parsedBody.body as string);
}
return parsedBody;
} catch (ex) {
const msg = ex.messages ? ex.messages : "we have problem to fetch";
throwErr(msg);
}
};
return {
setup,
api,
};
};
//One example of how to use it
// const newApi = funreq<FunQLRequest, FunQLResponseWithDetails>();
// newApi.setup({ url: "http://localhost:8000/funql" });
// export const getData = async () => {
// const data = await newApi.api({
// contents: "dynamic",
// wants: {
// model: "BlogCategory",
// doit: "createBlogCategory",
// },
// details: {
// set: {
// name: "kjsdh",
// enName: "ksdjhf",
// icon: "sdkjfh",
// description: "skdjfh",
// },
// get: {},
// },
// });
// return data;
// };