SlideShare una empresa de Scribd logo
1 de 58
Descargar para leer sin conexión
A single language for Backend and
Frontend: from AngularJS to Cloud
AngularConf 2016 - Turin
corley.it
Walter Dal Mut
github.com/wdalmut
twitter.com/walterdalmut
the problem
The REST webservice
Decoupling
Caching
Stateless
Quota planning (API Limits)
Extendable
Proxable
etc...
Planning
GET    → /book Access to a list of books
GET    → /book/:id Access to a single book
POST   → /book Create a new book
PATCH  → /book/:id Update a given book
DELETE → /book/:id Delete a given book
We can extends this using authentication header Authorization
We have a simple API
'use strict' ; 
angular.module( 'myApp').service( 'bookService' , function($http) { 
  return { 
    "list": function() { 
      return $http.get( "http://localhost:8085/book" ); 
    }, 
    ... // more methods  
  }; 
});
So we create a service
Or we can create a provider to configure the URLs etc
With a service we have a box
with different methods
bookService
Get all books: list()
Get a single book: get(:bookId)
Create a book: create(:bookModel)
...
The Book model is stable across our application
{title: "the book title" , isbn: "12345678" , available : true}
Or we resolve the book dependency with the book link (thanks to API uniquiness)
{ 
    name: "my favourites" , 
    books: [ 1,2,3] 
}
So:
$q.all( 
  [1,2,3].map(bookService.get)  
).then(function(books) {  
    //books is my favourites list with details  
});
Where the GET
'use strict' ; 
angular.module( 'myApp').service( 'bookService' , function($http) { 
  return { 
    "get": function(id) { 
      return $http.get( "http://localhost:8085/book/" +id); 
    }, 
    "list": function() { 
      return $http.get( "http://localhost:8085/book" ); 
    }, 
    ... // more methods  
  }; 
});
Return back to
A controller can request data
angular.module( 'myApp') 
  .controller( 'MainCtrl' , function ($scope, bookService) {  
    $scope.books = [];  
    bookService.list().success(function(books) {  
      $scope.books = books;  
    }); 
  });
Thanks to the controller we can pass our books to the view
The scope the communication channel for the data
Q: how can i verify the scope interface?
R: via testing (unit testing)?
Add a test case (1/2)
describe( "MainCtrl" , function() { 
    beforeEach(module( 'myApp')); 
    beforeEach(inject(function ($controller, $rootScope, $httpBackend) {  
        scope = $rootScope.$new();  
        httpBackend = $httpBackend;  
        MainCtrl = $controller( 'MainCtrl' , { 
            $scope: scope,  
            // other mocks  
        });  
    })); 
    // continue...  
});
Add a test case (2/2)
it('should attach a list of books to the scope' , function () {  
    // when someone require the "/book" endpoint reply with a valid response  
    httpBackend.whenGET( "http://localhost:8085/book" ).respond([  
      { id: 1, title: "This is a book" , isbn: "9835623" , available:  true }, 
      { id: 2, title: "Another super book" , isbn: "9835624" , available:  true }, 
      { id: 3, title: "A rare book to read" , isbn: "9835625" , available:  false } 
    ]); 
    // force the HTTP data resolution  
    httpBackend.flush();  
    // my expectation are that we books in the controller scope.  
    expect(scope.books.length).toBe( 3); 
    expect(scope.books.map((item) => item.title)).toEqual([  
      "This is a book" , 
      "Another super book" , 
      "A rare book to read"  
    ]); 
  });
$httpBackend act as a spy for HTTP requests
main.html
<!­­ books is in the current scope ­­>  
<books­list  books="books"></books­list >
The directive (web component)
angular.module("myApp") 
  .directive( 'booksList' , function() { 
    return { 
      replace:  true,
      templateUrl:  "app/views/books­list.html" , 
      restrict:  "E",
      scope: {  
        "books": "=", 
      }, 
      link:  function() {}, 
    }; 
  });
books-list.html
<div> 
    <book ng­if="book.available"  book="book" ng­repeat ="book in books" ></book> 
</div>
The book web component
angular.module("myApp") 
  .directive( 'book', function() { 
    return { 
      replace:  true,
      templateUrl:  "app/views/book.html" , 
      restrict:  "E",
      scope: {  
        "book": "=", 
      }, 
      link:  function() {}, 
    }; 
  });
book.html
<div>
    {{ book.title }}  
</div>
Components testing (1/3)
describe( "Books List" , function() { 
  var $compile,  
    $rootScope;  
  beforeEach(module( 'myApp')); 
  beforeEach(function() {  
    inject(function( _$compile_, _$rootScope _){ 
      $compile =  _$compile_; 
      $rootScope =  _$rootScope _; 
    }); 
  });
});
Components testing (2/3)
it("should expose our books" , function() { 
    $rootScope.books = [  
        { id:  1, title:  "This is a book" , isbn: "9835623" , available: true }  
        { id:  2, title:  "Another book" , isbn: "9835624" , available: true }  
        { id:  2, title:  "A secret book" , isbn: "9835625" , available: false }  
    ]; 
    var element = $compile( '<books­list books="books"></books­list>' )($rootScope);  
    $rootScope.$digest();  
    var html = element.html();  
    expect(html).toContain( "This is a book" ); 
    expect(html).toContain( "Another book" ); 
    expect(html).not.toContain( "A secret book" ); 
});
Components testing (3/3)
Single book directive testing
it("should expose a single book" , function() { 
    $rootScope.book = {  
        id:  1, 
        title:  "This is a single book" , 
        isbn:  "9835623" , 
        available: true  
    }; 
    var element = $compile( '<book book="book"></book>' )($rootScope);  
    $rootScope.$digest();  
    var html = element.html();  
    expect(html).toContain( "This is a single book" ); 
});
Add a book creation
We need the create book service method
We need another dummy web component
We use the controller to save the book model
The create method
angular.module( 'myApp').service( 'bookService' , function($http) {  
  return {  
    "create": function(book) {  
      return $http.post( "http://localhost:8085/book" , book); 
    }, 
    /* already implemented */  
    "get": function(id) {  
      return $http.get( "http://localhost:8085/book/" +id); 
    }, 
    "list": function() {  
      return $http.get( "http://localhost:8085/book" ); 
    }, 
  }; 
});
Dummy web component (1/3)
angular.module("myApp") 
  .directive( 'bookForm' , function() { 
    return { 
      replace:  true,
      templateUrl:  "app/views/book­form.html" , 
      restrict:  "E",
      scope: {  
        "book": "=", 
        "save": "=", 
      } 
    }; 
  });
We can also skip the book model pass-through
Dummy web component (2/3)
<div>
    <form> 
        Title: < input type="text" ng­model= "book.title"  /><br> 
        ISBN: < input type="text" ng­model= "book.isbn"  /><br> 
        Available: < input type="checkbox"  ng­model= "book.available"  /><br> 
        <button  type="button" ng­click= "save(book)" >Save</button>< br> 
    </form> 
</div>
Pay attention on ng-click that pass the book model
Dummy web component (3/3)
it("should expose a book", function(done) { 
  $rootScope.book = {}; 
  $rootScope.save = function(book) { 
    expect(book.title).toEqual("Some text"); 
    expect(book.isbn).toEqual("123456"); 
    expect(book.available).toBe(true); 
    done(); 
  }; 
  var element = $compile('<book­form book="book" save="save"></book­form>')($rootScope); 
  $rootScope.$digest(); 
  angular.element(element.find('input')[0]).val('Some text').triggerHandler('input'); 
  angular.element(element.find('input')[1]).val('123456').triggerHandler('input'); 
  angular.element(element.find('input')[2]).prop('checked', 'checked').triggerHandler('click'); 
  $rootScope.$apply(); 
  element.find('button')[0].click(); 
});
So we have validated that the directive calls the save method
But... Who have the save method? Controller + Book Service
Previous Controller (1/2)
angular.module( 'myApp') 
  .controller( 'MainCtrl' , function ($scope, bookService) {  
    $scope.book = {};  
    $scope.save = function(book) {  
      bookService.create(book).success(function(book) {  
        $scope.books = $scope.books.concat([book]);  
      });  
      $scope.book = {};  
    }; 
    // old parts...  
    $scope.books = [];  
    bookService.list().success(function(books) {  
      $scope.books = books;  
    }); 
  });
<book­form book="book" save="save"></book­form>
Previous Controller (2/2)
it('should create a new book', function () {  
  // something uses the save method  
  var book = {title: "This is a book", isbn: "9835623", available: true }; 
  scope.save(book); 
  // then the backend should works as expected  
  httpBackend.whenGET("http://localhost:8085/book" ).respond([]); 
  httpBackend.whenPOST("http://localhost:8085/book" ).respond( 
    Object.assign({}, book, {id: 1}) 
  );
  httpBackend.flush(); 
  expect(scope.book).toEqual({}); 
  expect(scope.books.length).toBe(1); 
  expect(scope.books[0].id).toBe(1); 
  expect(scope.books[0].title).toEqual("This is a book"); 
  expect(scope.books[0].isbn).toEqual("9835623"); 
  expect(scope.books[0].available).toBe(true); 
});
We can develop the app but...
How to deliver a scalable and
cost-effective backend?
ServerLess environments
Those envs allows us to pay just for every single requests
No requests? No payments! [more or less]
No server maintenance (platform as a service)
Amazon Web Services
AWS API Gateway [✔]
AWS Lambda [✔]
AWS DynamoDB [✔]
AWS SNS [ ]
AWS SQS [ ]
AWS CloudWatch [ ]
so many services... [ ... ]
API Gateway
Thanks to API Gateway you can create/publish/maintain/monitor
and secure APIs at any scale
Essentially: with API Gateway you declare your APIs interfaces and delegate to another component (like Lambda,
EC2, etc) the functionality
Lambda is a compute service that can run the code on your behalf
using AWS infrastructure
Amazon DynamoDB is a fully managed NoSQL database service that
provides fast and predictable performance with seamless scalability.
["apiGateway", "lambda", "dynamodb"].reduce(myAppFn);
Dealing with
ApiGateway + Lambda
manually is tricky
AWS releases a project: ServerLess that
helps a lot the wiring
https://github.com/serverless/serverless
ServerLess is interesting but for REST API
is not super simple to use imho...
I prefer to use Claudia.js
https://github.com/claudiajs/claudia
Claudia expose a very simple interface
var ApiBuilder =  require('claudia­api­builder' ), 
    api =  new ApiBuilder();  
api.get('/hello', function (request, response)  { 
    return "Hello"; 
});
Similar to express or hapi
You can use return codes and more
features...
api.post('/account' , function (request) {  
    return api.ApiResponse ({ 
        name: "Walter", 
        surname: "Dal Mut"  
    }, 201); 
});
Claudia.js prepare the whole ApiGateway and Lambda
configuration (with CORS) automatically for you
claudia create   
    ­­name book­ module  
    ­­region eu­west­ 1  
    ­­api­module book  
    ­­config claudia­books.json
It creates a new module book-module and store in claudia-books.json the Claudia.js con guration
Claudia.js manage also all updates
claudia update  
    ­­config claudia­ conf.json
So we have to develop our API
Thanks to Joi we can add data validation to our API
var joi = require(' Joi');
var result = joi.object().keys({  
  id: joi.number().required(),  
  title: joi. string().min(1).required()  
}).validate(request.body);  
if (result.error) {  
    return new api. ApiResponse (result.error, 406);
} 
// continue
Claudia.js manage JSON data automatically
Claudia.js manage A+ Promises as a
return element
api.post( "/say­ok" , function(request)  { 
    var d = q.promise();  
    setTimeout( function() { 
        d.resolve( "OK"); 
    }, 2000); 
    return d.promise;  
});
So...
api.post( "/say­ok" , function(request)  { 
    // validation...  
    return db.save(request.body);  
});
For Node.js DynamoDB offers a
"Document client"
docClient =  new AWS.DynamoDB.DocumentClient({region:  "eu­west­1" }); 
docClient.put({  
  Item: {name:  "Walter", surname:  "Dal Mut" }, 
  TableName: tableName  
}).promise();  
docClient.get( ...); // primary key  
docClient.query( ...); // on a secondary index and/or primary key  
docClient.scan( ...); // search without index (table scan)
All methods have a A+ Promise implementation integrated
Put all together
api.post( "/book", function(request) {  
  var d = q.promise();  
  var result = joi.object().keys({  
    title: joi. string().min(1).required(),  
    isbn: joi. string().min(1).required(),  
    available: joi.boolean().required()  
  }).validate(request.body);  
  if (result.error) {  
    return new api. ApiResponse (result.error, 406);
  } 
  var id = uuid.v4();  
  var item = Object.assign({}, {id: id}, request.body);  
  docClient.put({ Item: item, TableName : tableName}).promise().then(function() {  
    d.resolve(item);  
  });; 
  return d.promise;  
});
Of course you can split all responsabilities to di erent components
Thank you for listening
If you are interested in workshops and/or training sessions feel free
to contact info@corley.it
Check out also our page for training at: corsi.corley.it
Check out our corporate website: corley.it

Más contenido relacionado

La actualidad más candente

Practical Use of MongoDB for Node.js
Practical Use of MongoDB for Node.jsPractical Use of MongoDB for Node.js
Practical Use of MongoDB for Node.jsasync_io
 
The Django Book chapter 5 Models
The Django Book chapter 5 ModelsThe Django Book chapter 5 Models
The Django Book chapter 5 ModelsVincent Chien
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony AppsKris Wallsmith
 
Welcome the Offical C# Driver for MongoDB
Welcome the Offical C# Driver for MongoDBWelcome the Offical C# Driver for MongoDB
Welcome the Offical C# Driver for MongoDBMongoDB
 
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway ichikaway
 
Eve - REST API for Humans™
Eve - REST API for Humans™Eve - REST API for Humans™
Eve - REST API for Humans™Nicola Iarocci
 
Cleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQueryCleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQueryRebecca Murphey
 
2013-08-08 | Mantle (Cocoaheads Vienna)
2013-08-08 | Mantle (Cocoaheads Vienna)2013-08-08 | Mantle (Cocoaheads Vienna)
2013-08-08 | Mantle (Cocoaheads Vienna)Dominik Gruber
 
jQuery and Rails, Sitting in a Tree
jQuery and Rails, Sitting in a TreejQuery and Rails, Sitting in a Tree
jQuery and Rails, Sitting in a Treeadamlogic
 
Code Samples &amp; Screenshots
Code Samples &amp; ScreenshotsCode Samples &amp; Screenshots
Code Samples &amp; ScreenshotsNii Amah Hesse
 
How to use MongoDB with CakePHP
How to use MongoDB with CakePHPHow to use MongoDB with CakePHP
How to use MongoDB with CakePHPichikaway
 
Time to React!
Time to React!Time to React!
Time to React!STX Next
 
Firebase for Apple Developers
Firebase for Apple DevelopersFirebase for Apple Developers
Firebase for Apple DevelopersPeter Friese
 
Apache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux FestApache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux FestMyles Braithwaite
 
Rails 3 ActiveRecord
Rails 3 ActiveRecordRails 3 ActiveRecord
Rails 3 ActiveRecordBlazing Cloud
 
Beyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS AppsBeyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS AppsRebecca Murphey
 
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsSymfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsIgnacio Martín
 

La actualidad más candente (20)

Practical Use of MongoDB for Node.js
Practical Use of MongoDB for Node.jsPractical Use of MongoDB for Node.js
Practical Use of MongoDB for Node.js
 
The Django Book chapter 5 Models
The Django Book chapter 5 ModelsThe Django Book chapter 5 Models
The Django Book chapter 5 Models
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
Welcome the Offical C# Driver for MongoDB
Welcome the Offical C# Driver for MongoDBWelcome the Offical C# Driver for MongoDB
Welcome the Offical C# Driver for MongoDB
 
Javascript - Beyond-jQuery
Javascript - Beyond-jQueryJavascript - Beyond-jQuery
Javascript - Beyond-jQuery
 
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
Tips of CakePHP and MongoDB - Cakefest2011 ichikaway
 
Eve - REST API for Humans™
Eve - REST API for Humans™Eve - REST API for Humans™
Eve - REST API for Humans™
 
Cleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQueryCleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQuery
 
2013-08-08 | Mantle (Cocoaheads Vienna)
2013-08-08 | Mantle (Cocoaheads Vienna)2013-08-08 | Mantle (Cocoaheads Vienna)
2013-08-08 | Mantle (Cocoaheads Vienna)
 
jQuery and Rails, Sitting in a Tree
jQuery and Rails, Sitting in a TreejQuery and Rails, Sitting in a Tree
jQuery and Rails, Sitting in a Tree
 
MongoDB
MongoDBMongoDB
MongoDB
 
Code Samples &amp; Screenshots
Code Samples &amp; ScreenshotsCode Samples &amp; Screenshots
Code Samples &amp; Screenshots
 
How to use MongoDB with CakePHP
How to use MongoDB with CakePHPHow to use MongoDB with CakePHP
How to use MongoDB with CakePHP
 
Ruby gems
Ruby gemsRuby gems
Ruby gems
 
Time to React!
Time to React!Time to React!
Time to React!
 
Firebase for Apple Developers
Firebase for Apple DevelopersFirebase for Apple Developers
Firebase for Apple Developers
 
Apache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux FestApache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux Fest
 
Rails 3 ActiveRecord
Rails 3 ActiveRecordRails 3 ActiveRecord
Rails 3 ActiveRecord
 
Beyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS AppsBeyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS Apps
 
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsSymfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worlds
 

Similar a A single language for backend and frontend from AngularJS to cloud with Claudia.js

Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScriptAndrew Dupont
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackNelson Glauber Leal
 
Link.javaLink.javapackage com.bookstore.domain.model;import .docx
Link.javaLink.javapackage com.bookstore.domain.model;import .docxLink.javaLink.javapackage com.bookstore.domain.model;import .docx
Link.javaLink.javapackage com.bookstore.domain.model;import .docxSHIVA101531
 
Performances & SEO in AngularJS
Performances & SEO in AngularJSPerformances & SEO in AngularJS
Performances & SEO in AngularJSPhilos.io
 
First java-server-faces-tutorial-en
First java-server-faces-tutorial-enFirst java-server-faces-tutorial-en
First java-server-faces-tutorial-entechbed
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneRafael Felix da Silva
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackNelson Glauber Leal
 
Seu primeiro app Android e iOS com Compose Multiplatform
Seu primeiro app Android e iOS com Compose MultiplatformSeu primeiro app Android e iOS com Compose Multiplatform
Seu primeiro app Android e iOS com Compose MultiplatformNelson Glauber Leal
 
cake phptutorial
cake phptutorialcake phptutorial
cake phptutorialice27
 
A piece of sugar in your client-side development
A piece of sugar in your client-side developmentA piece of sugar in your client-side development
A piece of sugar in your client-side developmentNicolas Blanco
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5arajivmordani
 
Perl: Hate it for the Right Reasons
Perl: Hate it for the Right ReasonsPerl: Hate it for the Right Reasons
Perl: Hate it for the Right ReasonsMatt Follett
 
REST APIs in Laravel 101
REST APIs in Laravel 101REST APIs in Laravel 101
REST APIs in Laravel 101Samantha Geitz
 
Introduction to the new official C# Driver developed by 10gen
Introduction to the new official C# Driver developed by 10genIntroduction to the new official C# Driver developed by 10gen
Introduction to the new official C# Driver developed by 10genMongoDB
 

Similar a A single language for backend and frontend from AngularJS to cloud with Claudia.js (20)

Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScript
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com Jetpack
 
Link.javaLink.javapackage com.bookstore.domain.model;import .docx
Link.javaLink.javapackage com.bookstore.domain.model;import .docxLink.javaLink.javapackage com.bookstore.domain.model;import .docx
Link.javaLink.javapackage com.bookstore.domain.model;import .docx
 
Performances & SEO in AngularJS
Performances & SEO in AngularJSPerformances & SEO in AngularJS
Performances & SEO in AngularJS
 
First java-server-faces-tutorial-en
First java-server-faces-tutorial-enFirst java-server-faces-tutorial-en
First java-server-faces-tutorial-en
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com Backbone
 
Rails vu d'un Javaiste
Rails vu d'un JavaisteRails vu d'un Javaiste
Rails vu d'un Javaiste
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com Jetpack
 
Seu primeiro app Android e iOS com Compose Multiplatform
Seu primeiro app Android e iOS com Compose MultiplatformSeu primeiro app Android e iOS com Compose Multiplatform
Seu primeiro app Android e iOS com Compose Multiplatform
 
cake phptutorial
cake phptutorialcake phptutorial
cake phptutorial
 
A piece of sugar in your client-side development
A piece of sugar in your client-side developmentA piece of sugar in your client-side development
A piece of sugar in your client-side development
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5a
 
The Beauty of Java Script
The Beauty of Java ScriptThe Beauty of Java Script
The Beauty of Java Script
 
Perl: Hate it for the Right Reasons
Perl: Hate it for the Right ReasonsPerl: Hate it for the Right Reasons
Perl: Hate it for the Right Reasons
 
XQuery Rocks
XQuery RocksXQuery Rocks
XQuery Rocks
 
REST APIs in Laravel 101
REST APIs in Laravel 101REST APIs in Laravel 101
REST APIs in Laravel 101
 
Java Script Best Practices
Java Script Best PracticesJava Script Best Practices
Java Script Best Practices
 
Php introduction
Php introductionPhp introduction
Php introduction
 
Introduction to the new official C# Driver developed by 10gen
Introduction to the new official C# Driver developed by 10genIntroduction to the new official C# Driver developed by 10gen
Introduction to the new official C# Driver developed by 10gen
 
"Javascript" por Tiago Rodrigues
"Javascript" por Tiago Rodrigues"Javascript" por Tiago Rodrigues
"Javascript" por Tiago Rodrigues
 

Más de Corley S.r.l.

Aws rekognition - riconoscimento facciale
Aws rekognition  - riconoscimento faccialeAws rekognition  - riconoscimento facciale
Aws rekognition - riconoscimento faccialeCorley S.r.l.
 
AWSome day 2018 - scalability and cost optimization with container services
AWSome day 2018 - scalability and cost optimization with container servicesAWSome day 2018 - scalability and cost optimization with container services
AWSome day 2018 - scalability and cost optimization with container servicesCorley S.r.l.
 
AWSome day 2018 - API serverless with aws
AWSome day 2018  - API serverless with awsAWSome day 2018  - API serverless with aws
AWSome day 2018 - API serverless with awsCorley S.r.l.
 
AWSome day 2018 - database in cloud
AWSome day 2018 -  database in cloudAWSome day 2018 -  database in cloud
AWSome day 2018 - database in cloudCorley S.r.l.
 
Trace your micro-services oriented application with Zipkin and OpenTracing
Trace your micro-services oriented application with Zipkin and OpenTracing Trace your micro-services oriented application with Zipkin and OpenTracing
Trace your micro-services oriented application with Zipkin and OpenTracing Corley S.r.l.
 
Apiconf - The perfect REST solution
Apiconf - The perfect REST solutionApiconf - The perfect REST solution
Apiconf - The perfect REST solutionCorley S.r.l.
 
Apiconf - Doc Driven Development
Apiconf - Doc Driven DevelopmentApiconf - Doc Driven Development
Apiconf - Doc Driven DevelopmentCorley S.r.l.
 
Authentication and authorization in res tful infrastructures
Authentication and authorization in res tful infrastructuresAuthentication and authorization in res tful infrastructures
Authentication and authorization in res tful infrastructuresCorley S.r.l.
 
Flexibility and scalability of costs in serverless infrastructures
Flexibility and scalability of costs in serverless infrastructuresFlexibility and scalability of costs in serverless infrastructures
Flexibility and scalability of costs in serverless infrastructuresCorley S.r.l.
 
CloudConf2017 - Deploy, Scale & Coordinate a microservice oriented application
CloudConf2017 - Deploy, Scale & Coordinate a microservice oriented applicationCloudConf2017 - Deploy, Scale & Coordinate a microservice oriented application
CloudConf2017 - Deploy, Scale & Coordinate a microservice oriented applicationCorley S.r.l.
 
AngularJS: Service, factory & provider
AngularJS: Service, factory & providerAngularJS: Service, factory & provider
AngularJS: Service, factory & providerCorley S.r.l.
 
The advantage of developing with TypeScript
The advantage of developing with TypeScript The advantage of developing with TypeScript
The advantage of developing with TypeScript Corley S.r.l.
 
Angular coding: from project management to web and mobile deploy
Angular coding: from project management to web and mobile deployAngular coding: from project management to web and mobile deploy
Angular coding: from project management to web and mobile deployCorley S.r.l.
 
Corley cloud angular in cloud
Corley cloud   angular in cloudCorley cloud   angular in cloud
Corley cloud angular in cloudCorley S.r.l.
 
Measure your app internals with InfluxDB and Symfony2
Measure your app internals with InfluxDB and Symfony2Measure your app internals with InfluxDB and Symfony2
Measure your app internals with InfluxDB and Symfony2Corley S.r.l.
 
Read Twitter Stream and Tweet back pictures with Raspberry Pi & AWS Lambda
Read Twitter Stream and Tweet back pictures with Raspberry Pi & AWS LambdaRead Twitter Stream and Tweet back pictures with Raspberry Pi & AWS Lambda
Read Twitter Stream and Tweet back pictures with Raspberry Pi & AWS LambdaCorley S.r.l.
 
Deploy and Scale your PHP App with AWS ElasticBeanstalk and Docker- PHPTour L...
Deploy and Scale your PHP App with AWS ElasticBeanstalk and Docker- PHPTour L...Deploy and Scale your PHP App with AWS ElasticBeanstalk and Docker- PHPTour L...
Deploy and Scale your PHP App with AWS ElasticBeanstalk and Docker- PHPTour L...Corley S.r.l.
 
Middleware PHP - A simple micro-framework
Middleware PHP - A simple micro-frameworkMiddleware PHP - A simple micro-framework
Middleware PHP - A simple micro-frameworkCorley S.r.l.
 
From Chef to Saltstack on Cloud Providers - Incontro DevOps 2015
From Chef to Saltstack on Cloud Providers - Incontro DevOps 2015From Chef to Saltstack on Cloud Providers - Incontro DevOps 2015
From Chef to Saltstack on Cloud Providers - Incontro DevOps 2015Corley S.r.l.
 

Más de Corley S.r.l. (20)

Aws rekognition - riconoscimento facciale
Aws rekognition  - riconoscimento faccialeAws rekognition  - riconoscimento facciale
Aws rekognition - riconoscimento facciale
 
AWSome day 2018 - scalability and cost optimization with container services
AWSome day 2018 - scalability and cost optimization with container servicesAWSome day 2018 - scalability and cost optimization with container services
AWSome day 2018 - scalability and cost optimization with container services
 
AWSome day 2018 - API serverless with aws
AWSome day 2018  - API serverless with awsAWSome day 2018  - API serverless with aws
AWSome day 2018 - API serverless with aws
 
AWSome day 2018 - database in cloud
AWSome day 2018 -  database in cloudAWSome day 2018 -  database in cloud
AWSome day 2018 - database in cloud
 
Trace your micro-services oriented application with Zipkin and OpenTracing
Trace your micro-services oriented application with Zipkin and OpenTracing Trace your micro-services oriented application with Zipkin and OpenTracing
Trace your micro-services oriented application with Zipkin and OpenTracing
 
Apiconf - The perfect REST solution
Apiconf - The perfect REST solutionApiconf - The perfect REST solution
Apiconf - The perfect REST solution
 
Apiconf - Doc Driven Development
Apiconf - Doc Driven DevelopmentApiconf - Doc Driven Development
Apiconf - Doc Driven Development
 
Authentication and authorization in res tful infrastructures
Authentication and authorization in res tful infrastructuresAuthentication and authorization in res tful infrastructures
Authentication and authorization in res tful infrastructures
 
Flexibility and scalability of costs in serverless infrastructures
Flexibility and scalability of costs in serverless infrastructuresFlexibility and scalability of costs in serverless infrastructures
Flexibility and scalability of costs in serverless infrastructures
 
CloudConf2017 - Deploy, Scale & Coordinate a microservice oriented application
CloudConf2017 - Deploy, Scale & Coordinate a microservice oriented applicationCloudConf2017 - Deploy, Scale & Coordinate a microservice oriented application
CloudConf2017 - Deploy, Scale & Coordinate a microservice oriented application
 
React vs Angular2
React vs Angular2React vs Angular2
React vs Angular2
 
AngularJS: Service, factory & provider
AngularJS: Service, factory & providerAngularJS: Service, factory & provider
AngularJS: Service, factory & provider
 
The advantage of developing with TypeScript
The advantage of developing with TypeScript The advantage of developing with TypeScript
The advantage of developing with TypeScript
 
Angular coding: from project management to web and mobile deploy
Angular coding: from project management to web and mobile deployAngular coding: from project management to web and mobile deploy
Angular coding: from project management to web and mobile deploy
 
Corley cloud angular in cloud
Corley cloud   angular in cloudCorley cloud   angular in cloud
Corley cloud angular in cloud
 
Measure your app internals with InfluxDB and Symfony2
Measure your app internals with InfluxDB and Symfony2Measure your app internals with InfluxDB and Symfony2
Measure your app internals with InfluxDB and Symfony2
 
Read Twitter Stream and Tweet back pictures with Raspberry Pi & AWS Lambda
Read Twitter Stream and Tweet back pictures with Raspberry Pi & AWS LambdaRead Twitter Stream and Tweet back pictures with Raspberry Pi & AWS Lambda
Read Twitter Stream and Tweet back pictures with Raspberry Pi & AWS Lambda
 
Deploy and Scale your PHP App with AWS ElasticBeanstalk and Docker- PHPTour L...
Deploy and Scale your PHP App with AWS ElasticBeanstalk and Docker- PHPTour L...Deploy and Scale your PHP App with AWS ElasticBeanstalk and Docker- PHPTour L...
Deploy and Scale your PHP App with AWS ElasticBeanstalk and Docker- PHPTour L...
 
Middleware PHP - A simple micro-framework
Middleware PHP - A simple micro-frameworkMiddleware PHP - A simple micro-framework
Middleware PHP - A simple micro-framework
 
From Chef to Saltstack on Cloud Providers - Incontro DevOps 2015
From Chef to Saltstack on Cloud Providers - Incontro DevOps 2015From Chef to Saltstack on Cloud Providers - Incontro DevOps 2015
From Chef to Saltstack on Cloud Providers - Incontro DevOps 2015
 

Último

%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...Jittipong Loespradit
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...masabamasaba
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...masabamasaba
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024VictoriaMetrics
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrandmasabamasaba
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...SelfMade bd
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfonteinmasabamasaba
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is insideshinachiaurasa2
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...masabamasaba
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Hararemasabamasaba
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...masabamasaba
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 

Último (20)

%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 

A single language for backend and frontend from AngularJS to cloud with Claudia.js

  • 1. A single language for Backend and Frontend: from AngularJS to Cloud AngularConf 2016 - Turin
  • 5. The REST webservice Decoupling Caching Stateless Quota planning (API Limits) Extendable Proxable etc...
  • 6. Planning GET    → /book Access to a list of books GET    → /book/:id Access to a single book POST   → /book Create a new book PATCH  → /book/:id Update a given book DELETE → /book/:id Delete a given book We can extends this using authentication header Authorization
  • 7. We have a simple API 'use strict' ;  angular.module( 'myApp').service( 'bookService' , function($http) {    return {      "list": function() {        return $http.get( "http://localhost:8085/book" );      },      ... // more methods     };  }); So we create a service Or we can create a provider to configure the URLs etc
  • 8. With a service we have a box with different methods bookService Get all books: list() Get a single book: get(:bookId) Create a book: create(:bookModel) ...
  • 9. The Book model is stable across our application {title: "the book title" , isbn: "12345678" , available : true} Or we resolve the book dependency with the book link (thanks to API uniquiness) {      name: "my favourites" ,      books: [ 1,2,3]  } So: $q.all(    [1,2,3].map(bookService.get)   ).then(function(books) {       //books is my favourites list with details   });
  • 10. Where the GET 'use strict' ;  angular.module( 'myApp').service( 'bookService' , function($http) {    return {      "get": function(id) {        return $http.get( "http://localhost:8085/book/" +id);      },      "list": function() {        return $http.get( "http://localhost:8085/book" );      },      ... // more methods     };  });
  • 12. A controller can request data angular.module( 'myApp')    .controller( 'MainCtrl' , function ($scope, bookService) {       $scope.books = [];       bookService.list().success(function(books) {         $scope.books = books;       });    }); Thanks to the controller we can pass our books to the view The scope the communication channel for the data
  • 13. Q: how can i verify the scope interface? R: via testing (unit testing)?
  • 14. Add a test case (1/2) describe( "MainCtrl" , function() {      beforeEach(module( 'myApp'));      beforeEach(inject(function ($controller, $rootScope, $httpBackend) {           scope = $rootScope.$new();           httpBackend = $httpBackend;           MainCtrl = $controller( 'MainCtrl' , {              $scope: scope,               // other mocks           });       }));      // continue...   });
  • 15. Add a test case (2/2) it('should attach a list of books to the scope' , function () {       // when someone require the "/book" endpoint reply with a valid response       httpBackend.whenGET( "http://localhost:8085/book" ).respond([         { id: 1, title: "This is a book" , isbn: "9835623" , available:  true },        { id: 2, title: "Another super book" , isbn: "9835624" , available:  true },        { id: 3, title: "A rare book to read" , isbn: "9835625" , available:  false }      ]);      // force the HTTP data resolution       httpBackend.flush();       // my expectation are that we books in the controller scope.       expect(scope.books.length).toBe( 3);      expect(scope.books.map((item) => item.title)).toEqual([         "This is a book" ,        "Another super book" ,        "A rare book to read"       ]);    }); $httpBackend act as a spy for HTTP requests
  • 17. The directive (web component) angular.module("myApp")    .directive( 'booksList' , function() {      return {        replace:  true,       templateUrl:  "app/views/books­list.html" ,        restrict:  "E",       scope: {           "books": "=",        },        link:  function() {},      };    });
  • 19. The book web component angular.module("myApp")    .directive( 'book', function() {      return {        replace:  true,       templateUrl:  "app/views/book.html" ,        restrict:  "E",       scope: {           "book": "=",        },        link:  function() {},      };    });
  • 21. Components testing (1/3) describe( "Books List" , function() {    var $compile,       $rootScope;     beforeEach(module( 'myApp'));    beforeEach(function() {       inject(function( _$compile_, _$rootScope _){        $compile =  _$compile_;        $rootScope =  _$rootScope _;      });    }); });
  • 22. Components testing (2/3) it("should expose our books" , function() {      $rootScope.books = [           { id:  1, title:  "This is a book" , isbn: "9835623" , available: true }           { id:  2, title:  "Another book" , isbn: "9835624" , available: true }           { id:  2, title:  "A secret book" , isbn: "9835625" , available: false }       ];      var element = $compile( '<books­list books="books"></books­list>' )($rootScope);       $rootScope.$digest();       var html = element.html();       expect(html).toContain( "This is a book" );      expect(html).toContain( "Another book" );      expect(html).not.toContain( "A secret book" );  });
  • 23. Components testing (3/3) Single book directive testing it("should expose a single book" , function() {      $rootScope.book = {           id:  1,          title:  "This is a single book" ,          isbn:  "9835623" ,          available: true       };      var element = $compile( '<book book="book"></book>' )($rootScope);       $rootScope.$digest();       var html = element.html();       expect(html).toContain( "This is a single book" );  });
  • 24. Add a book creation We need the create book service method We need another dummy web component We use the controller to save the book model
  • 25. The create method angular.module( 'myApp').service( 'bookService' , function($http) {     return {       "create": function(book) {         return $http.post( "http://localhost:8085/book" , book);      },      /* already implemented */       "get": function(id) {         return $http.get( "http://localhost:8085/book/" +id);      },      "list": function() {         return $http.get( "http://localhost:8085/book" );      },    };  });
  • 26. Dummy web component (1/3) angular.module("myApp")    .directive( 'bookForm' , function() {      return {        replace:  true,       templateUrl:  "app/views/book­form.html" ,        restrict:  "E",       scope: {           "book": "=",          "save": "=",        }      };    }); We can also skip the book model pass-through
  • 27. Dummy web component (2/3) <div>     <form>          Title: < input type="text" ng­model= "book.title"  /><br>          ISBN: < input type="text" ng­model= "book.isbn"  /><br>          Available: < input type="checkbox"  ng­model= "book.available"  /><br>          <button  type="button" ng­click= "save(book)" >Save</button>< br>      </form>  </div> Pay attention on ng-click that pass the book model
  • 28. Dummy web component (3/3) it("should expose a book", function(done) {    $rootScope.book = {};    $rootScope.save = function(book) {      expect(book.title).toEqual("Some text");      expect(book.isbn).toEqual("123456");      expect(book.available).toBe(true);      done();    };    var element = $compile('<book­form book="book" save="save"></book­form>')($rootScope);    $rootScope.$digest();    angular.element(element.find('input')[0]).val('Some text').triggerHandler('input');    angular.element(element.find('input')[1]).val('123456').triggerHandler('input');    angular.element(element.find('input')[2]).prop('checked', 'checked').triggerHandler('click');    $rootScope.$apply();    element.find('button')[0].click();  });
  • 29. So we have validated that the directive calls the save method But... Who have the save method? Controller + Book Service
  • 30. Previous Controller (1/2) angular.module( 'myApp')    .controller( 'MainCtrl' , function ($scope, bookService) {       $scope.book = {};       $scope.save = function(book) {         bookService.create(book).success(function(book) {           $scope.books = $scope.books.concat([book]);         });         $scope.book = {};       };      // old parts...       $scope.books = [];       bookService.list().success(function(books) {         $scope.books = books;       });    }); <book­form book="book" save="save"></book­form>
  • 31. Previous Controller (2/2) it('should create a new book', function () {     // something uses the save method     var book = {title: "This is a book", isbn: "9835623", available: true };    scope.save(book);    // then the backend should works as expected     httpBackend.whenGET("http://localhost:8085/book" ).respond([]);    httpBackend.whenPOST("http://localhost:8085/book" ).respond(      Object.assign({}, book, {id: 1})    );   httpBackend.flush();    expect(scope.book).toEqual({});    expect(scope.books.length).toBe(1);    expect(scope.books[0].id).toBe(1);    expect(scope.books[0].title).toEqual("This is a book");    expect(scope.books[0].isbn).toEqual("9835623");    expect(scope.books[0].available).toBe(true);  });
  • 32. We can develop the app but...
  • 33.
  • 34. How to deliver a scalable and cost-effective backend?
  • 35. ServerLess environments Those envs allows us to pay just for every single requests No requests? No payments! [more or less] No server maintenance (platform as a service)
  • 36. Amazon Web Services AWS API Gateway [✔] AWS Lambda [✔] AWS DynamoDB [✔] AWS SNS [ ] AWS SQS [ ] AWS CloudWatch [ ] so many services... [ ... ]
  • 37. API Gateway Thanks to API Gateway you can create/publish/maintain/monitor and secure APIs at any scale Essentially: with API Gateway you declare your APIs interfaces and delegate to another component (like Lambda, EC2, etc) the functionality
  • 38.
  • 39. Lambda is a compute service that can run the code on your behalf using AWS infrastructure
  • 40.
  • 41. Amazon DynamoDB is a fully managed NoSQL database service that provides fast and predictable performance with seamless scalability.
  • 42.
  • 44. Dealing with ApiGateway + Lambda manually is tricky
  • 45. AWS releases a project: ServerLess that helps a lot the wiring https://github.com/serverless/serverless
  • 46. ServerLess is interesting but for REST API is not super simple to use imho...
  • 47. I prefer to use Claudia.js https://github.com/claudiajs/claudia
  • 48. Claudia expose a very simple interface var ApiBuilder =  require('claudia­api­builder' ),      api =  new ApiBuilder();   api.get('/hello', function (request, response)  {      return "Hello";  }); Similar to express or hapi
  • 49. You can use return codes and more features... api.post('/account' , function (request) {       return api.ApiResponse ({          name: "Walter",          surname: "Dal Mut"       }, 201);  });
  • 50. Claudia.js prepare the whole ApiGateway and Lambda configuration (with CORS) automatically for you claudia create        ­­name book­ module       ­­region eu­west­ 1       ­­api­module book       ­­config claudia­books.json It creates a new module book-module and store in claudia-books.json the Claudia.js con guration
  • 51. Claudia.js manage also all updates claudia update       ­­config claudia­ conf.json
  • 52. So we have to develop our API
  • 53. Thanks to Joi we can add data validation to our API var joi = require(' Joi'); var result = joi.object().keys({     id: joi.number().required(),     title: joi. string().min(1).required()   }).validate(request.body);   if (result.error) {       return new api. ApiResponse (result.error, 406); }  // continue Claudia.js manage JSON data automatically
  • 54. Claudia.js manage A+ Promises as a return element api.post( "/say­ok" , function(request)  {      var d = q.promise();       setTimeout( function() {          d.resolve( "OK");      }, 2000);      return d.promise;   });
  • 55. So... api.post( "/say­ok" , function(request)  {      // validation...       return db.save(request.body);   });
  • 56. For Node.js DynamoDB offers a "Document client" docClient =  new AWS.DynamoDB.DocumentClient({region:  "eu­west­1" });  docClient.put({     Item: {name:  "Walter", surname:  "Dal Mut" },    TableName: tableName   }).promise();   docClient.get( ...); // primary key   docClient.query( ...); // on a secondary index and/or primary key   docClient.scan( ...); // search without index (table scan) All methods have a A+ Promise implementation integrated
  • 57. Put all together api.post( "/book", function(request) {     var d = q.promise();     var result = joi.object().keys({       title: joi. string().min(1).required(),       isbn: joi. string().min(1).required(),       available: joi.boolean().required()     }).validate(request.body);     if (result.error) {       return new api. ApiResponse (result.error, 406);   }    var id = uuid.v4();     var item = Object.assign({}, {id: id}, request.body);     docClient.put({ Item: item, TableName : tableName}).promise().then(function() {       d.resolve(item);     });;    return d.promise;   }); Of course you can split all responsabilities to di erent components
  • 58. Thank you for listening If you are interested in workshops and/or training sessions feel free to contact info@corley.it Check out also our page for training at: corsi.corley.it Check out our corporate website: corley.it