---
# System prepended metadata

title: WEPPO Egzamin

---

# Wykład 2.
---

## Uruchomienie kodu Javascript w vscode:
potrzebujemy utworzyć plik launch.json. Zawiera on informacje jak uruchomic program.
## 1. Przydatne komendy
`npm init -y` - inicjacja pliku package.json, w którym znajdują się informacje o używanych modułach.

`npm install (moduł)` - zainstaluje w bieżącym projekcie pakiet (moduł)

`npm install (moduł) --save` - zainstaluje moduł lokalnie oraz dodatkowo dopisze zależność do package.json

`npm install (moduł) --g` - zainstaluje modułu globalnie

`npm install` - odtwarza wszystkie zależności zgodnie z opisem w package.json

**Node Package Manager (npm)** - narzędzie npm służy do instalacji i aktualizacji pakietów z globalnego repozytorium. Repozytorium npm jest największym repozytorium pakietów kodu.

**${file}** - informacja w pliku launch.json o tym, że kompilujemy obecnie wyświetlany plik.


---

## 2. Język JavaScript
JavasSript zalicza się do języków luźnotypowanych.

### 2.1 Deklarowanie zmiennych w JS
```javascript=
var a = 12;     // oznacza zmienną, ma zasięg funkcyjny, obecnie zastąpione przez poniższe:
let b = 23;     // oznacza zmienną, ma zasięg blokowy
const c = 34;   // oznacza stałą, ma zasięg blokowy
```

### 2.2 Typy w JavaScript:
**Typy proste (prymitywne)** – proste typy danych, wartości, nie można do nich dodawać składowych, są reprezentowane w pamięci jako tablice bajtów

W JavaScript mamy następujące typy proste:
* `null`
* `undefined`
* `boolean`
* `string`
* `number` w reprezentacji `IEEE 754`, obiekt Math (każda liczba jest 64-bitową liczbą zmiennoprzecinkową)

```javascript=
var num = 20;                 // prosta liczba
var text = "To jest tekst";   // prosty łańcuch znaków
var p = true;                 // logiczny - prawda/fałsz
var n = null;                 // nic
var x;                        // zmienna z nieokreśloną wartością
```

**Typy złożone (referencyjne)** - obiekty, są reprezentowane jako „referencje” do pamięci zawierającej stany obiektów
```javascript=
var a = { };
a.foo = 123;     // dodawanie składowych do obiektu
a['foo'] = 234;  // to jest prawie równoważne, ale pozwala np. definiować klucze zawierające spację
a['fo o'] = 345;
```
Każdy obiekt ma zdefiniowane funkcje `ToString()` oraz `valueOf()`, które można przeciążyć.

`Object.keys(obiekt)` wypisuje klucze obiektu

### 2.3 Typy opakowujące
```javascript=
var a = 1;
a.foo = 'foo';
console.log( a.foo ); // wypisze undefined, bo a jest typu prostego

var b = Number(1);    // równoważne z powyższym
b.foo = 'foo';
console.log( b.foo ); // wypisze undefined, bo a jest typu prostego

var c = new Number(1);
c.foo = 'foo';
console.log( c.foo ); // wypisze 'foo', bo tworzymy obiekt reprezentujący wartość 1
```

### 2.4 Konwersja (koercja) typów w JS
**Typy konwertowane do false**:
0, -0, NaN, "", false

**Operatory logiczne:**
* `!` -> not
* `||` -> or (jest leniwy tzn na poczatku jest wyliczana wartosc pierwszego wyrazenia i dopiero gdy okaze sie ono false to przechodzimy do drugiego wyrazenia)
*  `&&` -> and

**Przykładowe konwersje:**
```javascript=
var p = {};
console.log( p );              // Object
console.log( !p );             // false
console.log( !p+[] );          // 'false'
console.log( [] );             // []
console.log( +[] );            // 0
console.log( (!p+[])[+[]] );   // 'f'
```

### 2.5 typeof, instanceOf
```javascript= 
var a = 1;
console.log( typeof a ); // zwraca napis reprezentujący typ

if ( a instanceof Number ) { // sprawdza czy coś jest instancją obiektu
    console.log( 'Number' );
}
```

### 2.6 Operatory porównania
* `==` -> "luźne" porównanie, sprawdza czy wartości są takie same, ale po dokonaniu konwersji typów
* `===` -> "dokładne porównanie", sprawdza czy wartości są dokładnie takie same

### 2.7 Napisy
* "" ograniczniki zwykłego napisu
* `` ograniczniki szablonu (*${zmienna}*)

**Przydatne metody**
* `toLowerCase()` Metoda ta konwertuje cały ciąg znaków na małe litery.
* `toUpperCase()` Metoda ta konwertuje cały ciąg znaków na duże litery.
* `replace(oldChar, newChar)` Zamienia wszystkie wystąpienia określonego znaku (oldChar) na nowy znak (newChar).
* `trim()` Usuwa wszystkie spacje z początku i końca ciągu znaków.
* `indexOf(substring)` Zwraca indeks pierwszego wystąpienia określonego podciągu znaków (substring) w ciągu. Jeśli nie znajdzie, zwraca -1.
* `startsWith(prefix)` Sprawdza, czy ciąg znaków zaczyna się od określonego prefiksu (prefix). Zwraca true, jeśli tak, w przeciwnym razie false.
* `endsWith(suffix)` Sprawdza, czy ciąg znaków kończy się określonym sufiksem (suffix). Zwraca true, jeśli tak, w przeciwnym razie false.

### 2.8 Getter/Setter
JavaScript posiada lukier syntaktyczny do definiowania właściwości obiektu, wymagający określenia akcesorów `get` i `set`.

```javascript=
var foo = {
    num : 0,
    get bar() {
        return foo.num;
    },
    set bar(i) {
        foo.num = i;
    }
}
console.log( foo.bar ); // wypisze 0
foo.bar = 5;
console.log( foo.bar ); // wypisze 5
```

Możliwe jest ogólniejsze podejście, użycie `Object.defineProperty` za pomocą którego można dodać do obiektu dowolną wartość (pole, właściwość, funkcję)

```javascript=
var foo = { }

Object.defineProperty(foo, 'qux', {
    get: function () {
        return 18;
    }
});

Object.defineProperty(foo, 'baz', {
    value: function () {
        return 34;
    }
});
console.log(foo.qux);   // wypisze 18
console.log(foo.baz()); // wypisze 34
```

### 2.9 Tablice

* `slice(start, end)` Wybiera fragment listy na podstawie podanych indeksów.
* `splice(index, k, item1, ...)` Modyfikuje tablicę poprzez usuwanie (k) i/lub dodawanie elementów (item1, ...) od danego indeksu (index).
* `filter(function)` Filtruje elementy tablicy na podstawie zdefiniowanego warunku (function).
* `map(function)` Wykonuje określoną funkcję (function) dla każdego elementu tablicy i zwraca nową listę zawierającą wyniki.


### 2.10 JSON

```javascript=
var p = {
    a : 1,
    b : {
        c : 2
    }
}
console.log(p) // zwroci {a :1, b : {...}}
var s = JSON.stringify(p)
console.log(p) // zwroci {"a":1, "b":{ "c":2}}
console.log(s) // 
```

### 2.11 Nawiasowanie
```javascript=
function a() {
    
}
// tak dobrze

function a()
{
    
}
// tak nie robimy bo domyslnie w javascript sa wstawiane sredniki na koncu linii moze to prowadzic do komplikacji
```
![image](https://hackmd.io/_uploads/rkSXkGHY1e.png)
![image](https://hackmd.io/_uploads/B1bo1fBFye.png)

### Lista 2
**Zadanie 2**
```javascript=
// 1. Użycie argumentów innego typu niż string dla operatora [] dostępu do składowej obiektu.

// Co się dzieje jeśli argumentem operatora jest liczba?
const person = {
    1: "Jakub",
    2: 20
};
console.log(person[1]); // wypisze "Jakub"

// 2. Użycie argumentów innego typu niż number dla operatora [] dostępu do tablicy.

// Co się dzieje jeśli argumentem operatora jest inny obiekt?
const k = {
    prop: "1"
};
console.log(person[k.prop]); // Wypisze "Jakub"

// Co się dzieje jeśli argumentem operatora jest napis?
const fruits = ["apple", "orange", "banana"];
console.log(fruits["1"]);  //Wypisze "orange"

// Co się dzieje jeśli argumentem operatora jest inny obiekt dla tablic?
const key2 = {
    prop: "1"
};
console.log(fruits[key2.prop]); // wypisze "orange"

// Czy i jak zmienia się zawartość tablicy jeśli zostanie do niej dopisana właściwość pod kluczem, który nie jest liczbą?
fruits["2"] = "strawberry"; // wstawi "strawberry" na miejscu o indeksie 2

// Czy można ustawiać wartość atrybutu length tablicy na inną wartość niż liczba elementów w tej tablicy? 
fruits.length = 10;
console.log(fruits.length) // wypisze 10

fruits.length = 2;
console.log(fruits.length) // wypisze 2
```

# Wykład 3.
## 1. Funkcje

### 1.1 Zmienna ilość argumentów
Operator rozrzucania, czyli trzykropek: `...` pozwala na użycie dowolnej ilości argumentów w funkcji. 

```javascript=
function(...args) {
    for (let i = 0; i < args.length; i++) {
        console.log(args[i])
    }
}
```

### 1.2 Funkcje anonimowe
```javascript=
function(x) {
    x > 2
}

(x) => {
    x > 2
}
```


### 1.3 Funkcja w funkcji
Aby wywołać funkcję w funkcji należy podać jej argumenty w drugim nawiasie.
```javascript=
function create() {
    return function () {
        return 1;
    }
}
console.log(create())     // wypisze [Function (anonymous)]
console.log(create()());  // wypisze 1
```

### 1.4 Domknięcie funkcji
**Domnknięcie funkcji** to dodatkowy obiekt wiążący funkcję ze środowiskiem. 
```javascript=
function sumpartial(x) {
    return (y) => {
        return x + y;
    }
}
var sum1 = sumpartial(1);
console.log(sum1(2));
console.log(sumpartial(1)(2))
```

Nieskończona ilość aplikowalnych argumentów:
```javascript=
function sumpartial(x) {
    var acc = x; // nasz akumulator "zapamiętujący" obecną sumę
    
    var func = (y) => {
        acc += y;
        return func;
    }
    
    func.valueOf = () => {
        return acc;
    }
    
    return func;
}
console.log(+sumpartial(4)(5)(6));
```

### 1.5 Memoizacja
Przydaje się zwłaszcza w przypadku, gdy funkcja w argumencie jest rekurencyjna (np. ciąg Fibonacciego)
```javascript=
function memo(func){
    var cache = {}

    return function(n){
        if (n in cache){
            return cache[n];
        }
        else{
            var result = func(n);
            cache[n] = result;
            return result;
        }
    }
}
```
### 1.6 IIFE
Funkcja jest wywołana zaraz po zdefiniowaniu.
Let to lukier syntaktyczny dla IIFE, obie poniższe definicje są sobie równoważne i zmienna k ma zasięg blokowy.
```javascript=
{
    (function() {
        var k;
    }())

    let k
}
```

### 1.7 Currying
Currying to inaczej rozwijanie funkcji, w którym częściowa aplikacja jest możliwa dla każdego argumentu z osobna (wywołanie z n argumentami zamienia się na n wywołań z jednym argumentem).

```javascript=
function sum3(x, y, z) {
    return x + y + z;
}

function curry(fn) {
    function rec(fn, i, args) {
        if (i < fn.length) {
            return (x) => {
                args.push(x);
                return rec(fn, i + 1, args);
            }
        }
        else {
            return fn(...args);
        }
    }
    return rec(fn, 0, []);
}

var currysum3 = curry(sum3);
console.log(currysum3(1)(2)(3));
```

### 1.8 this, call, bind, apply
* **this**
W funkcji wywołanej z wiązaniem na obiekcie(`o.funkcja()`), `this` ma wartość referencji do tego obiektu.
```javascript=
var person = {
    name: 'jan',
    say: function () {
        return this.name;
    }
}
console.log(person.say());
```
Alternatywnie:
```javascript=
var person = {
    name: 'jan',
    say: say // lub po prostu say
}
function say() {
    return this.name
}
console.log(person.say());
```
* **call**
Służy do wywołania funkcji, gdzie argumentem jest obiekt, w którego kontekście ma być wywołana. Argumentami `call` jest to, co ma być widoczne jako `this`, wewnątrz funkcji.
```javascript=
var person = {
    name: 'jan',
}
function say() {
    return this.name
}
console.log(say.call(person));
```
* **apply**
Działa bardzo podobnie do `call`, z tą różnicą że argumenty są przekazywane jako lista, nie po przecinku jak w `call`.
Poniższe zapisy są sobie równoważne:

```javascript=
function f(a, b, c){
    return this, a, b, c
}
var o = {
    x: 1
}
f.apply(o, [1, 2, 3])
f.call(o, 1, 2, 3)
```

* **bind**
Bind zaaplikowany do funkcji, zwraca inną funkcję, w której `this` już jest zawsze zamieniony na jakiś obiekt.
```javascript=
function foo(y, z) {
    return this.x + y + z;
}
var o = { 
    x: 1 
}
var baz = foo.bind(o);
console.log(baz(1, 2)); // wypisze 4
```
## 2. Iteratory, generatory
### 2.1 Iterator
**Iterator** to funkcja bezargumentowa która zwraca obiekt, który ma jedno pole, `next`, które jest funkcją zwracającą obiekt o polach `value` i `done`.
```javascript=
function createIterator() {
    var acc = 0;
    return {
        next: function () {
            return {
                value: acc,
                done: acc++ >= 10
            }
        }
    }
}
var it = createIterator();

for (var result; result = it.next(), !result.done;) {
    console.log(result.value);
}
```
Funkcja iteratora jeśli zostanie użyta w obiekcie jako wartość składowej `Symbol.iterator`, obiekt uzyskuje możliwość iterowania jego zawartości za pomocą for-of.
```javascript=
var foo = {
    [Symbol.iterator]: createIterator
}
for (var f of foo) {
    console.log(f);
}
```
W obu przypadkach zostaną wypisane liczby od 0 do 9.

### 2.2 Generator
**Generator** to skrócony sposób zapisu kodu iteratora, dodający zwracanie bieżącej wartości za pomocą `yield`. Iterowanie generatora działa tak samo jak iteratora. 
```javascript=
function* createGenerator() {
    for (var i = 0; i < 10; i++) {
        yield i;
    }
}
```
Gwiazdka przy `function` jest niezbędna. Pętla for, oraz for-of działają tak samo jak w iteratorze.

### 2.3 Próba oszustwa
Iterator/Generator powinien być funkcją bezargumentową, ale jednak chcemy przekazać mu jakieś wartości. Można po prostu zwrócić funkcję bezargumentową.
```javascript=
function createGenerator(n) {
    return function* () {
        for (var i = 0; i < n; i++) {
            yield i;
        }
    }
}
var foo = {
    [Symbol.iterator]: createGenerator(10)
}
for (var val of foo) {
    console.log(val); // wypisze liczby od 0 do 9
}
```

### Lista 3
**Zadanie 2**
```javascript=
function forEach(a, f){
    if (a[0] === undefined){
        return [undefined];
    }
    else{
        f(a[0]);
        forEach(a.slice(1), f);
    }
}

function map(a, f){
    if (a.length == 0){
        return [];
    }
    else{
        return [(f(a[0])), ...map(a.slice(1), f)];
    }
}

function filter(a, f){
    if (a.length == 0){
        return [];
    }
    else if (f(a[0])){
        return [a[0], ...filter(a.slice(1), f)]
    }
    else{
        return [...filter(a.slice(1), f)]
    }
}
```
---

# Wykład 4.

## 1. Paradygmat obiektowy
**Projektowanie obiektowe** - określanie odpowiedzialności obiektów (klas) i ich relacji względem siebie. Wszystkie dobre praktyki, zasady, wzorce sprowadzają się do tego jak właściwie rozdzielić odpowiedzialność na zbiór obiektów (klas).

W JavaScript jeżeli dwa niepowiązane ze sobą w żaden sposób obiekty mają „podobny wygląd” (pola/metody), to obu można użyć w tym samym kontekście i do tego nie jest potrzebna żadna kontrola typów:
```javascript=
var person = {
    name: 'jan',
    say: function () {
        return this.name;
    }
}
var car = {
    brand: 'skoda',
    say: function () {
        return this.brand;
    }
}
function describe(item) {
    console.log(item.say());
}
describe(person);
describe(car);
```
Jest to tzw. **Duck Typing**, czyli rozpoznawanie typu obiektu poprzez pola, które zawiera.
*„If it walks like a duck and it quacks like a duck, then it must be a duck.”*

W Javascript są trzy równoważne modele implementowania struktur obiektów:
* `{}`
* `new`
* `Object.create()`

W językach takich jak C# czy Java jest tylko jeden sposób tworzenia nowych instancji obiektów – to operator `new`

## 2. Obiektowość z { }, bez dziedziczenia
Pierwsza technika obiektowości w JS to 'udawanie' konstruktorów, poprzez proste funkcje tworzące obiekty. Wadą jest jednak niepotrzebne zużycie pamięci na kopiowanie metod.
```javascript=
function Person(name, surname) {
    return {
        name: name,
        surname: surname,
        say: function () {
            return `${this.name} ${this.surname}`;
        }
    }
}
var p = Person('jan', 'kowalski');
console.log(p.say());
```

## 3. Obiektowość prototypowa
Obiektowość prototypowa zestawia wiele instancji obiektów w łańcuchy, w których każdy obiekt wskazuje na swój prototyp.

### 3.1 Prototyp
Prototyp to taki "poprzednik" istniejącego obiektu. 
Nadrzędnym prototypem każdego obiektu jest `Object.prototype`, z którego każdy inny obiekt dziedziczy metody np. `toString()` albo `valueOf()`.
* Aby zmienić prototyp używamy funkcji: `Object.setPrototypeOf(obiekt, nowyPrototyp)`
* Aby odczytać prototyp istniejącego obiektu używamy funkcji: `Object.setPrototypeOf(obiekt)`

```javascript=
var o = {
    foo: null
}
var proto = {
    foo: 1,
    bar: 2
}
Object.setPrototypeOf(o, proto);

console.log(o.foo); // wypisze null
console.log(o.bar); // bar pochodzi z obiektu proto, wypisze 2
console.log(o.foo); // wypisze null
```
#### Ograniczenia
* Obiekt może mieć pusty prototyp. W szczególności, ten prototyp wszystkich obiektów, czyli `Object.prototype`, ma pusty prototyp. Dzięki temu łańcuch prototypów zawsze się kończy.
* Łańcuch prototypów nie może mieć cykli. Dosyć logiczne.
## 4. Obiektowość z new
W JavaScript obiektowość z użyciem słowa kluczowego `new` odnosi się do tworzenia nowych instancji obiektów przy użyciu konstruktorów. 
```javascript=
function Person(name, age) {
    this.name = name;
    this.age = age;
}
// dodawanie nowych metod, prototyp wszystkich nowych instancji obiektu:
Person.prototype.say = function () {
    return this.name;
};

var person = new Person("Jan", 21);
console.log(person.age);
```
Wewnątrz konstruktora `this` odnosi się do nowo tworzonej instancji obiektu.
Możemy też łatwo modyfikować pola nowych instancji:
```javascript=
person.age = 22
console.log(person.age); // wypisze 22
```

#### Dziedziczenie
Możemy w łatwy sposób osiągnąć coś na wzór dziedziczenia:
```javascript=
var Worker = function (name, surname, age) {
    Person.call(this, name, age);
    this.surname = surname;
}

// ustawienie prototypu dla worker
Worker.prototype = Object.create(Person.prototype);

var worker = new Worker('jan', 'kowalski', 48);
console.log(worker.say());
```
Dodanie nowej funkcjonalności (pola lub funkcji) do prototypu automatycznie dodaje ją do wszystkich obiektów o tym prototypie.

#### Przykładowe prototypy:
```javascript=
var o = {}
console.log( Object.getPrototypeOf(o) === Object.prototype ); // true

function foo() {}
console.log( Object.getPrototypeOf(foo) === Function.prototype ); // true

var s = 'ala ma kota';
console.log( Object.getPrototypeOf(s) === String.prototype ); // true
```

## 5. Obiektowość z Object.create()
Funkcja `Object.create()` tworzy nową instancję obiektu i ustawia jej wskazany obiekt jako prototyp.
Konstruktor - musi być rozdzielony na tworzenie przez `Object.create` (poprawne zestawienie łańcucha prototypów) i metodę `init` która jedynie inicuje stan obiektu.
```javascript=
var Person = {
    init: function (name, surname) {
        this.name = name;
        this.surname = surname;
    },
    say: function () {
        return this.name;
    }
}
var Worker = Object.create(Person);

Worker.init = function (name, surname, age) {
    person.init.call(this, name, surname);
    this.age = age;
}

var w = Object.create(Worker);
w.init('tomasz', 'malinowski', 48);
console.log(w.say());
```

Oba sposoby implementacji obiektowości, ten w którym `Object.create()` jest pierwotne i ten w którym `new` jest pierwotne, są równoważne.

## 6. Lukier syntaktyczny definicji klas
```javascript=
class Person {
    constructor(name, surname) {
        this.name = name;
        this.surname = surname;
    }
    say() {
        return this.name + this.surname;
    }
}
class Worker extends Person {
    constructor(name, surname, age) {
        super(name, surname);
        this.age = age;
    }
    say() {
        var prev = super.say();
        return prev + this.age;
    }
}
var w = new Worker('tomasz', 'malinowski', 48);
console.log(w.say());
```

## Lista 4
**Zadanie 2**
Jak odróżnić składową, która pochodzi z obiektu od takiej która pochodzi z prototypu?
```javascript=
var person = {
    name: 'jan'
}

var personProto = {
    surname: 'kowalski',
    age: 30
}

Object.setPrototypeOf(person, personProto);

// zwraca true, jeżeli obiekt zawiera takie pole
function isInObject(obj, propertyName) {
    return obj.hasOwnProperty(propertyName);
}

// Wypisuje pola, również te z łańcucha prototypów
for (key in person) {
    console.log(key);
}
```

**Zadanie 3**
```javascript=
var Person = function(name) {
    this.name = name;
}
var Worker = function(name, age) { 
    Person.call(this, name);
    this.age = age
}
```
* Poprawne podejście
```javascript=
Worker.prototype = Object.create(Person.prototype);
```
Poprawna wersja z wykładu izoluje prototyp, zmiany w dziedziczącym prototypie nie wpłyną na prototyp rodzica.
* Błędne podejście 1:
```javascript=
Worker.prototype = Person.prototype;
```
Modyfikując `Worker.prototype`, poprzez dodanie pola/metody dodajemy je zarówno do Worker.prototype jak i do Person.prototype.

* Błędne podejście 2:
```javascript=
Worker.prototype = new Person();
```
Tworzymy nowy obiekt person wywołujemy jego konstruktor. Nie przekażemy argumentów konstruktora odpowiednich dla `Worker`.
**Zadanie 4**
Nie można dodawać prototypów do typów prostych. Prototypem typów prostych jest `object`.
**Zadanie 5**
Efekt składowych prywatnych.
```javascript=
function Foo() {
    this.Bar = function() {
        Qux();
    }
    function Qux(){ // brak dostępu
        console.log("qux")
    }
    
    this.getName = function() {
        return _name;
    }
    var _name = name; // brak dostępu
}
```


---

# Wykład 5.
## 1. Klasy
### 1.1 Przestrzenie nazw
Inne języki: `namespace`
JavaScript: obiekty zagnieżdżone w obiektach:
```javascript=
UWr = {}
UWr.weppo = {};
UWr.weppo.Person = function(name) {
    this.name = name;
}
var p = new UWr.weppo.Person('jan');
console.log(p.name);
```
### 1.2 Moduły
```javascript=
// module.js
module.exports = { module_function };
```
```javascript=
// main.js
let var = require('./module');
var.module_function(5);
```

### 1.3 Dokumentacja
**JSDoc** - standard dokumentacji kodu, pozwala edytorom na wyświetlanie komentarzy, po najechaniu na funkcję napisaną przez nas. Pojawia się przed opisywaną funkcją.
```javascript=
/**
* Funkcja dodająca dwie liczby.
* @param {number} a - Pierwsza liczba.
* @param {number} b - Druga liczba.
* @returns {number} Suma dwóch liczb.
*/
function sum(a, b) {
    return a + b;
}
```

## 2. Programowanie asynchroniczne :(
Programowanie asynchroniczne w języku JavaScript polega na wykonywaniu operacji, które mogą trwać różną ilość czasu, bez blokowania wykonywania kolejnych instrukcji.

Główne cechy programowania asynchronicznego w JavaScript to:
* **Funkcje zwrotne (Callbacks)** 
Polega to na przekazywaniu funkcji do innych funkcji, które zostaną wykonane, gdy operacja asynchroniczna zakończy się.
* **Obietnice (Promises)**
Obietnice to obiekty reprezentujące wartość, która może być dostępna natychmiast lub w przyszłości.
* **Funkcje async/await**
Funkcje oznaczone jako async zwracają obietnice, a słowo kluczowe await używane jest do oczekiwania na zakończenie operacji asynchronicznej wewnątrz funkcji async.

Podejście async-await jest równoważne callbackom.

### 2.1 Callback Hell
Kolejne wywołania funkcji asynchronicznych w jednym potoku powodują konieczność charakterystycznego zagnieżdżania funkcji zwrotnych, nazwanego **Callback Hell**. Nieumiejętność radzenia sobie z tą niedogodnością struktury kodu jest jednym z powodów dla których Javascript miał przez lata tak niedobrą opinię.
```javascript=
funkcja1(function(response1) {
    funkcja2(response1, function(response2) {
        funkcja3(response2, function(response3) {
            // i tak dalej...
        });
    });
});
```
### 2.2 Promise
Alternatywą dla funkcji zwrotnych jest wzorzec struktury kodu oparty na obiektach Promise. 
Promise jest obiektem który ma:
* **Stan** (Pending, Fulfilled, Rejected)
* **Funkcję do zmiany stanu**
* **Listę tzw. kontynuacji** czyli funkcji, które trzeba wykonać wtedy kiedy wynik będzie dostępny `then()` lub zostanie wyrzucony wyjątek `catch()`

Konytnuacja z kolei zawsze zwraca `Promise`, nawet jeśli technicznie nic nie zwraca. Dzięki temu możliwe jest łańcuchowanie wywołań.
```javascript=
var promise = new Promise((resolve, reject) => {
    resolve(17); // zmiana stanu
});

promise
    .then(result => {
        console.log(result);
    })
    .then(result => {
        console.log(result + 1);
    })
    .catch(error => {
        console.error(error); 
    });
```

### 2.3 async/await
Lukier syntaktyczny, który umożliwia pisanie asynchronicznego kodu w sposób, który wygląda jak synchroniczny, co znacznie ułatwia zarządzanie asynchronicznością i czytelność kodu.

* **async**: 
Funkcje oznaczone jako `async` zwracają obietnice (Promise). Wewnątrz funkcji `async` możemy korzystać z słowa kluczowego `await`, które czeka na zakończenie operacji asynchronicznej i zwraca jej rezultat.
* **await**: 
Słowo kluczowe `await` może być używane wewnątrz funkcji oznaczonej jako `async` do oczekiwania na zakończenie operacji asynchronicznej. Działanie funkcji `await` polega na "zawieszeniu" wykonywania funkcji do momentu rozwiązania obietnicy.
```javascript=
function pobierzDane() {
    return new Promise(function(resolve) {
        setTimeout(function() {
            resolve("Dane zostały pobrane!");
        }, 2000);
    });
}

(async function dzialanie() {
    try {
        var wynik = await pobierzDane();
        console.log(wynik); // "Dane zostały pobrane!"
    } 
    catch (error) {
        console.error(error);
    }
})();
```
## Lista 5
**Zadanie 1**
Aby zbudować cykl modułów wystarczy na początku pliku dodać `module.exports`.
```javascript=
module.exports = { test2 }
const a = require('./module1.js')
console.log('Module 2 loaded module 1')

function test2(x){
    if (x > 0){
        console.log(`Module 2: ${x}`)
        a.test1(x - 1)
    }
}
```
```javascript=
module.exports = { test1 } 
const b = require('./module2.js')
console.log('Module 1 loaded module 2')

function test1(x){
    if (x > 0){
        console.log(`Module 1: ${x}`)
        b.test2(x - 1)
    }
}
```

**Zadanie 4**
Odczytywanie i wypisywanie zawartości pliku.
```javascript=
var fs = require('fs');

function read() {
    return new Promise((resolve, reject) => {
        fs.readFile('text.txt', 'utf-8', (err, answer) => {
            if (err) {
                reject(answer);
            }
            else{
                resolve(answer);
            }
        })
    });
};

(async function main() {
    t = await read()
    console.log(t)
})()
```


---

# Wykład 6.
## 1. Kilka słów o TypeScript
**TypeScript** to język programowania stworzony przez Microsoft, który rozszerza składnię języka JavaScript poprzez dodanie statycznego typowania. Oznacza to, że TypeScript pozwala programistom określać typy zmiennych, parametrów funkcji i innych elementów kodu, co ułatwia wykrywanie błędów i refaktoryzację kodu.

#### Kilka cech TypeScript:
* **Statyczne typowanie**: 
TypeScript umożliwia definiowanie typów zmiennych, parametrów funkcji, wartości zwracanych itp.
* **Kompilacja do JavaScript**: 
Kod napisany w TypeScript jest kompilowany do kodu JavaScript, co oznacza, że może być uruchamiany na każdej platformie wspierającej JavaScript. Kod sprawdzany jest w momencie kompilacji.
* **Obsługa klas i interfejsów:** 
TypeScript wspiera obiektowość poprzez koncepcje klas i interfejsów.

#### Przydatne komendy:
* `npm install typescript -g` - globalna instalacja TS
* `tsc --init` - inicjalizacja pliku tsconfig.json
* `tsc --watch` - uruchamia kompilator TypeScripta (tsc) w trybie śledzenia. Oznacza to, że kompilator będzie śledził pliki źródłowe TypeScript i  automatycznie kompilował je za każdym razem, gdy zostaną zmodyfikowane.

**ts-node** to środowisko uruchomieniowe TypeScript, które rozszerza node o kompilację TS „w locie”. Do tego należy używać polecenia `ts-node plik.ts`.

## 2. System typów
![image](https://hackmd.io/_uploads/ry4b3ZWip.png)
* **unknown** najbardziej ogólny typ, który reprezentuje wartość, o której nie wiadomo, jakiego typu jest w momencie kompilacji. "Bezpieczniejszy" w stosunku do typu`any`.
* **never** można nadać go nadać zmiennej, ale takiej zmiennej nie da się nadać żadnej wartości. Wykorzystuje się go np. w sytuacjach w których funkcja nigdy nie zakończy się, lub jej wartość nigdy nie zostanie zwrócona.

**System typów TS jest znacznie bogatszy niż system typów JS.** Wynika to z tego, że o ile część typów TS i JS pokrywa się (np. zmienna zadeklarowana w TS jako `string` będzie miała w JS też typ `string`) to sporo typów zadeklarowanych w TS po prostu zniknie po kompilacji do JS (np.wszystkie typy zadeklarowane przez programistę z użyciem `type/interface`)


```typescript=
// Typ prosty w TS
let s: string = 's';
console.log(Object.getPrototypeOf(s) === String.prototype); // true

// Typ złożony (strukturalny) w TS
type Person = {
    name: string;
    surname: string;
}

let p: Person = {
    name: 'jan',
    surname: 'jan'
}
// po uruchomieniu, na poziomie JS, prototypem p jest Object.prototype
// Person "znika" z pola widzenia systemu typów czasu wykonania
console.log(Object.getPrototypeOf(p) === Object.prototype); //true
```

### 2.1 Inne rodzaje typów

```typescript=
// typ literalny anonimowy: typem zmiennej jest 'x'
let _x1: 'x' = 'x';

// typ literalny został nazwany, X
type X = 'x';
let _x2: X = 'x';

// typ strukturalny anonimowy:
// typem zmiennej jest { name: string, surname: string }
let _person1: { name: string, surname: string } = {
    name: 'jan', 
    surname: 'kowalski'
};

// typ strukturalny został nazwany, Person
type Person = { name: string, surname: string };
let _person2: Person = { name: 'jan', surname: 'kowalski' }
```

#### Type vs Interface
Różnice między `type` a `interface` są nieznaczne i można powiedzieć że to synonimy, z zastrzeżeniem:
* `type` pozwala na tworzenie nowych, bardziej skomplikowanych typów danych, podczas gdy `interface` służy głównie do definiowania kształtu obiektów. Może zawierać tylko deklaracje właściwości i metod, ale nie implementacje.
```typescript=
type Osoba = {
    imie: string;
    wiek: number;
}

type Adres = {
    ulica: string;
    kodPocztowy: string;
}

type Klient = Osoba & Adres;
```
```typescript=
interface Osoba {
    imie: string;
    wiek: number;
}

interface Adres {
    ulica: string;
    kodPocztowy: string;
}

interface Klient extends Osoba, Adres {
    nrTelefonu: string;
}
```

### 2.2 Inferencja typów
**Inferencja typów** to mechanizm, który pozwala na automatyczne wywnioskowanie typów zmiennych na podstawie ich wartości lub kontekstu, bez konieczności jawnego określania typów przez programistę.
```typescript=
type Person = {
    name: string,
    surname: string
}
function DoWork(p: Person): Person {
    // zwraca obiekt literalny - ale struktura jest zgodna!
    return {
        name: p.name + ' from doWork',
        surname: p.surname + " from doWork"
    };
}
```
Ani obiekt zwracany z funkcji, ani obiekt przekazywany do funkcji nie ma jawnie zadeklarowanego typu (choć mógłby!) i w obu przypadkach TS jest w stanie zweryfikować poprawność wywołania na podstawie wyłącznie zgodności pól.
typu. **W TypeScript strukturalnie typ** `Person` **oraz typ** `{name: string, surname: string}` **są równoważne!**
### 2.3 Unie i przecięcia typów

* Unia typów `|`
```typescript=
// Unia typów string lub number
let zmienna: string | number;
zmienna = "Hello"; // OK
zmienna = 10; // OK
zmienna = true; // Błąd, wartość typu boolean nie jest częścią unii
```
* Przecięcie typów `&`
```typescript=
// Przecięcie typów Osoba i Adres
interface Osoba {
    imie: string;
    wiek: number;
}

interface Adres {
    ulica: string;
    kodPocztowy: string;
}

type Klient = Osoba & Adres;
// Klient będzie zawierać właściwości imie, wiek, ulica i kodPocztowy
```
### 2.4 Strażnik typów
**Strażnik typów** zwraca informacje o przynależności obiektu do jakiegoś typu.
```typescript=
type Person = {
    name: string
}
type WorkingPerson = Person & { position: string }
// stażnik typowy (type guard)
function isWorkingPerson(p: Person): p is WorkingPerson {
    return 'position' in p;
}
```
### 2.5 Przeciążenie funkcji
TypeScript nie pozwala przeciążyć implementacji funkcji, ale zamiast tego pozwala na przeciążenie samej sygnatury (sposób określania typów parametrów funkcji oraz typu wartości zwracanej przez funkcję).

### 2.6 Jeszcze więcej typów
#### Typy generyczne
```typescript=
function identyfikator<T>(arg: T): T {
    return arg;
}

let identyfikatorString: string = identyfikator("hello");
let identyfikatorLiczba: number = identyfikator(42);
```
#### Typy indeksowane
```typescript=
interface Dictionary<T> {
    [klucz: string]: T;
}

let slownik: Dictionary<number> = {};
slownik["jeden"] = 1;
slownik["dwa"] = 2;
```
#### Typy funkcyjne
```typescript=
type FunkcjaDodawania = (a: number, b: number) => number;

let dodaj: FunkcjaDodawania = (x, y) => x + y;
let wynik: number = dodaj(3, 5); // wynik: 8
```
### 2.7 keyof, typeof
* `typeof` jest operatorem używanym do uzyskiwania typu wartości, zmiennej lub wyrażenia.
* `keyof` jest operatorem używanym do uzyskiwania typu, który zawiera wszystkie klucze obiektu lub typu.
```typescript=
const liczba = 42;
type TypLiczby = typeof liczba; // TypLiczby zawiera typ "number"
```
```typescript=
type Osoba = {
    imie: string;
    wiek: number;
    email: string;
};
type KluczeOsoby = keyof Osoba; // KluczeOsoby zawiera typ "imie" | "wiek" | "email"

```
### 2.8 Typy mapowane
Jeśli keyof działa tak że z typu strukturalnego wybiera klucze, to czy istnieje operacja odwrotna? Taka, że dla zadanej unii kluczy tworzy typ strukturalny z tymi kluczami? Tak. Do tego służą typy mapowane.
```typescript=
type Osoba = {
    imie: string;
    wiek: number;
};

type OsobaZDwomaStringami = {
    [K in keyof Osoba]: string;
};
// OsobaZDwomaStringami będzie miało typ { imie: string, wiek: string }
```
Typy warunkowe pozwalają na wybór typu na podstawie warunku logicznego.
```typescript=
type AcceptOnly<T> = T extends 'name' ? T : never;

type Name = AcceptOnly<'name'> // 'name'
type NoName = AcceptOnly<'noname'> // never
```

#### Inny ważny przykład

```typescript=
type Person = {
    name: string,
    surname: string,
    age: number,
    position: number
}
// pomiń klucze
type ExceptKeys<T, U> = T extends U ? never : T;
// mapuj obiekt na obiekt z pominiętymi kluczami
type OmitKeys<T, K extends keyof T> = { [k in ExceptKeys<keyof T, K>]: T[k] }
// {
// age: number.
// position: number
//}
type WorkingPerson = OmitKeys<Person, 'name' | 'surname'>
```


### 2.9 Kilka wbudowanych typów generycznych

* `Partial<Type>` Konstruuje z zadanego typu typ, który ma wszystkie składowe opcjonalne
* `Required<Type>` Konstruuje z zadanego typu typ, który ma wszystkie składowe wymagane
* `Readonly<Type>` Konstruuje z zadanego typu typ, który ma wszystkie składowe tylko-do-odczytu
* `Record<Keys, Type>` Konstruuje typ z zadanych kluczy i typu wartości
* `Extract<Keys, Keys>` Z zadanej unii typowej zwraca wskazane elementy
* `Exclude<Keys, Keys>` Z zadanej unii typowej wyrzuca wskazane elementy
* `Pick<Type, Keys>` Z zadanego typu struktury zwraca podtyp ze wskazanych kluczy
* `Omit<Type, Keys>` Z zadanego typu struktury zwraca podtyp z wyrzuconymi wskazanymi kluczami


---

# Wykład 7
## 1. HTTP
### 1.1 Protokół
**Protokół HTTP** opracowano na początku lat 90tych. Jest to oparty o TCP/IP protokół komunikacyjny, zaprojektowany do przekazywania treści multimedialnych.
Przez oparty o TCP/IP rozumiemy tu protokół, w warstwie transportowej którego używane są gniazda BSD, czyli standard z początku lat 80tych, zaadoptowany do POSIX jako de facto interoperacyjny standard komunikacyjny. Interfejs gniazd przyjął się w dużej mierze dzięki swojej prostocie konceptualnej, opartej o funkcje:
- **bind**, **listen** i **accept** na serwerze
- **connect** na kliencie
- **send** i **recv** na kliencie i serwerze

![image](https://hackmd.io/_uploads/rkxbUlZsp.png)

### 1.2 Żądanie
Tekst złożony z **wielu linii**, z których **pierwsza** określa **rodzaj żądania i nazwę zasobu**, a **kolejne linie** oznaczają tzw. **nagłówki HTTP**. **Pusta linia oznacza koniec żądania**, chyba że jest to żądanie z parametrami (np. POST czy PUT), wtedy treść żądania może być dowolnie długa. W takim przypadku obowiązkowy jest **nagłówek Content-length**, który określa **długość tej dodatkowej opcjonalnej części**.

### 1.3 Odpowiedź
Tekst lub strumień binarny, interpretowany przez klienta na podstawie opisu w nagłówku **Content-type**, o długości zadanej przez nagłówek **Content-length**

### 1.4 Klienci i debuggery HTTP
Przeglądarka może posiadać **funkcję podglądu sieciowego**, ponieważ podgląd odbywa się w samej przeglądarce, nie ma problemu z podglądem ruchu szyfrowanego (**HTTPs**)

Zewnątrzprocesowy podgląd ruchu między klientem a serwerem możliwy jest albo za pomocą narzędzi niskopoziomowych (np. Wireshark) albo tzw. **debuggerów http** (wykorzystując to, że przeglądarki pozwalają na ustawienie tzw. **proxy** dla ruchu HTTP)

> Przykładowy klient wykorzystujący POST do ścieżki https://httpbin.org/post
```javascript=
var https = require('https');

function promisedRequest() {
    return new Promise(function (resolve, reject) {
        var qs = new URLSearchParams();
        qs.append('foo', 'foo');
        qs.append('bar', 'bar');
        var postData = qs.toString();
        /**
        * @type {http.RequestOptions}
        */
        var requestParameters = {
        host: 'httpbin.org',
        port: '443',
        path: '/post',
        method: 'POST',
        headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Content-Length': Buffer.byteLength(postData)
        }
    };
        
    var client = https.request(requestParameters, function (res) {
        var buffer = '';
        res
            .on('data', function (data) {
            buffer += data.toString();
            })
            .on('end', function () {
            resolve(buffer);
            });
        });
        client.write( postData );
        client.end();
    });
}

(async function() {
    var result = await promisedRequest();
    console.log( result );
})();
```

### 1.5 Fiddler i Burp
Darmowe debugery http.

Oba narzędzia pozwalają na tworzenie własnych żądań - **kopiowanie i modyfikowanie istniejących** i/lub **tworzenie żądań od** **"zera"**

**Node.js** posiada wsparcie dla tworzenia serwerów HTTP bezpośrednio w bibliotece standardowej, np.

```javascript
var http = require("http");
var server =
    http.createServer(
    (req, res) => {
        //Wymuszenie interpretowania odpowiedzi w określonym kodowaniu
        res.setHeader('Content-type', 'text/html; charset=utf-8');
        
        res.end(`hello world ${new Date()}`);
    });
    
server.listen(3000);
console.log('started');
```

Argumentem funkcji tworzącej jest **callback** przyjmujący dwa argumenty:
- **req** typu **IncomingMessage** który jest modelem dla żądania od klienta (stąd można odczytać adres i typ żądania, nagłówki, cookies)
- **res** typu **ServerResponse** który jest modelem dla odpowiedzi dla klienta 

Funkcje zwrotne kolejnych żądań (np. wielu użytkowników) trafiają do pętli zdarzeń i tworzą **kolejkę** oczekujących żądań. Są one obsługiwane ***jednowątkowo***.

Asynchroniczność jest kluczowa do zwiększenia przepustowości - procesor przetwarza wyłącznie kod i można zrezygnować z kosztownego oczekiwania na żądanie synchroniczne do zewnętrznego zasobu.

> Na przykład:
> - serwer dostaje żądanie A, ustawia się w kolejce zdarzeń
> - serwer dostaje żądanie B, ustawia się w kolejce zdarzeń
> - serwer rozpoczyna przetwarzanie żądania A, w ramach niego zaczyna odczytywać jakiś plik
> - serwer rozpoczyna przetwarzanie żądania B, w ramach niego zaczyna odczytywać jakiś plik
> - ... serwer czeka w pętli aż zakończy się odczyt plików ...
> - odczyt z żądania A kończy się i do pętli zdarzeń trafia kontynuacja
> - odpowiedź na żądanie A jest przesyłana do klienta
> - odczyt z żądania B kończy się i do pętli zdarzeń trafia kontynuacja
> - odpowiedź na żądanie B jest przesyłana do klienta 
> 
> W trakcie obsługi obu żądań procesor w żadnym momencie nie czekał na odczyt danych z plików - bo w tym czasie przetwarzał inne żadania z pętli zdarzeń

### 1.6 Klaster
W node.js to grupa procesów, które współdzielą ten sam port TCP. Żądanie trafia do któregoś z procesów dzielących się portem.

## 2. HTTPs
Rozszerzenie protokołu **HTTP** w którym pod żądaniem typu **CONNECT** pojawia się dodatkowy tzw. **handshake** czyli **sekwencja komunikatów zmierzająca do ustalenia klucza szyfrującego komunikację**

Ta część komunikacji wykorzystuje algorytm asymetryczny (RSA), gdzie **serwer** ma **klucz publiczny** (certyfikat) i **klucz prywatny** (nie ujawniony).

Serwer przesyła dane do klienta, a klient używa certyfikatu do zaszyfrowania klucza do szyfrowania dalszej komunikacji.

### 2.1 Generowanie certyfikatów
Ceryfikat SSL można wygenerować przy pomocy **OpenSSL**. Przemysłowe certyfikaty, mające zaufane organizacje na szczycie **łańcucha poświadczeń** można kupić lub pozyskać bezpłatnie.

Najprostszy serwer HTTPs w node.js:
```javascript
var fs = require('fs');
var https = require('https');

(async function () {
    var pfx = await fs.promises.readFile('test.pfx');
    var server - https.createServer({
        pfx: pfx,
        passphrase: 'test'
    },
        (req, res) => {
            res.setHeader('Content-type', 'text/html; charset=utf-8');
            res.end('hello world ${new Date()}')
    });
    
    server.listen(3000);
    console.log('started');
})
```

### 2.2 HTTP/2
rozszerza protokól http o optymalizacje w warstwie transportowej:
- otwiera zawsze **jedno gniazdo** między klientem a serwerem
- ruch jest **kompresowany, binarny**
- możliwe jest **zrównoleglanie wielu żądań i wielu odpowiedzi**
- możliwe jest **przesyłanie danych** z serwera do klienta **zanim klient zrobi żądanie**


### 2.3 Rzeczywistość

W pliku **etc/host** możliwe jest mapowanie DNS na potrzeby lokalnej maszyny. W praktyce oznacza to możliwość zamapowania na lokalny sinterfejs sieciowy **127.0.0.X** dowolnego nagłówka hosta.

W rzeczywistości wykorzystuje się co najmniej dwie warstwy serwerów i tzw. **mechanizm reverse proxy**, w którym ruch trafia do warstwy serwerów frontowych na portach 80/443, a stamtąd do serwerów backendowych, schowanych wewnątrz sieci dostawcy.

### 2.4 Formularz, HTTP POST
Komunikacja zwrotna klienta z serwerem możliwa jest dzięki **formularzom**

> Np.:
> ```html
> <!DOCTYPE html>
> <html lang="en">
> <head>
>  <meta charset="UTF-8">
>  <meta name="viewport" content="width=device-width, initial-scale=1.0">
>  <meta http-equiv="X-UA-Compatible" content="ie=edge">
>  <title>Document</title>
> </head>
> <body>
> <form method="POST" enctype="application/x-www-form-urlencoded">
>  <div>
>  Login: <input type='text' name='login' /><br/>
>  <button>Login</button>
>  </div>
>  </form>
> </body>
> </html>
> ```

# Wykład 8
## 1. Express
Najpopularniejszy i najprzystępniejszy framework do wytwarzania w node.js aplikacji niternetowych opartych o klasyczny schemat **Request-Reply**.

Inne podejście - **Single-Page Applications**, gdzie strony nie przeładowują się z każdą interakcją użytkownika (React/Angular)

## 2. Middleware
Funkcja, która obsługuje żądanie i która może delegować częśc pracy do kolejnej funkcji typu middleware. Obsługa żądania może tworzyć łańcuch wywołań:
![image](https://hackmd.io/_uploads/rka42GWs6.png)

Celem tego jest rozdzielenie obsługi autentykacji od obsługi renderowania od obsługi błędów itp.

DO obsługi błędów służy przeciążenie funkcji middleware **z czterema argumentami**. Poniżej przykład, gdzie przekazanie błędu wymaga przekazania jednego paramteru do **next**:

```javascript=
var http = require('http');
var express = require('express');

var app = express();

app.use( (req, res, next) => {
    if ( true ) //warunek błędu
        next('describtion');
    else
        res.end('poprawne działanie');
});

app.use( (errm req, res, next) => {
    res.end( `Error handling request: ${err}`);
});

http.createServer(app).listen(3000);
```

## 3. EJS (Embedded Javascript)
Jeden z wielu silników renderowania dla Express. Zwalnia on z konieczności ręcznego zarządzania szablonami "stron". Wymaga foldera, w którym zapisane są widoki.

Sprawia to, że silnik szablonów jest niezależny od silnika aplikacji.

Konfiguruje się to w ten sposób:
- Konfiguracja silnika renderowania - parametr **view engine**
- Konfiguarcja lokalizacji z widokami - parametr **views**

> ```javascript
> //...
> var app = express();
> app.set('view engine', 'ejs');
> app.set('views', './views');
> //...
> ```
Domyślne rozszerzenie stron **(.ejs)** można zmienić na **.html** z dodatkową prostą konfiguracją
```javascript
app.engine('html', ejs.renderFile);
app.set('view engine', 'html');
```

Najważniejszą cechą EJS jest możliwość mieszania elementów deklaratywnych i imperatywnych wewnątrz widoków, w tym m.in. deklarowanie zmiennych lokalnych
- **<%** i **%>** - ograniczniki struktury imperatywnej
- **<%=** i **%>** - umożliwiają wypisanie wartości
- **<%-** i **%>** - wypisanie wartości zakodowanej (tzw. HTML encoding)

```html
<% var foo = 'bar' %>

<% for ( var i=0; i<5; i++ ) { %>
     <div>
     Element <%= i %>
     </div>
<% } %>

Zmienna foo: <%= foo %>
```

## 4. Dodatkowe elementy architektury aplikacji
### 4.1 Middleware do plików statycznych

Middleware **epxress.static** pozwala określić folder, z którego serwowane są pliki statyczne - w strukturze plików aplikacji jest to zwykle podfolder, ale z punktu widzenia http adresowanie jest względne do roota aplikacji.

### 4.2 Kontrola typu zwracanej odpowiedzi
Za pomocą ustawiania nagłówków możliwe jest kontrolowanie typu odpowiedzi (np. wymuszenie potraktowania odpowiedzi jako pliku do pobrania możliwe jest za pomocą nagłówka Content-disposition)

### 4.3 Obsługa nawigacji między "stronami"
Do przekierowania żądania do innego adresu służy metoda **redirect** obiektu odpowiedzi. Serwer odsyła do przeglądarki status **302 Object moved** z nagłówkiem Location wskazującym na nowy adres. Przeglądarka sama udaje się pod nowy adres z żądaniem typu **GET**

![image](https://hackmd.io/_uploads/ByaNtXWsT.png)

### 4.4 Odczytywanie parametrów przekazanych w pasku adresowym
Odczyt parametrów przekazanych w pasku adresowym możliwy jest za pomocą właściwości **query** obiektu żądania.

### 4.5 Ścieżki dla żądań różnego typu (GET/POST)
Express umożliwia powiązanie funkcji middleware z typem żądania (GET/POST). Zwyczajowo używa się tego do odróżnienia pierwszego żądania, które renderuje zawartość (GET) od kolejnych, które obsługują zwrotnie odesłany formularz (POST)

Odczyt danych z formularza (POST) wymaga dodatkowego middleware, **express.urlencoded**.

# Wykład 9
### Domyślne middleware do obsługi nieobsłużonych ścieżek oraz zagrożenie Cross-Site Scripting
"Domyślne" middleware, dodane jako ostatnie, będzie obsługiwać wszystkie nieobsłużone do tej pory ścieżki.

Użycie znacznika **<%= i %>** chroni aplikację przed zagrożeniem (typu atak polagający na przesłaniu przez atakującego spreparowanego odnośnika zawierającego fragment skryptu do wykonania, np: **http://localhost:3000/foobar<script>window.alert(‘hello’)</script>**)

### Użycie parametrów w ścieżkach i zagrożenie Web Parameter Tampering
Możliwe jest dynamiczne parametryzowanie ścieżek. Sparametryzowana ścieżka dospwuje się do całej klasy ścieżek, a ograniczenie dopasowania polega na możliwości użycia wyrażenia regularnego, (na przykład wymuszającego tylko liczby).

Jednym z typowych mechanizmów ochrony przed tym zagrożeniem jest użycie dodatkowego parametru weryfikującego poprawność odnośnika, wykorzystującego mechanizm HMAC (Hash Message Authentication Code)/

Na serwerze parametr ścieżki adresowej jest łączony z **kluczem tajnym** a otrzymana wartość jest używa jako argument do jednokierunkowej funkcji skrótu.

Wynik jest dodawany do adresu jako jego "podpis", a niezgodność podpisu wyliczonego z oczekiwanym oznacza, że użytkownik **zmodyfikował** wartość parametru.

_____
Inny, prostszy ale nie zawsze możliwy sposób ochrony przed tym zagrożeniem pojawia się gdy link dotyczy **zalogowanego użytkownika** (który na przykład dostał dane z bazy danych powiązanych jakoś ze swoimi danymi).
Czyli - jest zapytanie, które dla zalogowanego użytkownika zwraca listę dozwolonych identyfikatorów i ona pojawia się jako część listy odnośników.

Zatem sprwadzane są warunki:
- użytkownik niezalogowany - zwracana informacja o błędzie
- użytkownik zalogowany - zapytanie wyciągające zbiór identyfiaktorów jest powtarzane a nasepnie sprawdza się czy przychodząca wartość parametru znajduje się w zbiorze:
    - nie znajduje się - zwracana informacja o błędzie
    - znajduje się - zwracamy dane

## Obsługa ciasteczek
Używa się middleware **cookie-parser**.


# Wykład 13
## 1. Trochę SQLa
### 1.1 SELECT
* Do pobrania danych z tabeli służy zapytanie typu `SELECT`
```sql=
SELECT * from Parent 
``` 
* Zbiór wynikowy może być dodatkowo ograniczony klauzulą `WHERE`
```sql=
SELECT * from Parent WHERE ParentName='parent1'
```
* Klauzul może być wiele i mogą tworzyć całe wyrażenie logiczne, tutaj wybieramy wszystkie wiersze leżące pomiędzy tymi dwoma
```sql=
SELECT * from Parent WHERE 'parent'<ParentName AND ParentName<'parent1'
```
* Zbiór może być dodatkowo uporządkowany za pomocą `ORDER BY`
```sql=
SELECT * from Parent WHERE 'parent'<ParentName AND ParentName<'parent1'
ORDER BY ParentName
```

## 1.2 INSERT
Dodawanie danych do tabeli możliwe jest za pomocą zapytania typu `INSERT`. 
* To zapytanie wstawia nowy wiersz do tabeli Parent i przypisuje wartość 'Parent1' do kolumny ParentName
```sql= 
INSERT INTO Parent (ParentName) VALUES ('Parent1')
```
Z kolei w sytuacji gdy jako generator wartości klucza głównego służy sekwencja mamy:
```sql=
CREATE SEQUENCE sequence_name START WITH 1 INCREMENT BY 1;
```
* Wstawianie rekordów z użyciem sekwencji
```sql=
INSERT INTO Parent (Imie, Nazwisko, Plec) VALUES ('Jan', 'Kowalski', 'M');
```
## 1.3 UPDATE/DELETE
* Do modyfikacji rekordów służy zapytanie typu UPDATE np.
```sql=
UPDATE Parent SET ParentName='new name' WHERE ID=1
```
* Do usuwania rekordów – DELETE
```sql=
DELETE FROM Parent WHERE ID=1
```
#TODO