SlideShare a Scribd company logo
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...
A single language for backend and frontend  from AngularJS to cloud with Claudia.js
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
A single language for backend and frontend  from AngularJS to cloud with Claudia.js
Lambda is a compute service that can run the code on your behalf
using AWS infrastructure
A single language for backend and frontend  from AngularJS to cloud with Claudia.js
Amazon DynamoDB is a fully managed NoSQL database service that
provides fast and predictable performance with seamless scalability.
A single language for backend and frontend  from AngularJS to cloud with Claudia.js
["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
Ad

Recommended

Mvc - Model: the great forgotten
Mvc - Model: the great forgotten
David Rodenas
 
Modules in angular 2.0 beta.1
Modules in angular 2.0 beta.1
David Rodenas
 
Firebase for Apple Developers - SwiftHeroes
Firebase for Apple Developers - SwiftHeroes
Peter Friese
 
MVS: An angular MVC
MVS: An angular MVC
David Rodenas
 
Mongoose and MongoDB 101
Mongoose and MongoDB 101
Will Button
 
Mongoose: MongoDB object modelling for Node.js
Mongoose: MongoDB object modelling for Node.js
Yuriy Bogomolov
 
Mongoose getting started-Mongo Db with Node js
Mongoose getting started-Mongo Db with Node js
Pallavi Srivastava
 
Nodejs mongoose
Nodejs mongoose
Fin Chen
 
Practical Use of MongoDB for Node.js
Practical Use of MongoDB for Node.js
async_io
 
The Django Book chapter 5 Models
The Django Book chapter 5 Models
Vincent Chien
 
How Kris Writes Symfony Apps
How Kris Writes Symfony Apps
Kris Wallsmith
 
Welcome the Offical C# Driver for MongoDB
Welcome the Offical C# Driver for MongoDB
MongoDB
 
Javascript - Beyond-jQuery
Javascript - Beyond-jQuery
Tanner Moushey ❖ Mission Lab - WordPress Agency
 
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™
Nicola Iarocci
 
Cleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQuery
Rebecca Murphey
 
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 Tree
adamlogic
 
MongoDB
MongoDB
Steve Klabnik
 
Code Samples &amp; Screenshots
Code Samples &amp; Screenshots
Nii Amah Hesse
 
How to use MongoDB with CakePHP
How to use MongoDB with CakePHP
ichikaway
 
Ruby gems
Ruby gems
Papp Laszlo
 
Time to React!
Time to React!
STX Next
 
Firebase for Apple Developers
Firebase for Apple Developers
Peter Friese
 
Apache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux Fest
Myles Braithwaite
 
Rails 3 ActiveRecord
Rails 3 ActiveRecord
Blazing Cloud
 
Beyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS Apps
Rebecca Murphey
 
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worlds
Ignacio Martín
 
FITC presents: Mobile & offline data synchronization in Angular JS
FITC presents: Mobile & offline data synchronization in Angular JS
FITC
 
AngularJS for Java Developers
AngularJS for Java Developers
Loc Nguyen
 

More Related Content

What's hot (20)

Practical Use of MongoDB for Node.js
Practical Use of MongoDB for Node.js
async_io
 
The Django Book chapter 5 Models
The Django Book chapter 5 Models
Vincent Chien
 
How Kris Writes Symfony Apps
How Kris Writes Symfony Apps
Kris Wallsmith
 
Welcome the Offical C# Driver for MongoDB
Welcome the Offical C# Driver for MongoDB
MongoDB
 
Javascript - Beyond-jQuery
Javascript - Beyond-jQuery
Tanner Moushey ❖ Mission Lab - WordPress Agency
 
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™
Nicola Iarocci
 
Cleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQuery
Rebecca Murphey
 
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 Tree
adamlogic
 
MongoDB
MongoDB
Steve Klabnik
 
Code Samples &amp; Screenshots
Code Samples &amp; Screenshots
Nii Amah Hesse
 
How to use MongoDB with CakePHP
How to use MongoDB with CakePHP
ichikaway
 
Ruby gems
Ruby gems
Papp Laszlo
 
Time to React!
Time to React!
STX Next
 
Firebase for Apple Developers
Firebase for Apple Developers
Peter Friese
 
Apache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux Fest
Myles Braithwaite
 
Rails 3 ActiveRecord
Rails 3 ActiveRecord
Blazing Cloud
 
Beyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS Apps
Rebecca Murphey
 
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worlds
Ignacio Martín
 
Practical Use of MongoDB for Node.js
Practical Use of MongoDB for Node.js
async_io
 
The Django Book chapter 5 Models
The Django Book chapter 5 Models
Vincent Chien
 
How Kris Writes Symfony Apps
How Kris Writes Symfony Apps
Kris Wallsmith
 
Welcome the Offical C# Driver for MongoDB
Welcome the Offical C# Driver for MongoDB
MongoDB
 
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™
Nicola Iarocci
 
Cleaner, Leaner, Meaner: Refactoring your jQuery
Cleaner, Leaner, Meaner: Refactoring your jQuery
Rebecca Murphey
 
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 Tree
adamlogic
 
Code Samples &amp; Screenshots
Code Samples &amp; Screenshots
Nii Amah Hesse
 
How to use MongoDB with CakePHP
How to use MongoDB with CakePHP
ichikaway
 
Time to React!
Time to React!
STX Next
 
Firebase for Apple Developers
Firebase for Apple Developers
Peter Friese
 
Apache CouchDB talk at Ontario GNU Linux Fest
Apache CouchDB talk at Ontario GNU Linux Fest
Myles Braithwaite
 
Rails 3 ActiveRecord
Rails 3 ActiveRecord
Blazing Cloud
 
Beyond the DOM: Sane Structure for JS Apps
Beyond the DOM: Sane Structure for JS Apps
Rebecca Murphey
 
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worlds
Ignacio Martín
 

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

FITC presents: Mobile & offline data synchronization in Angular JS
FITC presents: Mobile & offline data synchronization in Angular JS
FITC
 
AngularJS for Java Developers
AngularJS for Java Developers
Loc Nguyen
 
Angular js for Beginnners
Angular js for Beginnners
Santosh Kumar Kar
 
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
PHP Conference Argentina
 
Build REST API clients for AngularJS
Build REST API clients for AngularJS
Almog Baku
 
Angular js introduction
Angular js introduction
Hsiu Shan
 
Angular js 1.0-fundamentals
Angular js 1.0-fundamentals
Venkatesh Narayanan
 
Karlsruher Entwicklertag 2013 - Webanwendungen mit AngularJS
Karlsruher Entwicklertag 2013 - Webanwendungen mit AngularJS
Philipp Burgmer
 
Introduction to Angular JS
Introduction to Angular JS
Santhosh Kumar Srinivasan
 
AngularJS - a radically different way of building Single Page Apps
AngularJS - a radically different way of building Single Page Apps
jivkopetiov
 
The future of web development write once, run everywhere with angular.js and ...
The future of web development write once, run everywhere with angular.js and ...
Mark Roden
 
The future of web development write once, run everywhere with angular js an...
The future of web development write once, run everywhere with angular js an...
Mark Leusink
 
Basics of AngularJS
Basics of AngularJS
Filip Janevski
 
Busy Developers Guide to AngularJS (Tiberiu Covaci)
Busy Developers Guide to AngularJS (Tiberiu Covaci)
ITCamp
 
AngularJs Crash Course
AngularJs Crash Course
Keith Bloomfield
 
Pengenalan AngularJS
Pengenalan AngularJS
Edi Santoso
 
Practical AngularJS
Practical AngularJS
Wei Ru
 
introduction to Angularjs basics
introduction to Angularjs basics
Ravindra K
 
How to build an AngularJS backend-ready app WITHOUT BACKEND
How to build an AngularJS backend-ready app WITHOUT BACKEND
Enrique Oriol Bermúdez
 
A gently introduction to AngularJS
A gently introduction to AngularJS
Gregor Woiwode
 
FITC presents: Mobile & offline data synchronization in Angular JS
FITC presents: Mobile & offline data synchronization in Angular JS
FITC
 
AngularJS for Java Developers
AngularJS for Java Developers
Loc Nguyen
 
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
2013 - Nate Abele: HTTP ALL THE THINGS: Simplificando aplicaciones respetando...
PHP Conference Argentina
 
Build REST API clients for AngularJS
Build REST API clients for AngularJS
Almog Baku
 
Angular js introduction
Angular js introduction
Hsiu Shan
 
Karlsruher Entwicklertag 2013 - Webanwendungen mit AngularJS
Karlsruher Entwicklertag 2013 - Webanwendungen mit AngularJS
Philipp Burgmer
 
AngularJS - a radically different way of building Single Page Apps
AngularJS - a radically different way of building Single Page Apps
jivkopetiov
 
The future of web development write once, run everywhere with angular.js and ...
The future of web development write once, run everywhere with angular.js and ...
Mark Roden
 
The future of web development write once, run everywhere with angular js an...
The future of web development write once, run everywhere with angular js an...
Mark Leusink
 
Busy Developers Guide to AngularJS (Tiberiu Covaci)
Busy Developers Guide to AngularJS (Tiberiu Covaci)
ITCamp
 
Pengenalan AngularJS
Pengenalan AngularJS
Edi Santoso
 
Practical AngularJS
Practical AngularJS
Wei Ru
 
introduction to Angularjs basics
introduction to Angularjs basics
Ravindra K
 
How to build an AngularJS backend-ready app WITHOUT BACKEND
How to build an AngularJS backend-ready app WITHOUT BACKEND
Enrique Oriol Bermúdez
 
A gently introduction to AngularJS
A gently introduction to AngularJS
Gregor Woiwode
 
Ad

Recently uploaded (20)

ElectraSuite_Prsentation(online voting system).pptx
ElectraSuite_Prsentation(online voting system).pptx
mrsinankhan01
 
IDM Crack with Internet Download Manager 6.42 Build 41 [Latest 2025]
IDM Crack with Internet Download Manager 6.42 Build 41 [Latest 2025]
pcprocore
 
CodeCleaner: Mitigating Data Contamination for LLM Benchmarking
CodeCleaner: Mitigating Data Contamination for LLM Benchmarking
arabelatso
 
Advance Doctor Appointment Booking App With Online Payment
Advance Doctor Appointment Booking App With Online Payment
AxisTechnolabs
 
Modern Platform Engineering with Choreo - The AI-Native Internal Developer Pl...
Modern Platform Engineering with Choreo - The AI-Native Internal Developer Pl...
WSO2
 
Which Hiring Management Tools Offer the Best ROI?
Which Hiring Management Tools Offer the Best ROI?
HireME
 
Enable Your Cloud Journey With Microsoft Trusted Partner | IFI Tech
Enable Your Cloud Journey With Microsoft Trusted Partner | IFI Tech
IFI Techsolutions
 
Complete WordPress Programming Guidance Book
Complete WordPress Programming Guidance Book
Shabista Imam
 
MOVIE RECOMMENDATION SYSTEM, UDUMULA GOPI REDDY, Y24MC13085.pptx
MOVIE RECOMMENDATION SYSTEM, UDUMULA GOPI REDDY, Y24MC13085.pptx
Maharshi Mallela
 
Streamlining CI/CD with FME Flow: A Practical Guide
Streamlining CI/CD with FME Flow: A Practical Guide
Safe Software
 
IObit Driver Booster Pro 12 Crack Latest Version Download
IObit Driver Booster Pro 12 Crack Latest Version Download
pcprocore
 
HYBRIDIZATION OF ALKANES AND ALKENES ...
HYBRIDIZATION OF ALKANES AND ALKENES ...
karishmaduhijod1
 
ERP Systems in the UAE: Driving Business Transformation with Smart Solutions
ERP Systems in the UAE: Driving Business Transformation with Smart Solutions
dheeodoo
 
Introduction to Agile Frameworks for Product Managers.pdf
Introduction to Agile Frameworks for Product Managers.pdf
Ali Vahed
 
Best Practice for LLM Serving in the Cloud
Best Practice for LLM Serving in the Cloud
Alluxio, Inc.
 
A Guide to Telemedicine Software Development.pdf
A Guide to Telemedicine Software Development.pdf
Olivero Bozzelli
 
arctitecture application system design os dsa
arctitecture application system design os dsa
za241967
 
Zoneranker’s Digital marketing solutions
Zoneranker’s Digital marketing solutions
reenashriee
 
The Anti-Masterclass Live - Peak of Data & AI 2025
The Anti-Masterclass Live - Peak of Data & AI 2025
Safe Software
 
Emvigo Capability Deck 2025: Accelerating Innovation Through Intelligent Soft...
Emvigo Capability Deck 2025: Accelerating Innovation Through Intelligent Soft...
Emvigo Technologies
 
ElectraSuite_Prsentation(online voting system).pptx
ElectraSuite_Prsentation(online voting system).pptx
mrsinankhan01
 
IDM Crack with Internet Download Manager 6.42 Build 41 [Latest 2025]
IDM Crack with Internet Download Manager 6.42 Build 41 [Latest 2025]
pcprocore
 
CodeCleaner: Mitigating Data Contamination for LLM Benchmarking
CodeCleaner: Mitigating Data Contamination for LLM Benchmarking
arabelatso
 
Advance Doctor Appointment Booking App With Online Payment
Advance Doctor Appointment Booking App With Online Payment
AxisTechnolabs
 
Modern Platform Engineering with Choreo - The AI-Native Internal Developer Pl...
Modern Platform Engineering with Choreo - The AI-Native Internal Developer Pl...
WSO2
 
Which Hiring Management Tools Offer the Best ROI?
Which Hiring Management Tools Offer the Best ROI?
HireME
 
Enable Your Cloud Journey With Microsoft Trusted Partner | IFI Tech
Enable Your Cloud Journey With Microsoft Trusted Partner | IFI Tech
IFI Techsolutions
 
Complete WordPress Programming Guidance Book
Complete WordPress Programming Guidance Book
Shabista Imam
 
MOVIE RECOMMENDATION SYSTEM, UDUMULA GOPI REDDY, Y24MC13085.pptx
MOVIE RECOMMENDATION SYSTEM, UDUMULA GOPI REDDY, Y24MC13085.pptx
Maharshi Mallela
 
Streamlining CI/CD with FME Flow: A Practical Guide
Streamlining CI/CD with FME Flow: A Practical Guide
Safe Software
 
IObit Driver Booster Pro 12 Crack Latest Version Download
IObit Driver Booster Pro 12 Crack Latest Version Download
pcprocore
 
HYBRIDIZATION OF ALKANES AND ALKENES ...
HYBRIDIZATION OF ALKANES AND ALKENES ...
karishmaduhijod1
 
ERP Systems in the UAE: Driving Business Transformation with Smart Solutions
ERP Systems in the UAE: Driving Business Transformation with Smart Solutions
dheeodoo
 
Introduction to Agile Frameworks for Product Managers.pdf
Introduction to Agile Frameworks for Product Managers.pdf
Ali Vahed
 
Best Practice for LLM Serving in the Cloud
Best Practice for LLM Serving in the Cloud
Alluxio, Inc.
 
A Guide to Telemedicine Software Development.pdf
A Guide to Telemedicine Software Development.pdf
Olivero Bozzelli
 
arctitecture application system design os dsa
arctitecture application system design os dsa
za241967
 
Zoneranker’s Digital marketing solutions
Zoneranker’s Digital marketing solutions
reenashriee
 
The Anti-Masterclass Live - Peak of Data & AI 2025
The Anti-Masterclass Live - Peak of Data & AI 2025
Safe Software
 
Emvigo Capability Deck 2025: Accelerating Innovation Through Intelligent Soft...
Emvigo Capability Deck 2025: Accelerating Innovation Through Intelligent Soft...
Emvigo Technologies
 
Ad

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...
  • 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
  • 39. Lambda is a compute service that can run the code on your behalf using AWS infrastructure
  • 41. Amazon DynamoDB is a fully managed NoSQL database service that provides fast and predictable performance with seamless scalability.
  • 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 [email protected] Check out also our page for training at: corsi.corley.it Check out our corporate website: corley.it