Tomasz Ducin
10th December 2016, Wrocław
Backend-less Development Revisited
Tomasz Ducin
11th October 2016, Kraków
Backend-less Development Revisited
Tomasz Ducin
15th September 2016, Kraków
Backend-less Development Revisited
Tomasz Ducin
15th July 2016, London
Backend-less Development Revisited
Backend-less Development Revisited
conference on JavaScript, Node & Internet of Things
conference on JavaScript, Node & Internet of Things
Tomasz Ducin
15th July 2016, London
Tomasz Ducin
16th June 2016, Darmstadt
Backend-less Development Revisited
Tomasz Ducin
13th May 2016, Kraków
Tomasz Ducin
11th April 2016, Warsaw
Tomasz Ducin
25th February 2016, the WEB
Tomasz Ducin
22nd February 2016, Warsaw
senior software consultant @ Cybercom Poland
trainer @ Bottega IT Solutions
blah, blah, blah...
solution architect
let's modify JSON response!
but why?
because the new structure fits better
server-less architecture
server-less architecture
delivering data: different levels
{
"title": "Example Schema",
"type": "object",
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"age": {
"description": "Age in years",
"type": "integer",
"minimum": 0
}
},
"additionalProperties": false,
"required": ["firstName", "lastName"]
}
{
"firstName": "John",
"lastName": "Lennon",
"age": 40
}
{
"firstName": "Paul",
"lastName": "McCartney"
}
API Blueprint
Swagger
RAML:
RESTful API Modelling Language
/songs
get
post
/{songId}
get
/file-content
get
post
/artists
get
post
/{artistId}
get
/albums
get
/albums
get
post
/{albumId}
get
/songs
get
/songs:
description: Collection of available songs in Jukebox
get:
description: Get a list of songs based on the song title.
queryParameters:
songTitle:
description: "The title of the song to search (...)"
required: true
minLength: 3
type: string
example: "Get L"
[...]
[...]
responses:
200:
body:
application/json:
example: |
"songs": [
{
"songId": "550e8400-e29b-41d4-a716-446655440000",
"songTitle": "Get Lucky"
},
{
"songId": "550e8400-e29b-41d4-a716-446655440111",
"songTitle": "Loose yourself to dance"
},
{
"songId": "550e8400-e29b-41d4-a716-446655440222",
"songTitle": "Gio sorgio by Moroder"
}
]
var fs = sinon.fakeServer.create();
fs.respondWith(HTTP_METHOD, URL,
[HTTP_STATUS, HEADERS, DATA]
);
var value = [{"name": "John", "age": 68 }, ...];
var fakeServerWrapper = {
init: function() {
this.fs = sinon.fakeServer.create();
this.fs.respondWith("GET", 'customers/',
[200, { "Content-Type": "application/json" },
JSON.stringify(value) ]);
this.fs.autoRespond = true;
},
restore: function() {
this.fs.restore();
}
};
// fakeServerWrapper.init();
when(method, url, [data], [headers])
.respond(HTTP_STATUS, DATA, HEADERS);
whenGET(url, [headers]);
whenHEAD(url, [headers]);
whenDELETE(url, [headers]);
whenPOST(url, [data], [headers]);
whenPUT(url, [data], [headers]);
...
when(method, url, [data], [headers])
.respond(function(...){
return [HTTP_STATUS, DATA, HEADERS];
});
whenGET(url, [headers]);
whenHEAD(url, [headers]);
whenDELETE(url, [headers]);
whenPOST(url, [data], [headers]);
whenPUT(url, [data], [headers]);
...
var demoApp = angular.module('demoApp', ['ngResource']);
demoApp.controller('fetchCtrl', function ($scope, $resource) {
var Events = $resource('/events/:eventId', {
eventId: '@id'
});
$scope.fetch = function () {
Events.query({'eventId': 6}, function (data) {
// do something with data
});
};
});
// ...
// mock part
var data = [{
"name": "FullStack",
"edition": 2016
}, ...];
demoApp.config(function ($provide) {
$provide.decorator('$httpBackend',
angular.mock.e2e.$httpBackendDecorator);
});
demoApp.run(function ($httpBackend) {
$httpBackend.whenGET('/events/6').respond(
200, data, {header: 'one'}
);
});
...
<script type="text/javascript" src="app.js"></script>
<script type="text/javascript" src="mock.js"></script>
...
mock.js
bundle
mock.js
bundle
[{
"firstName": "Hans",
"lastName": "Schmidt",
"age": 47,
"city": "Berlin"
}, {
"firstName": "Karl",
"lastName": "Fischer",
"age": 26,
"city": "Hamburg"
}, {
"firstName": "Peter",
"lastName": "Mueller",
"age": 71,
"city": "Leipzig"
}, ...]
var mockData = require('data.json');
function applyGETcollection(){ ...
return mockData;
}
function applyGETitem(id){ ...
return mockData[id];
}
function applyPOST(item){ ...
mockData[item.id] = item;
}
function applyPUT(item){ ...
mockData.push(item);
}
function applyDELETE(id){ ...
delete mockData[id];
}
mock.js
var modB = require('b');
var modC = require('c');
module.exports = ...
module.exports = ...
var modD = require('d');
module.exports = ...
module.exports = ...
a.js
b.js
c.js
d.js
a.js
b.js
c.js
d.js
require
a.js
b.js
c.js
d.js
...
<script type="text/javascript" src="app.js"></script>
<script type="text/javascript" src="mock.js"></script>
...
mock.js
grunt serve [--mock], gulp serve [--mock]
independent clients make
everybody benefit