Skip to content

Commit 2651236

Browse files
committed
chore: lint fix
1 parent 033441e commit 2651236

File tree

6 files changed

+119
-78
lines changed

6 files changed

+119
-78
lines changed

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,16 @@
7070
"@typescript-eslint/no-empty-function": "off",
7171
"@typescript-eslint/no-floating-promises": "off",
7272
"@typescript-eslint/ban-types": "off",
73+
"@typescript-eslint/no-restricted-types": "off",
74+
"@typescript-eslint/switch-exhaustiveness-check": "off",
7375
"import/no-unassigned-import": "off",
7476
"import/extensions": "off",
7577
"n/prefer-global/process": "off",
7678
"no-new-func": "off",
7779
"unicorn/prefer-global-this": "off",
7880
"unicorn/prefer-module": "off",
7981
"unicorn/no-new-array": "off",
82+
"unicorn/no-array-callback-reference": "off",
8083
"unicorn/prevent-abbreviations": [
8184
"error",
8285
{

packages/burger-api/src/blob-service.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import fs from 'node:fs/promises';
22
import path from 'node:path';
3+
import { Buffer } from 'node:buffer';
34
import { BlobServiceClient, ContainerClient } from '@azure/storage-blob';
45
import { DefaultAzureCredential } from '@azure/identity';
56
import dotenv from 'dotenv';
@@ -95,16 +96,18 @@ export class BlobService {
9596
const imagesDirectory = path.join(process.cwd(), 'data', 'images');
9697

9798
// Get all jpg files in the directory
98-
const imageFiles = (await fs.readdir(imagesDirectory)).filter((file) => file.endsWith('.jpg'));
99+
const allFiles = await fs.readdir(imagesDirectory);
100+
const imageFiles = allFiles.filter((file) => file.endsWith('.jpg'));
99101

100102
console.log(`Found ${imageFiles.length} images to upload`);
101103

102-
// Upload each image
103-
for (const imageFile of imageFiles) {
104+
// Upload all images in parallel
105+
const { containerClient } = this;
106+
const uploadPromises = imageFiles.map(async (imageFile) => {
104107
const filePath = path.join(imagesDirectory, imageFile);
105108
const fileContent = await fs.readFile(filePath);
106109

107-
const blockBlobClient = this.containerClient.getBlockBlobClient(imageFile);
110+
const blockBlobClient = containerClient.getBlockBlobClient(imageFile);
108111

109112
await blockBlobClient.upload(fileContent, fileContent.length, {
110113
blobHTTPHeaders: {
@@ -113,8 +116,10 @@ export class BlobService {
113116
});
114117

115118
console.log(`Uploaded ${imageFile}`);
116-
}
119+
return imageFile;
120+
});
117121

122+
await Promise.all(uploadPromises);
118123
console.log('All images uploaded successfully');
119124
} catch (error) {
120125
console.error('Error uploading images:', error);
@@ -155,7 +160,7 @@ export class BlobService {
155160
}
156161

157162
// Convert stream to buffer
158-
return new Promise<Buffer>((resolve, reject) => {
163+
return await new Promise<Buffer>((resolve, reject) => {
159164
const chunks: Buffer[] = [];
160165
const stream = downloadResponse.readableStreamBody!;
161166

packages/burger-api/src/db-service.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { Order, OrderStatus } from './order.js';
1212
dotenv.config({ path: path.join(process.cwd(), '../../.env') });
1313

1414
// Helper to strip properties starting with underscore from an object
15-
function stripUnderscoreProperties<T extends Record<string, unknown>>(object: T): T {
15+
function stripUnderscoreProperties<T extends object>(object: T): T {
1616
if (!object || typeof object !== 'object') return object;
1717
const result: Record<string, any> = {};
1818
for (const key of Object.keys(object)) {
@@ -149,26 +149,26 @@ export class DbService {
149149
try {
150150
// Check if Burgers container is empty
151151
const burgerIterator = this.burgersContainer!.items.query('SELECT VALUE COUNT(1) FROM c');
152-
const burgerCount = (await burgerIterator.fetchAll()).resources[0];
152+
const burgerResponse = await burgerIterator.fetchAll();
153+
const burgerCount = burgerResponse.resources[0];
153154

154155
if (burgerCount === 0) {
155156
console.log('Seeding burgers data to Cosmos DB...');
156157
const burgers = burgersData as Burger[];
157-
for (const burger of burgers) {
158-
await this.burgersContainer!.items.create(burger);
159-
}
158+
const burgerCreationPromises = burgers.map(async (burger) => this.burgersContainer!.items.create(burger));
159+
await Promise.all(burgerCreationPromises);
160160
}
161161

162162
// Check if Toppings container is empty
163163
const toppingIterator = this.toppingsContainer!.items.query('SELECT VALUE COUNT(1) FROM c');
164-
const toppingCount = (await toppingIterator.fetchAll()).resources[0];
164+
const toppingResponse = await toppingIterator.fetchAll();
165+
const toppingCount = toppingResponse.resources[0];
165166

166167
if (toppingCount === 0) {
167168
console.log('Seeding toppings data to Cosmos DB...');
168169
const toppings = toppingsData as Topping[];
169-
for (const topping of toppings) {
170-
await this.toppingsContainer!.items.create(topping);
171-
}
170+
const toppingCreationPromises = toppings.map(async (topping) => this.toppingsContainer!.items.create(topping));
171+
await Promise.all(toppingCreationPromises);
172172
}
173173
} catch (error) {
174174
console.error('Error seeding initial data:', error);
@@ -457,7 +457,7 @@ export class DbService {
457457
}
458458

459459
try {
460-
const { resource } = await this.usersContainer.item(id, id).read();
460+
const { resource } = await this.usersContainer.item(id).read();
461461
return resource?.name;
462462
} catch (error) {
463463
console.error('Error fetching user:', error);
@@ -472,7 +472,7 @@ export class DbService {
472472
}
473473

474474
try {
475-
const { resource } = await this.usersContainer.item(id, id).read();
475+
const { resource } = await this.usersContainer.item(id).read();
476476
return Boolean(resource);
477477
} catch (error) {
478478
console.error('Error checking user existence:', error);

packages/burger-api/src/functions/orders-post.ts

Lines changed: 65 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,36 @@ interface CreateOrderRequest {
1212
}>;
1313
}
1414

15+
// Helper function for topping validation
16+
async function validateAndCalculateToppingsPrice(
17+
dataService: DbService,
18+
toppingIds?: string[],
19+
): Promise<number | { status: number; jsonBody: { error: string } }> {
20+
if (!toppingIds || toppingIds.length === 0) {
21+
return 0;
22+
}
23+
24+
// Validate all toppings exist in parallel
25+
const toppingPromises = toppingIds.map(async (toppingId) => {
26+
const topping = await dataService.getTopping(toppingId);
27+
if (!topping) {
28+
throw new Error(`Topping with ID ${toppingId} not found`);
29+
}
30+
31+
return topping.price;
32+
});
33+
34+
try {
35+
const toppingPrices = await Promise.all(toppingPromises);
36+
return toppingPrices.reduce((sum, price) => sum + price, 0);
37+
} catch (error) {
38+
return {
39+
status: 400,
40+
jsonBody: { error: (error as Error).message },
41+
};
42+
}
43+
}
44+
1545
app.http('orders-post', {
1646
methods: ['POST'],
1747
authLevel: 'anonymous',
@@ -35,11 +65,11 @@ app.http('orders-post', {
3565
// Check if userId exists in the database
3666
const userExists = await dataService.userExists(requestBody.userId);
3767
if (!userExists) {
38-
const registrationUrl = process.env.REGISTRATION_WEBAPP_URL ?? '<unspecified>';
68+
const registrationUrl = process.env.AGENT_WEBAPP_URL ?? '<unspecified>';
3969
return {
4070
status: 401,
4171
jsonBody: {
42-
error: `The specified userId is not registered. Please register to get a valid userId at: ${registrationUrl}`,
72+
error: `The specified userId is not registered. Please login to get a valid userId at: ${registrationUrl}`,
4373
},
4474
};
4575
}
@@ -64,7 +94,6 @@ app.http('orders-post', {
6494
}
6595

6696
// Convert request items to order items
67-
const orderItems: OrderItem[] = [];
6897
let totalPrice = 0;
6998

7099
// Calculate total burger count and validate limit
@@ -76,47 +105,51 @@ app.http('orders-post', {
76105
};
77106
}
78107

79-
for (const item of requestBody.items) {
108+
// Validate and process items in parallel
109+
const itemValidationPromises = requestBody.items.map(async (item) => {
80110
// Validate quantity is a positive integer
81111
if (!Number.isInteger(item.quantity) || item.quantity <= 0) {
82-
return {
83-
status: 400,
84-
jsonBody: { error: `Quantity for burgerId ${item.burgerId} must be a positive integer` },
85-
};
112+
throw new Error(`Quantity for burgerId ${item.burgerId} must be a positive integer`);
86113
}
87114

88115
const burger = await dataService.getBurger(item.burgerId);
89116
if (!burger) {
90-
return {
91-
status: 400,
92-
jsonBody: { error: `Burger with ID ${item.burgerId} not found` },
93-
};
117+
throw new Error(`Burger with ID ${item.burgerId} not found`);
94118
}
95119

96-
// Validate and calculate price for extra toppings
97-
let extraToppingsPrice = 0;
98-
if (item.extraToppingIds && item.extraToppingIds.length > 0) {
99-
for (const toppingId of item.extraToppingIds) {
100-
const topping = await dataService.getTopping(toppingId);
101-
if (!topping) {
102-
return {
103-
status: 400,
104-
jsonBody: { error: `Topping with ID ${toppingId} not found` },
105-
};
106-
}
107-
108-
extraToppingsPrice += topping.price;
109-
}
120+
// Validate all extra toppings exist
121+
const extraToppingsPrice = await validateAndCalculateToppingsPrice(dataService, item.extraToppingIds);
122+
if (typeof extraToppingsPrice === 'object') {
123+
throw new TypeError(extraToppingsPrice.jsonBody.error);
110124
}
111125

112126
const itemPrice = (burger.price + extraToppingsPrice) * item.quantity;
113-
totalPrice += itemPrice;
114127

115-
orderItems.push({
116-
burgerId: item.burgerId,
117-
quantity: item.quantity,
118-
extraToppingIds: item.extraToppingIds,
119-
});
128+
return {
129+
orderItem: {
130+
burgerId: item.burgerId,
131+
quantity: item.quantity,
132+
extraToppingIds: item.extraToppingIds,
133+
},
134+
itemPrice,
135+
};
136+
});
137+
138+
let validatedItems;
139+
try {
140+
validatedItems = await Promise.all(itemValidationPromises);
141+
} catch (error) {
142+
return {
143+
status: 400,
144+
jsonBody: { error: (error as Error).message },
145+
};
146+
}
147+
148+
// Calculate total price and build order items
149+
const orderItems: OrderItem[] = [];
150+
for (const { orderItem, itemPrice } of validatedItems) {
151+
totalPrice += itemPrice;
152+
orderItems.push(orderItem);
120153
}
121154

122155
// Calculate estimated completion time based on burger count

packages/burger-api/src/functions/orders-status-timer.ts

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,18 @@ app.timer('orders-status-timer', {
1515
const orders = allOrders.filter((order) =>
1616
[OrderStatus.Pending, OrderStatus.InPreparation, OrderStatus.Ready].includes(order.status),
1717
);
18-
const updatePromises: Array<Promise<{ id: string; status: string; success: boolean; error?: Error }>> = [];
18+
19+
const updateTasks = [];
1920
for (const order of orders) {
2021
switch (order.status) {
2122
case OrderStatus.Pending: {
2223
const minutesSinceCreated = (now.getTime() - new Date(order.createdAt).getTime()) / 60_000;
2324
if (minutesSinceCreated > 3 || (minutesSinceCreated >= 1 && Math.random() < 0.5)) {
24-
updatePromises.push(
25-
db
26-
.updateOrder(order.id, { status: OrderStatus.InPreparation })
27-
.then(() => ({ id: order.id, status: 'in-preparation', success: true }))
28-
.catch((error: any) => {
29-
context.error(`ERROR: Failed to update order ${order.id} to in-preparation:`, error);
30-
return { id: order.id, status: 'in-preparation', success: false, error };
31-
}),
32-
);
25+
updateTasks.push({
26+
orderId: order.id,
27+
update: { status: OrderStatus.InPreparation },
28+
statusName: 'in-preparation',
29+
});
3330
}
3431

3532
break;
@@ -39,15 +36,11 @@ app.timer('orders-status-timer', {
3936
const estimatedCompletionAt = new Date(order.estimatedCompletionAt);
4037
const diffMinutes = (now.getTime() - estimatedCompletionAt.getTime()) / 60_000;
4138
if (diffMinutes > 3 || (Math.abs(diffMinutes) <= 3 && Math.random() < 0.5)) {
42-
updatePromises.push(
43-
db
44-
.updateOrder(order.id, { status: OrderStatus.Ready, readyAt: now.toISOString() })
45-
.then(() => ({ id: order.id, status: 'ready', success: true }))
46-
.catch((error: any) => {
47-
context.error(`ERROR: Failed to update order ${order.id} to ready:`, error);
48-
return { id: order.id, status: 'ready', success: false, error };
49-
}),
50-
);
39+
updateTasks.push({
40+
orderId: order.id,
41+
update: { status: OrderStatus.Ready, readyAt: now.toISOString() },
42+
statusName: 'ready',
43+
});
5144
}
5245

5346
break;
@@ -58,15 +51,11 @@ app.timer('orders-status-timer', {
5851
const readyAt = new Date(order.readyAt);
5952
const minutesSinceReady = (now.getTime() - readyAt.getTime()) / 60_000;
6053
if (minutesSinceReady >= 1 && (minutesSinceReady > 2 || Math.random() < 0.5)) {
61-
updatePromises.push(
62-
db
63-
.updateOrder(order.id, { status: OrderStatus.Completed, completedAt: now.toISOString() })
64-
.then(() => ({ id: order.id, status: 'completed', success: true }))
65-
.catch((error: any) => {
66-
context.error(`ERROR: Failed to update order ${order.id} to completed:`, error);
67-
return { id: order.id, status: 'completed', success: false, error };
68-
}),
69-
);
54+
updateTasks.push({
55+
orderId: order.id,
56+
update: { status: OrderStatus.Completed, completedAt: now.toISOString() },
57+
statusName: 'completed',
58+
});
7059
}
7160
}
7261

@@ -76,7 +65,18 @@ app.timer('orders-status-timer', {
7665
}
7766
}
7867

68+
const updatePromises = updateTasks.map(async (task) => {
69+
try {
70+
await db.updateOrder(task.orderId, task.update);
71+
return { id: task.orderId, status: task.statusName, success: true };
72+
} catch (error) {
73+
context.error(`ERROR: Failed to update order ${task.orderId} to ${task.statusName}:`, error);
74+
return { id: task.orderId, status: task.statusName, success: false, error: error as Error };
75+
}
76+
});
77+
7978
const results = await Promise.all(updatePromises);
79+
8080
const updated = results.filter((r) => r.success).length;
8181
const failed = results.filter((r) => !r.success).length;
8282
const elapsedMs = Date.now() - startTime;

0 commit comments

Comments
 (0)