Dynamic form validation, Java applet communication (Netscape Communicator 2.0) To profit from Java’s popularity, LiveScript was renamed to JavaScript (there are no technical relations whatsoever) Language Web Engineering II JavaScript Intro
type conversions - Dynamic: Type checks during runtime - Duck Typing: Type is not determined by class, but by object shape (methods, properties) Language Web Engineering II JavaScript Intro
(arbitrarily large integer) String (Unicode) Null (no value) Undefined (not defined) Symbol (unique atomic value) Object Language Web Engineering II JavaScript Intro
let x; // Assign values via “=” x = 3; let y = 4; Note: The return value of an assignment (without declaration) is the value itself! Variables Web Engineering II JavaScript Intro
Names not allowed as an identifier const astrid = { "foo.bar": 3, "!": 4 } astrid['foo.bar']; // 3 astrid['!']; // 4 Property Access Expressions Web Engineering II JavaScript Intro
name: 'Astrid', age: 31 }]; 1. Get Peter and store as variable “p” using square bracket notation 2. Get his age from the variable using dot notation 3. Get Peter using a destructuring assignment 4. Get Astrid’s name by only using the square bracket notation Property Access Expressions LAB #3 Web Engineering II JavaScript Intro
name: 'Astrid', age: 31 }]; 1. Get Peter and store as variable using square bracket notation const peter = persons[0]; 2. Get his age from the variable using dot notation peter.age; 3. Get Peter using a destructuring assignment const [ peter ] = persons; 4. Get Astrid’s name by only using the square bracket notation persons[1]['name']; Property Access Expressions LAB #3 Web Engineering II JavaScript Intro
const object = { a: 3 } object.b; // undefined object.b.x; // TypeError: Cannot read property 'x' of undefined You cannot read properties from null or undefined! Be careful: undefined is not a reserved keyword! Property Access Expressions Web Engineering II JavaScript Intro
}; astrid.age = 32; astrid['!'] = 3.14159; const does not mean that the object is immutable! Only the reference to the object is immutable, i.e. astrid can’t be redefined to point to a different object. Properties can be updated, created or deleted. delete astrid.age; Property Assignment Web Engineering II JavaScript Intro
new (empty) object literal as the first element of the persons array 2. Update the object literal to have a name property set to Peter 3. Update the name property to contain Astrid instead Property Assignment LAB #4 Web Engineering II JavaScript Intro
new (empty) object literal as the first element of the persons array persons[0] = {}; 2. Update the object literal to have a name property set to Peter persons[0].name = 'Peter'; 3. Update the name property to contain Astrid instead persons[0].name = 'Astrid'; Property Assignment LAB #4 Web Engineering II JavaScript Intro
3; // 3 // Subtract let i = 5; i -= 2; // 3 // Multiply let i = 2; i *= 3; // 6 // Divide let i = 25; i /= 5; // 5 Operators Web Engineering II JavaScript Intro
= i++; // i = 1, j = 0 // Decrement let i = 5; let j = i--; // i = 4, j = 5 // Increment let i = 0; let j = ++i; // i = 1, j = 1 // Decrement let i = 5; let j = --i; // i = 4, j = 4 Operators Web Engineering II JavaScript Intro
> const delta = { x: 3, y: -9 }; You received two objects, one describing the original mouse position, the other an object that describes how far the mouse was moved. What’s the new x and y position of the mouse? const newPoint = { /* … */ }; Operators LAB #5 Web Engineering II JavaScript Intro
> const delta = { x: 3, y: -9 }; You received two objects, one describing the original mouse position, the other an object that describes how far the mouse was moved. What’s the new x and y position of the mouse? const newPoint = {x: point.x + delta.x, y: point.y + delta.y}; // { x: 4, y: 11 } Operators LAB #5 Web Engineering II JavaScript Intro
> 3 == 3 > "3" == 3 > [1] == 1 > 1 == true > 100 == true > NaN == NaN What’s the result? What did you expect? Operators LAB #6 Web Engineering II JavaScript Intro
> 3 === 3 > "3" === 3 > [1] === 1 > 1 === true > 100 === true > NaN === NaN What’s the result? What did you expect? Operators LAB #7 Web Engineering II JavaScript Intro
boom() { throw new Error('boom'); } - Can have a name - Can have parameters - Can return a result (or undefined) - Can throw errors Functions Web Engineering II JavaScript Intro
x + y; }; add(1, 3); // 4 const person = {name: 'Peter'}; person.greet = function () { return `Hallo ${this.name}`; } person.greet(); // 'Hallo Peter' Can be used in any context, e.g. as object methods (greet) Functions Web Engineering II JavaScript Intro
peter = new Person('Peter'); peter.name; // 'Peter' The only functions that may have an uppercase identifier (important convention) Instances can be created via new Functions Web Engineering II JavaScript Intro
= name; } const peter = new Person('Peter'); peter.name; // 'Peter' class Person { constructor(name) { this.name = name; } } const peter = new Person('Peter'); peter.name; // 'Peter' Functions Web Engineering II JavaScript Intro
Global Context - Instance creation via new - Context of the caller - Virtually any value the function was bound to or called with This can cause problems. Functions Web Engineering II JavaScript Intro
b) => a + b; (a, b) => { const c = 123; return a + b + c; } () => ({ a: 123 }) No parameters = parentheses Single parameter = no parentheses Implicit return Curly braces = custom return/throw Return object = parentheses around curly braces Functions Web Engineering II JavaScript Intro
return functions function getMultiplier(multiplier) { return x => x * multiplier; } getMultiplier(10)(3); // 30 Functions Closure Web Engineering II JavaScript Intro
take other functions as arguments (e.g. callbacks) requestData(data => /* … */); [1, 2, 3].filter(value => value >= 2); Functions Web Engineering II JavaScript Intro
= name; } Person.prototype.sayHello = function () { console.log(`Hi, call me ${this.name}`); }; const alfred = new Person('Alfred'); alfred.sayHello();
for (let x in obj) { // for each property in obj } Object.keys(obj) .forEach(x => /* … */) (nur für eigene Eigenschaften) const arr = [1, 2, 3]; for (let x of arr) { // for each element of arr } arr.forEach(x => /* … */); Control Structures Web Engineering II JavaScript Intro
careful: JavaScript automatically inserts semicolons in some cases. Hence, it’s convention to always place braces in the same line. Control Structures Web Engineering II JavaScript Intro
{ // I know my customers now! }, err => { // Something bad has happened! }); Well-known model for handling asynchronous operations “When the operation is done, call this function.”
represents a future value (resolved asynchronously) (In the future) the operation can either succeed or it can fail Promises can be composed in an easy manner
Promise.all([p1, p2, p3]) resolves when all inner promises have been resolved Promise.race([p1, p2, p3]) resolves/rejects when the first inner promise resolves/rejects Promise.reject(new Error('boom')) wrap synchronous value in immediately rejected promise Promise.resolve({ result: 123 }) wrap synchronous value in immediately resolved promise
{ // This then block is only called if the previous op. was successful }).catch(err => { // This catch block catches any previous error, otherwise it's skipped // If it doesn’t reject, execution continues with the next then block return 'test'; }).then(value => { throw new Error(value); // What’s value here? }).finally(() => { // Must appear at last. Doesn’t get value/error, can’t manipulate result }); JavaScript Intro Web Engineering II Promises
single character, planet or starship of your choice! fetch('https://swapi.dev/…') fetch returns a promise wrapping the response. This has a json method for converting the response to JSON (again returns a promise): response.json() alert(`Hello I am ${obj.name}`); Promises Web Engineering II JavaScript Intro LAB #15
sugar over then & catch for using it in a synchronous manner async function getPlanet() { try { const response = await fetch('https://swapi.dev/api/planets/1/'); const planet = await response.json(); alert(`Hello my name is ${planet.name}`); } catch (err) { alert(`Oh no: ${err}`); } } getPlanet();
cancellable • Promise chain is only executed once (can only emit a single value) • Eager, i.e. is executed immediately without checking if somebody is actually interested in the return value • No operators for high-level flow composition • Unhandled promise rejections will terminate Node.js process in the future • Solution: Observables (“Callbacks 3.0”) à Angular
codebase into functional modules instead of one large monolith Often: packages/namespaces/assemblies/… In JavaScript: 1 file = 1 module Introduced in ES 2015 Note: There are different other module systems around (e.g. CommonJS)
export const productName = 'Windows'; // var, let function greet() { console.log('Hi!') }; export { greet as pi, greet }; // Default export (only one per script) export default function cube(x) { return x ** 3 }; export default greet; // Re-exports export * from 'other-file'; export { sum } from 'math';
import * as math from 'math'; import { test, apple as egg } from 'file'; // Default export (only one per script) import cube from 'cube'; // Side-effect import import 'other-file';
require('./cube'); // ./cube.js const cube2 = require('cube'); // node_modules/cube/index.js Be careful: Node.js and many module bundlers (SystemJS, Webpack) use a dot-slash to distinguish between npm modules (Node.js package manager) and files on the file system. Omitting the file extension is recommended (e.g. when using source-to- source compilers such as TypeScript à Angular)
Engineering II JavaScript Intro LAB #16 Node <9 Node 9+ Create cube.js and calculator.js Create cube.mjs and calculator.mjs In cube.js, provide a cube function and assign it to module.exports In cube.mjs, provide a cube function as the default export In calculator.js, consume the cube function by require('./cube') In calculator.mjs, consume the cube function by importing it Test your app by running node calculator.js Test your app by running node --experimental-modules calculator.mjs
valid JS is valid TS) Opt-in static typing TypeScript Compiler is a source-to-source transpiler (target: JavaScript of a given version) Additionally, TypeScript allows you to use (some) Stage 3 features and transpiles them to code understandable by older JavaScript engines (downlevel support). JavaScript Intro Web Engineering II TypeScript
programming, non-blocking infrastructure for scaling) Based on Google’s JavaScript engine V8 (node-chakracore runs on Microsoft’s Chakra Core engine) Can access native interfaces (e.g. file system, devices) in contrast to the browser Node.js Web Engineering II Node.js
both the server and the client Isomorphic JavaScript (2013) Future of web apps, same source is used to render on server/client Universal JavaScript (2015) JavaScript that is able to run in any environment JavaScript on the Server Web Engineering II Node.js
Manager (npm) Packages can be downloaded from a registry (default: https://registry.npmjs.org) npmjs.org is the largest software marketplace in the world npm packages typically cover a very small functionality (e.g. left-pad) npm makes it very easy to turn your app into a package as well “There’s an npm module for that!” Node.js Web Engineering II Node.js Package Manager
versions (v11, v13, v15) Even-numbered versions are typically covered by long-term support (LTS) for a period of 18 months After that, the version will enter maintenance support for another 12 months Hence: Even-numbered versions are supported for approx. 3 years, which make them a good choice for server environments https://github.com/nodejs/Release Node.js Web Engineering II Node.js
by asking a couple of questions This file specifies - name, version, description of your package - entry point of your package - license, author of the package - package dependencies - run scripts - and more… Node.js Web Engineering II Node.js Package Manager
retrieved from the package registry (typically https://registry.npmjs.org) Node.js packages are placed in a folder called node_modules The package manager has two modes: • Global mode (installs packages to a user-level directory): npm i -g @angular/cli • Local mode (installs packages to the current scope): npm i left-pad npm install installs package dependencies from package.json Node.js Web Engineering II Node.js Package Manager
has been changed in your package.json? - New entry dependencies - package name & version number with caret (^) Node.js Web Engineering II Node.js Package Manager LAB #18
during development time only (i.e. command-line tools, source-to-source transpilers) 3. peerDependencies: required to be installed by a dependant package 4. optionalDependencies: do not have to be installed Node.js Web Engineering II Node.js Package Manager
a breaking change is introduced - MINOR version when a backwards-compatible feature is introduced - PATCH when a backwards-compatible bugfix is introduced Plus: Additional labels (e.g. 3.0.0-beta.2+20180413011233) Exception: Major version zero (0.x.y), anything may change anytime. https://semver.org Node.js Web Engineering II Node.js Package Manager
but not 2.2.0 "2.1.x" Floating Minor (caret, default) "^2.1.3" à 2.1.3, 2.6.4, … but not 3.0.0 "2.x" Node.js Web Engineering II Node.js Package Manager
central cache or after installing it Convenient alternative to npm i –g in some cases npx cowsay -s "Yo" Node.js Web Engineering II Node.js Package Manager LAB #19
versions in your repository. This allows time travelling through the repository’s history (i.e. when switching back in time, the exact same package versions get installed that were in use back then) In addition, it ensures that both developer and build server use the same package versions. Node.js Web Engineering II Node.js Package Manager
the registry (npmjs.org by default) Requires prior login via npm login "private": true prevents accidental publication publishConfig allows specifying a set of whitelisted (private) registries Node.js Web Engineering II Node.js Package Manager
scripts for common tasks (e.g. running tests, building the application, deployments) The run scripts are defined in the scripts object: "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, Special scripts: start (npm start), test (npm test) Node.js Web Engineering II Node.js Package Manager
This pattern clearly separates events and event listeners and turns out to be more practical than callbacks Event emitters can emit multiple events over time http.request(options, response => { response.on("data", data => console.log(data)); }); Node.js Web Engineering II Simple HTTP Server
editor) in 2000 Architectural Styles and the Design of Network-based Software Architectures Client-server communication RESTful APIs are stateless Resource representation in XML, HTML, JSON, … https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm Node.js Web Engineering II Web APIs
Creates a new child resource. PUT Updates a given resource. DELETE Deletes a resource. HEAD Checks if the given resource exists. OPTIONS Determines which verbs can be executed on a given resource. Node.js Web Engineering II Web APIs
be called several times without different outcomes)? - safe (i.e. don’t modify resources)? GET / POST / PUT / DELETE / OPTIONS / HEAD Node.js Web Engineering II Web APIs LAB #22
be called several times without different outcomes)? GET, PUT, DELETE, OPTIONS, HEAD - safe (i.e. don’t modify resources)? GET, OPTIONS, HEAD GET / POST / PUT / DELETE / OPTIONS / HEAD Node.js Web Engineering II Web APIs LAB #22
and language (Accept-Language) via HTTP headers If the server can fulfill the request, it responds with the given format/charset/encoding/language. e.g. https://example.com/people/alfred Same resource, different representations (JSON, XML, etc.) Node.js Web Engineering II Web APIs
applications including RESTful APIs https://expressjs.com/ NestJS: Framework for building efficient, scalable Node.js server-side applications. Under the hood, Nest makes use of Express. https://docs.nestjs.com/ https://docs.nestjs.com/techniques/performance Node.js Web Engineering II Web APIs with Node.js LAB #24
Node.js + TypeScript NestJS uses Express or Fastify (http/2) under the hood Includes a command-line interface for scaffolding/running/building NestJS backends Heavily borrows from Angular’s architecture (e.g. controllers, pipes, guards, interceptors, dependency injection and more) Node.js Web Engineering II NestJS
npm as package manager cd project-name npm start Postman: GET http://localhost:3000 Git missing? Download it at: https://git-scm.org Node.js Web Engineering II NestJS LAB #25
GET /greet/hello @Controller('greet') export class GreetController { @Get('hello') getHello(): string { return 'Hello!'; } } Node.js Web Engineering II NestJS
e.g. GET /greet/Alfred @Controller('greet') export class GreetController { @Get(':name') getHello(@Param('name') name): string { return `Hello ${name}!`; } } Node.js Web Engineering II NestJS
HttpException('Forbidden', HttpStatus.FORBIDDEN); // Response objects are serialized throw new HttpException({ text: '403' }, HttpStatus.FORBIDDEN); // Shorthand exceptions throw new ImATeapotException(); Node.js Web Engineering II NestJS
now, this endpoint should always fail. Use an error that is suitable for communicating that there was a conflict (see https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) Test the endpoint using Postman. Node.js Web Engineering II NestJS LAB #28
id (number, optional for creation) - name (string) - done (boolean) { "id": 0, "name": "Wäsche waschen", "done": true } nest generate class todo Node.js Web Engineering II NestJS LAB #29
TODOs (GET /todos) - 200 OK + array - Fetching a single TODO (GET /todos/123) - 200 OK + object if it exists or 404 Not Found if it does not exist - Creating new TODOs (POST /todos + object without ID) - 201 Created + created object including ID! - Updates a TODO (PUT /todos/123 + object) - 204 No Content - Deletes a TODO (DELETE /todos/123) - 204 No Content Node.js Web Engineering II NestJS LAB #29
and a numeric ID. - Use an auto-incremented ID - map.set(id, elm) sets the element with the given ID - map.get(id) returns/accesses the element with the given ID - map.delete(id) removes the element with the given ID - Array.from(map.values()) returns all elements Node.js Web Engineering II NestJS LAB #29
Is she who she says she is? There are a large number of systems that handle this “checkpoint” level of identity and access management and help to reduce the number of credentials that a user needs to provide, often through single sign-on (or SSO). (https://www.cyberark.com/blog/distinguishing-authn-and-authz/, abgerufen 06.05.2018) Node.js Web Engineering II AuthN
this user or system be allowed to access (authz can manage service-to- service as well as user-to-service permissioning)? An authz platform might determine if a user is a developer, and then grant his/her permission to push source code to a Git repository, but prohibit the user from directly changing the software deployed into the production environment. (https://www.cyberark.com/blog/distinguishing-authn-and-authz/, abgerufen 06.05.2018) Node.js Web Engineering II AuthZ
at some point in the future Leaking the token does not leak the password Allows other means of authentication (Single sign-on, passwordless logins, etc.) Node.js Web Engineering II The Solution…
established in 2012 RFC 6749: “The OAuth 2.0 Authorization Framework” Designed with cross-platform applications and living room devices in mind Node.js Web Engineering II OAuth 2.0
Server Server storing protected resources (i.e. data). Client Application that wants to access resources from the resource server. Authorization Server Authenticates the resource owner and provides access tokens for a certain scope. Can be identical to the resource server. Node.js Web Engineering II OAuth 2.0
could make use of it?) Describe how this flow technically works (any special requirements?) Explain the scenario and the sequence diagram Can refresh tokens be issued? (Why?/Why not?) Are there known vulnerabilities? liebel.io/oauthflow Node.js Web Engineering II OAuth 2.0 LAB #31
sent to a different origin have to contain a Access-Control- Allow-Origin header that whitelists the origin where the request originated from Node.js Web Engineering II OAuth 2.0
Securely transmit information between parties as a JSON object Encoded in base64 Can be verified and trusted because it is digitally signed But: Data is not encrypted! Node.js Web Engineering II JWT
MiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoSK5hoDal rcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4XUVrWOL rLl0nx7RkKU8NXNHq-rvKMzqg Node.js Web Engineering II JWT
iss – entity that issued this token (issuer) sub – authorized subject aud – audience the token is intended for exp – when does the token expire? nbf – when does the token validity start? (not before) Node.js Web Engineering II JWT
that represents a cryptographic key. The members of the object represent properties of the key, including its value. JSON Web Key Set (JWKS) A JSON object that represents a set of JWKs. The JSON object MUST have a keys member, which is an array of JWKs. Node.js Web Engineering II Token Validation
you) Different transport methods: HTTP Long Polling, WebSockets (based on what’s available on the target platform) https://socket.io Node.js Web Engineering II Socket.io
@WebSocketGateway() export class EventsGateway { @WebSocketServer() server: Server; } https://docs.nestjs.com/websockets/gateways Node.js Web Engineering II Socket.io
version • September/October: odd version Deprecation Policy • Compatibility to previous major version (1 year) • Long-Term Supported Version (critical fixes/security patches only) • 6.x (Oct 2018–19, 1.5 years in total) Angular Kickstart Angular
server requirements (i.e., serving static files is sufficient) Disadvantages • Some logic (i.e., computation- intensive) can only be run on a server (connection required) • Logic is transfered to the client (code can’t be kept secret) Single-Page Web Application (SPA) Kickstart Angular
i -g @angular/cli 2. Please create a new Angular CLI project: ng new todoApp 3. Run the following command and navigate to http://localhost:4200: ng serve Angular CLI LAB #36 Kickstart Angular
be interpolated Or: UI references a method on the component instance that should be called on a certain event Automatically updates UI when the model is updated Keeps presentation and model in sync Data Binding Kickstart Angular
and initialize it with a CSS color value (e.g., hotpink) 2. Create a new div element in the AppComponent’s HTML template 3. Bind the value of the field to the background color of the div element Hint: [style.backgroundColor] Property Binding LAB #39 Kickstart Angular
(it opens an alert box: alert('Hello!')) 2. Create a new button element in the AppComponent’s HTML template 3. Bind the click event of the button to the onClick method Hint: (click)="onClick()" 4. Implement a new method “onMouseMove” on the component instance (it logs to the console) 5. Bind the mousemove event of the button to onMouseMove Event Binding LAB #40 Kickstart Angular
to be printed as UPPERCASE. 2. Add a new numeric field to your AppComponent. Bind this field to the template using the pipes: • Percent • Currency • Number (showing five decimal places) Example: {{ value | number:'0.3' }} Pipes LAB #42 Kickstart Angular
yell pipe should suffix the bound value with three exclamation marks. • The developer can optionally pass an argument to override the suffix. {{ value | yell }} à Hello!!!! {{ value | yell:'???' }} à Hello!??? Pipes LAB #44 Kickstart Angular
2. Add a new myTodo field to the AppComponent which holds a todo object { name: "Wash clothes", done: false, id: 3 } 3. Pass the myTodo object to the todo component from the AppComponent’s template. 4. In the TodoComponent’s template, bind the value of the todo field using the JSON pipe. Input LAB #47 Kickstart Angular
Add a button to your TodoComponent and an event binding for the click event of this button. When the button is clicked, emit the done event. Pass the current todo object as the event argument. 3. In the AppComponent’s template, bind to the done event and log the finalized item to the console. @Output() public done = new EventEmitter<any>(); // done.emit(todo); Output LAB #47 Kickstart Angular
bound to a boolean value. If the value is truthy, the class is set. If the value is falsy, the class is removed. 1. Add a HostListener that listens for any click on the host element. 2. Introduce a new boolean field called doneState. 3. Assign a HostBinding to it which sets the done class. 4. The click handler method should toggle the underlying field. 5. Bonus: Adjust the component’s CSS to strikethrough all the text inside the component when the done class is set. HostBinding/HostListener LAB #48 Kickstart Angular
classes can be used as providers and injectables, as interfaces vanish during TypeScript transpilation - Alternative for non-class dependencies: InjectionTokens - Classes have to be marked as @Injectable if they want to request dependencies - Dependencies can be requested by simply using them as a constructor parameter Angular Kickstart Angular DI
g s todo) 1. Which files have been created by the CLI? 2. What is their purpose? 3. (How) are they provided in the DI container? Services LAB #51 Kickstart Angular
create(todo: Todo): Todo - get(todoId: number): Todo - getAll(): Todo[] - update(todo: Todo): void - delete(todoId: number): void Add a very basic, synchronous implementation for getAll, get and create. Services LAB #53 Kickstart Angular
todos and assign the return value of todoService.getAll() to it - bind this field to the view using the *ngFor structural directive and an unordered list (<ul>) with one list item (<li>) for each todo <li *ngFor="let todo of todos"></li> Angular Kickstart *ngFor LAB #56
TodoComponent (app-todo) instead and pass the todo via the todo property binding. Adjust the template of TodoComponent to include: - A checkbox (input) to show the “done” state - A label to show the “name” text <label> <input type="checkbox" [checked]="todo.done"> {{ todo.name }} </label> Angular Kickstart Refactoring Step LAB #57
When we are using our Node.js-based TODO API, this will be an asynchronous task (due to network roundtrip) For a fast and fluid user experience, everything that could potentially take longer than 16ms (=> 60 fps) should be done asynchronously! Angular Kickstart Observables