Am atins urmatoarele subiecte:
Resursele pentru a doua sedinta, adica prezentarea PDF si inregistrarile video, pot fi gasite in acest folder de Gdrive
git clone https://gitlab.com/<your_project> - descarca proiectul cu tot istoricul modificarilor git init - se initializeaza repo-ul local (se creaza folderul .git) git remote add origin https://gitlab.com/<your_project> - daca aveti proiectul initializat local cu aceasta comanda il legati la repo-ul din cloud git status - va arata cateva detalii despre modificarile curente, pe ce branch sunteti etc git diff - va arata exact care sunt liniile de cod modificate git add <path_to_changes> - face ca fisierele modificate din locatia specificata sa fie incluse in urmatorul commit, puteti avea si expresii regulate pentru fiererele voastre (ex. * - include toate modicarile din proiect) git reset <path_to_changes> - face operatia inversa la add, va scoate modificarile de la fisire specificate git commit -m "SOMETHING" - adaugati un commit local cu modificarile puse la "git add" dinainte cu mesajul specificat (daca nu e folosit "-m" va deschide un editor de fisier sa creati mesajul) git branch <branch> - creati un nou branch pornind de la commitul pe care va aflati local git branch -d <branch> - stergeti branch-ul specificat git push -u origin <branch> - trimiteti toate commiturile locale de pe un branch catre repo-ul din cloud git pull origin <branch> - va actualizeaza branch-ul local cu modificarile noi din cloud git checkout -b origin/<branch> - va mutati pe branch-ul specificat cu modificarile din cloud git checkout -b <branch> - va mutati pe branch-ul specificat cu modificarile locale git merge <branch> - se incearca aducerea modificarilor de pe branch-ul specificat pe branch-ul curent git rebase <branch> - mutati toate commit-urile in oridine cronologica de pe branch-ul curent pe cel specificat in comanda git rebase <destination_branch> <source_branch> - mutati toate commit-urile in oridine cronologica de pe branch-ul surse pe cel destinatie git stash - va salveaza modificarile curente si revine la starea ultimului commit, util daca vreti sa lucrati la alte lucruri dar nu ati teminat git stash pop - va aplica modificarile la stash inapoi si le sterge din stocare temporara git cherry-pick <commit_hash> - va ia toate modificarile de la un anumit commit specificat prin hash-ul sau si le pune pe branch-ul curent git rebase -i Head~<N> - cu aceasta comanda puteti transforma ultimele N commituri intr-unul singur, in editorul care se deschite trebuie sa inlocuiti "pick" cu "squash" in afara de prima linie
Representational State Transfer (REST) este un stil arhitectural modern care defineste modul in care interactioneaza serviciile web. Acesta se bazeaza pe cereri HTTP (e.g.: GET, POST, PUT, DELETE) pentru a manipula informatia si pe media-types (e.g.: JSON) pentru a stabili cum arata informatia transferata.
Un API de tip REST este un serviciu Web care permite interactiunea prin mecanisme REST. Backendul pe care noi il vom dezvolta la laborator va fi un astfel de API.
NodeJS este un mediu de rulare pentru Javascript bazat pe motorul V8 de la Chrome. Acesta permite rularea scripturilor de JS pe calculator, fara sa fie nevoie de browser.
Deoarece backendul si frontendul vor fi realizate folosind tehnologii care se bazeaza pe Javascript, este elementar sa cunoasteti acest limbaj. Javascript este un limbaj de scripting cu o sintaxa foarte usoara, asemanatoare celei din C. Va prezentam mai jos cateva particularitati ale limbajului:
function myFunc(x) {console.log(x)}; // este identic cu const myFuncArrow = (x) => console.log(x); myFunc(3); //3 myFuncArrow(3); //3
const constanta = 'abc'; let variabila = 3; function adauga (x, y, z) { if (x === 'abc') { y = y + z; } return y; } const rezultat = adauga(constanta, variabila, 10); console.log(rezultat);
const a = 10; //a este numar const b = '10'; //b este sir de caractere console.log(a == b); //true console.log(a === b); //false const c = 'abc'; const d = 'abc'; console.log(c == d); //true console.log(c === d); //true const fals = false; //boolean const str = ''; //string const zero = 0; //number console.log(fals == str); //true console.log(fals == zero); //true console.log(str == zero); //true console.log(fals === str); //false console.log(fals === zero); //false console.log(str === zero); //false
const obj = {a:1, b:2}; console.log(obj.a); //1 console.log(obj['b']); //2
const obj1 = {a:2}; const obj2 = obj1; // copiere prin referinta obj2.a = 5; console.log(obj1); // {a:5} -> valoarea s-a modificat si in obiectul original const obj3 = Object.assign({}, obj1); // copiere prin valoare, incomplet pentru nivele mai adanci obj3.a = 10; console.log(obj1); // {a:5} -> valoarea nu s-a modificat const obj4 = {...obj1} // copiere prin valoare (modern, folosind spread operator, ES6, dar incomplet pentru nivele mai adanci) obj4.a = 9772; console.log(obj1); // {a:5} -> valoarea nu s-a modificat const obj5 = JSON.parse(JSON.stringify(obj1)); // copiere prin valoare completa obj5.a = ['ana', 'are', 'mere']; console.log(obj1); // {a:5} -> valoarea nu s-a modificat
const arr = [1, 2, 3, 4]; console.log(arr.map(x => x*2)); //2 4 6 8 const obj = { a:2, b:3, c: (x, y) => console.log(x + y)} console.log(obj.c(obj.a, obj['b'])); //5 const func1 = (x, cb) => cb(x); const func2 = y => console.log(y); func1(3, func2); //3
NodeJS este un ecosistem de Javascript care permite folosirea limbajului Javascript pe partea de server. Este bazat pe motorul V8 de la Chrome, ruleaza pe un singur fir de executie si este asincron, utilizand o bucla de evenimente pentru a executa operatiile cat mai rapid.
Un proiect de Node este structurat in module. Fiecare fisier Javascript din componenta unui proiect este considerat un modul. Puteti sa faceti analogia cu fisierele .c din C sau cu clasele din Java.
Un modul poate fi importat de catre oricare alt modul (adica fisier .js), folosind keyword-ul require si calea relativa catre el. Un modul poate expune informatii in exterior folosind proprietatea exports a obiectului global module.
const sayHello = () => { console.log("Hello world!"); } module.exports = { sayHello } /* module.exports = { sayHello } e identic cu const objForExport = { sayHello: sayHello }; module.exports = objForExport; */
const a = 2; const b = 3; const getA = () => { return a; } const getB = () => { return b; } module.exports = { getA }; // pentru oricine va importa acest modul, singurul lucru la care va avea acces va fi functia "getA"
const myModule = require('./modul1.js'); const a_from_module_1 = myModule.getA(); console.log(a_from_module_1); //2 const b_from_module_1 = myModule.getB(); //ReferenceError!
Asa cum in alte limbaje se pot folosi biblioteci externe pentru diverse functionalitati ce sunt deja implementate (exemplu, stdio.h in C pentru I/O) si in Node se pot folosi pachete.
Pachetele sunt module instalate din surse externe. Pentru a instala un pachet se foloseste NPM - node package manager in terminal.
Pentru a putea instala pachete intr-un proiect, este nevoie ca aceasta sa fie initializat. Pentru a initializa un proiect de node, este nevoie sa rulati comanda
npm init
In urma rularii acestei comenzi se va crea un fisier, package.json. Acest fisier are rolul de a retine informatii cu privire la proiect si la dependentele sale.
Pe langa dependente, in package.json sunt retinute si informatii cu privire la proiect (autor, repository, descriere) precum si scripturi de rulare si testare. Puteti asocia partea de scripts din package.json cu un Makefile.
Dupa ce ati initializat proiectul, puteti incepe sa instalati pachete. Pentru a instala un pachet, se executa comanda urmatoare:
npm install nume_pachet --save
Dupa ce instalati un pachet, se vor crea folderul node_modules si fisierul package-lock.json. In folder se afla toate pachetele instalate. In fisier se retine versiunea exacta a pachetului cu care se lucreaza.
Pentru a utiliza un pachet instalat, se foloseste tot keyword-ul require, insa se scrie doar numele pachetului, nu si calea catre locul unde a fost descarcat, aceasta deducandu-se automat din node_modules.
//presupunem ca am instalat inainte pachetul fictiv my-awesome-package const myAwesomePackage = require('my-awesome-package'); //do stuff
Pentru a rula un API de Node, este nevoie sa definiti un fisier de start. Acest fisier trebuie sa includa apoi referinte catre celelalte fisiere ce fac parte din proiect, atat direct, cat si indirect (e.g. start face referire catre modulul 1 iar modulul 1 face referire catre modulul 2).
Exemplu de API minimal cu express:
const express = require('express'); const app = express(); app.get('/', (req, res) => { res.send("Hello world!"); }); app.listen(3000);
Daca doriti sa utilizati scripturi de npm, va trebui sa includeti referinta catre fisierul de start si in package.json:
{ "name": "lab2", "version": "0.0.0", "private": true, "scripts": { "start": "node start.js", "my-other-start": "nodemon start.js" }, "dependencies": { "express": "~4.16.1" } }
Pentru a rula serverul, executati comanda:
npm run start
npm run my-other-start --> va rezulta in rularea folosind nodemon
Pentru a testa un API scris in Node, puteti sa folositi cURL, wget sau Postman. Noi va recomandam Postman, pentru ca ofera multe functionalitati utile, precum variabile de mediu, colectii, scripturi automate, etc…
express helmet morgan log-timestamp express-async-errors http-errors axios dotenv