food402 1.0.2 → 1.0.4-beta.1
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.
- package/README.md +27 -0
- package/dist/postinstall.d.ts +2 -0
- package/dist/postinstall.js +29 -0
- package/dist/shared/api.d.ts +23 -0
- package/dist/shared/api.js +945 -0
- package/dist/shared/types.d.ts +396 -0
- package/dist/shared/types.js +2 -0
- package/dist/src/api.d.ts +23 -0
- package/dist/src/api.js +88 -0
- package/dist/src/auth.d.ts +16 -0
- package/dist/src/auth.js +117 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +455 -0
- package/dist/src/postinstall.d.ts +2 -0
- package/dist/src/postinstall.js +29 -0
- package/package.json +2 -1
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
export interface Address {
|
|
2
|
+
id: number;
|
|
3
|
+
name: string;
|
|
4
|
+
surname: string;
|
|
5
|
+
phone: string;
|
|
6
|
+
countryPhoneCode: string;
|
|
7
|
+
addressLine: string;
|
|
8
|
+
addressName: string;
|
|
9
|
+
postalCode: string;
|
|
10
|
+
cityId: number;
|
|
11
|
+
cityName: string;
|
|
12
|
+
districtId: number;
|
|
13
|
+
districtName: string;
|
|
14
|
+
neighborhoodId: number;
|
|
15
|
+
neighborhoodName: string;
|
|
16
|
+
latitude: string;
|
|
17
|
+
longitude: string;
|
|
18
|
+
addressDescription: string;
|
|
19
|
+
apartmentNumber: string;
|
|
20
|
+
floor: string;
|
|
21
|
+
doorNumber: string;
|
|
22
|
+
addressType: string;
|
|
23
|
+
elevatorAvailable: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface AddressesResponse {
|
|
26
|
+
infoMessage: string | null;
|
|
27
|
+
id: string;
|
|
28
|
+
addresses: Address[];
|
|
29
|
+
}
|
|
30
|
+
export interface Restaurant {
|
|
31
|
+
id: number;
|
|
32
|
+
name: string;
|
|
33
|
+
kitchen: string;
|
|
34
|
+
rating: number;
|
|
35
|
+
ratingText: string;
|
|
36
|
+
minBasketPrice: number;
|
|
37
|
+
averageDeliveryInterval: string;
|
|
38
|
+
distance: number;
|
|
39
|
+
neighborhoodName: string;
|
|
40
|
+
isClosed: boolean;
|
|
41
|
+
campaignText?: string;
|
|
42
|
+
}
|
|
43
|
+
export interface RestaurantsResponse {
|
|
44
|
+
restaurants: Restaurant[];
|
|
45
|
+
totalCount: number;
|
|
46
|
+
currentPage: number;
|
|
47
|
+
pageSize: number;
|
|
48
|
+
hasNextPage: boolean;
|
|
49
|
+
}
|
|
50
|
+
export interface MenuItem {
|
|
51
|
+
id: number;
|
|
52
|
+
name: string;
|
|
53
|
+
description: string;
|
|
54
|
+
price: number;
|
|
55
|
+
likePercentage?: string;
|
|
56
|
+
}
|
|
57
|
+
export interface MenuCategory {
|
|
58
|
+
name: string;
|
|
59
|
+
slug: string;
|
|
60
|
+
items: MenuItem[];
|
|
61
|
+
}
|
|
62
|
+
export interface RestaurantInfo {
|
|
63
|
+
id: number;
|
|
64
|
+
name: string;
|
|
65
|
+
status: string;
|
|
66
|
+
rating: number;
|
|
67
|
+
ratingText: string;
|
|
68
|
+
workingHours: string;
|
|
69
|
+
deliveryTime: string;
|
|
70
|
+
minOrderPrice: number;
|
|
71
|
+
}
|
|
72
|
+
export interface RestaurantMenuResponse {
|
|
73
|
+
info: RestaurantInfo;
|
|
74
|
+
categories: MenuCategory[];
|
|
75
|
+
totalItems: number;
|
|
76
|
+
}
|
|
77
|
+
export interface RecommendedItem {
|
|
78
|
+
id: number;
|
|
79
|
+
name: string;
|
|
80
|
+
description: string | null;
|
|
81
|
+
price: number;
|
|
82
|
+
imageUrl: string;
|
|
83
|
+
}
|
|
84
|
+
export interface RecommendationCollection {
|
|
85
|
+
name: string;
|
|
86
|
+
items: RecommendedItem[];
|
|
87
|
+
}
|
|
88
|
+
export interface ProductRecommendationsResponse {
|
|
89
|
+
collections: RecommendationCollection[];
|
|
90
|
+
totalItems: number;
|
|
91
|
+
}
|
|
92
|
+
export interface ProductOption {
|
|
93
|
+
id: number;
|
|
94
|
+
name: string;
|
|
95
|
+
price: number;
|
|
96
|
+
selected: boolean;
|
|
97
|
+
isPopular?: boolean;
|
|
98
|
+
}
|
|
99
|
+
export interface ProductComponent {
|
|
100
|
+
type: "INGREDIENTS" | "MODIFIER_GROUP";
|
|
101
|
+
title: string;
|
|
102
|
+
description?: string;
|
|
103
|
+
modifierGroupId?: number;
|
|
104
|
+
options: ProductOption[];
|
|
105
|
+
isSingleChoice: boolean;
|
|
106
|
+
minSelections: number;
|
|
107
|
+
maxSelections: number;
|
|
108
|
+
}
|
|
109
|
+
export interface ProductDetailsResponse {
|
|
110
|
+
restaurantId: number;
|
|
111
|
+
restaurantName: string;
|
|
112
|
+
productId: number;
|
|
113
|
+
productName: string;
|
|
114
|
+
description: string;
|
|
115
|
+
imageUrl: string;
|
|
116
|
+
price: number;
|
|
117
|
+
maxQuantity: number;
|
|
118
|
+
components: ProductComponent[];
|
|
119
|
+
}
|
|
120
|
+
export interface IngredientExclusion {
|
|
121
|
+
id: number;
|
|
122
|
+
}
|
|
123
|
+
export interface ModifierProduct {
|
|
124
|
+
productId: number;
|
|
125
|
+
modifierGroupId: number;
|
|
126
|
+
modifierProducts: ModifierProduct[];
|
|
127
|
+
ingredientOptions: {
|
|
128
|
+
excludes: IngredientExclusion[];
|
|
129
|
+
includes: [];
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
export interface BasketItem {
|
|
133
|
+
productId: number;
|
|
134
|
+
quantity: number;
|
|
135
|
+
modifierProducts: ModifierProduct[];
|
|
136
|
+
ingredientOptions: {
|
|
137
|
+
excludes: IngredientExclusion[];
|
|
138
|
+
includes: [];
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
export interface AddToBasketRequest {
|
|
142
|
+
storeId: number;
|
|
143
|
+
items: BasketItem[];
|
|
144
|
+
isFlashSale: boolean;
|
|
145
|
+
storePickup: boolean;
|
|
146
|
+
latitude: number;
|
|
147
|
+
longitude: number;
|
|
148
|
+
}
|
|
149
|
+
export interface CartProduct {
|
|
150
|
+
productId: number;
|
|
151
|
+
itemId: string;
|
|
152
|
+
name: string;
|
|
153
|
+
quantity: number;
|
|
154
|
+
salePrice: number;
|
|
155
|
+
description: string;
|
|
156
|
+
}
|
|
157
|
+
export interface CartStore {
|
|
158
|
+
id: number;
|
|
159
|
+
name: string;
|
|
160
|
+
imageUrl: string;
|
|
161
|
+
rating: number;
|
|
162
|
+
averageDeliveryInterval: string;
|
|
163
|
+
minAmount: number;
|
|
164
|
+
}
|
|
165
|
+
export interface CartSummaryLine {
|
|
166
|
+
title: string;
|
|
167
|
+
amount: number;
|
|
168
|
+
isPromotion?: boolean;
|
|
169
|
+
}
|
|
170
|
+
export interface AddToBasketResponse {
|
|
171
|
+
store: CartStore;
|
|
172
|
+
products: CartProduct[];
|
|
173
|
+
summary: CartSummaryLine[];
|
|
174
|
+
totalProductCount: number;
|
|
175
|
+
totalProductPrice: number;
|
|
176
|
+
totalProductPriceDiscounted: number;
|
|
177
|
+
totalPrice: number;
|
|
178
|
+
deliveryPrice: number;
|
|
179
|
+
}
|
|
180
|
+
export interface SetShippingAddressRequest {
|
|
181
|
+
shippingAddressId: number;
|
|
182
|
+
invoiceAddressId: number;
|
|
183
|
+
}
|
|
184
|
+
export interface CartProductDetails extends CartProduct {
|
|
185
|
+
marketPrice: number;
|
|
186
|
+
modifierProducts: Array<{
|
|
187
|
+
productId: number;
|
|
188
|
+
modifierGroupId: number;
|
|
189
|
+
name: string;
|
|
190
|
+
price: number;
|
|
191
|
+
}>;
|
|
192
|
+
ingredientExcludes: Array<{
|
|
193
|
+
id: number;
|
|
194
|
+
name: string;
|
|
195
|
+
}>;
|
|
196
|
+
}
|
|
197
|
+
export interface CartStoreGroup {
|
|
198
|
+
store: CartStore;
|
|
199
|
+
products: CartProductDetails[];
|
|
200
|
+
}
|
|
201
|
+
export interface GetBasketResponse {
|
|
202
|
+
storeGroups: CartStoreGroup[];
|
|
203
|
+
summary: CartSummaryLine[];
|
|
204
|
+
totalProductCount: number;
|
|
205
|
+
totalProductPrice: number;
|
|
206
|
+
totalProductPriceDiscounted: number;
|
|
207
|
+
totalPrice: number;
|
|
208
|
+
deliveryPrice: number;
|
|
209
|
+
isEmpty: boolean;
|
|
210
|
+
}
|
|
211
|
+
export interface SearchProduct {
|
|
212
|
+
id: number;
|
|
213
|
+
name: string;
|
|
214
|
+
description?: string;
|
|
215
|
+
price: number;
|
|
216
|
+
imageUrl?: string;
|
|
217
|
+
}
|
|
218
|
+
export interface SearchRestaurant extends Restaurant {
|
|
219
|
+
products: SearchProduct[];
|
|
220
|
+
warning?: string;
|
|
221
|
+
}
|
|
222
|
+
export interface SearchRestaurantsResponse {
|
|
223
|
+
restaurants: SearchRestaurant[];
|
|
224
|
+
totalCount: number;
|
|
225
|
+
currentPage: number;
|
|
226
|
+
pageSize: number;
|
|
227
|
+
hasNextPage: boolean;
|
|
228
|
+
searchQuery: string;
|
|
229
|
+
}
|
|
230
|
+
export interface City {
|
|
231
|
+
id: number;
|
|
232
|
+
code: string;
|
|
233
|
+
name: string;
|
|
234
|
+
}
|
|
235
|
+
export interface District {
|
|
236
|
+
id: number;
|
|
237
|
+
name: string;
|
|
238
|
+
}
|
|
239
|
+
export interface Neighborhood {
|
|
240
|
+
id: number;
|
|
241
|
+
name: string;
|
|
242
|
+
}
|
|
243
|
+
export interface CitiesResponse {
|
|
244
|
+
cities: City[];
|
|
245
|
+
count: number;
|
|
246
|
+
}
|
|
247
|
+
export interface DistrictsResponse {
|
|
248
|
+
districts: District[];
|
|
249
|
+
count: number;
|
|
250
|
+
cityId: number;
|
|
251
|
+
}
|
|
252
|
+
export interface NeighborhoodsResponse {
|
|
253
|
+
neighborhoods: Neighborhood[];
|
|
254
|
+
count: number;
|
|
255
|
+
districtId: number;
|
|
256
|
+
}
|
|
257
|
+
export interface AddAddressRequest {
|
|
258
|
+
name: string;
|
|
259
|
+
surname: string;
|
|
260
|
+
phone: string;
|
|
261
|
+
apartmentNumber?: string;
|
|
262
|
+
floor?: string;
|
|
263
|
+
doorNumber?: string;
|
|
264
|
+
addressName: string;
|
|
265
|
+
addressDescription?: string;
|
|
266
|
+
addressLine: string;
|
|
267
|
+
cityId: number;
|
|
268
|
+
districtId: number;
|
|
269
|
+
neighborhoodId: number;
|
|
270
|
+
latitude: string;
|
|
271
|
+
longitude: string;
|
|
272
|
+
countryCode?: string;
|
|
273
|
+
elevatorAvailable?: boolean;
|
|
274
|
+
}
|
|
275
|
+
export interface AddAddressResponse {
|
|
276
|
+
success: boolean;
|
|
277
|
+
address?: Address;
|
|
278
|
+
requiresOtp?: boolean;
|
|
279
|
+
message: string;
|
|
280
|
+
}
|
|
281
|
+
export interface SavedCard {
|
|
282
|
+
cardId: number;
|
|
283
|
+
name: string;
|
|
284
|
+
maskedCardNumber: string;
|
|
285
|
+
cardTypeName: string;
|
|
286
|
+
bankName: string;
|
|
287
|
+
isDebitCard: boolean;
|
|
288
|
+
cvvRequired: boolean;
|
|
289
|
+
cardNetwork: string;
|
|
290
|
+
}
|
|
291
|
+
export interface SavedCardsResponse {
|
|
292
|
+
cards: SavedCard[];
|
|
293
|
+
hasCards: boolean;
|
|
294
|
+
message?: string;
|
|
295
|
+
}
|
|
296
|
+
export interface CheckoutReadyResponse {
|
|
297
|
+
ready: boolean;
|
|
298
|
+
store: CartStore;
|
|
299
|
+
products: CartProductDetails[];
|
|
300
|
+
summary: CartSummaryLine[];
|
|
301
|
+
totalPrice: number;
|
|
302
|
+
deliveryPrice: number;
|
|
303
|
+
warnings: string[];
|
|
304
|
+
}
|
|
305
|
+
export interface PlaceOrderResponse {
|
|
306
|
+
success: boolean;
|
|
307
|
+
orderId?: string;
|
|
308
|
+
requires3DSecure?: boolean;
|
|
309
|
+
redirectUrl?: string;
|
|
310
|
+
htmlContent?: string;
|
|
311
|
+
message: string;
|
|
312
|
+
}
|
|
313
|
+
export interface CustomerNoteRequest {
|
|
314
|
+
customerNote: string;
|
|
315
|
+
noServiceWare: boolean;
|
|
316
|
+
contactlessDelivery: boolean;
|
|
317
|
+
dontRingBell: boolean;
|
|
318
|
+
}
|
|
319
|
+
export interface OrderStatus {
|
|
320
|
+
status: string;
|
|
321
|
+
statusText: string;
|
|
322
|
+
statusColor: string;
|
|
323
|
+
}
|
|
324
|
+
export interface OrderStore {
|
|
325
|
+
id: number;
|
|
326
|
+
name: string;
|
|
327
|
+
}
|
|
328
|
+
export interface OrderPrice {
|
|
329
|
+
totalPrice: number;
|
|
330
|
+
totalPriceText: string;
|
|
331
|
+
refundedPrice: number;
|
|
332
|
+
cancelledPrice: number;
|
|
333
|
+
totalDeliveryPrice: number;
|
|
334
|
+
totalServicePrice: number;
|
|
335
|
+
}
|
|
336
|
+
export interface OrderProductSummary {
|
|
337
|
+
productId: number;
|
|
338
|
+
name: string;
|
|
339
|
+
imageUrl: string;
|
|
340
|
+
}
|
|
341
|
+
export interface Order {
|
|
342
|
+
id: string;
|
|
343
|
+
orderDate: string;
|
|
344
|
+
store: OrderStore;
|
|
345
|
+
status: OrderStatus;
|
|
346
|
+
price: OrderPrice;
|
|
347
|
+
productSummary: string;
|
|
348
|
+
products: OrderProductSummary[];
|
|
349
|
+
isReady: boolean;
|
|
350
|
+
}
|
|
351
|
+
export interface OrdersResponse {
|
|
352
|
+
orders: Order[];
|
|
353
|
+
pagination: {
|
|
354
|
+
currentPage: number;
|
|
355
|
+
pageSize: number;
|
|
356
|
+
totalCount: number;
|
|
357
|
+
hasNext: boolean;
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
export interface OrderDetailProduct {
|
|
361
|
+
name: string;
|
|
362
|
+
imageUrl: string;
|
|
363
|
+
salePrice: number;
|
|
364
|
+
salePriceText: string;
|
|
365
|
+
quantity: number;
|
|
366
|
+
description: string;
|
|
367
|
+
}
|
|
368
|
+
export interface OrderStatusStep {
|
|
369
|
+
status: string;
|
|
370
|
+
statusText: string;
|
|
371
|
+
}
|
|
372
|
+
export interface OrderShipmentItem {
|
|
373
|
+
status: OrderStatus;
|
|
374
|
+
statusSteps: OrderStatusStep[];
|
|
375
|
+
products: OrderDetailProduct[];
|
|
376
|
+
}
|
|
377
|
+
export interface OrderDetail {
|
|
378
|
+
orderId: string;
|
|
379
|
+
orderNumber: string;
|
|
380
|
+
orderDate: string;
|
|
381
|
+
customerNote: string;
|
|
382
|
+
store: OrderStore;
|
|
383
|
+
eta: string;
|
|
384
|
+
deliveredDate: string;
|
|
385
|
+
status: OrderStatus;
|
|
386
|
+
statusSteps: OrderStatusStep[];
|
|
387
|
+
products: OrderDetailProduct[];
|
|
388
|
+
price: OrderPrice;
|
|
389
|
+
paymentDescription: string;
|
|
390
|
+
deliveryAddress: {
|
|
391
|
+
name: string;
|
|
392
|
+
address: string;
|
|
393
|
+
districtCity: string;
|
|
394
|
+
phoneNumber: string;
|
|
395
|
+
};
|
|
396
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as sharedApi from "../shared/api.js";
|
|
2
|
+
export type { Address, AddressesResponse, Restaurant, RestaurantsResponse, MenuItem, MenuCategory, RestaurantInfo, RestaurantMenuResponse, RecommendedItem, RecommendationCollection, ProductRecommendationsResponse, ProductOption, ProductComponent, ProductDetailsResponse, IngredientExclusion, ModifierProduct, BasketItem, AddToBasketRequest, CartProduct, CartStore, CartSummaryLine, AddToBasketResponse, SetShippingAddressRequest, CartProductDetails, CartStoreGroup, GetBasketResponse, SearchProduct, SearchRestaurant, SearchRestaurantsResponse, City, District, Neighborhood, CitiesResponse, DistrictsResponse, NeighborhoodsResponse, AddAddressRequest, AddAddressResponse, SavedCard, SavedCardsResponse, CheckoutReadyResponse, PlaceOrderResponse, CustomerNoteRequest, OrderStatus, OrderStore, OrderPrice, OrderProductSummary, Order, OrdersResponse, OrderDetailProduct, OrderStatusStep, OrderShipmentItem, OrderDetail, } from "../shared/types.js";
|
|
3
|
+
export declare function getAddresses(): Promise<sharedApi.AddressesResponse>;
|
|
4
|
+
export declare function getRestaurants(latitude: string, longitude: string, page?: number): Promise<sharedApi.RestaurantsResponse>;
|
|
5
|
+
export declare function getRestaurantMenu(restaurantId: number, latitude: string, longitude: string): Promise<sharedApi.RestaurantMenuResponse>;
|
|
6
|
+
export declare function getProductRecommendations(restaurantId: number, productIds: number[]): Promise<sharedApi.ProductRecommendationsResponse>;
|
|
7
|
+
export declare function getProductDetails(restaurantId: number, productId: number, latitude: string, longitude: string): Promise<sharedApi.ProductDetailsResponse>;
|
|
8
|
+
export declare function setShippingAddress(request: sharedApi.SetShippingAddressRequest): Promise<void>;
|
|
9
|
+
export declare function addToBasket(request: sharedApi.AddToBasketRequest): Promise<sharedApi.AddToBasketResponse>;
|
|
10
|
+
export declare function getBasket(): Promise<sharedApi.GetBasketResponse>;
|
|
11
|
+
export declare function removeFromBasket(itemId: string): Promise<sharedApi.GetBasketResponse>;
|
|
12
|
+
export declare function clearBasket(): Promise<void>;
|
|
13
|
+
export declare function getCities(): Promise<sharedApi.CitiesResponse>;
|
|
14
|
+
export declare function getDistricts(cityId: number): Promise<sharedApi.DistrictsResponse>;
|
|
15
|
+
export declare function getNeighborhoods(districtId: number): Promise<sharedApi.NeighborhoodsResponse>;
|
|
16
|
+
export declare function addAddress(request: sharedApi.AddAddressRequest): Promise<sharedApi.AddAddressResponse>;
|
|
17
|
+
export declare function updateCustomerNote(request: sharedApi.CustomerNoteRequest): Promise<void>;
|
|
18
|
+
export declare function getSavedCards(): Promise<sharedApi.SavedCardsResponse>;
|
|
19
|
+
export declare function getCheckoutReady(): Promise<sharedApi.CheckoutReadyResponse>;
|
|
20
|
+
export declare function placeOrder(cardId: number): Promise<sharedApi.PlaceOrderResponse>;
|
|
21
|
+
export declare function getOrders(page?: number): Promise<sharedApi.OrdersResponse>;
|
|
22
|
+
export declare function getOrderDetail(orderId: string): Promise<sharedApi.OrderDetail>;
|
|
23
|
+
export declare function searchRestaurants(searchQuery: string, latitude: string, longitude: string, page?: number): Promise<sharedApi.SearchRestaurantsResponse>;
|
package/dist/src/api.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// src/api.ts - TGO Yemek API Functions (Local wrapper using getToken)
|
|
2
|
+
import { getToken } from "./auth.js";
|
|
3
|
+
import * as sharedApi from "../shared/api.js";
|
|
4
|
+
// Wrapper functions that automatically inject the token
|
|
5
|
+
export async function getAddresses() {
|
|
6
|
+
const token = await getToken();
|
|
7
|
+
return sharedApi.getAddresses(token);
|
|
8
|
+
}
|
|
9
|
+
export async function getRestaurants(latitude, longitude, page = 1) {
|
|
10
|
+
const token = await getToken();
|
|
11
|
+
return sharedApi.getRestaurants(token, latitude, longitude, page);
|
|
12
|
+
}
|
|
13
|
+
export async function getRestaurantMenu(restaurantId, latitude, longitude) {
|
|
14
|
+
const token = await getToken();
|
|
15
|
+
return sharedApi.getRestaurantMenu(token, restaurantId, latitude, longitude);
|
|
16
|
+
}
|
|
17
|
+
export async function getProductRecommendations(restaurantId, productIds) {
|
|
18
|
+
const token = await getToken();
|
|
19
|
+
return sharedApi.getProductRecommendations(token, restaurantId, productIds);
|
|
20
|
+
}
|
|
21
|
+
export async function getProductDetails(restaurantId, productId, latitude, longitude) {
|
|
22
|
+
const token = await getToken();
|
|
23
|
+
return sharedApi.getProductDetails(token, restaurantId, productId, latitude, longitude);
|
|
24
|
+
}
|
|
25
|
+
export async function setShippingAddress(request) {
|
|
26
|
+
const token = await getToken();
|
|
27
|
+
return sharedApi.setShippingAddress(token, request);
|
|
28
|
+
}
|
|
29
|
+
export async function addToBasket(request) {
|
|
30
|
+
const token = await getToken();
|
|
31
|
+
return sharedApi.addToBasket(token, request);
|
|
32
|
+
}
|
|
33
|
+
export async function getBasket() {
|
|
34
|
+
const token = await getToken();
|
|
35
|
+
return sharedApi.getBasket(token);
|
|
36
|
+
}
|
|
37
|
+
export async function removeFromBasket(itemId) {
|
|
38
|
+
const token = await getToken();
|
|
39
|
+
return sharedApi.removeFromBasket(token, itemId);
|
|
40
|
+
}
|
|
41
|
+
export async function clearBasket() {
|
|
42
|
+
const token = await getToken();
|
|
43
|
+
return sharedApi.clearBasket(token);
|
|
44
|
+
}
|
|
45
|
+
export async function getCities() {
|
|
46
|
+
const token = await getToken();
|
|
47
|
+
return sharedApi.getCities(token);
|
|
48
|
+
}
|
|
49
|
+
export async function getDistricts(cityId) {
|
|
50
|
+
const token = await getToken();
|
|
51
|
+
return sharedApi.getDistricts(token, cityId);
|
|
52
|
+
}
|
|
53
|
+
export async function getNeighborhoods(districtId) {
|
|
54
|
+
const token = await getToken();
|
|
55
|
+
return sharedApi.getNeighborhoods(token, districtId);
|
|
56
|
+
}
|
|
57
|
+
export async function addAddress(request) {
|
|
58
|
+
const token = await getToken();
|
|
59
|
+
return sharedApi.addAddress(token, request);
|
|
60
|
+
}
|
|
61
|
+
export async function updateCustomerNote(request) {
|
|
62
|
+
const token = await getToken();
|
|
63
|
+
return sharedApi.updateCustomerNote(token, request);
|
|
64
|
+
}
|
|
65
|
+
export async function getSavedCards() {
|
|
66
|
+
const token = await getToken();
|
|
67
|
+
return sharedApi.getSavedCards(token);
|
|
68
|
+
}
|
|
69
|
+
export async function getCheckoutReady() {
|
|
70
|
+
const token = await getToken();
|
|
71
|
+
return sharedApi.getCheckoutReady(token);
|
|
72
|
+
}
|
|
73
|
+
export async function placeOrder(cardId) {
|
|
74
|
+
const token = await getToken();
|
|
75
|
+
return sharedApi.placeOrder(token, cardId);
|
|
76
|
+
}
|
|
77
|
+
export async function getOrders(page = 1) {
|
|
78
|
+
const token = await getToken();
|
|
79
|
+
return sharedApi.getOrders(token, page);
|
|
80
|
+
}
|
|
81
|
+
export async function getOrderDetail(orderId) {
|
|
82
|
+
const token = await getToken();
|
|
83
|
+
return sharedApi.getOrderDetail(token, orderId);
|
|
84
|
+
}
|
|
85
|
+
export async function searchRestaurants(searchQuery, latitude, longitude, page = 1) {
|
|
86
|
+
const token = await getToken();
|
|
87
|
+
return sharedApi.searchRestaurants(token, searchQuery, latitude, longitude, page);
|
|
88
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import "dotenv/config";
|
|
2
|
+
/**
|
|
3
|
+
* Custom error class for authentication failures
|
|
4
|
+
*/
|
|
5
|
+
export declare class AuthenticationError extends Error {
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Force a fresh login, bypassing the cache
|
|
10
|
+
*/
|
|
11
|
+
export declare function login(): Promise<string>;
|
|
12
|
+
/**
|
|
13
|
+
* Get a valid authentication token
|
|
14
|
+
* Returns cached token if valid, otherwise performs fresh login
|
|
15
|
+
*/
|
|
16
|
+
export declare function getToken(): Promise<string>;
|
package/dist/src/auth.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// src/auth.ts - TGO Yemek Authentication Module
|
|
2
|
+
import "dotenv/config";
|
|
3
|
+
const CREDENTIALS = {
|
|
4
|
+
email: process.env.TGO_EMAIL || "",
|
|
5
|
+
password: process.env.TGO_PASSWORD || ""
|
|
6
|
+
};
|
|
7
|
+
const USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36";
|
|
8
|
+
// Token cache
|
|
9
|
+
let cachedToken = null;
|
|
10
|
+
let tokenExpiry = 0;
|
|
11
|
+
/**
|
|
12
|
+
* Custom error class for authentication failures
|
|
13
|
+
*/
|
|
14
|
+
export class AuthenticationError extends Error {
|
|
15
|
+
constructor(message) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.name = "AuthenticationError";
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Parse a specific cookie from Set-Cookie header
|
|
22
|
+
*/
|
|
23
|
+
function parseCookie(setCookieHeader, name) {
|
|
24
|
+
if (!setCookieHeader)
|
|
25
|
+
return null;
|
|
26
|
+
// Set-Cookie can have multiple cookies separated by comma (for multiple Set-Cookie headers joined)
|
|
27
|
+
// or be a single cookie with attributes separated by semicolon
|
|
28
|
+
const cookies = setCookieHeader.split(/,(?=\s*[^;]+=[^;]+)/);
|
|
29
|
+
for (const cookie of cookies) {
|
|
30
|
+
const parts = cookie.trim().split(";");
|
|
31
|
+
const [cookieName, ...valueParts] = parts[0].split("=");
|
|
32
|
+
if (cookieName.trim() === name) {
|
|
33
|
+
return valueParts.join("=").trim();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Decode JWT to get expiry timestamp
|
|
40
|
+
*/
|
|
41
|
+
function getTokenExpiry(token) {
|
|
42
|
+
try {
|
|
43
|
+
const parts = token.split(".");
|
|
44
|
+
if (parts.length !== 3)
|
|
45
|
+
return 0;
|
|
46
|
+
const payload = JSON.parse(Buffer.from(parts[1], "base64").toString("utf-8"));
|
|
47
|
+
// JWT exp is in seconds, convert to milliseconds
|
|
48
|
+
return payload.exp ? payload.exp * 1000 : 0;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return 0;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Check if the cached token is still valid
|
|
56
|
+
* Considers token invalid if it expires within 60 seconds
|
|
57
|
+
*/
|
|
58
|
+
function isTokenValid() {
|
|
59
|
+
if (!cachedToken)
|
|
60
|
+
return false;
|
|
61
|
+
// Add 60 second buffer before expiry
|
|
62
|
+
return Date.now() < tokenExpiry - 60000;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Force a fresh login, bypassing the cache
|
|
66
|
+
*/
|
|
67
|
+
export async function login() {
|
|
68
|
+
// Step 1: Get CSRF token
|
|
69
|
+
const csrfResponse = await fetch("https://tgoyemek.com/api/auth/csrf", {
|
|
70
|
+
headers: {
|
|
71
|
+
"User-Agent": USER_AGENT
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
if (!csrfResponse.ok) {
|
|
75
|
+
throw new AuthenticationError(`Failed to fetch CSRF token: ${csrfResponse.status} ${csrfResponse.statusText}`);
|
|
76
|
+
}
|
|
77
|
+
const csrfToken = parseCookie(csrfResponse.headers.get("set-cookie"), "tgo-csrf-token");
|
|
78
|
+
if (!csrfToken) {
|
|
79
|
+
throw new AuthenticationError("CSRF token not found in response");
|
|
80
|
+
}
|
|
81
|
+
// Step 2: Login with credentials
|
|
82
|
+
const loginResponse = await fetch("https://tgoyemek.com/api/auth/login", {
|
|
83
|
+
method: "POST",
|
|
84
|
+
headers: {
|
|
85
|
+
"Content-Type": "text/plain;charset=UTF-8",
|
|
86
|
+
"Cookie": `tgo-csrf-token=${csrfToken}`,
|
|
87
|
+
"User-Agent": USER_AGENT
|
|
88
|
+
},
|
|
89
|
+
body: JSON.stringify({
|
|
90
|
+
username: CREDENTIALS.email,
|
|
91
|
+
password: CREDENTIALS.password,
|
|
92
|
+
csrfToken: csrfToken
|
|
93
|
+
})
|
|
94
|
+
});
|
|
95
|
+
if (!loginResponse.ok) {
|
|
96
|
+
throw new AuthenticationError(`Login failed: ${loginResponse.status} ${loginResponse.statusText}`);
|
|
97
|
+
}
|
|
98
|
+
// Step 3: Extract tgo-token from response
|
|
99
|
+
const token = parseCookie(loginResponse.headers.get("set-cookie"), "tgo-token");
|
|
100
|
+
if (!token) {
|
|
101
|
+
throw new AuthenticationError("Authentication token not found in login response");
|
|
102
|
+
}
|
|
103
|
+
// Cache the token
|
|
104
|
+
cachedToken = token;
|
|
105
|
+
tokenExpiry = getTokenExpiry(token);
|
|
106
|
+
return token;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get a valid authentication token
|
|
110
|
+
* Returns cached token if valid, otherwise performs fresh login
|
|
111
|
+
*/
|
|
112
|
+
export async function getToken() {
|
|
113
|
+
if (isTokenValid() && cachedToken) {
|
|
114
|
+
return cachedToken;
|
|
115
|
+
}
|
|
116
|
+
return login();
|
|
117
|
+
}
|