diff --git a/package-lock.json b/package-lock.json index 65aa212..a26d152 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,7 +7,6 @@ "": { "name": "core-assignment-week-10", "version": "1.0.0", - "hasInstallScript": true, "license": "CC BY-NC-SA 4.0", "dependencies": { "@inquirer/prompts": "^7.0.0", @@ -1585,7 +1584,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -1822,7 +1820,6 @@ "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", diff --git a/task-1/cocktail.js b/task-1/cocktail.js index 6fd5a62..7563eb6 100644 --- a/task-1/cocktail.js +++ b/task-1/cocktail.js @@ -1,10 +1,41 @@ -// API documentation: https://www.thecocktaildb.com/api.php - import path from 'path'; +import { writeFile } from 'fs/promises'; const BASE_URL = 'https://www.thecocktaildb.com/api/json/v1/1'; -// Add helper functions as needed here +function generateMarkdown(drinks) { + let markdown = '# Cocktail Recipes\n\n'; + + for (const drink of drinks) { + markdown += `## ${drink.strDrink}\n\n`; + + if (drink.strDrinkThumb) { + markdown += `![${drink.strDrink}](${drink.strDrinkThumb}/medium)\n\n`; + } + + markdown += `**Category**: ${drink.strCategory}\n\n`; + markdown += `**Alcoholic**: ${drink.strAlcoholic === 'Alcoholic' ? 'Yes' : 'No'}\n\n`; + + markdown += `### Ingredients\n`; + + for (let i = 1; i <= 15; i++) { + const ingredient = drink[`strIngredient${i}`]; + const measure = drink[`strMeasure${i}`]; + + if (!ingredient) break; + + markdown += `- ${measure ? measure.trim() + ' ' : ''}${ingredient}\n`; + } + + markdown += `\n`; + markdown += `### Instructions\n`; + markdown += `${drink.strInstructions}\n\n`; + markdown += `Serve in: ${drink.strGlass}\n\n`; + markdown += `---\n\n`; + } + + return markdown; +} export async function main() { if (process.argv.length < 3) { @@ -19,15 +50,30 @@ export async function main() { const outPath = path.join(__dirname, `./output/${cocktailName}.md`); try { - // 1. Fetch data from the API at the given URL - // 2. Generate markdown content to match the examples - // 3. Write the generated content to a markdown file as given by outPath + const response = await fetch(url); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + + if (!data.drinks) { + console.error('No cocktails found with that name.'); + await writeFile(outPath, `# No results found for "${cocktailName}"`); + return; + } + + const markdown = generateMarkdown(data.drinks); + + await writeFile(outPath, markdown); + console.log(`File created at ${outPath}`); } catch (error) { - // 4. Handle errors + console.error('Something went wrong:', error.message); } } // Do not change the code below if (!process.env.VITEST) { main(); -} +} \ No newline at end of file diff --git a/task-1/output/margarita.md b/task-1/output/margarita.md new file mode 100644 index 0000000..5c20d70 --- /dev/null +++ b/task-1/output/margarita.md @@ -0,0 +1,23 @@ +# Cocktail Recipes + +## Margarita + +![Margarita](https://www.thecocktaildb.com/images/media/drink/5noda61589575158.jpg/medium) + +**Category**: Ordinary Drink + +**Alcoholic**: Yes + +### Ingredients +- 1 1/2 oz Tequila +- 1/2 oz Triple sec +- 1 oz Lime juice +- Salt + +### Instructions +Rub the rim of the glass. + +Serve in: Cocktail glass + +--- + diff --git a/task-1/output/nonexistentcocktail.md b/task-1/output/nonexistentcocktail.md new file mode 100644 index 0000000..bf39ff7 --- /dev/null +++ b/task-1/output/nonexistentcocktail.md @@ -0,0 +1 @@ +# No results found for "nonexistentcocktail" \ No newline at end of file diff --git a/task-2/post-cli/src/services.js b/task-2/post-cli/src/services.js index 2601f57..8f1db62 100644 --- a/task-2/post-cli/src/services.js +++ b/task-2/post-cli/src/services.js @@ -1,71 +1,49 @@ -// Change base URL for API requests to the local IP of the Post Central API server const BASE_URL = 'http://localhost:3000'; -// ============================================================================ -// AUTH TOKEN - Stored after login/register, sent with every request -// ============================================================================ - -/** - * The JWT token received from login or register. - * This token proves who you are to the server. - */ let authToken = null; -/** - * Save the token. Called by the UI after login/register and by unit tests. - */ +// ================= TOKEN ================= + const setToken = (token) => { authToken = token; }; -/** - * Get the current token. Use this to build the Authorization header - * for authenticated requests: `Bearer ${getToken()}` - */ const getToken = () => authToken; -// ============================================================================ -// HELLO ENDPOINT - Already implemented! Read this as a reference for your code. -// ============================================================================ +// ================= HELLO ================= -/** - * Get a hello message from Post Central - * Method: GET | Endpoint: /posts/hello | Auth: No - * Response: { id: number, user: string, text: string, timestamp: string } - */ const getHello = async () => { const response = await fetch(`${BASE_URL}/posts/hello`); + if (!response.ok) { throw new Error( `Failed to get hello: HTTP ${response.status} ${response.statusText}` ); } + return await response.json(); }; -// ============================================================================ -// STAGE 1: GET REQUEST - Read data from the server -// ============================================================================ +// ================= AUTH ================= -/** - * Get current user information - * Method: GET | Endpoint: /users/me | Auth: Yes - * Response: { user: string } - */ -const getMe = async () => { - // TODO -}; +const loginUser = async (name, password) => { + const response = await fetch(`${BASE_URL}/users/login`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ name, password }), + }); -// ============================================================================ -// STAGE 2: POST REQUEST - createUser() is provided as a reference. Implement loginUser(). -// ============================================================================ + if (!response.ok) { + throw new Error( + `Failed to login: HTTP ${response.status} ${response.statusText}` + ); + } + + return await response.json(); +}; -/** - * Register a new user - * Method: POST | Endpoint: /users/register | Auth: No - * Body: { name, password } - * Response: { user: string, token: string } - */ const createUser = async (name, password) => { const response = await fetch(`${BASE_URL}/users/register`, { method: 'POST', @@ -74,78 +52,125 @@ const createUser = async (name, password) => { }, body: JSON.stringify({ name, password }), }); + if (!response.ok) { throw new Error( `Failed to create user: HTTP ${response.status} ${response.statusText}` ); } + return await response.json(); }; -/** - * Log in an existing user - * Method: POST | Endpoint: /users/login | Auth: No - * Body: { name, password } - * Response: { user: string, token: string } - */ -const loginUser = async (name, password) => { - // TODO -}; +const getMe = async () => { + const response = await fetch(`${BASE_URL}/users/me`, { + headers: { + Authorization: `Bearer ${getToken()}`, + }, + }); -// ============================================================================ -// STAGE 3: More CRUD Operations -// ============================================================================ + if (!response.ok) { + throw new Error( + `Failed to get user: HTTP ${response.status} ${response.statusText}` + ); + } -/** - * Create a new post - * Method: POST | Endpoint: /posts | Auth: Yes - * Body: { text } - * Response: { id: number, text: string, user: string } - */ -const createPost = async (text) => { - // TODO + return await response.json(); }; -/** - * Get all posts for the current user - * Method: GET | Endpoint: /posts/me | Auth: Yes - * Response: Array of { id, text, user } - */ +// ================= POSTS ================= + const getPosts = async () => { - // TODO + const response = await fetch(`${BASE_URL}/posts/me`, { + headers: { + Authorization: `Bearer ${getToken()}`, + }, + }); + + if (!response.ok) { + throw new Error( + `Failed to get posts: HTTP ${response.status} ${response.statusText}` + ); + } + + return await response.json(); }; -/** - * Update an existing post - * Method: PUT | Endpoint: /posts/:id | Auth: Yes - * Body: { text } - * Response: { id: number, text: string } - */ -const updatePost = async (id, text) => { - // TODO +const createPost = async (text) => { + const response = await fetch(`${BASE_URL}/posts`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${getToken()}`, + }, + body: JSON.stringify({ text }), + }); + + if (!response.ok) { + throw new Error( + `Failed to create post: HTTP ${response.status} ${response.statusText}` + ); + } + + return await response.json(); }; -/** - * Delete current user - * Method: DELETE | Endpoint: /users/me | Auth: Yes - * Response: { user: string, message: string } - */ -const deleteUser = async () => { - // TODO +const updatePost = async (id, text) => { + const response = await fetch(`${BASE_URL}/posts/${id}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${getToken()}`, + }, + body: JSON.stringify({ text }), + }); + + if (!response.ok) { + throw new Error( + `Failed to update post: HTTP ${response.status} ${response.statusText}` + ); + } + + return await response.json(); }; -/** - * Delete a post - * Method: DELETE | Endpoint: /posts/:id | Auth: Yes - * Response: { id: number, text: string, message: string } - */ const deletePost = async (id) => { - // TODO + const response = await fetch(`${BASE_URL}/posts/${id}`, { + method: 'DELETE', + headers: { + Authorization: `Bearer ${getToken()}`, + }, + }); + + if (!response.ok) { + throw new Error( + `Failed to delete post: HTTP ${response.status} ${response.statusText}` + ); + } + + return await response.json(); +}; + +// ================= USER DELETE ================= + +const deleteUser = async () => { + const response = await fetch(`${BASE_URL}/users/me`, { + method: 'DELETE', + headers: { + Authorization: `Bearer ${getToken()}`, + }, + }); + + if (!response.ok) { + throw new Error( + `Failed to delete user: HTTP ${response.status} ${response.statusText}` + ); + } + + return await response.json(); }; -// ============================================================================ -// EXPORTS - Make functions available for testing and main.js -// ============================================================================ +// ================= EXPORTS ================= export { createPost, @@ -159,4 +184,4 @@ export { loginUser, setToken, updatePost, -}; +}; \ No newline at end of file