$30 off During Our Annual Pro Sale. View Details »

#TDC2015: Know hook and how to use it

#TDC2015: Know hook and how to use it

My speech about hook at The Developers Conference 2015, Brazil (Front-end track)

https://github.com/doubleleft/hook

Endel Dreyer

July 21, 2015
Tweet

More Decks by Endel Dreyer

Other Decks in Programming

Transcript

  1. View Slide

  2. @endel
    twitter.com/endel
    github.com/endel
    [email protected]

    View Slide

  3. The problem
    • Projets with short delivery time (<1 month)
    • Repetitive back-end code
    • Lack of front-end integration standards

    View Slide

  4. Backend as a Service
    • baasbox/baasbox - Java
    • deployd/deployd - NodeJS / MongoDB
    • hoodiehq/hoodie.js - NodeJS / CouchDB
    • parse.com - Closed source / $$$$$
    • doubleleft/hook - PHP / MySQL

    View Slide

  5. hook
    • REST API
    • Data persistance (CRUD)
    • MySQL / PostgreSQL / MSSQL /
    MongoDB
    • User authentication
    • Extensible

    View Slide

  6. Installation
    • Dependencies: PHP 5.5+ / node 0.12+
    • github.com/doubleleft/hook
    $ curl -sSL https://
    raw.githubusercontent.com/
    doubleleft/hook/master/scripts/
    install.sh | bash

    View Slide

  7. WTF backend?

    View Slide

  8. Static Web Apps
    • “Static Web Applications run independently
    of the need for server-side dynamic
    processing.”
    • “Static web architecture eases common
    web development headaches without
    introducing additional complexity.”
    • http://www.staticapps.org/

    View Slide

  9. Static Web Apps

    View Slide

  10. Getting started
    • Back-end (doubleleft/hook)
    • Command-line Interface (doubleleft/hook-
    cli)
    • Front-end (doubleleft/hook-javascript)

    View Slide

  11. Getting started
    $ hook app:new tdc2015

    View Slide

  12. Getting started
    $ hook app:new tdc2015
    create hook-ext/security.yaml
    create hook-ext/packages.yaml
    create hook-ext/schedule.yaml
    create hook-ext/schema.yaml
    create hook-ext/config/config.yaml
    create hook-ext/config/config.development.yaml
    create hook-ext/credentials/development/cli.json
    create hook-ext/credentials/development/browser.json
    create hook-ext/credentials/development/device.json
    create hook-ext/credentials/development/server.json
    Application created successfully.

    View Slide

  13. Getting started
    $ hook app:new tdc2015
    create hook-ext/security.yaml
    create hook-ext/packages.yaml
    create hook-ext/schedule.yaml
    create hook-ext/schema.yaml
    create hook-ext/config/config.yaml
    create hook-ext/config/config.development.yaml
    create hook-ext/credentials/development/cli.json
    create hook-ext/credentials/development/browser.json
    create hook-ext/credentials/development/device.json
    create hook-ext/credentials/development/server.json
    Application created successfully.
    Collection’s
    exposure level

    View Slide

  14. Getting started
    $ hook app:new tdc2015
    create hook-ext/security.yaml
    create hook-ext/packages.yaml
    create hook-ext/schedule.yaml
    create hook-ext/schema.yaml
    create hook-ext/config/config.yaml
    create hook-ext/config/config.development.yaml
    create hook-ext/credentials/development/cli.json
    create hook-ext/credentials/development/browser.json
    create hook-ext/credentials/development/device.json
    create hook-ext/credentials/development/server.json
    Application created successfully.
    Back-end dependencies
    (Composer)

    View Slide

  15. Getting started
    $ hook app:new tdc2015
    create hook-ext/security.yaml
    create hook-ext/packages.yaml
    create hook-ext/schedule.yaml
    create hook-ext/schema.yaml
    create hook-ext/config/config.yaml
    create hook-ext/config/config.development.yaml
    create hook-ext/credentials/development/cli.json
    create hook-ext/credentials/development/browser.json
    create hook-ext/credentials/development/device.json
    create hook-ext/credentials/development/server.json
    Application created successfully.
    Crontab

    View Slide

  16. Getting started
    $ hook app:new tdc2015
    create hook-ext/security.yaml
    create hook-ext/packages.yaml
    create hook-ext/schedule.yaml
    create hook-ext/schema.yaml
    create hook-ext/config/config.yaml
    create hook-ext/config/config.development.yaml
    create hook-ext/credentials/development/cli.json
    create hook-ext/credentials/development/browser.json
    create hook-ext/credentials/development/device.json
    create hook-ext/credentials/development/server.json
    Application created successfully.
    Database
    migration

    View Slide

  17. Getting started
    $ hook app:new tdc2015
    create hook-ext/security.yaml
    create hook-ext/packages.yaml
    create hook-ext/schedule.yaml
    create hook-ext/schema.yaml
    create hook-ext/config/config.yaml
    create hook-ext/config/config.development.yaml
    create hook-ext/credentials/development/cli.json
    create hook-ext/credentials/development/browser.json
    create hook-ext/credentials/development/device.json
    create hook-ext/credentials/development/server.json
    Application created successfully.
    Back-end
    configurations
    (smtp, oauth, etc)

    View Slide

  18. Getting started
    $ hook app:new tdc2015
    create hook-ext/security.yaml
    create hook-ext/packages.yaml
    create hook-ext/schedule.yaml
    create hook-ext/schema.yaml
    create hook-ext/config/config.yaml
    create hook-ext/config/config.development.yaml
    create hook-ext/credentials/development/cli.json
    create hook-ext/credentials/development/browser.json
    create hook-ext/credentials/development/device.json
    create hook-ext/credentials/development/server.json
    Application created successfully.
    Configurations
    per environment
    (“development”)

    View Slide

  19. Getting started
    $ hook app:new tdc2015
    create hook-ext/security.yaml
    create hook-ext/packages.yaml
    create hook-ext/schedule.yaml
    create hook-ext/schema.yaml
    create hook-ext/config/config.yaml
    create hook-ext/config/config.development.yaml
    create hook-ext/credentials/development/cli.json
    create hook-ext/credentials/development/browser.json
    create hook-ext/credentials/development/device.json
    create hook-ext/credentials/development/server.json
    Application created successfully.
    Application credentials
    (“development”)

    View Slide

  20. Getting started
    $ hook app:new tdc2015 —environment production
    create hook-ext/security.yaml
    create hook-ext/packages.yaml
    create hook-ext/schedule.yaml
    create hook-ext/schema.yaml
    create hook-ext/config/config.yaml
    create hook-ext/config/config.production.yaml
    create hook-ext/credentials/production/cli.json
    create hook-ext/credentials/production/browser.json
    create hook-ext/credentials/production/device.json
    create hook-ext/credentials/production/server.json
    Application created successfully.
    Environment-specific
    files
    (“production”)

    View Slide

  21. App Credentials
    • cli - deploy, seed, full-access
    • browser - for web applications
    • device - for mobile applications
    • server - for server-to-server communication

    View Slide

  22. App Credentials
    • cli - deploy, seed, full-access
    • browser - para uso em webapps
    • device - para uso em mobiles
    • server - para comunicação server-to-server
    KEEP IT
    SAFE!!!!!1111

    View Slide

  23. Front-end
    • Friendly API
    • HTTP Requests
    • Status Codes

    View Slide

  24. JavaScript Client
    var hook = new Hook.Client({
    endpoint: "http://localhost:4665/",
    app_id: 1,
    key: "c2cee0f2575e3547315e123ddfbe8029"
    });

    View Slide

  25. JavaScript Client
    var hook = new Hook.Client({
    endpoint: process.env.HOOK_ENDPOINT,
    app_id: process.env.HOOK_APP_ID,
    key: process.env.HOOK_BROWSER_KEY
    });

    View Slide

  26. Collections
    • Database table
    • Typed attributes
    • Automatic migrations
    • File upload
    • Security rules (security.yaml)

    View Slide

  27. Collections API
    • #create
    • #where
    • #update
    • #remove
    • #then / #first

    View Slide

  28. collection().create
    hook.collection('books').create({
    name: "JavaScript: The Good Parts",
    author: "Douglas Crockford"
    })

    View Slide

  29. collection().create
    hook.collection('books').create({
    name: "JavaScript: The Good Parts",
    author: "Douglas Crockford"
    })
    Promise

    View Slide

  30. collection().create
    hook.collection('books').create({
    name: "JavaScript: The Good Parts",
    author: "Douglas Crockford"
    }).then(function(book) {
    console.log(book._id, book.name)
    console.log(book.author)
    console.log(book.created_at)
    }).otherwise(function(error) {
    console.log(error)
    })

    View Slide

  31. collection().create
    hook.collection('books').create({
    name: "JavaScript: The Good Parts",
    author: "Douglas Crockford"
    }).then(function(book) {
    console.log(book._id, book.name)
    console.log(book.author)
    console.log(book.created_at)
    }).otherwise(function(error) {
    console.log(error)
    })
    Success

    View Slide

  32. collection().create
    hook.collection('books').create({
    name: "JavaScript: The Good Parts",
    author: "Douglas Crockford"
    }).then(function(book) {
    console.log(book._id, book.name)
    console.log(book.author)
    console.log(book.created_at)
    }).otherwise(function(error) {
    console.log(error)
    })
    Error

    View Slide

  33. collection().where
    hook.collection('books').
    where("author", "Douglas Crockford")

    View Slide

  34. collection().where
    hook.collection('books').
    where("author", "Douglas Crockford")
    Hook.Collection

    View Slide

  35. collection().where
    hook.collection('books').
    where("author", "Douglas Crockford").
    where("name", "like", "%javascript%")
    Hook.Collection

    View Slide

  36. collection().then
    hook.collection('books').
    where("author", "Douglas Crockford").
    where("name", "like", "%javascript%").
    then(function(rows) {
    console.log(rows.length)
    // => 1
    console.log(rows[0].name)
    // => "JavaScript: The Good Parts"
    })

    View Slide

  37. collection().then
    hook.collection('books').
    where("author", "Douglas Crockford").
    where("name", "like", "%javascript%").
    then(function(rows) {
    console.log(rows.length)
    // => 1
    console.log(rows[0].name)
    // => "JavaScript: The Good Parts"
    })
    Array

    View Slide

  38. collection().first
    hook.collection('books').
    where("author", "Douglas Crockford").
    where("name", "like", "%javascript%").
    first(function(row) {
    console.log(row.name)
    // => "JavaScript: The Good Parts"
    console.log(row._id)
    // => 1
    })

    View Slide

  39. collection().first
    hook.collection('books').
    where("author", "Douglas Crockford").
    where("name", "like", "%javascript%").
    first(function(row) {
    console.log(row.name)
    // => "JavaScript: The Good Parts"
    console.log(row._id)
    // => 1
    })
    Object

    View Slide

  40. hook.collection('books').
    where("author", "Douglas Crockford").
    where("name", "like", "%javascript%").
    remove(function(data) {
    console.log(data.success)
    // => 1
    })
    collection().remove

    View Slide

  41. hook.collection('books').
    where("author", "Douglas Crockford").
    where("name", "like", "%javascript%").
    remove(function(data) {
    console.log(data.success)
    // => 1
    })
    collection().remove
    Object

    View Slide

  42. collection().update
    hook.collection('books').
    where("author", "Douglas Crockford").
    where("name", "like", "%javascript%").
    update({
    isbn: "978-0-596-51774-8"
    }).
    then(function(data) {
    console.log(data.success)
    // => true
    console.log(data.affected)
    // => 1
    })

    View Slide

  43. hook.collection('books').
    where("author", "Douglas Crockford").
    where("name", "like", "%javascript%").
    update({
    isbn: "978-0-596-51774-8"
    }).
    then(function(data) {
    console.log(data.success)
    // => true
    console.log(data.affected)
    // => 1
    })
    collection().update

    View Slide

  44. hook.collection('books').
    where("author", "Douglas Crockford").
    where("name", "like", "%javascript%").
    update({
    isbn: "978-0-596-51774-8"
    }).
    then(function(data) {
    console.log(data.success)
    // => true
    console.log(data.affected)
    // => 1
    })
    collection().update
    hook-ext/security.yaml

    View Slide

  45. hook-ext/
    security.yaml

    View Slide

  46. hook.collection('books').
    where("author", "Douglas Crockford").
    where("name", "like", "%javascript%").
    update({
    isbn: "978-0-596-51774-8"
    }).
    then(function(data) {
    console.log(data.success)
    // => true
    console.log(data.affected)
    // => 1
    })
    collection().update
    Object

    View Slide

  47. Seeding
    $ hook generate:seed books
    ...
    Seed created at 'hook-ext/seeds/books.yaml'.

    View Slide

  48. Seeding

    View Slide

  49. Seeding
    TRUNCATE TABLE `books`

    View Slide

  50. Seeding
    New rows

    View Slide

  51. Seeding
    $ hook db:seed
    ...
    Truncating 'books'... Success.
    Seeding 'books': 100%
    Done.

    View Slide

  52. Console
    $ hook console

    View Slide

  53. ( thnks node <3 )

    View Slide

  54. Schema
    • Database definitions / migrations
    • Collection data types
    • Collection relationships
    • Serves as documentation

    View Slide

  55. schema.yaml

    View Slide

  56. schema.yaml
    CREATE / UPDATE
    attribute

    View Slide

  57. schema.yaml
    Disable
    automatic migrations

    View Slide

  58. schema.yaml
    Relationships:
    - belongs_to
    - has_one
    - has_many
    - has_many (though)
    View the documentation!

    View Slide

  59. schema.yaml
    hook.collection('books').
    join('author').
    first(function(book) {
    console.log(book.name)
    console.log(book.author.name)
    })

    View Slide

  60. schema.yaml
    hook.collection('books').
    join('author').
    first(function(book) {
    console.log(book.name)
    console.log(book.author.name)
    })

    View Slide

  61. schema.yaml

    View Slide

  62. Authentication
    • Auth
    • OAuth (plugin)

    View Slide

  63. Authentication API
    • #register
    • #login
    • #logout
    • #update
    • #currentUser

    View Slide

  64. auth.register()
    hook.auth.register({
    email: "[email protected]",
    password: "1234"
    })

    View Slide

  65. auth.register()
    Promise
    hook.auth.register({
    email: "[email protected]",
    password: "1234"
    })

    View Slide

  66. auth.register()
    Required
    hook.auth.register({
    email: "[email protected]",
    password: "1234"
    })

    View Slide

  67. auth.register()
    hook.auth.register({
    email: "[email protected]",
    password: "1234"
    }).then(function(auth) {
    console.log("Registered!", auth)
    }).otherwise(function(data) {
    console.log(data.error)
    })

    View Slide

  68. auth.register()
    hook.auth.register({
    email: "[email protected]",
    password: "1234"
    }).then(function(auth) {
    console.log("Registered!", auth)
    }).otherwise(function(data) {
    console.log(data.error)
    })
    Object

    View Slide

  69. auth.register()
    hook.auth.register({
    email: "[email protected]",
    password: "1234"
    }).then(function(auth) {
    console.log("Registered!", auth)
    }).otherwise(function(data) {
    console.log(data.error)
    })
    Object

    View Slide

  70. auth.register()
    hook.auth.register({
    email: "[email protected]",
    password: "1234"
    }).then(function(auth) {
    console.log("Registered!", auth)
    }).otherwise(function(data) {
    console.log(data.error)
    })

    View Slide

  71. auth.register()
    hook.auth.register({
    email: "[email protected]",
    password: ""
    }).then(function(auth) {
    console.log("Registered!", auth)
    }).otherwise(function(data) {
    console.log(data.error)
    })

    View Slide

  72. auth.login()
    hook.auth.login({
    email: "[email protected]",
    password: "1234"
    })

    View Slide

  73. auth.login()
    Promise
    hook.auth.login({
    email: "[email protected]",
    password: "1234"
    })

    View Slide

  74. auth.login()
    Required
    hook.auth.login({
    email: "[email protected]",
    password: "1234"
    })

    View Slide

  75. auth.login()
    hook.auth.login({
    email: "[email protected]",
    password: "1234"
    }).then(function(auth) {
    console.log("Logged in!", auth)
    }).otherwise(function(data) {
    console.log(data.error)
    })

    View Slide

  76. auth.login()
    hook.auth.login({
    email: "[email protected]",
    password: "1234"
    }).then(function(auth) {
    console.log("Logged in!", auth)
    }).otherwise(function(data) {
    console.log(data.error)
    })
    Object

    View Slide

  77. auth.login()
    hook.auth.login({
    email: "[email protected]",
    password: "1234"
    }).then(function(auth) {
    console.log("Logged in!", auth)
    }).otherwise(function(data) {
    console.log(data.error)
    })
    Object

    View Slide

  78. auth.login()
    hook.auth.login({
    email: "[email protected]",
    password: "12345678"
    }).then(function(auth) {
    console.log("Logged in!", auth)
    }).otherwise(function(data) {
    console.log(data.error)
    })

    View Slide

  79. auth.login()
    hook.auth.login({
    email: "[email protected]",
    password: "not my password"
    }).then(function(auth) {
    console.log("Logged in!", auth)
    }).otherwise(function(data) {
    console.log(data.error)
    })

    View Slide

  80. auth.update()
    hook.auth.update({
    birthdate: "26/05/1990"
    }).then(function(auth) {
    // success
    }).otherwise(function(data) {
    // failure
    })

    View Slide

  81. auth.update()
    hook.auth.update({
    birthdate: "1990-26-05"
    }).then(function(auth) {
    // success
    }).otherwise(function(data) {
    // failure
    })

    View Slide

  82. OAuth
    • JavaScript Plugin
    • 3rd party service configuration (hook-ext/
    config.yaml)
    • Dependency (hook-ext/packages.yaml)
    hook.oauth.popup('facebook').then(function(auth) {
    console.log("Logged in!", auth)
    }).otherwise(function(data) {
    console.log(data.error)
    })

    View Slide

  83. user data

    View Slide

  84. user data
    hook.collection('items').create({
    auth_id: hook.auth.currentUser._id,
    name: "User item"
    })

    View Slide

  85. user data
    hook.collection('items').create({
    auth_id: hook.auth.currentUser._id,
    name: "User item"
    })
    owner

    View Slide

  86. user data
    hook-ext/security.yaml

    View Slide

  87. user data
    hook-ext/security.yaml

    View Slide

  88. Extending the back-
    end
    • Routes
    • Observers
    • Schedule
    • Composer packages

    View Slide

  89. Routes
    $ hook generate:route last_posts
    ...
    Route created at ‘hook-ext/routes/
    get_last_posts.php'.

    View Slide

  90. Routes

    View Slide

  91. Routes

    View Slide

  92. Routes
    hook.get('last_posts').then(...)

    View Slide

  93. Schedule
    hook-ext/schedule.yaml

    View Slide

  94. Schedule

    View Slide

  95. (php is ugly sry)

    View Slide

  96. (php is ugly sry)

    View Slide

  97. (php is ugly sry)

    View Slide

  98. (php is ugly sry)

    View Slide

  99. (php is ugly sry)

    View Slide

  100. Collection observers
    • toArray
    • creating / created
    • updating / updated
    • saving / saved
    • deleting / deleted

    View Slide

  101. Observers
    $ hook generate:observer auth
    class Auths
    {
    public function created($model)
    {
    $message = Mail::message('Welcome ' . $model->name);
    $message->from(Config::get('email.from'))
    ->to($model->email)
    ->subject("Welcome")
    ->send();
    }
    }

    View Slide

  102. Observers
    $ hook generate:observer auth
    class Auths
    {
    public function toArray($model, $array)
    {
    unset($array['endereco']);
    unset($array['cpf']);
    return $array;
    }
    public function creating($model)
    {
    $message = Mail::message('Welcome ' . $model->name);

    View Slide

  103. Composer packages
    • PHP’s Package Manager

    View Slide

  104. Composer packages
    • PHP’s Package Manager

    View Slide

  105. Clients
    • JavaScript
    • Corona SDK
    • C# (Unity)
    • Android
    • C++
    • …

    View Slide

  106. DEMO
    • hook-admin 


    https://github.com/doubleleft/hook-admin

    View Slide

  107. Thanks!
    twitter.com/endel
    github.com/endel
    [email protected]

    View Slide