chore(i18n,curriculum): processed translations - new ukrainian (#44447)

This commit is contained in:
camperbot
2021-12-10 11:14:24 +05:30
committed by GitHub
parent 8651ee1797
commit 0473dedf47
1663 changed files with 156692 additions and 1 deletions

View File

@@ -0,0 +1,611 @@
---
id: 5a8b073d06fa14fcfde687aa
title: Трекер вправ
challengeType: 4
forumTopicId: 301505
dashedName: exercise-tracker
---
# --description--
Створіть full stack додаток на JavaScript, який функціонально схожий до цього: <https://exercise-tracker.freecodecamp.rocks/>. Робота над цим проектом залучатиме тебе писати свій код використовуючи один з наступних методів:
- Клонувати [цей репозиторій з GitHub](https://github.com/freeCodeCamp/boilerplate-project-exercisetracker/) та локально завершити свій проект.
- Використати [наш проект для початківців на Replit](https://replit.com/github/freeCodeCamp/boilerplate-project-exercisetracker) для завершення свого проекту.
- Використати конструктор сайтів на свій вибір для завершення проекту. Впевніться, що ви зберегли всі файли із нашого GitHub репозиторію.
По завершенню переконайтеся, що працююча демоверсія вашого проекту розміщена у відкритому доступі. Потім введіть його URL-адресу в поле `Solution Link`. За бажанням також можете ввести посилання на вихідний код вашого проекту в полі `GitHub Link`.
# --instructions--
Ваші відповіді повинні мати наступні структури.
Вправа:
```js
{
username: "fcc_test"
description: "test",
duration: 60,
date: "Mon Jan 01 1990",
_id: "5fb5853f734231456ccb3b05"
}
```
Користувач:
```js
{
username: "fcc_test",
_id: "5fb5853f734231456ccb3b05"
}
```
Лог:
```js
{
username: "fcc_test",
count: 1,
_id: "5fb5853f734231456ccb3b05",
log: [{
description: "test",
duration: 60,
date: "Mon Jan 01 1990",
}]
}
```
**Підказка:** для отримування очікуваного результату властивості `date` може використовуватися метод `toDateString` з `Date` API.
# --hints--
Вам необхідно вказати свій власний проект, а не приклад URL-адреси.
```js
(getUserInput) => {
const url = getUserInput('url');
assert(
!/.*\/exercise-tracker\.freecodecamp\.rocks/.test(getUserInput('url'))
);
};
```
Ви можете виконати `POST` запит до `/api/users` з даними форми `username` для створення нового користувача.
```js
async (getUserInput) => {
const url = getUserInput('url');
const res = await fetch(url + '/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `username=fcc_test_${Date.now()}`.substr(0, 29)
});
assert.isTrue(res.ok);
if(!res.ok) {
throw new Error(`${res.status} ${res.statusText}`)
};
};
```
Отримана відповідь від `POST /api/users` з даними форми `username` буде об'єктом з властивостями `username` та `_id`.
```js
async (getUserInput) => {
const url = getUserInput('url');
const res = await fetch(url + '/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `username=fcc_test_${Date.now()}`.substr(0, 29)
});
if (res.ok) {
const { _id, username } = await res.json();
assert.exists(_id);
assert.exists(username);
} else {
throw new Error(`${res.status} ${res.statusText}`);
}
};
```
Ви можете зробити запит `GET` на `/api/users`, щоб отримати список всіх користувачів.
```js
async(getUserInput) => {
const url = getUserInput('url');
const res = await fetch(url + '/api/users');
assert.isTrue(res.ok);
if(!res.ok) {
throw new Error(`${res.status} ${res.statusText}`)
};
};
```
Запит `GET` на `/api/users` повертає масив.
```js
async(getUserInput) => {
const url = getUserInput('url');
const res = await fetch(url + '/api/users');
if(res.ok){
const users = await res.json();
assert.isArray(users);
} else {
throw new Error(`${res.status} ${res.statusText}`);
};
};
```
Кожен елемент у масиві, який повернувся з `GET /api/users`, є літералом об'єкта з `username` та `_id` користувача.
```js
async(getUserInput) => {
const url = getUserInput('url');
const res = await fetch(url + '/api/users');
if(res.ok){
const users = await res.json();
const user = users[0];
assert.exists(user);
assert.exists(user.username);
assert.exists(user._id);
assert.isString(user.username);
assert.isString(user._id);
} else {
throw new Error(`${res.status} ${res.statusText}`);
};
};
```
Ви можете виконати `POST` запит до `/api/users/:_id/exercises` з даними форм `description`, `duration` та за бажанням `date`. Якщо дата не вказана, буде використовуватись поточна дата.
```js
async (getUserInput) => {
const url = getUserInput('url');
const res = await fetch(url + '/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `username=fcc_test_${Date.now()}`.substr(0, 29)
});
if (res.ok) {
const { _id, username } = await res.json();
const expected = {
username,
description: 'test',
duration: 60,
_id,
date: 'Mon Jan 01 1990'
};
const addRes = await fetch(url + `/api/users/${_id}/exercises`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `description=${expected.description}&duration=${expected.duration}&date=1990-01-01`
});
assert.isTrue(addRes.ok);
if(!addRes.ok) {
throw new Error(`${addRes.status} ${addRes.statusText}`)
};
} else {
throw new Error(`${res.status} ${res.statusText}`);
}
};
```
Відповідь, що повернулася від `POST /api/users/:_id/exercises`, буде об'єктом користувача з доданими полями з вправи.
```js
async (getUserInput) => {
const url = getUserInput('url');
const res = await fetch(url + '/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `username=fcc_test_${Date.now()}`.substr(0, 29)
});
if (res.ok) {
const { _id, username } = await res.json();
const expected = {
username,
description: 'test',
duration: 60,
_id,
date: 'Mon Jan 01 1990'
};
const addRes = await fetch(url + `/api/users/${_id}/exercises`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `description=${expected.description}&duration=${expected.duration}&date=1990-01-01`
});
if (addRes.ok) {
const actual = await addRes.json();
assert.deepEqual(actual, expected);
assert.isString(actual.description);
assert.isNumber(actual.duration);
assert.isString(actual.date);
} else {
throw new Error(`${addRes.status} ${addRes.statusText}`);
}
} else {
throw new Error(`${res.status} ${res.statusText}`);
}
};
```
Ви можете зробити запит `GET` на `/api/users/:_id/logs`, щоб отримати повний журнал вправ будь-якого користувача.
```js
async (getUserInput) => {
const url = getUserInput('url');
const res = await fetch(url + '/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `username=fcc_test_${Date.now()}`.substr(0, 29)
});
if (res.ok) {
const { _id, username } = await res.json();
const expected = {
username,
description: 'test',
duration: 60,
_id,
date: new Date().toDateString()
};
const addRes = await fetch(url + `/api/users/${_id}/exercises`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `description=${expected.description}&duration=${expected.duration}`
});
if (addRes.ok) {
const logRes = await fetch(url + `/api/users/${_id}/logs`);
assert.isTrue(logRes.ok);
if(!logRes.ok) {
throw new Error(`${logRes.status} ${logRes.statusText}`)
};
} else {
throw new Error(`${addRes.status} ${addRes.statusText}`);
}
} else {
throw new Error(`${res.status} ${res.statusText}`);
}
};
```
Запит до журналу користувача `GET /api/users/:_id/logs` повертає об'єкт користувача разом з властивістю `count` яка представляє кількість вправ, що належать цьому користувачеві.
```js
async (getUserInput) => {
const url = getUserInput('url');
const res = await fetch(url + '/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `username=fcc_test_${Date.now()}`.substr(0, 29)
});
if (res.ok) {
const { _id, username } = await res.json();
const expected = {
username,
description: 'test',
duration: 60,
_id,
date: new Date().toDateString()
};
const addRes = await fetch(url + `/api/users/${_id}/exercises`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `description=${expected.description}&duration=${expected.duration}`
});
if (addRes.ok) {
const logRes = await fetch(url + `/api/users/${_id}/logs`);
if (logRes.ok) {
const { count } = await logRes.json();
assert(count);
} else {
throw new Error(`${logRes.status} ${logRes.statusText}`);
}
} else {
throw new Error(`${addRes.status} ${addRes.statusText}`);
}
} else {
throw new Error(`${res.status} ${res.statusText}`);
}
};
```
Запит `GET` на `/api/users/:id/logs` поверне об'єкт користувача з `log`, - масивом всіх доданих вправ.
```js
async(getUserInput) => {
const url = getUserInput('url');
const res = await fetch(url + '/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: `username=fcc_test_${Date.now()}`.substr(0, 29)
})
if(res.ok){
const {_id, username} = await res.json();
const expected = {
username,
description: 'test',
duration: 60,
_id,
date: new Date().toDateString()
};
const addRes = await fetch(url + `/api/users/${_id}/exercises`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `description=${expected.description}&duration=${expected.duration}`
});
if(addRes.ok){
const logRes = await fetch(url + `/api/users/${_id}/logs`);
if(logRes.ok) {
const {log} = await logRes.json();
assert.isArray(log);
assert.equal(1, log.length);
} else {
throw new Error(`${logRes.status} ${logRes.statusText}`);
}
} else {
throw new Error(`${addRes.status} ${addRes.statusText}`);
};
} else {
throw new Error(`${res.status} ${res.statusText}`)
};
};
```
Кожен елемент у масиві `log`, який повернувся з `GET /api/users/:id/logs` це об'єкт, який повинен мати `description` `duration` і `date` властивості.
```js
async(getUserInput) => {
const url = getUserInput('url');
const res = await fetch(url + `/api/users`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: `username=fcc_test_${Date.now()}`.substr(0, 29)
});
if(res.ok) {
const {_id, username} = await res.json();
const expected = {
username,
description: 'test',
duration: 60,
_id,
date: new Date().toDateString()
};
const addRes = await fetch(url + `/api/users/${_id}/exercises`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `description=${expected.description}&duration=${expected.duration}`
});
if(addRes.ok) {
const logRes = await fetch(url + `/api/users/${_id}/logs`);
if(logRes.ok) {
const {log} = await logRes.json();
const exercise = log[0];
assert.exists(exercise);
assert.exists(exercise.description);
assert.exists(exercise.duration);
assert.exists(exercise.date);
} else {
throw new Error(`${logRes.status} ${logRes.statusText}`);
};
} else {
throw new Error(`${addRes.status} ${addRes.statusText}`);
};
} else {
throw new Error(`${res.status} ${res.statusText}`)
};
};
```
Властивість `description` будь-якого об'єкту в масиві `log`, що повернувся з `GET /api/users/:id/logs` повинен бути рядкового типу.
```js
async(getUserInput) => {
const url = getUserInput('url');
const res = await fetch(url + '/api/users/', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `username=fcc_test_${Date.now()}`.substr(0,29)
});
if(res.ok) {
const {_id, username} = await res.json();
const expected = {
username,
description: 'test',
duration: 60,
_id,
date: new Date().toDateString()
};
const addRes = await fetch(url + `/api/users/${_id}/exercises`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `description=${expected.description}&duration=${expected.duration}`
});
if(addRes.ok) {
const logRes = await fetch(url + `/api/users/${_id}/logs`);
if(logRes.ok){
const {log} = await logRes.json();
const exercise = log[0];
assert.isString(exercise.description);
assert.equal(exercise.description, expected.description);
} else {
throw new Error(`${logRes.status} ${logRes.statusText}`);
}
} else {
throw new Error(`${addRes.status} ${addRes.statusText}`);
};
} else {
throw new Error(`${res.status} ${res.statusText}`);
};
};
```
Властивість `duration` будь-якого об'єкту в масиві `log`, що повернувся з `GET /api/users/:id/logs`, повинна бути числового типу.
```js
async(getUserInput) => {
const url = getUserInput('url');
const res = await fetch(url + '/api/users/', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `username=fcc_test_${Date.now()}`.substr(0,29)
});
if(res.ok) {
const {_id, username} = await res.json();
const expected = {
username,
description: 'test',
duration: 60,
_id,
date: new Date().toDateString()
};
const addRes = await fetch(url + `/api/users/${_id}/exercises`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `description=${expected.description}&duration=${expected.duration}`
});
if(addRes.ok) {
const logRes = await fetch(url + `/api/users/${_id}/logs`);
if(logRes.ok){
const {log} = await logRes.json();
const exercise = log[0];
assert.isNumber(exercise.duration);
assert.equal(exercise.duration, expected.duration);
} else {
throw new Error(`${logRes.status} ${logRes.statusText}`);
}
} else {
throw new Error(`${addRes.status} ${addRes.statusText}`);
};
} else {
throw new Error(`${res.status} ${res.statusText}`);
};
};
```
Властивість `date` будь-якого об'єкту в масиві `log`, що повернувся з `GET /api/users/:id/logs`, повинна бути рядкового типу.. Використовуйте `dateString` формат з `Date` API.
```js
async(getUserInput) => {
const url = getUserInput('url');
const res = await fetch(url + '/api/users/', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `username=fcc_test_${Date.now()}`.substr(0,29)
});
if(res.ok) {
const {_id, username} = await res.json();
const expected = {
username,
description: 'test',
duration: 60,
_id,
date: new Date().toDateString()
};
const addRes = await fetch(url + `/api/users/${_id}/exercises`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `description=${expected.description}&duration=${expected.duration}`
});
if(addRes.ok) {
const logRes = await fetch(url + `/api/users/${_id}/logs`);
if(logRes.ok){
const {log} = await logRes.json();
const exercise = log[0];
assert.isString(exercise.date);
assert.equal(exercise.date, expected.date);
} else {
throw new Error(`${logRes.status} ${logRes.statusText}`);
}
} else {
throw new Error(`${addRes.status} ${addRes.statusText}`);
};
} else {
throw new Error(`${res.status} ${res.statusText}`);
};
};
```
Ви можете додати параметри `from`, `to` та `limit` у запит `GET /api/users/:_id/logs` для отримання частини журналу будь-якого користувача. `from` та `to` - дати у форматі `yyyy-mm-dd`. `limit` - це ціле число того, скільки журналів потрібно надіслати назад.
```js
async (getUserInput) => {
const url = getUserInput('url');
const res = await fetch(url + '/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `username=fcc_test_${Date.now()}`.substr(0, 29)
});
if (res.ok) {
const { _id, username } = await res.json();
const expected = {
username,
description: 'test',
duration: 60,
_id,
date: new Date().toDateString()
};
const addExerciseRes = await fetch(url + `/api/users/${_id}/exercises`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `description=${expected.description}&duration=${expected.duration}&date=1990-01-01`
});
const addExerciseTwoRes = await fetch(url + `/api/users/${_id}/exercises`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `description=${expected.description}&duration=${expected.duration}&date=1990-01-02`
});
if (addExerciseRes.ok && addExerciseTwoRes.ok) {
const logRes = await fetch(
url + `/api/users/${_id}/logs?from=1989-12-31&to=1990-01-03`
);
if (logRes.ok) {
const { log } = await logRes.json();
assert.isArray(log);
assert.equal(2, log.length);
} else {
throw new Error(`${logRes.status} ${logRes.statusText}`);
}
const limitRes = await fetch(
url + `/api/users/${_id}/logs?limit=1`
);
if (limitRes.ok) {
const { log } = await limitRes.json();
assert.isArray(log);
assert.equal(1, log.length);
} else {
throw new Error(`${limitRes.status} ${limitRes.statusText}`);
}
} else {
throw new Error(`${res.status} ${res.statusText}`);
}
} else {
throw new Error(`${res.status} ${res.statusText}`);
}
};
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,77 @@
---
id: bd7158d8c443edefaeb5bdff
title: Мікросервіс парсингу заголовків запиту
challengeType: 4
forumTopicId: 301507
dashedName: request-header-parser-microservice
---
# --description--
Створіть full stack додаток на JavaScript, який функціонально схожий до цього:<https://request-header-parser-microservice.freecodecamp.rocks/>. Робота над цим проектом залучатиме тебе писати свій код використовуючи один з наступних методів:
- Клонувати [цей репозиторій з GitHub](https://github.com/freeCodeCamp/boilerplate-project-headerparser/) та локально завершити свій проект.
- Використати [наш проект для початківців на Replit](https://replit.com/github/freeCodeCamp/boilerplate-project-headerparser) для завершення свого проекту.
- Використати конструктор сайтів на свій вибір для завершення проекту. Впевніться, що ви зберегли всі файли із нашого GitHub репозиторію.
По завершенню переконайтеся, що працююча демоверсія вашого проекту розміщена у відкритому доступі. Потім введіть його URL-адресу в поле `Solution Link`. За бажанням також можете ввести посилання на вихідний код вашого проекту в полі `GitHub Link`.
# --hints--
Вам необхідно вказати свій власний проект, а не приклад URL-адреси.
```js
(getUserInput) => {
assert(
!/.*\/request-header-parser-microservice\.freecodecamp\.rocks/.test(
getUserInput('url')
)
);
};
```
Запит на `/api/whoami` повинен повернути об'єкт JSON з вашою IP-адресою у ключі `ipaddress`.
```js
(getUserInput) =>
$.get(getUserInput('url') + '/api/whoami').then(
(data) => assert(data.ipaddress && data.ipaddress.length > 0),
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
Запит на `/api/whoami` повинен повернути об’єкт JSON з вашою бажаною мовою у ключі `language`.
```js
(getUserInput) =>
$.get(getUserInput('url') + '/api/whoami').then(
(data) => assert(data.language && data.language.length > 0),
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
Запит на `/api/whoami` повинен повернути об'єкт JSON з вашим програмним забезпеченням у ключі `software`.
```js
(getUserInput) =>
$.get(getUserInput('url') + '/api/whoami').then(
(data) => assert(data.software && data.software.length > 0),
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,79 @@
---
id: 587d7fb1367417b2b2512bf4
title: Ланцюгове підпрограмне забезпечення для створення сервера часу
challengeType: 2
forumTopicId: 301510
dashedName: chain-middleware-to-create-a-time-server
---
# --description--
Програмне забезпечення можна підключити за певним маршрутом за допомогою `app.METHOD(path, middlewareFunction)`. Підрограмне забезпечення також може бути поєднане всередині визначення маршруту.
Розглянемо наступний приклад:
```js
app.get('/user', function(req, res, next) {
req.user = getTheUserSync(); // Hypothetical synchronous operation
next();
}, function(req, res) {
res.send(req.user);
});
```
Цей підхід корисний для поділу серверних операцій на менші одиниці. Це призводить до кращої структури додатків, та можливості повторного використання коду в різних місцях. Цей підхід також може бути використаний для проведення деякої перевірки даних. У кожній точці стеку підпрограмного забезпечення ви можете заблокувати виконання поточного ланцюга та передати управління функціями, спеціально розробленими для обробки помилок. Або ви можете передати контроль до наступних відповідних маршрутів, щоб впоратися з особливими випадками. Ми побачимо як у розділі розширений Експрес.
# --instructions--
У маршруті `app.get('/now', ...)` об'єднайте підппрограмне забезпечення та остаточний обробник. У функції підпрограмне забезпечення ви повинні додати поточний час до об’єкта запиту в `req.time` ключі. Ви можете використати `new Date().toString()`. В обробнику, відповідайте на об'єкт JSON, використовуючи структуру `{time: req.time}`.
**Примітка:** Тест не пройде, якщо ви не об'єднаєте підпрограмне забезпечення. Якщо ви встановите функцію десь в іншому місці, тест зазнає невдачі, навіть якщо результат виводу правильний.
# --hints--
Кінцева точка /now повинна бути підключена до проміжного програмного забезпечення
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/chain-middleware-time').then(
(data) => {
assert.equal(
data.stackLength,
2,
'"/now" route has no mounted middleware'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
/now кінцева точка повинна повернути час, який відтепер складає +/-20 сек
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/chain-middleware-time').then(
(data) => {
var now = new Date();
assert.isAtMost(
Math.abs(new Date(data.time) - now),
20000,
'the returned time is not between +- 20 secs from now'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,78 @@
---
id: 587d7fb2367417b2b2512bf8
title: Отримання даних з POST запитів
challengeType: 2
forumTopicId: 301511
dashedName: get-data-from-post-requests
---
# --description--
Встановіть POST обробник за шляхом `/name`. Це той самий шлях, що і раніше. Ми підготували форму на головній сторінці html. Вона надсилатиме такі ж дані, як і у вправі 10 (рядок запиту). Якщо body-parser налаштований правильно, ви повинні знайти параметри в об’єкті `req.body`. Подивіться на простий приклад з бібліотеки:
<blockquote>маршрут: POST '/library'<br>urlencoded_body: userId=546&#x26;bookId=6754 <br>req.body: {userId: '546', bookId: '6754'}</blockquote>
Дайте відповідь тим же об’єктом JSON, як і раніше: `{name: 'firstname lastname'}`. Перевірте, чи ваша кінцева точка працює з використанням Html-форми, яку ми надали на головній сторінці додатку.
Порада: є кілька інших способів, крім GET та POST. І за загальноприйнятим правилом існує відповідність між дієсловом http та операцією, яку ви будете виконувати на сервері. Стандартна відповідність наступна:
POST (іноді PUT) - Створити новий ресурс, використовуючи інформацію, що надсилається з запитом,
GET - Прочитати існуючий ресурс не змінюючи його,
PUT або PATCH (іноді POST) - Оновити ресурс за допомогою відправлених даних,
DELETE => Видалити ресурс.
Є також кілька інших методів, які використовуються для узгодження зв'язку з сервером. За винятком GET, всі інші перераховані вище методи, можуть мати корисне навантаження (тобто дані на вміст запиту). Проміжне програмне забезпечення Body-parser також працює з цими методами.
# --hints--
Тест 1: Ваша кінцева точка API повинна співпадати з правильним іменем
```js
(getUserInput) =>
$.post(getUserInput('url') + '/name', { first: 'Mick', last: 'Jagger' }).then(
(data) => {
assert.equal(
data.name,
'Mick Jagger',
'Test 1: "POST /name" route does not behave as expected'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
Тест 2: Ваша кінцева точка API повинна співпадати з правильним іменем
```js
(getUserInput) =>
$.post(getUserInput('url') + '/name', {
first: 'Keith',
last: 'Richards'
}).then(
(data) => {
assert.equal(
data.name,
'Keith Richards',
'Test 2: "POST /name" route does not behave as expected'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,67 @@
---
id: 587d7fb2367417b2b2512bf6
title: Отримання вхідних даних параметра запиту від клієнта
challengeType: 2
forumTopicId: 301512
dashedName: get-query-parameter-input-from-the-client
---
# --description--
Інший поширений шлях отримати вхідні дані від клієнта - це кодування даних шляхом маршруту, використовуючи рядок запиту. Рядок запиту обмежений знаком питання (?), і включає в себе поле=пари значення. Кожна пара розділена амперсандами (&). Експрес може проаналізувати дані з рядка запиту і заповнити об’єкт `req.query`. Деякі символи, як-от відсотки (%), не можуть бути в URL-адресі і повинні бути закодовані в іншому форматі перед їх відправкою. Якщо ви використовуєте API з JavaScript, ви можете використовувати певні методи для кодування/декодування цих символів.
<blockquote>маршрут: '/library'<br>actual_request_URL: '/library?userId=546&#x26;bookId=6754' <br>req.query: {userId: '546', bookId: '6754'}</blockquote>
# --instructions--
Створіть кінцеву точку API, монтовану в `GET /name`. Відреагуйте JSON документом, використовуючи структуру `{ name: 'firstname lastname'}`. Перший і останній параметри імені повинні бути закодовані в рядку запиту, наприклад `?first=firstname&last=lastname`.
**Примітка:** У цьому завданні ви будете отримувати дані з POST-запиту, з того ж `/name` маршруту. За бажанням, можете використовувати `app.route(path).get(handler).post(handler)`. Цей синтаксис дозволяє об'єднувати різні обробники дієслів на тому ж шляху. Вам не знадобиться багато друкувати і ви матимете чистіший код.
# --hints--
Тест 1: Ваша кінцева точка API повинна співпадати з правильним іменем
```js
(getUserInput) =>
$.get(getUserInput('url') + '/name?first=Mick&last=Jagger').then(
(data) => {
assert.equal(
data.name,
'Mick Jagger',
'Test 1: "GET /name" route does not behave as expected'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
Тест 2: Ваша кінцева точка API повинна співпадати з правильним іменем
```js
(getUserInput) =>
$.get(getUserInput('url') + '/name?last=Richards&first=Keith').then(
(data) => {
assert.equal(
data.name,
'Keith Richards',
'Test 2: "GET /name" route does not behave as expected'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,65 @@
---
id: 587d7fb2367417b2b2512bf5
title: Отримати ввід параметру маршруту від Клієнта
challengeType: 2
forumTopicId: 301513
dashedName: get-route-parameter-input-from-the-client
---
# --description--
Створюючи API, ми повинні дозволити користувачам спілкуватися з нами, на тему того, що вони хочуть отримати від наших послуг. Наприклад, якщо клієнт запитує інформацію про користувача, збереженого в базі даних, їм потрібно мати шлях повідомити нам, який саме користувач їх цікавить. Одним із можливих способів досягнення цього результату є використання параметрів маршруту. Параметри маршруту мають назву сегментів URL, розділені косою рискою (/). Кожен сегмент фіксує значення частини URL, який відповідає його позиції. Збережені значення можна знайти в об’єкті `req.params`.
<blockquote>маршрут: '/user/:userId/book/:bookId'<br>actual_request_URL: '/user/546/book/6754' <br>req.params: {userId: '546', bookId: '6754'}</blockquote>
# --instructions--
Побудуйте ехо-сервер, вмонтований у маршрут `GET /:word/echo`. Відреагуйте JSON об'єктом, використовуючи структуру `{echo: word}`. Ви можете знайти слово, яке потрібно повторити у `req.params.word`. Ви можете перевірити свій маршрут з адресної стрічки вашого браузера, відвідавши деякі відповідні маршрути, наприклад `your-app-rootpath/freecodecamp/echo`.
# --hints--
Тест 1: Ваш ехо сервер повинен коректно повторити слова
```js
(getUserInput) =>
$.get(getUserInput('url') + '/eChOtEsT/echo').then(
(data) => {
assert.equal(
data.echo,
'eChOtEsT',
'Test 1: the echo server is not working as expected'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
Тест 2: Ваш ехо сервер повинен коректно повторити слова
```js
(getUserInput) =>
$.get(getUserInput('url') + '/ech0-t3st/echo').then(
(data) => {
assert.equal(
data.echo,
'ech0-t3st',
'Test 2: the echo server is not working as expected'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,57 @@
---
id: 587d7fb1367417b2b2512bf3
title: Реалізація підпрограмного забезпечення з журналу запитів кореневого рівня
challengeType: 2
forumTopicId: 301514
dashedName: implement-a-root-level-request-logger-middleware
---
# --description--
Раніше ви ознайомились з функцією підпрограмного забезпечення `express.static()`. А зараз саме час більш детально розглянути, що таке підпрограмне забезпечення. Функції підпрограмного забезпечення це функції, які мають 3 аргументи: об'єкт запиту, об'єкт відповіді й наступна функція циклу запиту-відповіді додатку. Ці функції виконують певний код, який може мати побічний ефект на додаток і зазвичай додає інформацію до об'єктів запиту й відповіді. Ще вони можуть закінчити цикл, надіславши відповідь, коли стикаються з певними умовами. Якщо після завершення вони не надсилають відповідь, вони починають виконувати наступну функцію в стеку. Це запускає третій аргумент `next()`.
Розглянемо наступний приклад:
```js
function(req, res, next) {
console.log("I'm a middleware...");
next();
}
```
Припустімо, ви підключили цю функцію до маршруту. Коли запит збігається з маршрутом, відображається рядок “Im a middleware…“, потім виконується наступна функція в стеку. У цій вправі ви створите підпрограмне забезпечення кореневого рівня. Як ви бачили в завданні 4, щоб встановити функцію підпрограмного забезпечення на кореневий рівень, ви можете скористатись методом `app.use(<mware-function>)`. У такому випадку ця функція виконається для всіх запитів, але ви також можете встановити конкретніші умови. Наприклад, якщо ви хочете виконати функцію лише для запитів POST, можна скористатись `app.post(<mware-function>)`. Аналогічні методи існують для всіх дієслів HTTP (GET, DELETE, PUT, …).
# --instructions--
Створіть простий журнал. Для кожного запиту в консолі має записуватись рядок в наступному форматі: `method path - ip`. Приклад виглядатиме так: `GET /json - ::ffff:127.0.0.1`. Зверніть увагу, що між `method` і `path` є пробіл, і що дефіс, який розділяє `path` і `ip`, виділено пробілами з обох сторін. Ви можете дізнатись метод запиту (дієслово http), відносний шлях маршруту й ip абонента з об'єкта запиту, скориставшись `req.method`, `req.path` і `req.ip`. Коли закінчите, не забудьте запустити `next()`, бо інакше ваш сервер заблокується назавжди. Обов'язково відкрийте “Журнал“ і подивіться, що відбувається, коли надходять певні запити.
**Note:** Вираз оцінює функції в тому ж порядку, в якому вони з'являються в коді. Це стосується й підпрограмного забезпечення. Якщо ви хочете, щоб це працювало для всіх маршрутів, встановіть його перед ними.
# --hints--
Підпрограмне забезпечення журналу кореневого рівня має бути активним
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/root-middleware-logger').then(
(data) => {
assert.isTrue(
data.passed,
'root-level logger is not working as expected'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,53 @@
---
id: 587d7fb0367417b2b2512bed
title: Знайомство з консоллю Node
challengeType: 2
forumTopicId: 301515
dashedName: meet-the-node-console
---
# --description--
Робота над цими завданнями передбачає написання коду одним із таких методів:
- Клонуйте [ цей репозиторій](https://github.com/freeCodeCamp/boilerplate-express/) та виконайте ці завдання локально.
- Використовуйте [ наш стартовий проєкт Replit](https://replit.com/github/freeCodeCamp/boilerplate-express) для виконання цих завдань.
- Для виконання проєкту скористуйтеся будь-яким конструктором сайтів на ваш розсуд. Впевніться, що ви маєте усі файли з нашого GitHub репозиторію.
Коли ви завершили, переконайтеся, що демоверсія вашого проєкту розміщена у відкритому доступі. Потім введіть URL-адресу проєкту у поле `Solution Link`.
Під час процесу розробки важливо перевіряти, що відбувається у коді.
Node - це всього лише середовище JavaScript. Як у клієнтському JavaScript, ви можете використовувати консоль для відображення корисної інформації для налагодження недоліків. На вашому локальному комп'ютері ви побачите вивід консолі в терміналі. На Replit термінал відкритий на правій панелі за замовчуванням.
Ми рекомендуємо тримати термінал відкритим під час роботи над цими завданнями. Читаючи вивід в терміналі, ви можете побачити будь-які помилки, що можуть виникнути.
# --instructions--
Модифікуйте `myApp.js` для виводу "Hello World" на консоль.
# --hints--
`"Hello World"` має бути в консолі
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/hello-console').then(
(data) => {
assert.isTrue(data.passed, '"Hello World" is not in the server console');
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,51 @@
---
id: 587d7fb0367417b2b2512bef
title: Робота з файлами у форматі HTML
challengeType: 2
forumTopicId: 301516
dashedName: serve-an-html-file
---
# --description--
Ви можете відповідати на запити файлом, використовуючи метод `res.sendFile(path)`. Ви можете додати його до обробника маршрутів `app.get('/', ...)`. Насправді цей метод встановлює відповідні заголовки, які вказуватимуть вашому браузеру, як обробляти файл, який потрібно надіслати, відповідно до його типу. Потім він (метод) файл буде прочитаний та надісланий. Для цього методу потрібен абсолютний шлях до файлу. Ми рекомендуємо вам використовувати глобальну змінну Node `__dirname` для обчислення шляху, як вказано нижче:
```js
absolutePath = __dirname + relativePath/file.ext
```
# --instructions--
Надішліть файл `/views/index.html` у відповідь на запит GET шляхом `/`. Якщо ви переглядаєте свій додаток у реальному часі, ви можете побачити великий заголовок HTML (і форму, яку ми будемо використовувати пізніше…), без стилю.
**Примітка:** Ви можете редагувати результат попереднього завдання або створити нове. Якщо ви створюєте нове рішення, майте на увазі, що Express оцінює маршрути зверху вниз і запускає обробник для першого збігу. Ви повинні прокоментувати попереднє рішення, інакше сервер буде продовжувати відповідати за допомогою рядку.
# --hints--
Ваш додаток повинен використовувати файл views/index.html
```js
(getUserInput) =>
$.get(getUserInput('url')).then(
(data) => {
assert.match(
data,
/<h1>.*<\/h1>/,
'Your app does not serve the expected HTML'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,47 @@
---
id: 587d7fb1367417b2b2512bf1
title: Передавання JSON за певним маршрутом
challengeType: 2
forumTopicId: 301517
dashedName: serve-json-on-a-specific-route
---
# --description--
У той час як HTML сервер передає HTML, API передає дані. <dfn>REST</dfn> (REpresentational State Transfer) API дозволяє обмінюватися даними простим способом, без необхідності, щоб клієнти знали будь-які деталі про сервер. Клієнту лише потрібно знати, де знаходиться ресурс (URL-адреса), та дію, яку він хоче на ньому виконати (дієслово). Дієслово GET використовується, коли ви отримуєте деяку інформацію, нічого не змінюючи. У наші часи JSON є найкращим форматом даних для переміщення інформації через інтернет. Простіше кажучи, JSON - це зручний спосіб представити об’єкт JavaScript у вигляді рядка, тому його можна легко передати.
Створімо простий API, створивши маршрут, який відповідає JSON на шляху `/json`. Ви можете це зробити, як зазвичай, за допомогою метода `app.get()`. Усередині обробника маршруту використовуйте метод `res.json()`, передаючи об'єкт як аргумент. Це метод закриває цикл запит-відповідь, повертаючи дані. По суті, він перетворює дійсний об’єкт JavaScript object у рядок, потім встановлює відповідні заголовки, щоб повідомити браузеру, що ви використовуєте JSON, і надсилає дані назад. Допустимий об'єкт має звичайну структуру `{key: data}`. `data` може бути числом, рядком, вкладеним об'єктом або масивом. `data` також може бути змінною або результатом виклику функції, в цьому випадку вони будуть оцінені перед перетворенням у рядок.
# --instructions--
Передайте об'єкт `{"message": "Hello json"}` у форматі JSON як відповідь на GET-запити до маршруту `/json`. Потім вказуючи вашому браузері `your-app-url/json`, ви повинні побачити повідомлення на екрані.
# --hints--
Кінцева точка `/json` має використовувати json-об'єкт `{"message": "Hello json"}`
```js
(getUserInput) =>
$.get(getUserInput('url') + '/json').then(
(data) => {
assert.equal(
data.message,
'Hello json',
"The '/json' endpoint does not serve the right data"
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,51 @@
---
id: 587d7fb0367417b2b2512bf0
title: Обслуговування статичного контенту
challengeType: 2
forumTopicId: 301518
dashedName: serve-static-assets
---
# --description--
Як правило, HTML-сервер має один чи кілька каталогів, доступних для користувача. Туди можна помістити статичний контент, необхідних для Вашого застосунку (таблиці стилів, скрипти, зображення).
В Express цю функцію можна підключити за допомогою проміжного програмного забезпечення `express.static(path)`, де параметр `path` - це абсолютний шлях до файлу з цим контентом.
Якщо Ви ніколи не чули про підпрограмне забезпечення, не хвилюйтеся. Пізніше ми детально його розглянемо. Загалом, підпрограмне забезпечення — це функції, що перехоплюють маршрутизатори, прикріплюючи певну інформацію. Підпрограмне забезпечення підключається за допомогою методу `app.use(path, middlewareFunction)`. Перший аргумент `path` є необов'язковим. Якщо цей аргумент не передається, підпрограмне забезпечення буде виконуватися для всіх запитів.
# --instructions--
Підключіть підпрограмне забезпечення `express.static()` до `/public` шляху з `app.use()`. Абсолютним шляхом до папки assets є `__dirname + /public`.
Тепер Ваш застосунок зможе обслуговувати CSS таблиці стилів. Зверніть увагу, що посилання на файл `/public/style.css` знаходиться у папці `/views/index.html` шаблону проєктування. Тепер Ваша головна сторінка виглядатиме краще!
# --hints--
Ваш застосунок обслуговуватиме файли з каталогу `/public` до шляху `/public`
```js
(getUserInput) =>
$.get(getUserInput('url') + '/public/style.css').then(
(data) => {
assert.match(
data,
/body\s*\{[^\}]*\}/,
'Your app does not serve static assets'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,57 @@
---
id: 587d7fb0367417b2b2512bee
title: Запуск робочого експрес-серверу
challengeType: 2
forumTopicId: 301519
dashedName: start-a-working-express-server
---
# --description--
У перших двох рядках файлу `myApp.js`, ви можете побачити, як легко створити об’єкт програми Express. Цей об’єкт має кілька методів, і ви багато із них вивчите за допомогою цих завдань. Одним із фундаментальних методів є `app.listen(port)`. Він повідомляє вашому серверу прослуховувати певний порт, переводячи його в робочий стан. З міркувань тестування нам потрібно, щоб програма працювала у фоновому режимі, тому ми для вас додали цей метод у файл `server.js`.
Давайте обслужимо наш перший рядок! В Express маршрути мають наступну структуру:`app.METHOD(PATH, HANDLER)`. METHOD - це метод http у нижньому регістрі. PATH - це відносний шлях на сервері (це може бути рядок або навіть регулярний вираз). HANDLER - це функція, яка викликає Express при узгодженні маршруту. Обробники приймають форму `function(req, res) {...}`, де req - об'єкт запиту, а res - об'єкт відповіді. Наприклад, обробник
```js
function(req, res) {
res.send('Response String');
}
```
буде обслуговувати рядок 'Рядок відповіді'.
# --instructions--
Використовуйте метод `app.get()`, щоб обслужити рядок "Hello Express" для GET запитів, які відповідають шляху `/` (root). Переконайтеся, що ваш код працює, переглянувши журнали, а потім перегляньте результати у попередньому перегляді, якщо ви використовуєте Replit.
**Примітка:** Весь код для цих уроків слід додати між кількома рядками коду, з яких ми починали.
# --hints--
Ваш додаток має обслуговувати рядок "Hello Express"
```js
(getUserInput) =>
$.get(getUserInput('url')).then(
(data) => {
assert.equal(
data,
'Hello Express',
'Your app does not serve the text "Hello Express"'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,63 @@
---
id: 587d7fb2367417b2b2512bf7
title: Обробка POST запитів за допомогою body-parser
challengeType: 2
forumTopicId: 301520
dashedName: use-body-parser-to-parse-post-requests
---
# --description--
Крім GET, є ще одне спільне дієслово HTTP, це POST. POST - це типовий метод для надсилання даних клієнта з HTML формами. У методі REST, POST використовується для відправки даних, щоб створити нові елементи в базі даних (новий користувач або новий допис). Ви не зобов'язані мати базу даних у цьому проєкті, але ви все-таки дізнаєтесь, як опрацьовувати запити POST.
У таких запитах дані не з'являються в URL, він прихований у тілі запиту. Тіло є частиною HTTP-запиту, а також називається корисним навантаженням. Незважаючи на те, що дані не видимі в URL, це не означає, що вони приватні. Щоб зрозуміти чому, подивіться на необроблений вміст HTTP-запиту POST:
```http
POST /path/subpath HTTP/1.0
From: john@example.com
User-Agent: someBrowser/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 20
name=John+Doe&age=25
```
Як ви можете побачити, тіло закодоване як рядок запиту. Це типовий формат, який використовується у HTML-формах. За допомогою Ajax, ви також можете використати JSON для обробки даних, що мають більш складну структуру. Існує також інший тип кодування: multipart/form-data. Цей файл використовується для завантаження бінарних файлів. У цій вправі ви будете використовувати тіло, кодоване посиланням. Щоб аналізувати дані, отримані з POST-запитів, необхідно встановити пакет `body-parser`. Цей пакет дозволяє використовувати низку підпрограмного забезпечення, який може декодувати дані в різних форматах.
# --instructions--
Встановіть модуль `body-parser` до вашого `package.json`. Тоді `require` його у верхній частині файлу. Збережіть його у змінній під назвою `bodyParser`. Проміжне програмне забезпечення, що має обробити Url-закодовані дані, повертається за допомогою `bodyParser.urlencoded({extended: false})`. Передайте функцію, повернуту попереднім викликом типу `app.use()`. Зазвичай підпрограмне забезпечення потрібно встановити перед маршрутами, які залежать від нього.
**Note:** `extended` це опція конфігурації, яка вказує `body-parser`, який парсинг необхідно використати. Коли `extended=false` він використовує класичне кодування `querystring` бібліотеки. Коли `extended=true` він використовує `qs` бібліотеку для парсингу.
При використанні `extended=false`, значення можуть бути тільки рядками або масивами. Об'єкт повертається, коли використання `querystring` не успадковується прототипно від `Object` JavaScript за замовчування, і означає, що функції `hasOwnProperty` та `toString` не будуть доступні. Розширена версія дозволяє підвищити гнучкість даних, але вона перевершує JSON.
# --hints--
Проміжне програмне забезпечення 'body-parser' має бути встановлено
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/add-body-parser').then(
(data) => {
assert.isAbove(
data.mountedAt,
0,
'"body-parser" is not mounted correctly'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,54 @@
---
id: 587d7fb1367417b2b2512bf2
title: Використання .env-файлу
challengeType: 2
forumTopicId: 301521
dashedName: use-the--env-file
---
# --description--
Файл `.env` - це прихований файл, який використовується для передачі змінних оточень у вашому додатку. Цей файл є таємним, ніхто, крім вас, не може отримати до нього доступ, та він може використовуватися для зберігання даних, які ви хочете залишити конфіденційними або прихованими. Наприклад, ви можете зберігати API-ключі з зовнішніх сервісів або URI вашої бази даних. Ви також можете використовувати його для зберігання параметрів конфігурації. Налаштовуючи параметри конфігурації, ви можете змінити поведінку вашої програми без необхідності переписувати код.
Змінні оточення доступні з додатку як `process.env.VAR_NAME`. Об'єкт `process.env` є глобальним об'єктом Node, а змінні передаються у вигляді рядків. Згідно з правилами, ідентифікатори змінних пишуться у верхньому регістрі, а слова поділяються знаком підкресленням. `.env` - це файл оболонки, тому вам не потрібно укладати імена або значення в лапки. Також важливо відзначити, що не має бути пробілу навколо знаку рівності, коли ви привласнюєте значення змінним, наприклад, `VAR_NAME=value`. Зазвичай ви ставите визначення кожної змінної в окремий рядок.
# --instructions--
Додаймо змінну оточення в якості параметра конфігурації.
Створіть файл `.env` в основі каталогу вашого проєкту та збережіть в ньому змінну `MESSAGE_STYLE=uppercase`.
Потім, в обробнику маршруту `/json` GET, який ви створили в останній задачі, перетворіть повідомлення об'єкта-відповіді у верхній регістр, якщо `process.env.MESSAGE_STYLE` дорівнює `uppercase`. Об'єкт відповіді має бути `{"message": "Hello json"}` або `{"message": "HELLO JSON"}`, в залежності від значення `MESSAGE_STYLE`.
**Примітка:** Якщо ви використовуєте Replit, ви не можете створити файл `.env`. Замість цього використовуйте вбудовану вкладку <dfn>SECRETS</dfn> для додавання змінної.
При локальній роботі вам знадобиться пакет `dotenv`. Він завантажує змінні середовища з вашого `.env` файлу в `process.env`. Встановіть його з `npm install dotenv`. Тоді, зверху вашого `myApp.js` файлу, оберіть імпортувати та завантажити змінні з `require('dotenv').config()`.
# --hints--
Відповідь кінцевої точки `/json` має змінюватися відповідно до змінної оточення `MESSAGE_STYLE`
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/use-env-vars').then(
(data) => {
assert.isTrue(
data.passed,
'The response of "/json" does not change according to MESSAGE_STYLE'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,52 @@
---
id: 587d7fb3367417b2b2512bfc
title: Додати опис до вашого package.json
challengeType: 2
forumTopicId: 301522
dashedName: add-a-description-to-your-package-json
---
# --description--
Наступна частина хорошого файлу package.json - це `description` поля, якому належить короткий, але інформативний опис вашого проєкту.
Якщо ви плануєте колись опублікувати пакет на npm, то він є рядком, що повинен продати вашу ідею користувачам, якщо вони вирішуватимуть чи встановлювати ваш пакет чи ні. Однак, це не єдиний випадок використання для опису, це чудовий спосіб узагальнити те, що робить проект. Це також важливо в будь-якому проєкті Node.js, щоб допомогти іншим розробникам, майбутнім творцям чи навіть самому собі швидко зрозуміти проєкт.
Незалежно від того, що ви плануєте для свого проєкту, опис є безумовно рекомендованим. Ось приклад:
```json
"description": "A project that does something awesome",
```
# --instructions--
Додайте `description` до файлу package.json вашого проєкту.
**Примітка:** Пам'ятайте: використовувати подвійні лапки для полів (") і коми (,) для розділення полів.
# --hints--
package.json повинен мати дійсний ключ "опис"
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/package.json').then(
(data) => {
var packJson = JSON.parse(data);
assert(packJson.description, '"description" is missing');
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,48 @@
---
id: 587d7fb4367417b2b2512bfe
title: Додайте ліцензію до вашого package.json
challengeType: 2
forumTopicId: 301523
dashedName: add-a-license-to-your-package-json
---
# --description--
Поле `license` дозволяє інформувати користувачів, які дії вони можуть виконувати з вашим проектом.
Деякі загальні ліцензії для проектів з відкритим кодом містять MIT та BSD. Ліцензійна інформація не являється обов'язковою і закони про авторські права в більшості країн дадуть вам право власності на те, що ви створюєте за замовчуванням. Проте завжди рекомендується чітко вказувати дії, які користувачам дозволено і не дозволено виконувати. Нижче наведено приклад, як виглядає поле ліцензії:
```json
"license": "MIT",
```
# --instructions--
Заповніть поле `license` для файлу package.json вашого проєкту, як вважаєте за потрібне.
# --hints--
package.json повинен містити допустимий ключ ліцензії
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/package.json').then(
(data) => {
var packJson = JSON.parse(data);
assert(packJson.license, '"license" is missing');
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,46 @@
---
id: 587d7fb4367417b2b2512bff
title: Додати опис до вашого package.json
challengeType: 2
forumTopicId: 301525
dashedName: add-a-version-to-your-package-json
---
# --description--
`version` є одним з необхідних полів вашого package.json файлу. Це поле описує поточну версію вашого проекту. Ось приклад:
```json
"version": "1.2.0",
```
# --instructions--
Додайте `version` до файлу package.json вашого проєкту.
# --hints--
package.json повинен мати допустимий ключ "версія"
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/package.json').then(
(data) => {
var packJson = JSON.parse(data);
assert(packJson.version, '"version" is missing');
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,84 @@
---
id: 587d7fb4367417b2b2512bfd
title: Додати ключові слова до вашого package.json
challengeType: 2
forumTopicId: 301526
dashedName: add-keywords-to-your-package-json
---
# --description--
Значення `keywords` - це місце, де ви можете описати ваш проєкт, використовуючи відповідні ключові слова. Ось приклад:
```json
"keywords": [ "descriptive", "related", "words" ],
```
Як бачите, це поле структуровано як масив подвійних цитованих рядків.
# --instructions--
Додайте масив відповідних рядків у `keywords` у файлі package.json вашого проєкту.
Одне з ключових слів має бути "freecodecamp".
# --hints--
package.json повинен мати допустимий ключ "ключові слова"
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/package.json').then(
(data) => {
var packJson = JSON.parse(data);
assert(packJson.keywords, '"keywords" is missing');
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
Поле "ключові слова" має бути масивом
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/package.json').then(
(data) => {
var packJson = JSON.parse(data);
assert.isArray(packJson.keywords, '"keywords" is not an array');
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
"ключові слова" мають включати "freecodecamp"
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/package.json').then(
(data) => {
var packJson = JSON.parse(data);
assert.include(
packJson.keywords,
'freecodecamp',
'"keywords" does not include "freecodecamp"'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,77 @@
---
id: 587d7fb4367417b2b2512c00
title: Розпакуйте ваш проєкт із зовнішніми пакетами через npm
challengeType: 2
forumTopicId: 301527
dashedName: expand-your-project-with-external-packages-from-npm
---
# --description--
Однією з найважливіших підстав для використання менеджера пакетів є їх потужне управління залежностями. Npm автоматично встановлює всі необхідні елементи під час встановлення проекту на новому комп'ютер і позбавляє вас необхідності встановлювати все кожного разу вручну. Але як npm може отримати інформацію, чого потребує ваш проєкт? Знайдіть розділ `dependencies` у вашому файлі package.json.
У цьому розділі зберігаються пакети, необхідні для вашого проєкту, в наступному форматі:
```json
"dependencies": {
"package-name": "version",
"express": "4.14.0"
}
```
# --instructions--
Додайте версію пакету "2.14.0" у поле `dependencies` вашого файлу package.json.
**Примітка:** Момент - це зручна бібліотека для дій з часом і днями.
# --hints--
"взаємозв'язки" повинні включати "момент"
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/package.json').then(
(data) => {
var packJson = JSON.parse(data);
assert.property(
packJson.dependencies,
'moment',
'"dependencies" does not include "moment"'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
версія "момент" повинна бути "2.14.0"
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/package.json').then(
(data) => {
var packJson = JSON.parse(data);
assert.match(
packJson.dependencies.moment,
/^[\^\~]?2\.14\.0/,
'Wrong version of "moment" installed. It should be 2.14.0'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,60 @@
---
id: 587d7fb3367417b2b2512bfb
title: 'Як використовувати package.json, ядро будь-якого Node.js проєкту або npm пакету'
challengeType: 2
forumTopicId: 301528
dashedName: how-to-use-package-json-the-core-of-any-node-js-project-or-npm-package
---
# --description--
Робота над цими завданнями включатиме написання вашого коду з використанням одного з наступних методів:
- Створіть [цей GitHub репозитарій](https://github.com/freeCodeCamp/boilerplate-npm/) і завершіть локально ці завдання.
- Використовуйте [ наш стартовий проєкт Replit](https://replit.com/github/freeCodeCamp/boilerplate-npm) для виконання цих завдань.
- Для завершення проєкту користуйтеся вибраним вами конструктором сайту. Переконайтеся, що ви зберегли всі файли з нашого репозиторію GitHub.
Коли ви завершили, переконайтеся, що ця демоверсія вашого проєкту розміщена у відкритому доступі. Потім введіть URL-адресу в поле `Solution Link`. За бажанням також можете ввести посилання на вихідний код вашого проєкту в полі `GitHub Link`.
Файл `package.json` є центром будь-якого проєкту Node.js або npm пакету. Він зберігає інформацію про ваш проєкт, схожий на те, як &lt;заголовок> секція HTML-документа описує вміст веб-сторінки. Він складається з одного об'єкту JSON, де інформація зберігається у парах ключ-значення. Є лише два обов'язкові поля; "ім'я" та "версія", але дуже добре практикуватися надавати додаткову інформацію про ваш проєкт, який може бути корисний майбутнім користувачам або керівникам.
Якщо подивитесь на дерево файлів вашого проєкту, то знайдете файл package.json на верхньому рівні дерева. Це файл, який ви будете покращуватись у наступних парах завдань.
Одне з найпоширеніших відомостей у цьому файлі є полем `author`. Він вказує на те, хто створив проект, і може складатися з рядка або об'єкта з контактом або іншими деталями. Об’єкт рекомендований для більших проєктів, але простий рядок, як наступний приклад, працюватиме для цього проєкту.
```json
"author": "Jane Doe",
```
# --instructions--
Додайте ваше ім'я як `author` проєкту у файл package.json.
**Примітка:** Пам'ятайте, що ви пишете JSON, бо всі назви полів повинні використовувати подвійні лапки (") і бути розділені комою (,).
# --hints--
package.json повинен мати допустимий ключ "автор"
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/package.json').then(
(data) => {
var packJson = JSON.parse(data);
assert(packJson.author, '"author" is missing');
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,73 @@
---
id: 587d7fb5367417b2b2512c01
title: Керування залежностями npm шляхом розуміння семантичної версії
challengeType: 2
forumTopicId: 301529
dashedName: manage-npm-dependencies-by-understanding-semantic-versioning
---
# --description--
Версії `Versions` пакетів npm у розділі залежностей вашого файлу package.json відповідають тому, що називається семантичним керуванням версій (SemVer), галузевим стандартом керування версій програмного забезпечення, спрямованим на спрощення керування залежностями. Бібліотеки, фреймворки чи інші інструменти, опубліковані на npm, повинні використовувати SemVer, щоб чітко повідомляти, що може змінитись у проєктах, якщо вони оновляться.
Знання SemVer може бути корисним при розробці програмного забезпечення, яке використовує зовнішні залежності (що ви майже завжди і робите). Одного дня ваше розуміння цих цифр захистить вас від випадкового внесення кардинальних змін у ваш проєкт без розуміння, чому речі, які працювали вчора, раптово не працюють сьогодні. Ось як працює керування семантичними версіями, згідно з інформацією на офіційному веб-сайті:
```json
"package": "MAJOR.MINOR.PATCH"
```
ОСНОВНА версія має збільшуватися, коли ви вносите несумісні зміни в API. ДРУГОРЯДНА версія має збільшуватися, коли ви додаєте функціональні можливості у зворотно сумісному порядку. Версія PATCH повинна збільшуватись, коли ви робите виправлення помилок зі зворотною сумісністю. Це означає, що ПАТЧІ - це виправлення помилок, а ДРУГОРЯДНІ версії додають нові функції, але жодна з них не порушує те, що функціонувало раніше. Нарешті, ОСНОВНІ версії додають зміни, не сумісні з попередніми версіями.
# --instructions--
У розділі залежностей вашого файлу package.json, змініть версію моменту `version`, щоб вона відповідала ОСНОВНІЙ версії 2, ДРУГОРЯДНІЙ версії 10 та версії ПАТЧА 2
# --hints--
"dependencies" повинні містити "moment"
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/package.json').then(
(data) => {
var packJson = JSON.parse(data);
assert.property(
packJson.dependencies,
'moment',
'"dependencies" does not include "moment"'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
версія "moment" повинна бути "2.10.2"
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/package.json').then(
(data) => {
var packJson = JSON.parse(data);
assert.equal(
packJson.dependencies.moment,
'2.10.2',
'Wrong version of "moment". It should be 2.10.2'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,52 @@
---
id: 587d7fb5367417b2b2512c04
title: Видалення пакету із залежностей
challengeType: 2
forumTopicId: 301530
dashedName: remove-a-package-from-your-dependencies
---
# --description--
Ви вже протестували кілька способів, як можна керувати залежностями Вашого проєкту за допомогою розділу dependencies файлу package.json. Ви також додали зовнішні пакети до Вашого файлу і навіть задали npm бажані версії за допомогою спеціальних символів: тильда та карет.
Але що робити, якщо Ви бажаєте видалити більше не потрібний зовнішній пакет? Певно, Ви вже здогадалися, треба просто видалити відповідну пару "ключ-значення" цього пакету із залежностей.
Видалення інших полів package.json також здійснюється цим методом
# --instructions--
Видаліть пакет moment із залежностей.
**Примітка:** Переконайтесь, що після видалення пакету у Вас вказано правильну кількість ком.
# --hints--
"dependencies" не має містити "moment"
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/package.json').then(
(data) => {
var packJson = JSON.parse(data);
assert.notProperty(
packJson.dependencies,
'moment',
'"dependencies" still includes "moment"'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,75 @@
---
id: 587d7fb5367417b2b2512c03
title: Використовуйте Caret-Character для використання останньої мінорної версії залежностей
challengeType: 2
forumTopicId: 301531
dashedName: use-the-caret-character-to-use-the-latest-minor-version-of-a-dependency
---
# --description--
Подібно символу тильда, про який ми дізналися в останньому завданні, npm дозволяє встановити найновіший ПАТЧ для залежності, символ карет (`^`) дозволяє npm також встановлювати майбутні оновлення. Відмінність полягає в тому, що символ карет дозволяє і ДРУГОРЯДНІ оновлення, і ПАТЧІ.
Ваша поточна версія моменту повинна бути "~ 2.10.2", що дозволяє npm встановлювати останню версію 2.10.x. Якби ви використовували символ (^) як префікс версії замість цього, npm було б дозволено оновлюватись до будь-якої версії 2.xx.
```json
"package": "^1.3.8"
```
Це б дозволило оновлювати будь-яку версію 1.xx пакета.
# --instructions--
Використовуйте символ (`^`), щоб встановити префікс версії моменту у ваших залежностях і дозволити npm оновити його до будь-якого оновлення ДРУГОРЯДНОЇ версії.
**Примітка:** Номери версій не слід змінювати.
# --hints--
"dependencies" повинні містити "moment"
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/package.json').then(
(data) => {
var packJson = JSON.parse(data);
assert.property(
packJson.dependencies,
'moment',
'"dependencies" does not include "moment"'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
версія "moment" повинна бути "^2.x.x"
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/package.json').then(
(data) => {
var packJson = JSON.parse(data);
assert.match(
packJson.dependencies.moment,
/^\^2\./,
'Wrong version of "moment". It should be ^2.10.2'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,75 @@
---
id: 587d7fb5367417b2b2512c02
title: Використовуйте символ тильди (~), щоб завжди мати доступ до останньої версії залежностей Patch
challengeType: 2
forumTopicId: 301532
dashedName: use-the-tilde-character-to-always-use-the-latest-patch-version-of-a-dependency
---
# --description--
В останньому завданні ви сказали npm включати тільки конкретну версію пакету. Це корисний спосіб призупинити блокування ваших залежностей, якщо вам потрібно переконатися, що різні частини вашого проєкту залишаються сумісними одна з одною. Але в більшості випадків ви не захочете пропустити виправлення помилок, оскільки вони часто містять важливі патчі безпеки і (як можна сподіватися) не порушують при цьому речі.
Щоб npm залежність оновилася до останньої версії PATCH, можна встановити префікс версії залежностей з символом тильди (`~`). Ось приклад оновлення для будь-якої версії 1.3.x.
```json
"package": "~1.3.8"
```
# --instructions--
У файлі package.json вашим поточним правилом для моменту оновлення npm є використання конкретної версії (2.10.2). Але тепер ви захочете останню версію 2.10.x.
Використовуйте символ тильди (`~`), щоб встановити префікс версії моменту у ваших залежностях і дозволити npm оновити його до будь-якого оновлення версії PATCH.
**Примітка:** Номери версій не слід змінювати.
# --hints--
"dependencies" повинні містити "moment"
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/package.json').then(
(data) => {
var packJson = JSON.parse(data);
assert.property(
packJson.dependencies,
'moment',
'"dependencies" does not include "moment"'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
версія "moment" повинна бути "~2.10.2"
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/package.json').then(
(data) => {
var packJson = JSON.parse(data);
assert.match(
packJson.dependencies.moment,
/^\~2\.10\.2/,
'Wrong version of "moment". It should be ~2.10.2'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,76 @@
---
id: 587d7fb9367417b2b2512c12
title: Пошукові ланцюгові помічники запитів для звуження результатів пошуку
challengeType: 2
forumTopicId: 301533
dashedName: chain-search-query-helpers-to-narrow-search-results
---
# --description--
Якщо ви не передаєте зворотній виклик як останній аргумент до `Model.find()` (або інших пошукових методів), запит не буде виконуватися. Ви можете зберегти запит в змінній для подальшого використання. Цей тип об'єкту дозволяє створювати запит за допомогою ланцюгового синтаксису. Фактичний пошук db виконується, коли ви остаточно з'єднали метод `.exec()`. Ви завжди повинні передати зворотній виклик цьому останньому методу. Існує багато помічників для запитів, тут ми використовуємо найбільш поширені.
# --instructions--
Змініть функцію `queryChain`, щоб знайти людей, що люблять їжу, вказану змінною `foodToSearch`. Посортуйте їх за `name`, знизьте кількість результатів до двох документів та приховайте їхній вік. Об'єднайте `.find()`, `.sort()`, `.limit()`, `.select()`, and then `.exec()`. Передайте зворотній виклик `done(err, data)` до `exec()`.
# --hints--
Використання ланцюгових помічників для запитів має бути успішним
```js
(getUserInput) =>
$.ajax({
url: getUserInput('url') + '/_api/query-tools',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify([
{ name: 'Pablo', age: 26, favoriteFoods: ['burrito', 'hot-dog'] },
{ name: 'Bob', age: 23, favoriteFoods: ['pizza', 'nachos'] },
{ name: 'Ashley', age: 32, favoriteFoods: ['steak', 'burrito'] },
{ name: 'Mario', age: 51, favoriteFoods: ['burrito', 'prosciutto'] }
])
}).then(
(data) => {
assert.isArray(data, 'the response should be an Array');
assert.equal(
data.length,
2,
'the data array length is not what expected'
);
assert.notProperty(
data[0],
'age',
'The returned first item has too many properties'
);
assert.equal(
data[0].name,
'Ashley',
'The returned first item name is not what expected'
);
assert.notProperty(
data[1],
'age',
'The returned second item has too many properties'
);
assert.equal(
data[1].name,
'Mario',
'The returned second item name is not what expected'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,88 @@
---
id: 587d7fb6367417b2b2512c07
title: Створити модель
challengeType: 2
forumTopicId: 301535
dashedName: create-a-model
---
# --description--
**C**RUD Частина І - Створення
Перш за все, вам необхідна схема. Кожна схема пов'язана з колекцією MongoDB. Вона визначає форму документів у цій колекції. Схеми - це блоки, які складають моделі. Вони можуть бути вкладеними для того, щоб створити складні моделі, але в цьому випадку ми не будемо все ускладнювати. Модель дозволяє створювати екземпляри ваших об’єктів, які називаються документами.
Replit - це справжній сервер, і на реальних серверах взаємодії з базою даних відбуваються у функціях обробника. Ці функції виконуються, коли трапляється якась подія (наприклад, хтось попадає на кінцеву точку вашого API). Ми будемо дотримуватись того самого підходу в цих вправах. Функція `done()` - це зворотний виклик, який повідомляє нас про те, що ми можемо продовжувати після завершення асинхронної операції, такої як вставка, оновлення чи видалення. Він відповідає конвенції Node і повинен називатися `done(null, data)` on success, or `done(err)` в разі помилки.
Увага! Помилки можуть виникнути при взаємодії з віддаленими службами!
```js
/* Example */
const someFunc = function(done) {
//... do something (risky) ...
if (error) return done(error);
done(null, result);
};
```
# --instructions--
Створіть особисту схему під назвою `personSchema`, яка має такий прототип:
```markup
- Person Prototype -
--------------------
name : string [required]
age : number
favoriteFoods : array of strings (*)
```
Використовуйте основні типи схем Mongoose. Якщо ви хочете, то також можете додати більше полів, використовувати прості валідатори, такі як обов’язкові або унікальні, і встановити значення за замовчуванням. Перегляньте [Mongoose docs](http://mongoosejs.com/docs/guide.html).
Тепер створіть модель під назвою `Person` from the `personSchema`.
# --hints--
Створення екземпляру зі схеми Mongoose повинно пройти успішно
```js
(getUserInput) =>
$.post(getUserInput('url') + '/_api/mongoose-model', {
name: 'Mike',
age: 28,
favoriteFoods: ['pizza', 'cheese']
}).then(
(data) => {
assert.equal(data.name, 'Mike', '"model.name" is not what expected');
assert.equal(data.age, '28', '"model.age" is not what expected');
assert.isArray(
data.favoriteFoods,
'"model.favoriteFoods" is not an Array'
);
assert.include(
data.favoriteFoods,
'pizza',
'"model.favoriteFoods" does not include the expected items'
);
assert.include(
data.favoriteFoods,
'cheese',
'"model.favoriteFoods" does not include the expected items'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,56 @@
---
id: 587d7fb6367417b2b2512c09
title: Створіть та збережіть запис моделі
challengeType: 2
forumTopicId: 301536
dashedName: create-and-save-a-record-of-a-model
---
# --description--
У цьому завданні вам буде потрібно створити та зберегти запис моделі.
# --instructions--
У межах функції `createAndSavePerson`, створіть екземпляр документа, використовуючи модель конструктора `Person`, який ви побудували раніше. Перенесіть до конструктора об'єкт, який має поля `name`, `age`, і `favoriteFoods`. Їх типи повинні збігатися з тими, що у `personSchema`. Опісля викличте метод `document.save()` у зворотньому екземплярі документа. Додайте до нього функцію зворотнього виклику використовуючи метод вузла. Це - загальний шаблон; всі такі CRUD-методи потребують функції зворотнього зв'язку в якості останнього аргументу.
```js
/* Example */
// ...
person.save(function(err, data) {
// ...do your stuff here...
});
```
# --hints--
Створення та збереження елемента БД має пройти успішно
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/create-and-save-person').then(
(data) => {
assert.isString(data.name, '"item.name" should be a String');
assert.isNumber(data.age, '28', '"item.age" should be a Number');
assert.isArray(
data.favoriteFoods,
'"item.favoriteFoods" should be an Array'
);
assert.equal(data.__v, 0, 'The db item should be not previously edited');
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,68 @@
---
id: 587d7fb7367417b2b2512c0a
title: Створюємо багато записів використовуючи model.create()
challengeType: 2
forumTopicId: 301537
dashedName: create-many-records-with-model-create
---
# --description--
Часом потрібно створити багато екземплярів ваших моделей, наприклад, під час заповнення бази даних початковими даними. `Model.create()` приймає масив об'єктів, таких як `[{name: 'John', ...}, {...}, ...]` в якості першого аргумента, і зберігає їх всіх до Бд.
# --instructions--
Перейменуйте функцію `createManyPeople` щоб створити багато людей, використовуючи `Model.create()` з аргументом `arrayOfPeople`.
**Note** Ви можете повторно використати модель встановлену в попередній вправі.
# --hints--
Створення одразу багатьох елементів БД має пройти успішно
```js
(getUserInput) =>
$.ajax({
url: getUserInput('url') + '/_api/create-many-people',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify([
{ name: 'John', age: 24, favoriteFoods: ['pizza', 'salad'] },
{ name: 'Mary', age: 21, favoriteFoods: ['onions', 'chicken'] }
])
}).then(
(data) => {
assert.isArray(data, 'the response should be an array');
assert.equal(
data.length,
2,
'the response does not contain the expected number of items'
);
assert.equal(data[0].name, 'John', 'The first item is not correct');
assert.equal(
data[0].__v,
0,
'The first item should be not previously edited'
);
assert.equal(data[1].name, 'Mary', 'The second item is not correct');
assert.equal(
data[1].__v,
0,
'The second item should be not previously edited'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,57 @@
---
id: 587d7fb8367417b2b2512c11
title: Видалення багатьох елементів за допомогою model.remove()
challengeType: 2
forumTopicId: 301538
dashedName: delete-many-documents-with-model-remove
---
# --description--
`Model.remove()` корисний для видалення всіх документів, що відповідають заданим критеріям.
# --instructions--
Змініть функцію `removeManyPeople`, щоб видалити всіх людей, ім'я яких знаходиться в змінній `nameToRemove`, за допомогою `Model.remove()`. Передайте його до документа запиту з набором полів `name`, і зворотнім викликом.
**Примітка:** `Model.remove()` не повертає видалений документ, а об'єкт JSON, що містить результат операції та кількість елементів, що постраждали. Не забудьте передати його до зворотного виклику `done()`, оскільки він буде використовуватися у тестах.
# --hints--
Видалення одразу декількох елементів має пройти успішно
```js
(getUserInput) =>
$.ajax({
url: getUserInput('url') + '/_api/remove-many-people',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify([
{ name: 'Mary', age: 16, favoriteFoods: ['lollipop'] },
{ name: 'Mary', age: 21, favoriteFoods: ['steak'] }
])
}).then(
(data) => {
assert.isTrue(!!data.ok, 'The mongo stats are not what expected');
assert.equal(
data.n,
2,
'The number of items affected is not what expected'
);
assert.equal(data.count, 0, 'the db items count is not what expected');
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,53 @@
---
id: 587d7fb8367417b2b2512c10
title: Видалення одного документа за допомогою model.findByIdAndRemove
challengeType: 2
forumTopicId: 301539
dashedName: delete-one-document-using-model-findbyidandremove
---
# --description--
`findByIdAndRemove` і `findOneAndRemove` схожі до попередніх методів оновлення. Вони передають вилучений документ до db. Використовуйте аргумент функції `personId` як ключ пошуку.
# --instructions--
Змініть функцію `removeById`, щоб видалити одну особу на основі її `_id`. Потрібно використовувати один із методів `findByIdAndRemove()` or `findOneAndRemove()`.
# --hints--
Видалення елемента має бути успішним
```js
(getUserInput) =>
$.post(getUserInput('url') + '/_api/remove-one-person', {
name: 'Jason Bourne',
age: 36,
favoriteFoods: ['apples']
}).then(
(data) => {
assert.equal(data.name, 'Jason Bourne', 'item.name is not what expected');
assert.equal(data.age, 36, 'item.age is not what expected');
assert.deepEqual(
data.favoriteFoods,
['apples'],
'item.favoriteFoods is not what expected'
);
assert.equal(data.__v, 0);
assert.equal(data.count, 0, 'the db items count is not what expected');
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,85 @@
---
id: 587d7fb6367417b2b2512c06
title: Встановлення і налаштування Mongoose
challengeType: 2
forumTopicId: 301540
dashedName: install-and-set-up-mongoose
---
# --description--
Робота над цими завданнями включатиме написання вашого коду з використанням одного з наступних методів:
- Створіть [цей GitHub репозитарій](https://github.com/freeCodeCamp/boilerplate-mongomongoose/) і локально завершіть ці завдання.
- Використовуйте [наш стартовий проєкт Replit](https://replit.com/github/freeCodeCamp/boilerplate-mongomongoose) для виконання цих завдань.
- Використовуйте конструктор сайту на власний розсуд, щоб завершити проєкт. Перевірте, що ви зберегли усі файли з нашого репозиторію GitHub.
По завершенню, переконайтеся, що працююча демоверсія вашого проєкту розміщена у відкритому доступі. Потім введіть URL - адресу проєкту в поле `Solution Link` field.
У цьому завданні, створіть базу даних MongoDB Atlas та імпортуйте необхідні пакети для підключення до неї.
Дотримуйтесь <a href='https://www.freecodecamp.org/news/get-started-with-mongodb-atlas/' rel='noopener noreferrer' target='_blank'>цих вказівок</a>, щоб налаштувати розміщену базу даних на MongoDB Atlas.
# --instructions--
Додайте `mongodb@~3.6.0` і `mongoose@~5.4.0` до `package.json` проєкту. Потім, необхідно встановити mongoose як `mongoose` у `myApp.js`. Створіть файл `.env` і додайте до нього змінну `MONGO_URI`. Його значенням має бути ваш URI бази даних MongoDB Atlas. Обов'язково помістіть URI в одинарні чи подвійні лапки, і пам'ятайте, що ви не можете використовувати пробіли навколо `=` у змінних середовища. Наприклад, `MONGO_URI='VALUE'`. Після завершення, під'єднайтесь до бази даних, використовуючи наступний синтаксис:
```js
mongoose.connect(<Your URI>, { useNewUrlParser: true, useUnifiedTopology: true });
```
# --hints--
Залежність "mongodb" слід вказати в package.json
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/file/package.json').then(
(data) => {
var packJson = JSON.parse(data);
assert.property(packJson.dependencies, 'mongodb');
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
Залежність "mongoose" слід вказати в package.json
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/file/package.json').then(
(data) => {
var packJson = JSON.parse(data);
assert.property(packJson.dependencies, 'mongoose');
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
"mongoose" слід підключити до бази даних
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/is-mongoose-ok').then(
(data) => {
assert.isTrue(data.isMongooseOk, 'mongoose is not connected');
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,54 @@
---
id: 587d7fb8367417b2b2512c0e
title: 'Виконайте класичні оновлення здійснюючи пошук, редагування і збереження'
challengeType: 2
forumTopicId: 301541
dashedName: perform-classic-updates-by-running-find-edit-then-save
---
# --description--
У старі добрі часи це було те, що вам потрібно було робити, якщо ви хотіли відредагувати документ і мати можливість якимсь чином ним користуватися (наприклад, надіслати його назад у відповіді сервера). Mongoose має спеціальний метод оновлення: `Model.update()`. Він прив'язаний до драйвера з низьким рівнем монго. Він може редагувати багато документів, що відповідають певним критеріям, але не надсилає оновлений документ, а лише повідомлення про статус. Крім того, це ускладнює перевірку моделі, оскільки просто викликає безпосередньо драйвер mongo.
# --instructions--
Змініть функцію `findEditThenSave`, щоб знайти особу за `_id` (використовуйте будь - який із вищезгаданих методів) з параметром `personId` як ключ пошуку. Додайте `"hamburger"` до списку `favoriteFoods` людини (можна використовувати `Array.push()`). Потім всередині зворотного виклику пошуку - `save()` оновлений`Person`.
**Примітка:** Це може бути складно, якщо у вашій схемі, ви визначили `favoriteFoods` як масив, не вказуючи тип (тобто `[String]`). В такому випадку `favoriteFoods` за замовчуванням приймає змішаний тип, і вам потрібно вручну позначити його як відредагований за допомогою `document.markModified('edited-field')`. Перегляньте [Mongoose documentation](https://mongoosejs.com/docs/schematypes.html#Mixed)
# --hints--
Пошук-редагування-оновлення елемента має бути успішним
```js
(getUserInput) =>
$.post(getUserInput('url') + '/_api/find-edit-save', {
name: 'Poldo',
age: 40,
favoriteFoods: ['spaghetti']
}).then(
(data) => {
assert.equal(data.name, 'Poldo', 'item.name is not what is expected');
assert.equal(data.age, 40, 'item.age is not what expected');
assert.deepEqual(
data.favoriteFoods,
['spaghetti', 'hamburger'],
'item.favoriteFoods is not what expected'
);
assert.equal(data.__v, 1, 'The item should be previously edited');
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,58 @@
---
id: 587d7fb8367417b2b2512c0f
title: Виконання нових оновлень для документа за допомогою model.findOneAndUpdate()
challengeType: 2
forumTopicId: 301542
dashedName: perform-new-updates-on-a-document-using-model-findoneandupdate
---
# --description--
Останні версії Mongoose мають методи спрощення оновлення документів. Деякі більш розширені функції (наприклад, хуки до/після, перевірка) поводяться з таким підходом по-різному, тому класичний метод все ще корисний у багатьох ситуаціях. `findByIdAndUpdate()` можна використовувати під час пошуку за id.
# --instructions--
Змініть функцію `findAndUpdate`, щоб знайти особу за `Name` і встановити вік особи за `20`. Використовуйте параметр функції `personName` як ключ пошуку.
**Примітка:** Ви повинні повернути оновлений документ. Для цього необхідно передати опції документа `{ new: true }` як третій аргумент `findOneAndUpdate()`. За замовчуванням ці методи повертають немодифікований об'єкт.
# --hints--
пошук OneAndUpdate елемента має бути успішним
```js
(getUserInput) =>
$.post(getUserInput('url') + '/_api/find-one-update', {
name: 'Dorian Gray',
age: 35,
favoriteFoods: ['unknown']
}).then(
(data) => {
assert.equal(data.name, 'Dorian Gray', 'item.name is not what expected');
assert.equal(data.age, 20, 'item.age is not what expected');
assert.deepEqual(
data.favoriteFoods,
['unknown'],
'item.favoriteFoods is not what expected'
);
assert.equal(
data.__v,
0,
'findOneAndUpdate does not increment version by design!'
);
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,53 @@
---
id: 587d7fb7367417b2b2512c0b
title: Використання model.find() для пошуку вашої бази даних
challengeType: 2
forumTopicId: 301543
dashedName: use-model-find-to-search-your-database
---
# --description--
У найпростішому використанні, `Model.find()` приймає документ - запит ( об'єкт JSON) як перший аргумент, а потім - зворотній виклик. Це повертає масив збігів. Це підтримує надзвичайно широкий спектр варіантів пошуку. Читайте більше в документації.
# --instructions--
Змініть функцію `findPeopleByName`, щоб знайти всіх людей з даним іменем, використовуючи <code>Model.find() -\> [Person]</code>
Використовуйте аргумент функції `personName` як ключ пошуку.
# --hints--
Пошук усіх елементів, що відповідають критеріям, мають бути успішними
```js
(getUserInput) =>
$.post(getUserInput('url') + '/_api/find-all-by-name', {
name: 'r@nd0mN4m3',
age: 24,
favoriteFoods: ['pizza']
}).then(
(data) => {
assert.isArray(data, 'the response should be an Array');
assert.equal(
data[0].name,
'r@nd0mN4m3',
'item.name is not what expected'
);
assert.equal(data[0].__v, 0, 'The item should be not previously edited');
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,48 @@
---
id: 587d7fb7367417b2b2512c0d
title: Використання model.findById() для пошуку вашої бази даних за допомогою _id
challengeType: 2
forumTopicId: 301544
dashedName: use-model-findbyid-to-search-your-database-by-id
---
# --description--
При збереженні документу, MongoDB автоматично додає поле `_id`, і встановлює для нього унікальний алфавітно-цифровий ключ. Пошук за `_id` є надзвичайно частою операцією, тому Mongoose надає для цього спеціалізований метод.
# --instructions--
Змініть `findPersonById`, щоб знайти лише одну особу, яка має заданий `_id`, використовуючи `Model.findById() -> Person`. Використовуйте аргумент функції `personId` як ключ пошуку.
# --hints--
Пошук елемента за Id має бути успішним
```js
(getUserInput) =>
$.get(getUserInput('url') + '/_api/find-by-id').then(
(data) => {
assert.equal(data.name, 'test', 'item.name is not what expected');
assert.equal(data.age, 0, 'item.age is not what expected');
assert.deepEqual(
data.favoriteFoods,
['none'],
'item.favoriteFoods is not what expected'
);
assert.equal(data.__v, 0, 'The item should be not previously edited');
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```

View File

@@ -0,0 +1,51 @@
---
id: 587d7fb7367417b2b2512c0c
title: Використання model.findOne() для повернення єдиного відповідного документа з вашої бази даних
challengeType: 2
forumTopicId: 301545
dashedName: use-model-findone-to-return-a-single-matching-document-from-your-database
---
# --description--
`Model.findOne()` функціонує як `Model.find()`, але повертає лише один документ (не масив), навіть якщо є кілька елементів. Це особливо корисно під час пошуку за властивостями, які були оголошені як унікальні.
# --instructions--
Змініть функцію `findOneByFood`, щоб знайти лише одну особу, яка має певну їжу у своїх вподобаннях, використовуючи модель `Model.findOne() -> Person`. Використовуйте аргумент функції `food` як ключ пошуку.
# --hints--
Пошук елемента має бути успішним
```js
(getUserInput) =>
$.post(getUserInput('url') + '/_api/find-one-by-food', {
name: 'Gary',
age: 46,
favoriteFoods: ['chicken salad']
}).then(
(data) => {
assert.equal(data.name, 'Gary', 'item.name is not what expected');
assert.deepEqual(
data.favoriteFoods,
['chicken salad'],
'item.favoriteFoods is not what expected'
);
assert.equal(data.__v, 0, 'The item should be not previously edited');
},
(xhr) => {
throw new Error(xhr.responseText);
}
);
```
# --solutions--
```js
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```