@shakerquiz/utilities 0.1.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,202 @@
1
+ import * as cookies from '@yurkimus/cookies'
2
+ import { MessageError } from '@yurkimus/errors'
3
+ import * as message from '@yurkimus/message'
4
+ import { ResponseStatus } from '@yurkimus/response-status'
5
+
6
+ import {
7
+ FeatureKinds,
8
+ FeatureRequests,
9
+ FeatureUrls,
10
+ } from '../enumerations/features.js'
11
+ import { Kinds } from '../enumerations/kinds.js'
12
+
13
+ let handleMessage = (feature, [response, body]) => {
14
+ switch (response.status) {
15
+ case 200:
16
+ case 201:
17
+ return body
18
+
19
+ case 204:
20
+ switch (FeatureKinds[feature]) {
21
+ case Kinds.Item:
22
+ return null
23
+
24
+ case Kinds.List:
25
+ return []
26
+ }
27
+
28
+ case 400:
29
+ case 401:
30
+ case 403:
31
+ case 404:
32
+ case 409:
33
+ case 415:
34
+ case 500:
35
+ case 502:
36
+ throw MessageError(
37
+ body.message,
38
+ ResponseStatus(response.status),
39
+ )
40
+
41
+ default:
42
+ throw body
43
+ }
44
+ }
45
+
46
+ /**
47
+ * @template {FeaturesUnion} Feature
48
+ * @template {MethodsUnion} Method
49
+ * @template {NetworksUnion} Network
50
+ *
51
+ * @param {Feature} feature
52
+ * @param {Method} method
53
+ * @param {Network} network
54
+ * @param {import('@yurkimus/url').URLOptions | undefined} options
55
+ * @param {RequestInit} init
56
+ */
57
+ let makeRequest = (feature, method, network, options, init) => {
58
+ if (!('method' in init))
59
+ init.method = method
60
+
61
+ let url = FeatureUrls
62
+ .get(feature)
63
+ .get(network)
64
+
65
+ let request = new Request(url(options), init)
66
+
67
+ if (!request.headers.has('Content-Type'))
68
+ request.headers.set(
69
+ 'Content-Type',
70
+ 'application/json',
71
+ )
72
+
73
+ if ('cookie' in init)
74
+ request.headers.set(
75
+ 'Authorization',
76
+ cookies.read('shaker-quiz-token', init.cookie),
77
+ )
78
+
79
+ return fetch(request)
80
+ .then(message.read)
81
+ .then(handleMessage.bind(undefined, feature))
82
+ }
83
+
84
+ /**
85
+ * @type {WeakMap<Function, Map<'onbefore' | 'onfulfilled' | 'onrejected', Set<Function>>>}
86
+ */
87
+ export let Extensions = new WeakMap()
88
+
89
+ /**
90
+ * @template {FeaturesUnion} Feature
91
+ * @template {MethodsUnion} Method
92
+ * @template {NetworksUnion} Network
93
+ *
94
+ * @param {Feature} feature
95
+ * @param {Method} method
96
+ * @param {Network} network
97
+ */
98
+ export let useRequest = (feature, method, network) => {
99
+ if (
100
+ !FeatureRequests
101
+ .has(feature)
102
+ )
103
+ throw TypeError(`Feature '${feature}' must be listed in 'FeatureRequests'.`)
104
+
105
+ if (
106
+ !FeatureRequests
107
+ .get(feature)
108
+ .has(method)
109
+ )
110
+ throw TypeError(`Method '${method}' must be listed in 'FeatureRequests'.`)
111
+
112
+ if (
113
+ !FeatureUrls
114
+ .has(feature)
115
+ )
116
+ throw TypeError(`Feature '${feature}' must be listed in 'FeatureUrls'.`)
117
+
118
+ if (
119
+ !FeatureUrls
120
+ .get(feature)
121
+ .has(network)
122
+ )
123
+ throw TypeError(`Network '${network}' must be listed in 'FeatureUrls'.`)
124
+
125
+ /**
126
+ * @param {import('@yurkimus/url').URLOptions} options
127
+ * @param {RequestInit} init
128
+ */
129
+ let request = (options, init) => {
130
+ let onbefore = parameters => {
131
+ let predicates = Extensions
132
+ .get(request)
133
+ .get('onbefore')
134
+
135
+ return (predicates.size > 0)
136
+ ? Array
137
+ .from(predicates)
138
+ .reduce(
139
+ (parameters, onbefore) => onbefore(parameters),
140
+ parameters,
141
+ )
142
+ : parameters
143
+ }
144
+
145
+ let onfulfilled = contract => {
146
+ let predicates = Extensions
147
+ .get(request)
148
+ .get('onfulfilled')
149
+
150
+ return (predicates.size > 0)
151
+ ? Array
152
+ .from(predicates)
153
+ .reduce(
154
+ (contract, onfulfilled) => onfulfilled(contract),
155
+ contract,
156
+ )
157
+ : contract
158
+ }
159
+
160
+ let onrejected = reason => {
161
+ let predicates = Extensions
162
+ .get(request)
163
+ .get('onrejected')
164
+
165
+ Array
166
+ .from(predicates)
167
+ .forEach(onrejected => onrejected(reason))
168
+
169
+ throw reason
170
+ }
171
+
172
+ return new Promise((resolve, reject) => {
173
+ try {
174
+ resolve(onbefore([options, init]))
175
+ } catch (reason) {
176
+ reject(reason)
177
+ }
178
+ })
179
+ .then(([options, init]) =>
180
+ makeRequest(
181
+ feature,
182
+ method,
183
+ network,
184
+ options,
185
+ init,
186
+ )
187
+ )
188
+ .then(onfulfilled)
189
+ .catch(onrejected)
190
+ }
191
+
192
+ Extensions.set(
193
+ request,
194
+ new Map([
195
+ ['onbefore', new Set([])],
196
+ ['onfulfilled', new Set([])],
197
+ ['onrejected', new Set([])],
198
+ ]),
199
+ )
200
+
201
+ return request
202
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * General
3
+ */
4
+
5
+ type Nullable<Type> = Type | null
6
+
7
+ /**
8
+ * Mixins
9
+ */
10
+
11
+ interface RequestInit {
12
+ /** A string to declaratively set the Authorization header. */
13
+ cookie?: string
14
+ }
@@ -0,0 +1,15 @@
1
+ /// <reference path="globals.d.ts" />
2
+ /// <reference path="results.d.ts" />
3
+ /// <reference path="rows.d.ts" />
4
+
5
+ export * from './enumerations/constants.js'
6
+ export * from './enumerations/cookies.js'
7
+ export * from './enumerations/features.js'
8
+ export * from './enumerations/game-statuses.js'
9
+ export * from './enumerations/kinds.js'
10
+ export * from './enumerations/methods.js'
11
+ export * from './enumerations/networks.js'
12
+ export * from './enumerations/phases.js'
13
+ export * from './enumerations/regexps.js'
14
+ export * from './enumerations/roles.js'
15
+ export * from './functions/request.js'
@@ -0,0 +1,11 @@
1
+ export * from './enumerations/constants.js'
2
+ export * from './enumerations/cookies.js'
3
+ export * from './enumerations/features.js'
4
+ export * from './enumerations/game-statuses.js'
5
+ export * from './enumerations/kinds.js'
6
+ export * from './enumerations/methods.js'
7
+ export * from './enumerations/networks.js'
8
+ export * from './enumerations/phases.js'
9
+ export * from './enumerations/regexps.js'
10
+ export * from './enumerations/roles.js'
11
+ export * from './functions/request.js'
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Checkin
3
+ */
4
+
5
+ type CheckinResult =
6
+ & {
7
+ id: UserRow['id']
8
+ first_name: UserRow['first_name']
9
+ last_name: UserRow['last_name']
10
+ third_name: UserRow['third_name']
11
+ phone: UserRow['phone']
12
+ email: UserRow['email']
13
+ }
14
+ & {
15
+ image_id: ImageMediaRow['id']
16
+ }
17
+ & {
18
+ role_id: string
19
+ role_name: string
20
+ }
21
+
22
+ /**
23
+ * City
24
+ */
25
+
26
+ type CityResult = CityRow
27
+
28
+ type CityPublicResult = {
29
+ address: CityRow['address']
30
+ alias: CityRow['alias']
31
+ country: CityRow['country']
32
+ custom_html: CityRow['custom_html']
33
+ custom_script: CityRow['custom_script']
34
+ email: CityRow['email']
35
+ id: CityRow['id']
36
+ inst_link: CityRow['inst_link']
37
+ max_members_count: CityRow['max_members_count']
38
+ meta_description: CityRow['meta_description']
39
+ meta_title: CityRow['meta_title']
40
+ min_members_count: CityRow['min_members_count']
41
+ name: CityRow['name']
42
+ phone: CityRow['phone']
43
+ tg_link: CityRow['tg_link']
44
+ vk_group_id: CityRow['vk_group_id']
45
+ vk_link: CityRow['vk_link']
46
+ yandex_metrica: CityRow['yandex_metrica']
47
+ }
48
+
49
+ /**
50
+ * Theme
51
+ */
52
+
53
+ type ThemeResult = {
54
+ id: ThemeRow['id']
55
+ time_created: ThemeRow['time_created']
56
+ name: ThemeRow['name']
57
+ description: ThemeRow['description']
58
+ short_description: ThemeRow['short_description']
59
+ media_path: MediaRow['path']
60
+ }
61
+
62
+ /**
63
+ * Game
64
+ */
65
+
66
+ type GameResult =
67
+ & {
68
+ event_id: GameRow['id']
69
+ event_alias: GameRow['alias']
70
+ event_number: GameRow['number']
71
+ event_time: GameRow['event_time']
72
+ event_status: GameRow['status']
73
+ }
74
+ & {
75
+ location_id: LocationRow['id']
76
+ location_name: LocationRow['name']
77
+ }
78
+ & {
79
+ city_id: CityRow['id']
80
+ city_alias: CityRow['alias']
81
+ city_name: CityRow['name']
82
+ city_is_franchise: CityRow['is_franchise']
83
+ }
84
+ & {
85
+ theme_id: ThemeRow['id']
86
+ theme_name: ThemeRow['name']
87
+ }
88
+ & {
89
+ media_id: ImageMediaRow['id']
90
+ media_title: ImageMediaRow['title']
91
+ media_path: ImageMediaRow['path']
92
+ }
93
+ & {
94
+ people_amount: number
95
+ people_reserve_amount: number
96
+ teams_amount: number
97
+ teams_reserve_amount: number
98
+ }
99
+
100
+ type GamePublicResult =
101
+ & {
102
+ theme_description: ThemeRow['description']
103
+ theme_id: ThemeRow['id']
104
+ theme_name: ThemeRow['name']
105
+ theme_short_description: ThemeRow['short_description']
106
+ }
107
+ & {
108
+ alias: GameRow['alias']
109
+ currency: GameRow['currency']
110
+ id: GameRow['id']
111
+ max_members_count: GameRow['max_members_count']
112
+ min_members_count: GameRow['min_members_count']
113
+ number: GameRow['number']
114
+ price: GameRow['price']
115
+ status: GameRow['status']
116
+ event_time: GameRow['event_time']
117
+ }
118
+ & {
119
+ city_alias: CityRow['alias']
120
+ city_id: CityRow['id']
121
+ }
122
+ & {
123
+ location_house_number: LocationRow['house_number']
124
+ location_id: LocationRow['id']
125
+ location_info: LocationRow['location_info']
126
+ location_name: LocationRow['name']
127
+ location_street: LocationRow['street']
128
+ }
129
+ & {
130
+ media_id: MediaRow['id']
131
+ media_path: MediaRow['path']
132
+ }
133
+ & {
134
+ image_id: ImageMediaRow['id']
135
+ }