├── .gitbook └── assets │ ├── akses-file-di-server.png │ ├── belajar-asinkron-nodejs.png │ ├── enable.png │ ├── geeklist.png │ ├── get-form.png │ ├── github-service.png │ ├── image-build.png │ ├── image-uploader.png │ ├── klout.png │ ├── learnboost.png │ ├── modul-npm.png │ ├── mypspace.png │ ├── nginx-apache-reqs-sec.png │ ├── node-sqlite3-enkripsi.png │ ├── node-sqlite3-no-enkripsi.png │ ├── notif.png │ ├── npm-flow.png │ ├── person-rest-delete.png │ ├── person-rest-get.png │ ├── person-rest-post.png │ ├── person-rest-update.png │ ├── persons-rest-api.png │ ├── persons-rest-diagram.png │ ├── post-urlencoded-data.png │ ├── server-response-dev-tool.png │ ├── shutterstock.png │ ├── testing-ci.png │ ├── testing-mocha.png │ ├── todatauri.png │ └── yummly.png ├── .github └── FUNDING.yml ├── README.md ├── SUMMARY.md ├── _book ├── asinkron_io_&_event │ ├── README.html │ ├── javascript_&_nodejs.html │ └── php_&_server_http_apache.html ├── cover.jpg ├── cover │ └── cover.xcf ├── cover_small.jpg ├── database │ └── README.html ├── expressjs │ └── README.html ├── gitbook │ ├── app.js │ ├── fonts │ │ ├── fontawesome │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ └── fontawesome-webfont.woff │ │ ├── merriweather │ │ │ ├── 250.woff │ │ │ ├── 250i.woff │ │ │ ├── 400.woff │ │ │ ├── 400i.woff │ │ │ ├── 700.woff │ │ │ ├── 700i.woff │ │ │ ├── 900.woff │ │ │ └── 900i.woff │ │ └── opensans │ │ │ ├── 300.woff │ │ │ ├── 300i.woff │ │ │ ├── 400.woff │ │ │ ├── 400i.woff │ │ │ ├── 600.woff │ │ │ ├── 600i.woff │ │ │ ├── 700.woff │ │ │ └── 700i.woff │ ├── images │ │ └── favicon.ico │ ├── jsrepl │ │ ├── engines │ │ │ └── javascript-default.js │ │ ├── jsrepl.js │ │ ├── langs │ │ │ └── javascript │ │ │ │ └── jsrepl_js.js │ │ ├── sandbox.html │ │ └── sandbox.js │ ├── plugins │ │ └── gitbook-plugin-mathjax │ │ │ └── plugin.js │ ├── print.css │ └── style.css ├── images │ └── npm-flow.gliffy ├── index.html ├── manifest.appcache ├── nodejs │ ├── README.html │ ├── javascript_di_server.html │ └── nodejs_show.html ├── npm │ ├── README.html │ ├── konsep.html │ └── npm.html ├── pemrosesan_data_form_html │ ├── README.html │ ├── multipart.html │ └── url_encoded.html ├── picture_uploader │ └── README.html ├── search_index.json ├── server_file_statis │ ├── README.html │ └── kode.html └── server_http_dasar │ ├── README.html │ └── menjalankan_server.html ├── asinkron_io_and_event ├── README.md ├── javascript_and_nodejs.md └── php_and_server_http_apache.md ├── book.json ├── cover.jpg ├── cover └── cover.xcf ├── cover_small.jpg ├── database ├── README.md ├── mongodb │ ├── README.md │ ├── mongoose.md │ └── node_mongodb.md ├── mysql │ ├── README.md │ └── node_mysql.md └── sqlite │ ├── README.md │ ├── enkripsi │ ├── README.md │ └── sqlchiper.md │ └── node-sqlite3.md ├── expressjs ├── README.md ├── kode.md ├── server │ ├── README.md │ ├── akses_server.md │ └── middleware.md └── server_rest.md ├── image_uploader.md ├── images ├── npm-flow.gliffy ├── persons.gliffy └── todatauri.gliffy ├── memakai_es6.md ├── nodejs ├── README.md ├── javascript_di_server.md └── nodejs_show.md ├── npm ├── README.md ├── konsep.md └── npm.md ├── pemrosesan_data_form_html ├── README.md ├── multipart.md └── url_encoded.md ├── pengarang.md ├── person_rest_api ├── README.md ├── inisialisasi.md ├── kode.md └── testing.md ├── server_file_statis.md ├── server_file_statis └── kode.md ├── server_http_dasar ├── README.md └── menjalankan_server.md ├── testing ├── README.md ├── automasi.md └── rest_testing.md └── todatauri ├── README.md ├── koneksi_mysql.md ├── konverter_gambar_png_ke_data_uri.md └── penggunaan.md /.gitbook/assets/akses-file-di-server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/akses-file-di-server.png -------------------------------------------------------------------------------- /.gitbook/assets/belajar-asinkron-nodejs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/belajar-asinkron-nodejs.png -------------------------------------------------------------------------------- /.gitbook/assets/enable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/enable.png -------------------------------------------------------------------------------- /.gitbook/assets/geeklist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/geeklist.png -------------------------------------------------------------------------------- /.gitbook/assets/get-form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/get-form.png -------------------------------------------------------------------------------- /.gitbook/assets/github-service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/github-service.png -------------------------------------------------------------------------------- /.gitbook/assets/image-build.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/image-build.png -------------------------------------------------------------------------------- /.gitbook/assets/image-uploader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/image-uploader.png -------------------------------------------------------------------------------- /.gitbook/assets/klout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/klout.png -------------------------------------------------------------------------------- /.gitbook/assets/learnboost.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/learnboost.png -------------------------------------------------------------------------------- /.gitbook/assets/modul-npm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/modul-npm.png -------------------------------------------------------------------------------- /.gitbook/assets/mypspace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/mypspace.png -------------------------------------------------------------------------------- /.gitbook/assets/nginx-apache-reqs-sec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/nginx-apache-reqs-sec.png -------------------------------------------------------------------------------- /.gitbook/assets/node-sqlite3-enkripsi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/node-sqlite3-enkripsi.png -------------------------------------------------------------------------------- /.gitbook/assets/node-sqlite3-no-enkripsi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/node-sqlite3-no-enkripsi.png -------------------------------------------------------------------------------- /.gitbook/assets/notif.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/notif.png -------------------------------------------------------------------------------- /.gitbook/assets/npm-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/npm-flow.png -------------------------------------------------------------------------------- /.gitbook/assets/person-rest-delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/person-rest-delete.png -------------------------------------------------------------------------------- /.gitbook/assets/person-rest-get.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/person-rest-get.png -------------------------------------------------------------------------------- /.gitbook/assets/person-rest-post.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/person-rest-post.png -------------------------------------------------------------------------------- /.gitbook/assets/person-rest-update.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/person-rest-update.png -------------------------------------------------------------------------------- /.gitbook/assets/persons-rest-api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/persons-rest-api.png -------------------------------------------------------------------------------- /.gitbook/assets/persons-rest-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/persons-rest-diagram.png -------------------------------------------------------------------------------- /.gitbook/assets/post-urlencoded-data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/post-urlencoded-data.png -------------------------------------------------------------------------------- /.gitbook/assets/server-response-dev-tool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/server-response-dev-tool.png -------------------------------------------------------------------------------- /.gitbook/assets/shutterstock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/shutterstock.png -------------------------------------------------------------------------------- /.gitbook/assets/testing-ci.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/testing-ci.png -------------------------------------------------------------------------------- /.gitbook/assets/testing-mocha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/testing-mocha.png -------------------------------------------------------------------------------- /.gitbook/assets/todatauri.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/todatauri.png -------------------------------------------------------------------------------- /.gitbook/assets/yummly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/.gitbook/assets/yummly.png -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [junwatu] 4 | 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pendahuluan 2 | 3 | > **Note:** This book is written in Bahasa Indonesia and the main reason for that is because most of Node.js beginners in my country Indonesia is having difficulties to find Node.js resources written in my native language. 4 | 5 | Buku ini cocok bagi siapa saja yang ingin mulai belajar pemrograman di platform Node.js khususnya untuk membangun aplikasi web. Syarat yang dibutuhkan adalah pembaca setidaknya pernah atau sudah bisa memakai bahasa pemrograman JavaScript. 6 | 7 | Ebook ini bisa anda akses dibeberapa tempat, 8 | 9 | * [Github IDJS](https://idjs.github.io/belajar-nodejs) 10 | * [Gitbook](https://app.gitbook.com/@junwatu/s/pengenalan-node-js/) 11 | * [Google Play Store](https://play.google.com/store/books/details?id=pdOfDwAAQBAJ) 12 | 13 | ## Feedback 14 | 15 | Untuk pertanyaan, kesalahan ketik atau permintaan silahkan mengisi [Github issue](https://github.com/idjs/belajar-nodejs/issues). 16 | 17 | ## Lisensi 18 | 19 | Pengenalan Node.js oleh [Equan Pr.](https://sajen.id) di kerjakan di bawah lisensi [Creative Commons Attribution-NonCommercial 4.0 International License](http://creativecommons.org/licenses/by-nc/4.0/). 20 | 21 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Table of contents 2 | 3 | * [Pendahuluan](README.md) 4 | * [Node.js](nodejs/README.md) 5 | * [JavaScript Di Server](nodejs/javascript_di_server.md) 6 | * [Node.js In Action](nodejs/nodejs_show.md) 7 | * [Asinkron I/O & Event](asinkron_io_and_event/README.md) 8 | * [PHP & Server HTTP Apache](asinkron_io_and_event/php_and_server_http_apache.md) 9 | * [Javascript & Node.js](asinkron_io_and_event/javascript_and_nodejs.md) 10 | * [Server HTTP Dasar](server_http_dasar/README.md) 11 | * [Menjalankan Server](server_http_dasar/menjalankan_server.md) 12 | * [Server File Statis](server_file_statis.md) 13 | * [Pemrosesan Data Form HTML](pemrosesan_data_form_html/README.md) 14 | * [URL Encode](pemrosesan_data_form_html/url_encoded.md) 15 | * [Multipart Data](pemrosesan_data_form_html/multipart.md) 16 | * [Module npm](npm/README.md) 17 | * [Konsep](npm/npm.md) 18 | * [Paket npm](npm/konsep.md) 19 | * [ExpressJS](expressjs/README.md) 20 | * [Server File](expressjs/server/README.md) 21 | * [Middleware](expressjs/server/middleware.md) 22 | * [Akses Server](expressjs/server/akses_server.md) 23 | * [Server REST](expressjs/server_rest.md) 24 | * [Database](database/README.md) 25 | * [SQLite](database/sqlite/README.md) 26 | * [Node Sqlite3](database/sqlite/node-sqlite3.md) 27 | * [Enkripsi](database/sqlite/enkripsi/README.md) 28 | * [sqlcipher](database/sqlite/enkripsi/sqlchiper.md) 29 | * [MySQL](database/mysql/README.md) 30 | * [Node MySQL](database/mysql/node_mysql.md) 31 | * [MongoDB](database/mongodb/README.md) 32 | * [Node MongoDB](database/mongodb/node_mongodb.md) 33 | * [Mongoose](database/mongodb/mongoose.md) 34 | * [Testing](testing/README.md) 35 | * [REST](testing/rest_testing.md) 36 | * [Automasi](testing/automasi.md) 37 | * [To Data URI](todatauri/README.md) 38 | * [Penggunaan](todatauri/penggunaan.md) 39 | * [todatauri.js](todatauri/konverter_gambar_png_ke_data_uri.md) 40 | * [Koneksi MySQL](todatauri/koneksi_mysql.md) 41 | * [Person REST API](person_rest_api/README.md) 42 | * [Cara Kerja](person_rest_api/inisialisasi.md) 43 | * [Server](person_rest_api/kode.md) 44 | * [Pengetesan](person_rest_api/testing.md) 45 | * [Image Uploader](image_uploader.md) 46 | * [Memakai ES6](memakai_es6.md) 47 | * [Tentang Pengarang](pengarang.md) 48 | 49 | -------------------------------------------------------------------------------- /_book/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/cover.jpg -------------------------------------------------------------------------------- /_book/cover/cover.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/cover/cover.xcf -------------------------------------------------------------------------------- /_book/cover_small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/cover_small.jpg -------------------------------------------------------------------------------- /_book/database/README.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Picture Uploader | Aplikasi Web Node.js 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
34 |
35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 |

84 | 85 | Aplikasi Web Node.js 86 |

87 |
88 | 89 | 90 | 91 |
92 | 95 | 326 |
327 | 328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 |
378 |
379 | 380 |
381 | 382 |
383 | 384 |

Picture Uploader

385 | 386 | 387 |
388 | 389 |
390 |
391 |
392 | 393 | 394 | 395 | 396 | 397 |
398 |
399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 418 | 419 | 420 | 421 | 422 | 423 | -------------------------------------------------------------------------------- /_book/expressjs/README.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ExpressJS | Aplikasi Web Node.js 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 |

86 | 87 | Aplikasi Web Node.js 88 |

89 |
90 | 91 | 92 | 93 |
94 | 97 | 328 |
329 | 330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 |
380 |
381 | 382 |
383 | 384 |
385 | 386 |

ExpressJS

387 | 388 | 389 |
390 | 391 |
392 |
393 |
394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 |
402 |
403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 422 | 423 | 424 | 425 | 426 | 427 | -------------------------------------------------------------------------------- /_book/gitbook/fonts/fontawesome/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/fonts/fontawesome/FontAwesome.otf -------------------------------------------------------------------------------- /_book/gitbook/fonts/fontawesome/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/fonts/fontawesome/fontawesome-webfont.eot -------------------------------------------------------------------------------- /_book/gitbook/fonts/fontawesome/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/fonts/fontawesome/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff -------------------------------------------------------------------------------- /_book/gitbook/fonts/merriweather/250.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/fonts/merriweather/250.woff -------------------------------------------------------------------------------- /_book/gitbook/fonts/merriweather/250i.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/fonts/merriweather/250i.woff -------------------------------------------------------------------------------- /_book/gitbook/fonts/merriweather/400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/fonts/merriweather/400.woff -------------------------------------------------------------------------------- /_book/gitbook/fonts/merriweather/400i.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/fonts/merriweather/400i.woff -------------------------------------------------------------------------------- /_book/gitbook/fonts/merriweather/700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/fonts/merriweather/700.woff -------------------------------------------------------------------------------- /_book/gitbook/fonts/merriweather/700i.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/fonts/merriweather/700i.woff -------------------------------------------------------------------------------- /_book/gitbook/fonts/merriweather/900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/fonts/merriweather/900.woff -------------------------------------------------------------------------------- /_book/gitbook/fonts/merriweather/900i.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/fonts/merriweather/900i.woff -------------------------------------------------------------------------------- /_book/gitbook/fonts/opensans/300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/fonts/opensans/300.woff -------------------------------------------------------------------------------- /_book/gitbook/fonts/opensans/300i.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/fonts/opensans/300i.woff -------------------------------------------------------------------------------- /_book/gitbook/fonts/opensans/400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/fonts/opensans/400.woff -------------------------------------------------------------------------------- /_book/gitbook/fonts/opensans/400i.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/fonts/opensans/400i.woff -------------------------------------------------------------------------------- /_book/gitbook/fonts/opensans/600.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/fonts/opensans/600.woff -------------------------------------------------------------------------------- /_book/gitbook/fonts/opensans/600i.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/fonts/opensans/600i.woff -------------------------------------------------------------------------------- /_book/gitbook/fonts/opensans/700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/fonts/opensans/700.woff -------------------------------------------------------------------------------- /_book/gitbook/fonts/opensans/700i.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/fonts/opensans/700i.woff -------------------------------------------------------------------------------- /_book/gitbook/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/_book/gitbook/images/favicon.ico -------------------------------------------------------------------------------- /_book/gitbook/jsrepl/engines/javascript-default.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright Joyent, Inc. and other Node contributors. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a 6 | copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to permit 10 | persons to whom the Software is furnished to do so, subject to the 11 | following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included 14 | in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 19 | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 20 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22 | USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | Original at: https://github.com/joyent/node/blob/master/lib/util.js 25 | */ 26 | (function(){function o(c){return c instanceof Array||Array.isArray(c)||c&&c!==Object.prototype&&o(c.__proto__)}function p(c){return c instanceof RegExp||typeof c==="function"&&c.constructor.name==="RegExp"&&c.compile&&c.test&&c.exec&&(""+c).match(/^\/.*\/[gim]{0,3}$/)}var q=80,l=function(c,h,b,f){function m(a,c){switch(typeof a){case "undefined":return d("undefined","undefined");case "string":var b="'"+JSON.stringify(a).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return d(b,"string"); 27 | case "number":return d(""+a,"number");case "boolean":return d(""+a,"boolean")}if(a===null)return d("null","null");var f=Object.keys(a),i=h?Object.getOwnPropertyNames(a):f;if(typeof a==="function"&&i.length===0)return p(a)?d(""+a,"regexp"):d("[Function"+(a.name?": "+a.name:"")+"]","special");if(a instanceof Date&&i.length===0)return d(a.toUTCString(),"date");var j,l;o(a)?(l="Array",b=["[","]"]):(l="Object",b=["{","}"]);typeof a==="function"?(j=a.name?": "+a.name:"",j=p(a)?" "+a:" [Function"+j+"]"): 28 | j="";a instanceof Date&&(j=" "+a.toUTCString());if(i.length===0)return b[0]+j+b[1];if(c<0)return p(a)?d(""+a,"regexp"):d("[Object]","special");k.push(a);i=i.map(function(b){var e,g;a.__lookupGetter__&&(a.__lookupGetter__(b)?g=a.__lookupSetter__(b)?d("[Getter/Setter]","special"):d("[Getter]","special"):a.__lookupSetter__(b)&&(g=d("[Setter]","special")));f.indexOf(b)<0&&(e="["+b+"]");g||(k.indexOf(a[b])<0?(g=c===null?m(a[b]):m(a[b],c-1),g.indexOf("\n")>-1&&(g=o(a)?g.split("\n").map(function(a){return" "+ 29 | a}).join("\n").substr(2):"\n"+g.split("\n").map(function(a){return" "+a}).join("\n"))):g=d("[Circular]","special"));if(typeof e==="undefined"){if(l==="Array"&&b.match(/^\d+$/))return g;e=JSON.stringify(""+b);e.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(e=e.substr(1,e.length-2),e=d(e,"name")):(e=e.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),e=d(e,"string"))}return e+": "+g});k.pop();var n=0;return i=i.reduce(function(a,b){n++;b.indexOf("\n")>=0&&n++;return a+b.length+1},0)>q?b[0]+ 30 | (j===""?"":j+"\n ")+" "+i.join(",\n ")+" "+b[1]:b[0]+j+" "+i.join(", ")+" "+b[1]}var k=[],d=function(a,b){var c={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},d={special:"cyan",number:"blue","boolean":"yellow",undefined:"grey","null":"bold",string:"green",date:"magenta",regexp:"red"}[b];return d?"\u001b["+c[d][0]+"m"+a+"\u001b["+c[d][1]+"m":a};f||(d=function(a){return a}); 31 | return m(c,typeof b==="undefined"?2:b)},r=/%[sdj%]/g,s=function(c){if(typeof c!=="string"){for(var h=[],b=0;b=m)return c;switch(c){case "%s":return String(f[b++]);case "%d":return Number(f[b++]);case "%j":return JSON.stringify(f[b++]);case "%%":return"%";default:return c}}),k=f[b];b-1?g.push(f.splice(b,1)):g.push(void 0)):g.push(this.listeners[b]=[]));return g};h.prototype.fire=function(a,c){var b,f,d,e,c=this.makeArray(c); 6 | f=this.listeners[a];if(f!=null){c.push(a);var g;g=[];for(d=0,e=f.length;d 2 | 3 | 4 | jsREPL Sandbox 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /_book/gitbook/jsrepl/sandbox.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 17 | 3. The names of its contributors may not be used to endorse or promote 18 | products derived from this software without specific prior written 19 | permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 25 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 28 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | Any feedback is very welcome. 34 | http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html 35 | email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) 36 | */ 37 | (function(c){try{c.window=c.window||c}catch(b){}try{c.self=c.self||c}catch(e){}var a;c.addEventListener("message",function(d){for(var d=JSON.parse(d.data),b=a,c=d.type.split("."),e=0;ethis.OUT_EVERY_MS&&(clearTimeout(this.outTimeout),this.flush())},flush:function(){if(this.output_buffer.length)this.post({type:"output",data:this.output_buffer.join("")}),this.outTimeout=0,this.output_buffer=[]},err:function(a){a={type:"error", 41 | data:a.toString()};this.flush();this.post(a)},input:function(a){this.input.write=a;this.flush();this.post({type:"input"})},result:function(a){a={type:"result",data:a};this.flush();this.post(a)},ready:function(){this.post({type:"ready"})},getNextLineIndent:function(a){this.post({type:"indent",data:this.engine.GetNextLineIndent(a)})},progress:function(a){this.post({type:"progress",data:a})},dbInput:function(){this.flush();this.post({type:"db_input"})},serverInput:function(){this.flush();this.post({type:"server_input"})}, 42 | bindAll:function(a){for(var b in a)(function(b){var c=a[b];typeof c=="function"&&(a[b]=function(){var b=[].slice.call(arguments);return c.apply(a,b)})})(b)},hide:function(a){try{Object.defineProperty(c,a,{writable:false,enumerable:false,configurable:false,value:c[a]})}catch(b){}},set_input_server:function(a){this.input_server={url:(a.url||"/emscripten/input/")+a.input_id,cors:a.cors||false}}};a.bindAll(a);c.Sandboss=a;a.hide("Sandboss");if(self.openDatabaseSync){var f=self.openDatabaseSync("replit_input", 43 | "1.0","Emscripted input",1024);self.prompt=function(){a.dbInput();var b=null;f.transaction(function(a){b=a});for(var c;!(c=b.executeSql("SELECT * FROM input").rows).length;)for(c=0;c<1E8;c++);b.executeSql("DELETE FROM input");return c.item(0).text};a.hide("prompt")}else if(!a.isFrame)self.prompt=function(){a.serverInput();var b;b=a.input_server.url;var c=new XMLHttpRequest;if(a.input_server.cors)if("withCredentials"in c)c.open("GET",b,false);else if(typeof XDomainRequest!="undefined")c=new XDomainRequest, 44 | c.open("GET",b);else throw Error("Your browser doesn' support CORS");else c.open("GET",b,false);b=c;b.send(null);return b.status===200?b.responseText:"ERROR: ON NON-WEBKIT BROWSERS CONNECTION TO THE SERVER IS NEEDED FOR INPUT"}})(this); 45 | (function(){var c=function(b){b==void 0&&(b=Date.now());this.N=624;this.M=397;this.MATRIX_A=2567483615;this.UPPER_MASK=2147483648;this.LOWER_MASK=2147483647;this.mt=Array(this.N);this.mti=this.N+1;this.init_genrand(b)};c.prototype.init_genrand=function(b){this.mt[0]=b>>>0;for(this.mti=1;this.mti>>30,this.mt[this.mti]=(((b&4294901760)>>>16)*1812433253<<16)+(b&65535)*1812433253+this.mti,this.mt[this.mti]>>>=0};c.prototype.init_by_array=function(b, 46 | c){var a,f,d;this.init_genrand(19650218);a=1;f=0;for(d=this.N>c?this.N:c;d;d--){var h=this.mt[a-1]^this.mt[a-1]>>>30;this.mt[a]=(this.mt[a]^(((h&4294901760)>>>16)*1664525<<16)+(h&65535)*1664525)+b[f]+f;this.mt[a]>>>=0;a++;f++;a>=this.N&&(this.mt[0]=this.mt[this.N-1],a=1);f>=c&&(f=0)}for(d=this.N-1;d;d--)h=this.mt[a-1]^this.mt[a-1]>>>30,this.mt[a]=(this.mt[a]^(((h&4294901760)>>>16)*1566083941<<16)+(h&65535)*1566083941)-a,this.mt[a]>>>=0,a++,a>=this.N&&(this.mt[0]=this.mt[this.N-1],a=1);this.mt[0]= 47 | 2147483648};c.prototype.genrand_int32=function(){var b,c=[0,this.MATRIX_A];if(this.mti>=this.N){var a;this.mti==this.N+1&&this.init_genrand(5489);for(a=0;a>>1^c[b&1];for(;a>>1^c[b&1];b=this.mt[this.N-1]&this.UPPER_MASK|this.mt[0]&this.LOWER_MASK;this.mt[this.N-1]=this.mt[this.M-1]^ 48 | b>>>1^c[b&1];this.mti=0}b=this.mt[this.mti++];b^=b>>>11;b^=b<<7&2636928640;b^=b<<15&4022730752;b^=b>>>18;return b>>>0};c.prototype.genrand_int31=function(){return this.genrand_int32()>>>1};c.prototype.genrand_real1=function(){return this.genrand_int32()*(1/4294967295)};c.prototype.random=function(){return this.genrand_int32()*(1/4294967296)};c.prototype.genrand_real3=function(){return(this.genrand_int32()+0.5)*(1/4294967296)};c.prototype.genrand_res53=function(){var b=this.genrand_int32()>>>5,c=this.genrand_int32()>>> 49 | 6;return(b*67108864+c)*1.1102230246251565E-16};(function(){Math._random=Math.random;var b=new c(42);Math.random=function(){return b.random()};Math.seed=function(e){b=new c(e)}})()})();if(!Date.now)Date.now=function(){return+new Date};if(!Object.keys)Object.keys=function(c){if(c!==Object(c))throw new TypeError("Object.keys called on non-object");var b=[],e;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&b.push(e);return b};if(!Object.getOwnPropertyNames)Object.getOwnPropertyNames=Object.keys; 50 | if(!Object.create)Object.create=function(c){function b(){}b.prototype=c;return new b};if(!Array.isArray)Array.isArray=function(c){return{}.toString.call(c)=="[object Array]"}; 51 | if(!Function.prototype.bind)Function.prototype.bind=function(c){if(typeof this!=="function")throw new TypeError("Function.prototype.bind - what is trying to be fBound is not callable");var b=Array.prototype.slice.call(arguments,1),e=this,a=function(){},f=function(){try{return e.apply(this instanceof a?this:c||window,b.concat(Array.prototype.slice.call(arguments)))}catch(d){return e.apply(c||window,b.concat(Array.prototype.slice.call(arguments)))}};a.prototype=this.prototype;f.prototype=new a;return f}; 52 | if(!Object.freeze)Object.freeze=function(c){return c.___frozen___=true};if(!Object.isFrozen)Object.isFrozen=function(c){return Boolean(c.___frozen___)}; 53 | -------------------------------------------------------------------------------- /_book/gitbook/plugins/gitbook-plugin-mathjax/plugin.js: -------------------------------------------------------------------------------- 1 | require(["gitbook"], function(gitbook) { 2 | MathJax.Hub.Config({ 3 | tex2jax: { 4 | inlineMath: [['$','$'], ['\\(','\\)']], 5 | processEscapes: true 6 | } 7 | }); 8 | 9 | 10 | gitbook.events.bind("page.change", function() { 11 | MathJax.Hub.Typeset() 12 | }); 13 | }); -------------------------------------------------------------------------------- /_book/gitbook/print.css: -------------------------------------------------------------------------------- 1 | .link-inherit{color:inherit}.link-inherit:hover,.link-inherit:focus{color:inherit}.hljs-comment,.hljs-title{color:#8e908c}.hljs-variable,.hljs-attribute,.hljs-tag,.hljs-regexp,.ruby .hljs-constant,.xml .hljs-tag .hljs-title,.xml .hljs-pi,.xml .hljs-doctype,.html .hljs-doctype,.css .hljs-id,.css .hljs-class,.css .hljs-pseudo{color:#c82829}.hljs-number,.hljs-preprocessor,.hljs-pragma,.hljs-built_in,.hljs-literal,.hljs-params,.hljs-constant{color:#f5871f}.ruby .hljs-class .hljs-title,.css .hljs-rules .hljs-attribute{color:#eab700}.hljs-string,.hljs-value,.hljs-inheritance,.hljs-header,.ruby .hljs-symbol,.xml .hljs-cdata{color:#718c00}.css .hljs-hexcolor{color:#3e999f}.hljs-function,.python .hljs-decorator,.python .hljs-title,.ruby .hljs-function .hljs-title,.ruby .hljs-title .hljs-keyword,.perl .hljs-sub,.javascript .hljs-title,.coffeescript .hljs-title{color:#4271ae}.hljs-keyword,.javascript .hljs-function{color:#8959a8}.hljs{display:block;background:white;color:#4d4d4c;padding:.5em}.coffeescript .javascript,.javascript .xml,.tex .hljs-formula,.xml .javascript,.xml .vbscript,.xml .css,.xml .hljs-cdata{opacity:.5}.book-chapter{display:none}article{page-break-after:always}pre,blockquote{border:1px solid #999;page-break-inside:avoid;background:#f1f1f1;padding:8px}img{max-width:100%!important;page-break-inside:avoid;margin:0 auto}.exercise,.quiz{margin:1cm 0;padding:.4cm;page-break-inside:avoid;border:3px solid #ddd}.exercise .exercise-header,.quiz .exercise-header{margin-bottom:.4cm;padding-bottom:.2cm;border-bottom:1px solid #ddd}.exercise .question,.quiz .question{margin-top:.4cm} -------------------------------------------------------------------------------- /_book/manifest.appcache: -------------------------------------------------------------------------------- 1 | CACHE MANIFEST 2 | # Revision 1403584076845 3 | 4 | CACHE: 5 | expressjs/README.html 6 | index.html 7 | asinkron_io_&_event/README.html 8 | asinkron_io_&_event/javascript_&_nodejs.html 9 | asinkron_io_&_event/php_&_server_http_apache.html 10 | database/README.html 11 | nodejs/README.html 12 | nodejs/javascript_di_server.html 13 | nodejs/nodejs_show.html 14 | npm/README.html 15 | npm/konsep.html 16 | npm/npm.html 17 | pemrosesan_data_form_html/README.html 18 | pemrosesan_data_form_html/multipart.html 19 | pemrosesan_data_form_html/url_encoded.html 20 | picture_uploader/README.html 21 | server_file_statis/README.html 22 | server_file_statis/kode.html 23 | server_http_dasar/README.html 24 | server_http_dasar/menjalankan_server.html 25 | gitbook/app.js 26 | gitbook/fonts/fontawesome/FontAwesome.otf 27 | gitbook/fonts/fontawesome/fontawesome-webfont.eot 28 | gitbook/fonts/fontawesome/fontawesome-webfont.svg 29 | gitbook/fonts/fontawesome/fontawesome-webfont.ttf 30 | gitbook/fonts/fontawesome/fontawesome-webfont.woff 31 | gitbook/fonts/merriweather/250.woff 32 | gitbook/fonts/merriweather/250i.woff 33 | gitbook/fonts/merriweather/400.woff 34 | gitbook/fonts/merriweather/400i.woff 35 | gitbook/fonts/merriweather/700.woff 36 | gitbook/fonts/merriweather/700i.woff 37 | gitbook/fonts/merriweather/900.woff 38 | gitbook/fonts/merriweather/900i.woff 39 | gitbook/fonts/opensans/300.woff 40 | gitbook/fonts/opensans/300i.woff 41 | gitbook/fonts/opensans/400.woff 42 | gitbook/fonts/opensans/400i.woff 43 | gitbook/fonts/opensans/600.woff 44 | gitbook/fonts/opensans/600i.woff 45 | gitbook/fonts/opensans/700.woff 46 | gitbook/fonts/opensans/700i.woff 47 | gitbook/images/favicon.ico 48 | gitbook/jsrepl/engines/javascript-default.js 49 | gitbook/jsrepl/jsrepl.js 50 | gitbook/jsrepl/langs/javascript/jsrepl_js.js 51 | gitbook/jsrepl/sandbox.html 52 | gitbook/jsrepl/sandbox.js 53 | gitbook/print.css 54 | gitbook/style.css 55 | gitbook/plugins/gitbook-plugin-mathjax/plugin.js 56 | 57 | NETWORK: 58 | * -------------------------------------------------------------------------------- /asinkron_io_and_event/README.md: -------------------------------------------------------------------------------- 1 | # Asinkron I/O & Event 2 | 3 | Tidak seperti kebanyakan bahasa backend lainnya operasi fungsi di javascript lebih bersifat `asinkron` dan banyak menggunakan `event` demikian juga dengan Node.js. Sebelum penjelasan lebih lanjut mari kita lihat terlebih dahulu tentang metode `sinkron` seperti yang dipakai pada PHP dengan web server Apache. 4 | 5 | -------------------------------------------------------------------------------- /asinkron_io_and_event/javascript_and_nodejs.md: -------------------------------------------------------------------------------- 1 | # Javascript & Node.js 2 | 3 | Kembali ke Javascript!. Untuk mengetahui apa yang dimaksud dengan pemrograman asinkron bisa lebih mudah dengan memakai pendekatan contoh kode. Perhatikan kode Javascript pada Node.js berikut 4 | 5 | ```text 6 | var fs = require('fs'); 7 | 8 | fs.readFile('./resource.json',function(err, data){ 9 | if(err) throw err; 10 | console.log(JSON.parse(data)); 11 | }); 12 | 13 | console.log('Selanjutnya...'); 14 | ``` 15 | 16 | fungsi `readFile()` akan membaca membaca isi dari file `resource.json` secara asinkron yang artinya proses eksekusi program tidak akan menunggu pembacaan file `resource.json` sampai selesai tetapi program akan tetap menjalankan kode Javascript selanjutnya yaitu `console.log('Selanjutnya...')`. Sekarng lihat apa yang terjadi jika kode javascript diatas dijalankan 17 | 18 | ![belajar-asinkron-nodejs](../.gitbook/assets/belajar-asinkron-nodejs.png) 19 | 20 | Jika proses pembacaan file `resource.json` selesai maka fungsi callback pada `readFile()` akan di jalankan dan hasilnya akan ditampilkan pada console. Yah, fungsi callback merupakan konsep yang penting dalam proses I/O yang asinkron karena melalui fungsi callback ini data data yang dikembalikan oleh proses I/O akan di proses. 21 | 22 | Lalu bagaimana platform Node.js mengetahui kalau suatu proses itu telah selesai atau tidak ?...jawabannya adalah [Event Loop](http://en.wikipedia.org/wiki/Event_loop). Event - event yang terjadi karena proses asinkron seperti pada fungsi `fs.readFile()` akan ditangani oleh yang namanya Event Loop ini. 23 | 24 | Campuran teknologi antara event driven dan proses asinkron ini memungkinkan pembuatan aplikasi dengan penggunaan data secara masif dan real-time. Sifat komunikasi Node.js I/O yang ringan dan bisa menangani user secara bersamaan dalam jumlah relatif besar tetapi tetap menjaga state dari koneksi supaya tetap terbuka dan dengan penggunaan memori yang cukup kecil memungkinkan pengembangan aplikasi dengan penggunaan data yang besar dan kolaboratif...Yeah, Node.js FTW! :metal: 25 | 26 | -------------------------------------------------------------------------------- /asinkron_io_and_event/php_and_server_http_apache.md: -------------------------------------------------------------------------------- 1 | # PHP & Server HTTP Apache 2 | 3 | Mari kita lihat contoh berikut yaitu operasi fungsi akses ke database MySQL oleh PHP yang dilakukan secara sinkron 4 | 5 | ```text 6 | $hasil = mysql_query("SELECT * FROM TabelAnggota"); 7 | print_r($hasil); 8 | ``` 9 | 10 | pengambilan data oleh `mysql_query()` diatas akan dijalankan dan operasi berikutnya `print_r()` akan diblok atau tidak akan berjalan sebelum akses ke database selesai. Yang perlu menjadi perhatian disini yaitu proses Input Output atau I/O akses ke database oleh `mysql_query()` dapat memakan waktu yang relatif mungkin beberapa detik atau menit tergantung dari waktu latensi dari I/O. Waktu latensi ini tergantung dari banyak hal seperti 11 | 12 | * Query database lambat akibat banyak pengguna yang mengakses 13 | * Kualitas jaringan untuk akses ke database jelek 14 | * Proses baca tulis ke disk komputer database yang membutuhkan waktu 15 | * ... 16 | 17 | Sebelum proses I/O selesai maka selama beberapa detik atau menit tersebut state dari proses `mysql_query()` bisa dibilang idle atau tidak melakukan apa-apa. 18 | 19 | Lalu jika proses I/O di blok bagaimana jika ada request lagi dari user ? apa yang akan dilakukan oleh server untuk menangani request ini ?..penyelesaiannya yaitu dengan memakai pendekatan proses `multithread`. Melalui pendekatan ini tiap koneksi yang terjadi akan ditangani oleh `thread`. Thread disini bisa dikatakan sebagai task yang dijalankan oleh prosesor komputer. 20 | 21 | Sepertinya permasalahan I/O yang terblok terselesaikan dengan pendekatan metode ini tetapi dengan bertambahnya koneksi yang terjadi maka `thread` akan semakin banyak sehingga prosesor akan semakin terbebani, belum lagi untuk switching antar thread menyebabkan konsumsi memory \(RAM\) komputer yang cukup besar. 22 | 23 | Berikut contoh benchmark antara web server Apache dan Nginx \(server HTTP seperti halnya Apache hanya saja Nginx memakai sistem asinkron I/O dan event yang mirip Node.js\). Gambar ini diambil dari [goo.gl/pvLL4](http://goo.gl/pvLL4) 24 | 25 | ![apache-vs-nginx-reqs-sec](../.gitbook/assets/nginx-apache-reqs-sec.png) 26 | 27 | Bisa dilihat bahwa Nginx bisa menangani request yang jauh lebih banyak daripada web server Apache pada jumlah koneksi bersama yang semakin naik. 28 | 29 | -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | { 2 | "gitbook": ">=2.0.0", 3 | "title": "Pengenalan Node.js", 4 | "description": "Pengenalan Node.js melalui aplikasi web", 5 | "language": "id" 6 | } 7 | -------------------------------------------------------------------------------- /cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/cover.jpg -------------------------------------------------------------------------------- /cover/cover.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/cover/cover.xcf -------------------------------------------------------------------------------- /cover_small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junwatu/pengenalan-nodejs-gitbook/2f412bcbe5cdec618209b8bb71331f3d574de82c/cover_small.jpg -------------------------------------------------------------------------------- /database/README.md: -------------------------------------------------------------------------------- 1 | # Database 2 | 3 | Berkembang pesatnya komunitas Node.js menyebabkan dukungan pustaka yang semakin cepat juga. Dengan waktu yang relatif cepat platform ini sekarang mendukung banyak tipe database seperti SQLite, MySQL, MongoDB, Redis, CouchDB dll. Dalam buku ini hanya akan dibahasa 3 database saja yaitu SQLite, MySQL dan MongoDB. 4 | 5 | -------------------------------------------------------------------------------- /database/mongodb/README.md: -------------------------------------------------------------------------------- 1 | # MongoDB 2 | 3 | Kalau anda sudah terbiasa memakai database relasional seperti MySQL mungkin diperlukan sedikit perubahan _mindset_ untuk mengenal tipe database yang namanya **NoSQL**. Seperti arti dari namanya, database ini merupakan database yang tidak memakai bahasa SQL query data tapi bisa secara langsung menggunakan bahasa pemrograman client sebagai contoh adalah [MongoDB](https://www.mongodb.org/). 4 | 5 | Database **NoSQL** seperti MongoDB menyimpan data sebagai dokumen yang _schema-less_ yang artinya yaitu data yang disimpan mempunyai _key - value_ yang tidak terikat atau bebas. Anda bisa membayangkannya sebagai data JSON yang tersimpan di database. 6 | 7 | Klien bisa berinteraksi langsung dengan database MongoDB dengan menggunakan shell JavaScript `mongo` untuk administrasi dan query data. Sebagai contoh jika kita ingin membuat sample data sebanyak 100 di **collection** `sample` maka perintah dalam shell adalah seperti berikut, 8 | 9 | ```text 10 | $ mongo 11 | MongoDB shell version: 2.6.9 12 | connecting to: test 13 | > use sample; 14 | switched to db sample 15 | 16 | > for(var i=0; i<100; i++){ db.sample.insert({band:"Dewa "+i})}; 17 | WriteResult({ "nInserted" : 1 }) 18 | 19 | > db.sample.count() 20 | 100 21 | 22 | > db.sample.find(); 23 | { "_id" : ObjectId("55cf520e2dd317a13673d11b"), "band" : "Dewa 0" } 24 | { "_id" : ObjectId("55cf520e2dd317a13673d11c"), "band" : "Dewa 1" } 25 | { "_id" : ObjectId("55cf520e2dd317a13673d11d"), "band" : "Dewa 2" } 26 | { "_id" : ObjectId("55cf520e2dd317a13673d11e"), "band" : "Dewa 3" } 27 | { "_id" : ObjectId("55cf520e2dd317a13673d11f"), "band" : "Dewa 4" } 28 | { "_id" : ObjectId("55cf520e2dd317a13673d120"), "band" : "Dewa 5" } 29 | { "_id" : ObjectId("55cf520e2dd317a13673d121"), "band" : "Dewa 6" } 30 | { "_id" : ObjectId("55cf520e2dd317a13673d122"), "band" : "Dewa 7" } 31 | { "_id" : ObjectId("55cf520e2dd317a13673d123"), "band" : "Dewa 8" } 32 | { "_id" : ObjectId("55cf520e2dd317a13673d124"), "band" : "Dewa 9" } 33 | { "_id" : ObjectId("55cf520e2dd317a13673d125"), "band" : "Dewa 10" } 34 | { "_id" : ObjectId("55cf520e2dd317a13673d126"), "band" : "Dewa 11" } 35 | { "_id" : ObjectId("55cf520e2dd317a13673d127"), "band" : "Dewa 12" } 36 | { "_id" : ObjectId("55cf520e2dd317a13673d128"), "band" : "Dewa 13" } 37 | { "_id" : ObjectId("55cf520e2dd317a13673d129"), "band" : "Dewa 14" } 38 | { "_id" : ObjectId("55cf520e2dd317a13673d12a"), "band" : "Dewa 15" } 39 | { "_id" : ObjectId("55cf520e2dd317a13673d12b"), "band" : "Dewa 16" } 40 | { "_id" : ObjectId("55cf520e2dd317a13673d12c"), "band" : "Dewa 17" } 41 | { "_id" : ObjectId("55cf520e2dd317a13673d12d"), "band" : "Dewa 18" } 42 | Type "it" for more 43 | > 44 | ``` 45 | 46 | Untuk lebih jelasnya jika anda tertarik untuk bermain main dengan terminal MongoDB silahkan kunjungi [dokumentasinya](https://docs.mongodb.org/getting-started/shell/). 47 | 48 | Sebelum kita lanjutkan ke koneksi Node.js dan MongoDB, perlu di ingat beberapa konsep penting dari MongoDB 49 | 50 | ## Collection 51 | 52 | **Collection** adalah kumpulan dari **document**, analoginya walaupun kurang tepat sebenarnya bisa dibilang seperti tabel kalo dalam database relasional. 53 | 54 | ## Document 55 | 56 | **Document** itu sendiri adalah data yang tersimpan di database NoSQL dan didefinisikan oleh yang namanya **Schema**. 57 | 58 | ## Schema 59 | 60 | Sebelumnya di katakan bahwa NoSQL menyimpan data yang _schema-less_, memang benar tapi tetap untuk menyimpan suatu dokumen di database biasanya aplikasi bekerja dengan model data tertentu misalnya untuk data `Person` bisa mempunyai _key - value_ seperti berikut 61 | 62 | ```text 63 | { 64 | nama: "Kebo Ijo", 65 | email: "mbolang@kebo.xyz", 66 | username: "obek_seloso" 67 | } 68 | ``` 69 | 70 | -------------------------------------------------------------------------------- /database/mongodb/mongoose.md: -------------------------------------------------------------------------------- 1 | # Mongoose 2 | 3 | Seperti dikatakan sebelumnya untuk memudahkan pemodelan data di MongoDB anda bisa memakai pustaka [Mongoose](http://mongoosejs.com/). Meskipun sebenarnya Mongoose memakai objek JavaScript biasa dan mendukung banyak metode `query` data tetapi yang paling membedakan adalah Mongoose mendukung schema type dan validasi di level schema. 4 | 5 | ```text 6 | data:{type: schemaType} 7 | ``` 8 | 9 | ## Schema Type 10 | 11 | Ada beberapa schema type yang didukung oleh pustaka ini yaitu 12 | 13 | * String 14 | * Number 15 | * Date 16 | * Boolean 17 | * Buffer \(untuk data binary misalnya gambar, mp3 dll.\) 18 | * Mixed \(data dengan tipe apa saja\) 19 | * Array 20 | * ObjectId 21 | 22 | ## Pemodelan Data 23 | 24 | Lalu bagaimana Mongoose memodel data? ambil contoh misalnya dalam pengembangan aplikasi, data yang akan dipakai seperti berikut 25 | 26 | ```text 27 | var lokasiWisataKotaBatu = [{ 28 | nama: 'Batu Night Square', 29 | alamat: 'Jl. Oro oro ombo 13, Tlekung' 30 | rating: 3, 31 | fasilitas: ['Wahana bermain','Roller coaster', 'Taman lampion'] 32 | }] 33 | ``` 34 | 35 | Dari data diatas dengan memakai Mongoose sangat mudah untuk diterjemahkan ke skema dan tipe data untuk tiap field 36 | 37 | ```text 38 | var lokasiWisataKotaBatuSchema = new mongoose.schema({ 39 | nama: String, 40 | alamat: String, 41 | rating: Number, 42 | fasilitas: [String] 43 | }) 44 | ``` 45 | 46 | Bagaimana dengan validasi data?. Jika anda lihat field data `rating` diatas dan umumnya mempunyai nilai antara 0 - 5 dan jika secara default diberi nilai 0 maka skema `rating` akan menjadi 47 | 48 | ```text 49 | rating: {type: Number, 'default': 0} 50 | ``` 51 | 52 | Anda juga bisa memakai key `required` untuk menandakan bahwa field data tersebut bersifat wajib ada misalnya 53 | 54 | ```text 55 | nama: {type: String, required: true} 56 | ``` 57 | 58 | Untuk lebih jelasnya silahakan lihat dokumentasi dari [Validators Mongoose](http://mongoosejs.com/docs/validation.html). 59 | 60 | Aplikasi node.js dengan database MongoDB yang memakai pustaka Mongoose dapat dikatakan mempunyai hubungan relasi satu-satu artinya dengan memakai model Mongoose berarti secara langsung aplikasi akan memakai data pada MongoDB. 61 | 62 | Kalau misalnya anda bekerja dengan database relasional MySQL maka anda akan memakai bahasa SQL seperti `INSERT INTO table VALUES (field1=data)` untuk memasukkan data sedangkan seperti anda ketahui jika dengan database NoSQL untuk menyimpan model object cukup dengan memakai metode misalnya `model.save()`. Dalam Mongoose untuk memakai model yang telah mempunyai schema seperti diatas 63 | 64 | ```text 65 | var LokasiModel = mongoose.model('Lokasi', lokasiWisataKotaBatuSchema, 'lokasiWisataBatu') 66 | ``` 67 | 68 | Kode diatas memberi arti bahwa aplikasi akan memakai model `Lokasi` dengan **schema type** yang telah di definisikan sebelumnya yaitu `lokasiWisataKotaBatuSchema` dan model ini akan di simpan pada koleksi data di MongoDB dengan nama koleksi adalah `lokasiWisataBatu`. 69 | 70 | Untuk memakai model `Lokasi` caranya adalah dengan menciptakan `instance` dari model tersebut 71 | 72 | ```text 73 | var lokasiModel = new LokasiModel() 74 | lokasiModel.nama = 'Museum Angkut' 75 | lokasiModel.alamat = 'Jl. Kembar 11' 76 | lokasiModel.rating = 5 77 | lokasiModel.fasilitas = ['Restoran', 'Parkir luas'] 78 | ``` 79 | 80 | Kemudian untuk menyimpan data tersebut ke dalam database MongoDB 81 | 82 | ```text 83 | lokasiModel.save(function(err){ 84 | if(!err) console.log('Data Disimpan!') 85 | }) 86 | ``` 87 | 88 | Cukup mudah bukan dan memang pustaka ini bertujuan untuk memudahkan developer dalam pemodelan data terutama jika data yang akan dimodel mempunyai struktur yang rumit misalnya nested document. Untuk lebih lengkapnya silahkan anda mengunjungi situs resmi [mongoosejs.com](http://mongoosejs.com/). 89 | 90 | ## Projek 91 | 92 | Bagi anda yang sudah mengerti gambaran umum dari pustaka Mongoose ini silahkan mengutak atik contoh projek sederhana yang memakai framework ExpressJS dan Mongoose, [Person REST API](../../person_rest_api/). 93 | 94 | -------------------------------------------------------------------------------- /database/mongodb/node_mongodb.md: -------------------------------------------------------------------------------- 1 | # Node MongoDB 2 | 3 | MongoDB menyediakan driver resmi untuk platform Node.js. Module npm ini tersedia di link berikut [https://www.npmjs.com/package/mongodb](https://www.npmjs.com/package/mongodb) dan dapat dengan mudah di install melalui `npm` 4 | 5 | ```text 6 | $ npm install --save mongodb 7 | ``` 8 | 9 | Penulis mengasumsikan bahwa MongoDB sudah terinstal dan berjalan pada sistem. Untuk memulai koneksi dapat dengan mudah dilakukan seperti script berikut ini, 10 | 11 | > app.js 12 | 13 | ```text 14 | var MongoClient = require('mongodb').MongoClient; 15 | var MONGODB_URL = 'mongodb://localhost:27017/sample'; 16 | 17 | MongoClient.connect(MONGODB_URL, function(err, db){ 18 | err ? console.log(err): console.log('Koneksi ke MongoDB Ok!'); 19 | db.close(); 20 | }); 21 | ``` 22 | 23 | MongoDB akan membuat database baru jika database tersebut tidak ada, seperti halnya dengan database `sample` pada kode diatas karena sebelumnya database ini tidak ada maka secara otomatis MongoDB akan membuatnya. Bentuk umum URI untuk koneksi ke MongoDB adalah seperti berikut 24 | 25 | ```text 26 | mongodb://:@:/ 27 | ``` 28 | 29 | Jalankan apikasi di terminal dan jika tidak ada masalah maka akan muncul pesan pada konsol bahwa koneksi ke MongoDB telah sukses. 30 | 31 | ```text 32 | $ node app.js 33 | Koneksi ke MongoDB Ok! 34 | ``` 35 | 36 | Berikutnya akan kita lakukan operasi dasar untuk MongoDB yaitu CRUD tapi sebelumnya kita buat _schema_ terlebih dahulu. 37 | 38 | > person.js 39 | 40 | ```text 41 | function PersonSchema(data) { 42 | this.nama = data.nama; 43 | this.email = data.email; 44 | this.username = data.username; 45 | }; 46 | 47 | module.exports = PersonSchema; 48 | ``` 49 | 50 | _Schema_ diatas merupakan model data sederhana yang dituliskan dalam object JavaScript dan tanpa _built-in type casting_ ataupun fitur validasi. Jika anda membutuhkan pemodelan data yang lebih handal dan lebih baik, maka pakailah pustaka ODM \(Object-Document Modeler\) seperti [Mongoose](http://mongoosejs.com/). 51 | 52 | Driver Node MongoDB menyediakan API yang lengkap untuk bekerja dengan database ini. Silahkan lihat link berikut untuk melihat lebih lengkap tentang API ini 53 | 54 | [http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html\#insert](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#insert) 55 | 56 | ## Insert 57 | 58 | Untuk memasukkan dokumen bisa memakai metode [insertOne\(\)](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#insertOne) untuk memasukkan satu dokumen 59 | 60 | > app.js 61 | 62 | ```text 63 | /** 64 | * Balajar Node - MongoDB 65 | * 66 | * 67 | * MIT 68 | * Equan Pr. 2015 69 | */ 70 | 71 | var PersonSchema = require('./person.js'); 72 | var MongoClient = require('mongodb').MongoClient; 73 | var MONGODB_URL = 'mongodb://localhost:27017/sample'; 74 | 75 | var person = new PersonSchema({ 76 | nama: 'Kebo Ijo', 77 | email: 'kebo@ijo.xyz', 78 | username: 'obek_rebo' 79 | }); 80 | 81 | MongoClient.connect(MONGODB_URL, function(err, db){ 82 | err ? console.log(err): console.log('Koneksi ke MongoDB Ok!'); 83 | db.collection('persons').insertOne(person, function(err, result){ 84 | if(err){ 85 | console.log(err); 86 | } else { 87 | console.log(result); 88 | } 89 | db.close(); 90 | }) 91 | }); 92 | ``` 93 | 94 | Secara otomatis operasi insert ini akan menghasilkan _primary key_ `_id` yang unik yaitu berupa `ObjectId`. Yang membedakan `_id` ini dengan id pada database yang lain adalah dengan `ObjectId` bisa didapatkan kapan data ini dimasukkan melalui pemakaian metode `getTimestamp()`. 95 | 96 | ```text 97 | $ mongo 98 | MongoDB shell version: 2.6.9 99 | connecting to: test 100 | 101 | > _id = ObjectId() 102 | ObjectId("55d81f48bb934a51424dbd37") 103 | 104 | > ObjectId("55d81f48bb934a51424dbd37").getTimestamp(); 105 | ISODate("2015-08-22T07:05:44Z") 106 | 107 | > 108 | ``` 109 | 110 | Jika anda mempunyai banyak dokumen, untuk memasukkan dokumen-dokumen tersebut ke collection `persons` anda bisa memakai metode `insertMany()`. 111 | 112 | ## Update 113 | 114 | Operasi update data juga cukup mudah apalagi jika anda sangat pahamn tentang MongoDB. Untuk meng-update data bisa dilakukan melalui metode `updateOne()` atau `updateMany()`. 115 | 116 | > app.js 117 | 118 | ```text 119 | var PersonSchema = require('./person.js'); 120 | var MongoClient = require('mongodb').MongoClient; 121 | var MONGODB_URL = 'mongodb://localhost:27017/sample'; 122 | 123 | var person = new PersonSchema({ 124 | nama: 'Kebo Ijo', 125 | email: 'kebo@ijo.xyz', 126 | username: 'obek_rebo' 127 | }); 128 | 129 | MongoClient.connect(MONGODB_URL, function(err, db){ 130 | err ? console.log(err): console.log('Koneksi ke MongoDB Ok!'); 131 | db.collection('persons').insertOne(person, function(err, result){ 132 | if(err){ 133 | console.log(err); 134 | } else { 135 | console.log('Simpan data person ok!'); 136 | 137 | //update data 138 | var personUpdate = { 139 | nama: 'Sukat Tandika' 140 | } 141 | db.collection('persons').updateOne({nama: person.nama}, personUpdate, function(err, result){ 142 | if(err) { 143 | console.log(err); 144 | } else { 145 | console.log('Data person berhasil dimodifikasi!'); 146 | } 147 | db.close(); 148 | }) 149 | } 150 | }) 151 | }); 152 | ``` 153 | 154 | Metode `updateOne()` mempunyai beberapa argumen seperti berikut 155 | 156 | ```text 157 | updateOne(filter, update, options, callback) 158 | ``` 159 | 160 | Untuk data update anda bisa memakai operator seperti `$set` contohnya seperti berikut ini 161 | 162 | ```text 163 | db.collection('persons').updateOne({nama: person.nama}, {$set:{nama: 'Angel'}}, function(err, result){ 164 | if(err) { 165 | console.log(err); 166 | } else { 167 | console.log('Data person berhasil dimodifikasi!'); 168 | } 169 | 170 | db.close(); 171 | }) 172 | ``` 173 | 174 | dari beberapa options yang terpenting adalah key `upsert` yaitu _update insert_ dan jika option ini diberikan maka jika data yang akan di-update tidak ada maka MongoDB secara otomatis akan membuat data yang baru. Untuk lebih jelasnya anda bisa melihat [dokumentasi dari API `updateOne()`](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#updateOne). 175 | 176 | ## Query 177 | 178 | Query data pada database MongoDB dapat dengan mudah dilakukan dengan memakai metode `find()`, sebagai contoh untuk menemukan data `person` pada collection `persons` 179 | 180 | ```text 181 | MongoClient.connect(MONGODB_URL, function(err, db){ 182 | if(!err){ 183 | findPerson({nama: 'Morbid Angel'}, db, function(err, doc){ 184 | if(!err){ 185 | console.log(doc); 186 | } else { 187 | console.log(err); 188 | } 189 | db.close(); 190 | }); 191 | } else { 192 | console.log(err); 193 | } 194 | }); 195 | 196 | 197 | function findPerson(filter, db, callback){ 198 | var cursor = db.collection('persons').find(filter); 199 | cursor.each(function(err, docResult){ 200 | if(err){ 201 | callback(err, null); 202 | } else { 203 | if(docResult != null) { 204 | console.log(docResult); 205 | callback(null, docResult); 206 | } else { 207 | callback(null, 'empty!'); 208 | } 209 | } 210 | }) 211 | } 212 | ``` 213 | 214 | Dengan metode `find()` anda bisa memakai operator query seperti `$lt`, `$gt`, operator kondisi `AND`, `OR` dll. Untuk lebih lengkapnya silahkan lihat [dokumentasi query](https://docs.mongodb.org/getting-started/node/query/) dari driver node MongoDB. 215 | 216 | ## Delete 217 | 218 | Untuk menghapus data anda bisa menggunakan fungsi `deleteOne()` atau `deleteMany()`. Misalnya untuk menghapus semua data pada collection `persons` anda bisa menggunakan empty object `{}` sebagai query. 219 | 220 | ```text 221 | function deleteAllPerson(db, callback){ 222 | db.collection('persons').deleteMany({}, function(err, rec){ 223 | if(!err) { 224 | callback(null, rec.result.n); 225 | } else { 226 | callback(err, null); 227 | } 228 | }) 229 | } 230 | ``` 231 | 232 | atau jika ingin menhapus satu data pada collection `person` 233 | 234 | ```text 235 | fucntion deletePerson(filter, db, callback){ 236 | db.collection('persons').deleteOne(filter, function(err, rec){ 237 | if(!err) { 238 | callback(null, rec.result.n); 239 | } else { 240 | callback(err, null); 241 | } 242 | }) 243 | } 244 | ``` 245 | 246 | Dua fungsi ini bisa anda lihat secara lengkap pada [dokumentasi](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#deleteMany) API MongoDB. 247 | 248 | -------------------------------------------------------------------------------- /database/mysql/README.md: -------------------------------------------------------------------------------- 1 | # MySQL 2 | 3 | Kalau anda terbiasa dengan bahasa pemrograman PHP maka pasti sudah tidak asing lagi dengan database relasional yang paling banyak di pakai saat ini yaitu MySQL. 4 | 5 | -------------------------------------------------------------------------------- /database/mysql/node_mysql.md: -------------------------------------------------------------------------------- 1 | # Node MySQL 2 | 3 | Implementasi driver dari MySQL untuk platform Node.jssudah sangat mature seperti modul **node-mysql** di [https://github.com/felixge/node-mysql/](https://github.com/felixge/node-mysql/) 4 | 5 | ## Instalasi 6 | 7 | Seperti biasa untuk menginstall modul ini dan secara otomatis menyimpan nama & versi modul di file `package.json` yaitu dengan memakai perintah berikut 8 | 9 | ```text 10 | $ npm install --save mysql 11 | ``` 12 | 13 | ## Koneksi Sederhana 14 | 15 | Untuk membuat koneksi ke database MySQL salah satu caranya adalah dengan menggunakan metode `connection.connect()` 16 | 17 | ```text 18 | //app.js 19 | var mysql = require('mysql'); 20 | 21 | /** 22 | * Setting opsi dari connection, 23 | * lihat https://github.com/felixge/node-mysql/ 24 | */ 25 | var connection = mysql.createConnection({ 26 | host: 'localhost', 27 | user: 'root', 28 | password: '' 29 | }); 30 | 31 | //Membuka koneksi ke database MySQL 32 | connection.connect(function(err){ 33 | if(err) { 34 | console.log(err); 35 | } else { 36 | console.log('Koneksi dengan id '+ connection.threadId); 37 | } 38 | }); 39 | 40 | // Query bisa dilakukan di sini 41 | 42 | //Menutup koneksi 43 | connection.end(function(err){ 44 | if(err) { 45 | console.log(err); 46 | } else { 47 | console.log('koneksi ditutup!'); 48 | } 49 | }); 50 | ``` 51 | 52 | ## Query 53 | 54 | Istilah `query` mungkin menurut mindset umum artinya adalah mengambil data dari database tetapi dalam modul node-mysql ini untuk membuat database atau schema juga didefiniskan sebagai `query`. Ada beberapa bentuk fungsi untuk wrapper `query` 55 | 56 | `connection.query(sqlString, callback)` 57 | 58 | Dengan memakai statemen SQL kita bisa membuat schema database **ebook** seperti berikut 59 | 60 | ```text 61 | var create_db = 'CREATE DATABASE IF NOT EXISTS ebook' 62 | 63 | connection.query(create_db, function(err, result){ 64 | if(err){ 65 | console.log(err); 66 | } else { 67 | console.log(result); 68 | } 69 | ) 70 | ``` 71 | 72 | `connection.query(sqlString, value, callback)` 73 | 74 | Misalnya untuk menyimpan data semua judul buku pada database **ebook** 75 | 76 | ```text 77 | var ebook = { 78 | id: 1, 79 | title: 'Wiro Sableng Pendekar Kapak Maut Naga Geni 212 : Batu Tujuh Warna', 80 | pengarang: 'Bastian Tito' 81 | } 82 | 83 | var insert_sql = 'INSERT INTO ebook SET ?'; 84 | 85 | connection.query(insert_sql, ebook, function(err, result){ 86 | err ? console.log(err): console.log(result); 87 | }) 88 | ``` 89 | 90 | Kalau dibutuhkan `escaping` value sebelum dimasukkan ke database MySQL bisa memakai metode `.escape()` atau pake placeholder `?`. 91 | 92 | ```text 93 | var ebook = { 94 | id: 1, 95 | title: 'Wiro Sableng Pendekar Kapak Maut Naga Geni 212 : Batu Tujuh Warna', 96 | pengarang: 'Bastian Tito' 97 | } 98 | 99 | var insert_sql = 'UPDATE ebook SET title = ? WHERE id = ?'; 100 | 101 | connection.query(insert_sql, [ebook.title, ebook.id], function(err, result){ 102 | err ? console.log(err): console.log(result); 103 | }) 104 | ``` 105 | 106 | `connection.query(options, callback)` 107 | 108 | Bentuk wrapper `query` yang terakhir ini cukup ringkas. Sesuaikan saja mana bentuk wrapper yang sesuai dengan kebutuhan anda. 109 | 110 | ```text 111 | var ebook = { 112 | sql: 'INSERT INTO ebook SET pengarang = ?', 113 | timeout: 14000, 114 | values: ['Pramoedya Ananta Toer'] 115 | } 116 | 117 | connection.query(ebook, function(err, result, fields){ 118 | if(err) { 119 | console.log(err); 120 | } else { 121 | console.log(result); 122 | } 123 | }) 124 | ``` 125 | 126 | Metode `query` ini sangat fleksibel dan pada intinya kita bisa memakai statemen SQL yang biasa dipakai untuk query data di MySQL. Jadi penggunaan dari modul npm ini sebenarnya cukuplah mudah. 127 | 128 | Untuk penggunaan modul npm ini lebih lanjut silahkan kunjungi Github [node-mysql](https://github.com/felixge/node-mysql/) dan untuk contoh aplikasi yang memanfaatkan database ini bisa dilihat pada bab [**Pengubah Gambar PNG Ke Data URI**](../../todatauri/). 129 | 130 | -------------------------------------------------------------------------------- /database/sqlite/README.md: -------------------------------------------------------------------------------- 1 | # SQLite 2 | 3 | Mungkin database ini sudah tidak asing lagi bagi developer seperti anda karena memang banyak digunakan dalam aplikasi portable dan embeddable. 4 | 5 | Kekuatan SQLite secara garis besar sebagai berikut 6 | 7 | _**Serverless**_ 8 | 9 | SQLite tidak memerlukan proses lain untuk beroperasi seperti pada database lain yang umumnya sebagai server. Library SQLite akan mengakses file data secara langsung. 10 | 11 | _**Zero Configuration**_ 12 | 13 | Karena sifatnya bukan server maka database ini tidak memerlukan setup tertentu. Untuk membuat database cukup seperti ketika membuat file baru. 14 | 15 | _**Cross-Platfrom**_ 16 | 17 | Semua data tersimpan pada satu sistem file yang bersifat cross platform dan tidak memerlukan administrasi. 18 | 19 | _**Self-Contained**_ 20 | 21 | Library SQLite sudah mencakup semua sistem database sehingga dengan mudah dapat diintegrasikan ke aplikasi host. 22 | 23 | _**Small Runtime Footprint**_ 24 | 25 | Ukuran default dari SQLite ini kurang dari 1MB dan membutuhkan hanya beberapa Megabyte memory. 26 | 27 | _**Transactional**_ 28 | 29 | Operasi transaksi kompatibel dengan ACID sehingga aman kalau harus mengakses data dari proses banyak thread. 30 | 31 | Untuk penjelasan lebih detil, silahkan kunjungi website resmi [http://sqlite.org](http://sqlite.org) 32 | 33 | -------------------------------------------------------------------------------- /database/sqlite/enkripsi/README.md: -------------------------------------------------------------------------------- 1 | # Enkripsi 2 | 3 | Kalau anda memakai SQLite dan membutuhkan supaya database ini terenkripsi maka beruntunglah karena node `sqlite3` mendukung penggunaan database SQLite yang terenkripsi. 4 | 5 | Enkripsi yang didukung oleh SQLite yaitu melalui ekstensi `sqlcipher`. Sqlcipher merupakan ekstensi sqlite yang mendukung enkripsi 256 bit AES. Ekstensi ini bisa di didownload melalui website berikut 6 | 7 | [https://github.com/sqlcipher/sqlcipher](https://github.com/sqlcipher/sqlcipher) 8 | 9 | -------------------------------------------------------------------------------- /database/sqlite/enkripsi/sqlchiper.md: -------------------------------------------------------------------------------- 1 | # sqlcipher 2 | 3 | Instalasi ekstensi ini sangat mudah yaitu jika anda berada dalam lingkungan Linux 4 | 5 | ```text 6 | $ sudo apt-get install libsqlcipher-dev 7 | ``` 8 | 9 | Kemudian kompilasi ulang node-sqlite3 dengan perintah berikut ini 10 | 11 | ```text 12 | $ npm install sqlite3 --build-from-source --sqlite_libname=sqlcipher \ 13 | --sqlite=/usr/ 14 | ``` 15 | 16 | Untuk menggunakan fitur enkripsi ini peru ditambahkan beberapa baris kode berikut pada aplikasi node-sqlite3. 17 | 18 | ```text 19 | //encrypt database 20 | db.run('PRAGMA key="passwordmu!"'); 21 | ``` 22 | 23 | Pada contoh CRUD node-sqlite3 pada bagian sebelumnya kode diatas bisa dituliskan sebelum operasi CRUD atau pada saat inisialisasi. 24 | 25 | ```text 26 | ... 27 | // Run SQL one at a time 28 | db.serialize(function() { 29 | 30 | //encrypt database 31 | db.run('PRAGMA key="passwordmu!"'); 32 | 33 | // Create table 34 | db.run(CREATE_TABLE, function(err) { 35 | if (err) { 36 | console.log(err); 37 | } else { 38 | console.log('CREATE TABLE'); 39 | } 40 | }); 41 | ... 42 | ``` 43 | 44 | Bandingkan jika SQLite tidak memakai enkripsi, anda bisa menggunakan SQLite Browser atau tool `hexdump` pada Linux 45 | 46 | ![node-sqlite3-no-enkripsi](../../../.gitbook/assets/node-sqlite3-no-enkripsi.png) 47 | 48 | dan jika SQLite memakai enkripsi bisa dilihat dari screenshot dibawah ini bahwa isi dari database menjadi "meaningless". 49 | 50 | ![node-sqlite3-enkripsi](../../../.gitbook/assets/node-sqlite3-enkripsi.png) 51 | 52 | -------------------------------------------------------------------------------- /database/sqlite/node-sqlite3.md: -------------------------------------------------------------------------------- 1 | # Node Sqlite3 2 | 3 | Komunitas node menyediakan banyak solusi untuk memakai SQLite di platform Node.js. Salah satu yang paling populer adalah modul [`node-sqlite3`](https://github.com/mapbox/node-sqlite3). 4 | 5 | ## Instal 6 | 7 | node `sqlite3` merupakan binding modul JavaScript yang asinkron untuk database sqlite3. 8 | 9 | Untuk penginstalan modul ini ketik perintah berikut 10 | 11 | ```text 12 | $ npm install sqlite3 --save 13 | ``` 14 | 15 | ## CRUD 16 | 17 | Operasi database seperti **Create**, **Read**, **Update** dan **Delete** untuk database SQLite sangat mudah seperti pada contoh berikut 18 | 19 | `app.js` 20 | 21 | ```text 22 | /** 23 | * Akses SQLite 3 24 | */ 25 | var sqlite = require('sqlite3').verbose(); 26 | var file = 'film.db'; 27 | var db = new sqlite.Database(file); 28 | var fs = require('fs'); 29 | 30 | // Sample Data 31 | var film = { 32 | judul: "Keramat", 33 | release: "2009", 34 | imdb: "http://www.imdb.com/title/tt1495818/", 35 | deskripsi: "Film horror paling horror!" 36 | } 37 | 38 | var filmUpdate = { 39 | id: 1, 40 | deskripsi: "Best Indonesian Horror Movie." 41 | } 42 | 43 | // SQL Statement 44 | var CREATE_TABLE = "CREATE TABLE IF NOT EXISTS fdb ( id INTEGER PRIMARY KEY AUTOINCREMENT, judul TEXT NOT NULL, release TEXT NOT NULL, imdb TEXT, deskripsi TEXT )"; 45 | var INSERT_DATA = "INSERT INTO fdb (judul, release, imdb, deskripsi) VALUES (?, ?, ?, ?)"; 46 | var SELECT_DATA = "SELECT * FROM fdb"; 47 | var UPDATE_DATA = "UPDATE fdb SET deskripsi=$deskripsi WHERE id=$id"; 48 | 49 | // Run SQL one at a time 50 | db.serialize(function() { 51 | // Create table 52 | db.run(CREATE_TABLE, function(err) { 53 | if (err) { 54 | console.log(err); 55 | } else { 56 | console.log('CREATE TABLE'); 57 | } 58 | }); 59 | 60 | // Insert data with sample data 61 | db.run(INSERT_DATA, [film.judul, film.release, film.imdb, film.deskripsi], function(err) { 62 | if (err) { 63 | console.log(err); 64 | } else { 65 | console.log('INSERT DATA'); 66 | } 67 | }); 68 | 69 | // Query all data 70 | selectAllData(); 71 | 72 | // Update data 73 | db.run(UPDATE_DATA, {$deskripsi: filmUpdate.deskripsi, $id: filmUpdate.id}, function(err){ 74 | if(err) { 75 | console.log(err); 76 | } else { 77 | console.log('UDATE DATA'); 78 | } 79 | }); 80 | 81 | selectAllData(); 82 | 83 | db.run('DELETE FROM fdb WHERE id=$id', {$id:1}, function(err){ 84 | if(err) { 85 | console.log(err) 86 | } else { 87 | console.log("DELETE DATA"); 88 | }; 89 | 90 | }) 91 | 92 | }); 93 | 94 | function selectAllData() { 95 | db.each(SELECT_DATA, function(err, rows) { 96 | if (!err) { 97 | console.log(rows); 98 | } 99 | }) 100 | } 101 | ``` 102 | 103 | Aplikasi diatas akan membuat tabel `fdb`, memasukkan data baru kemudian data tersebut akan di update dan terakhir akan dihapus. 104 | 105 | Contoh diatas memakai API berikut ini 106 | 107 | `db.serialize()` 108 | 109 | `db.run(operasi_sqlite, callback)` 110 | 111 | Dengan memakai fungsi `db.serialize()` maka eksekusi sql akan di eksekusi secara serial atau berurutan dan operasi SQL apa saja bisa di eksekusi oleh node-sqlite3 dengan memakai metode `db.run()` tersebut. 112 | 113 | Penjelasan API lebih lanjut untuk Node SQLite bisa dilihat pada link berikut 114 | 115 | [https://github.com/mapbox/node-sqlite3/wiki/API](https://github.com/mapbox/node-sqlite3/wiki/API). 116 | 117 | -------------------------------------------------------------------------------- /expressjs/README.md: -------------------------------------------------------------------------------- 1 | # ExpressJS 2 | 3 | Untuk memudahkan pembuatan aplikasi web anda bisa menggunakan framework [ExpressJS](http://expressjs.com/) daripada harus menggunakan module http bawaan Node.js. Framework ini menawarkan beberapa fitur seperti routing, rendering view dan mendukung middleware dengan kata lain anda akan banyak menghemat waktu dalam pengembangan aplikasi Node.js. 4 | 5 | ExpressJS merupakan framework minimal yang sangat fleksibel. Anda bisa membuat web server HTML, server file statik, aplikasi chat, search engine, sosial media, layanan web dengan akses melalui REST API atau aplikasi hybrid yaitu selain pengguna mempunyai akses melalui REST API juga mempunyai akses ke HTML page. 6 | 7 | -------------------------------------------------------------------------------- /expressjs/kode.md: -------------------------------------------------------------------------------- 1 | # Kode 2 | 3 | 4 | Jika anda ingat server file yang memakai modul http pada bab sebelumnya berikut merupakan versi yang memakai ExpressJS 5 | 6 | > app.js 7 | 8 | 'use strict'; 9 | 10 | var express = require('express'); 11 | var server = express(); 12 | var logger = require('morgan'); 13 | 14 | server.use(logger('dev')); 15 | 16 | server.use(express.static(__dirname+'/publik')); 17 | 18 | server.listen(4000, function(){ 19 | console.log('Server file sudah berjalan bos!'); 20 | }); 21 | 22 | Seperti yang dijelaskan pada bab sebelumnya untuk memakai module Node.js di gunakan keyword `require`. 23 | 24 | Modul `express` akan menangani tiap request dari user dan kemudian akan memberikan response berupa file yang diinginkan. Pada kode diatas file yang akan diberikan ke pengguna disimpan pada folder `publik`. 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /expressjs/server/README.md: -------------------------------------------------------------------------------- 1 | # Server File 2 | 3 | Sebelumnya bikin project kecil dengan mengetikkan perintah berikut pada direktori project 4 | 5 | ```text 6 | $ npm init 7 | ``` 8 | 9 | dan berikan nama project sebagai `server-file-statik`. Direktori project dari server file bisa dilihat pada sususan tree dibawah ini. 10 | 11 | > Susunan file dan direktori 12 | 13 | ```text 14 | 15 | 16 | server-file-statis 17 | ├── package.json 18 | ├── app.js 19 | ├── node_modules 20 | └── publik 21 | ├── index.html 22 | 23 | ``` 24 | 25 | Dengan adanya npm instalasi ExpressJS sangat mudah, ketik perintah berikut pada direktori project. 26 | 27 | ```text 28 | $ npm install express --save 29 | ``` 30 | 31 | > Catatan : 32 | > 33 | > Perintah diatas akan menginstall ExpressJS dengan versi yang paling terbaru \(pada saat buku ini ditulis versi terbaru adalah 4.x\). Jika membutuhkan versi tertentu cukup dengan menambahkan '@' dan nomer versi yang akan di inginkan seperti contoh berikut 34 | > 35 | > ```text 36 | > $ npm install express@3 --save 37 | > ``` 38 | 39 | Untuk kedepannya bahasan mengenai ExpressJS ini akan memakai versi 4.x. 40 | 41 | ## Kode 42 | 43 | Jika anda ingat server file yang memakai modul http pada bab sebelumnya berikut merupakan versi yang memakai ExpressJS 44 | 45 | > app.js 46 | 47 | ```text 48 | 'use strict'; 49 | 50 | var express = require('express'); 51 | var server = express(); 52 | var logger = require('morgan'); 53 | 54 | server.use(logger('dev')); 55 | 56 | server.use(express.static(__dirname+'/publik')); 57 | 58 | server.listen(4000, function(){ 59 | console.log('Server file sudah berjalan bos!'); 60 | }); 61 | ``` 62 | 63 | Seperti yang dijelaskan pada bab sebelumnya untuk memakai module Node.js di gunakan keyword `require`. 64 | 65 | Modul `express` akan menangani tiap request dari user dan kemudian akan memberikan response berupa file yang diinginkan. Pada kode diatas file yang akan diberikan ke pengguna disimpan pada folder `publik`. 66 | 67 | -------------------------------------------------------------------------------- /expressjs/server/akses_server.md: -------------------------------------------------------------------------------- 1 | # Akses Server 2 | 3 | Untuk menjalankan server file statik ini 4 | 5 | ```text 6 | $ node app.js 7 | ``` 8 | 9 | Anda bisa meletakkan file apa saja pada direktori 'publik'. Untuk mengakses server ini ketik alamat berikut pada browser 10 | 11 | ```text 12 | http://localhost:4000 13 | ``` 14 | 15 | dan secara default akan menampilkan file `index.html` di browser. 16 | 17 | Untuk mengakses file yang lain format URL adalah 18 | 19 | ```text 20 | http://localhost:4000/[nama-file] 21 | ``` 22 | 23 | misalnya untuk mengakses file `img.jpg` 24 | 25 | ![akses file di server](../../.gitbook/assets/akses-file-di-server.png) 26 | 27 | -------------------------------------------------------------------------------- /expressjs/server/middleware.md: -------------------------------------------------------------------------------- 1 | # Middleware 2 | 3 | Fungsionalitas yang diberikan oleh ExpressJS di bantu oleh yang namanya `middleware` yaitu fungsi asinkron yang bisa mengubah request dan respon di server. 4 | 5 | Pada kode diatas contoh middleware yaitu modul `morgan`. Cara pemakaian `middleware` yaitu melalui `app.use()`. 6 | 7 | Module `morgan` merupakan modul untuk logger yang berfungsi untuk pencatatan tiap request ke server. Pencatatan ini atau istilahnya `logging` akan ditunjukkan di console terminal. 8 | 9 | Untuk menginstall modul ini ketik perintah berikut 10 | 11 | ```text 12 | $ npm install morgan --save 13 | ``` 14 | 15 | Middleware middleware ini bisa anda lihat di link berikut 16 | 17 | [https://github.com/senchalabs/connect\#middleware](https://github.com/senchalabs/connect#middleware) 18 | 19 | -------------------------------------------------------------------------------- /expressjs/server_rest.md: -------------------------------------------------------------------------------- 1 | # Server REST 2 | 3 | Framework ExpressJS sangat banyak digunakan sebagai aplikasi RESTful. Bagi anda yang belum tahu, REST atau Representational State Transfer adalah arsitektur yang digunakan dalam desain aplikasi network. Idenya yaitu daripada memakai teknik seperti CORBA, SOAP atau RPC untuk membuat Web Service lebih baik jika memakai protokol HTTP yang lebih mudah. 4 | 5 | Aplikasi RESTful memakai request HTTP untuk operasi Create, Read, Update dan Delete data. REST itu sendiri bukanlah suatu standard jadi tidak ada yang namanya spec dari W3C. Sehingga sangat mudah bagi bahasa pemrograman untuk menggunakan arsitektur ini. Keuntungan lainnya yaitu dengan arsitektur ini bisa dibangun berbagai macam teknologi klien seperti web atau mobile ataupun dekstop untuk mengakses aplikasi RESTful tersebut. 6 | 7 | Untuk contoh aplikasi RESTful memakai ExpressJS akan diberikan pada Bab [**Person REST API**](../person_rest_api/). 8 | 9 | -------------------------------------------------------------------------------- /image_uploader.md: -------------------------------------------------------------------------------- 1 | # Image Uploader 2 | 3 | ![Image Uploader](.gitbook/assets/image-uploader.png) 4 | 5 | Aplikasi ini sangat sederhana, cara kerjanya yaitu gambar di upload ke server dan kemudian ditampilkan kembali ke browser. 6 | 7 | ## Server 8 | 9 | Pada sisi server aplikasi ini memakai framework ExpressJS untuk menangani request HTTP dan paket formidable untuk menangani file yang diupload. 10 | 11 | > Catatan: Aplikasi ini memakai sedikit fitur ES6 seperti `let`, `const`, _arrow function_ sehingga anda perlu menginstall setidaknya Node.js v4.2.1 LTS 12 | 13 | ```text 14 | server.post('/upload', (req, res) => { 15 | let form = new formidable.IncomingForm() 16 | form.uploadDir = path.join(__dirname, 'uploads') 17 | form.hash = true 18 | form.multiples = false 19 | form.keepExtensions = true 20 | 21 | form.parse(req, (err, fields, files) => { 22 | if (!err) { 23 | console.log(files.file.name) 24 | console.log(files.file.path) 25 | console.log(files.file.type) 26 | } 27 | res.end() 28 | }) 29 | }) 30 | ``` 31 | 32 | Kode diatas akan menangani file yang akan diupload dan menyimpan hasil upload pada direktori `uploads`. Formidable dapat dengan mudah dikonfigurasi, lihat [Github Formidable](https://github.com/felixge/node-formidable). 33 | 34 | ## Uploader 35 | 36 | Pada sisi klien uploder dibangun dengan memakai pustaka [DropzoneJS](http://www.dropzonejs.com) yang mendukung _drag n drop_ dan _preview thumbnail_. Pustaka ini sangat mudah untuk digunakan dan di kustomisasi 37 | 38 | ```text 39 | Dropzone.options.mydropzone = { 40 | init: function () { 41 | this.on("complete", function(file) { 42 | updateImage() 43 | }) 44 | }, 45 | maxFileSize : 2, 46 | acceptedFiles: 'image/*' 47 | } 48 | ``` 49 | 50 | Konfigurasi diatas mengakibatkan uploader hanya menerima file bertipe gambar dan ukuran file tidak lebih dari 2MB dan yang perlu dicatat yaitu ketika file selesai diupload yaitu dengan mendengarkan event `complete` maka _list view_ gambar yang dibuat dengan Kendo UI harus diupdate dengan memanggil metode `updateImage()`. 51 | 52 | ## Image List 53 | 54 | Kendo akan mengambil data dari server kemudian secara otomatis akan mengupdate `#listView` sesuai dengan banyaknya gambar yang telah terupload. 55 | 56 | ```text 57 | var updateImage = function () { 58 | var dataSource = new kendo.data.DataSource({ 59 | transport: { 60 | read: { 61 | url: document.location.href+'service/images', 62 | dataType: 'json' 63 | } 64 | }, 65 | pageSize: 21 66 | }) 67 | 68 | $('#pager').kendoPager({ 69 | dataSource: dataSource 70 | }) 71 | 72 | $('#listView').kendoListView({ 73 | dataSource: dataSource, 74 | template: kendo.template($('#template').html()) 75 | }) 76 | } 77 | ``` 78 | 79 | Komponen Kendo UI yang dipakai adalah `ListView` dan framework UI ini seperti framework kebanyakan lainnya juga memakai template untuk menghasilkan UI secara dinamik. 80 | 81 | ```text 82 |
83 |
84 |
85 |
86 | 87 | 93 | ``` 94 | 95 | Data yang akan diambil dari server yaitu data gambar harus mempunyai field `ImageName` dan `ImageId`. 96 | 97 | Komponen yang disediakan oleh Kendo cukup lengkap dan jika anda tertarik dengan Kendo UI lebih lanjut silahkan berkunjung ke website resmi [Telerik](http://www.telerik.com). 98 | 99 | Untuk mengambil daftar gambar yang telah diupload klien akan mengakses URL berikut 100 | 101 | ```text 102 | http://localhost:5005/service/images 103 | ``` 104 | 105 | Server hanya akan memfilter file dengan tipe `jpg` dan `png` pada folder `uploads`. Filter dilakukan dengan mengecek tipe file melalui paket `mime` tepatnya melalui metode `mime.lookup(image)`. 106 | 107 | ```text 108 | server.get('/service/images', (req, res) => { 109 | let images = [] 110 | fs.readdir(upload_dir, (err, files) => { 111 | if (!err) { 112 | for (let imageIndex = 0; imageIndex < files.length; imageIndex++) { 113 | let ftype = mime.lookup(path.join(upload_dir, files[imageIndex])) 114 | if (filetypes.indexOf(ftype) !== -1) { 115 | let data = {} 116 | data.ImageId = imageIndex 117 | data.ImageName = files[imageIndex] 118 | images.push(data) 119 | } 120 | } 121 | res.json(images) 122 | } else { 123 | res.end() 124 | } 125 | }) 126 | }) 127 | ``` 128 | 129 | Data yang dikembalikan ke klien adalah data JSON dengan format seperti berikut 130 | 131 | ```text 132 | [{ 133 | ImageId: 1, 134 | ImageName: 'file.jpg' 135 | }] 136 | ``` 137 | 138 | Kode sumber dari aplikasi ini bisa anda dapatkan pada repo Github [Image Uploader](http://github.com/junwatu/image-uploader). 139 | 140 | -------------------------------------------------------------------------------- /images/persons.gliffy: -------------------------------------------------------------------------------- 1 | {"contentType":"application/gliffy+json","version":"1.1","metadata":{"title":"untitled","revision":0,"exportBorder":false},"embeddedResources":{"index":0,"resources":[]},"stage":{"objects":[{"x":80,"y":360,"rotation":0,"id":30,"uid":"com.gliffy.shape.ui.ui_v2.forms_components.window","width":270,"height":100,"lockAspectRatio":false,"lockShape":false,"order":0,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.window.ui_v2","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":1.9148936170212765,"y":0,"rotation":0,"id":32,"uid":null,"width":266.17021276595744,"height":16,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"

Antar Muka Web atau CLI

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":170,"y":290,"rotation":270,"id":28,"uid":"com.gliffy.shape.basic.basic_v1.default.double_arrow","width":80,"height":30,"lockAspectRatio":false,"lockShape":false,"order":16,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.double_arrow.basic_v1","strokeWidth":2,"strokeColor":"#e2e2e2","fillColor":"#666666","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[],"linkMap":[]},{"x":379,"y":105,"rotation":0,"id":11,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":7,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":2,"endArrow":0,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":false,"interpolationType":"linear","cornerRadius":null,"controlPath":[[-16,13],[93,-11]],"lockSegments":{}}},"children":[{"x":0,"y":0,"rotation":0,"id":13,"uid":null,"width":24,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"both","vposition":"none","hposition":"none","html":"

GET

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":33.99999999999997,"y":46,"rotation":0,"id":6,"uid":"com.gliffy.shape.network.network_v3.home.cloud","width":340,"height":213,"lockAspectRatio":false,"lockShape":false,"order":5,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.cloud.network_v3","strokeWidth":2,"strokeColor":"#000000","fillColor":"#ffffff","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2.111801242236025,"y":0,"rotation":0,"id":20,"uid":null,"width":335.7763975155279,"height":41,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

Internet\n

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":490,"y":80,"rotation":0,"id":1,"uid":"com.gliffy.shape.basic.basic_v1.default.square","width":170,"height":170,"lockAspectRatio":true,"lockShape":false,"order":2,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.rectangle.basic_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[{"x":2,"y":0,"rotation":0,"id":5,"uid":null,"width":166,"height":28,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

Person REST \n

Server

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":382,"y":140,"rotation":0,"id":14,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":9,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":false,"interpolationType":"linear","cornerRadius":null,"controlPath":[[-1.1314218345384006,-8.526512829121202e-14],[94.04786015641184,-5.684341886080802e-14]],"lockSegments":{}}},"children":[{"x":0,"y":0,"rotation":0,"id":15,"uid":null,"width":47,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"both","vposition":"none","hposition":"none","html":"

DELETE

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":380,"y":178,"rotation":0,"id":16,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":11,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":false,"interpolationType":"linear","cornerRadius":null,"controlPath":[[-2,-7],[94.04786015641184,-5.684341886080802e-14]],"lockSegments":{}}},"children":[{"x":0,"y":0,"rotation":0,"id":17,"uid":null,"width":24,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"both","vposition":"none","hposition":"none","html":"

PUT

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":381,"y":225,"rotation":0,"id":18,"uid":"com.gliffy.shape.basic.basic_v1.default.line","width":100,"height":100,"lockAspectRatio":false,"lockShape":false,"order":13,"graphic":{"type":"Line","Line":{"strokeWidth":2,"strokeColor":"#000000","fillColor":"none","dashStyle":null,"startArrow":0,"endArrow":2,"startArrowRotation":"auto","endArrowRotation":"auto","ortho":false,"interpolationType":"linear","cornerRadius":null,"controlPath":[[-16,-32],[93,1]],"lockSegments":{}}},"children":[{"x":0,"y":0,"rotation":0,"id":19,"uid":null,"width":32,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"both","vposition":"none","hposition":"none","html":"

POST

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":765,"y":110,"rotation":0,"id":23,"uid":"com.gliffy.shape.basic.basic_v1.default.text","width":150,"height":16,"lockAspectRatio":false,"lockShape":false,"order":15,"graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

MongoDB

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null,"linkMap":[]},{"x":680,"y":160,"rotation":0,"id":3,"uid":"com.gliffy.shape.basic.basic_v1.default.double_arrow","width":100,"height":25,"lockAspectRatio":false,"lockShape":false,"order":4,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.double_arrow.basic_v1","strokeWidth":2,"strokeColor":"#333333","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[],"linkMap":[]},{"x":800,"y":132.5,"rotation":0,"id":0,"uid":"com.gliffy.shape.sitemap.sitemap_v1.default.database","width":80,"height":80,"lockAspectRatio":true,"lockShape":false,"order":1,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.database.sitemap_v1","strokeWidth":2,"strokeColor":"#666666","fillColor":"#6699CC","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[],"linkMap":[]}],"background":"#FFFFFF","width":913,"height":460,"maxWidth":5000,"maxHeight":5000,"nodeIndex":34,"autoFit":true,"exportBorder":false,"gridOn":true,"snapToGrid":true,"drawingGuidesOn":true,"pageBreaksOn":false,"printGridOn":false,"printPaper":"LETTER","printShrinkToFit":false,"printPortrait":true,"shapeStyles":{"com.gliffy.shape.sitemap.sitemap_v1.default":{"fill":"#6699CC","stroke":"#666666","strokeWidth":2},"com.gliffy.shape.basic.basic_v1.default":{"fill":"#666666","stroke":"#e2e2e2","strokeWidth":2,"shadow":true},"com.gliffy.shape.network.network_v3.home":{"fill":"#ffffff"}},"lineStyles":{"global":{"startArrow":0,"endArrow":2}},"textStyles":{},"themeData":null}} -------------------------------------------------------------------------------- /images/todatauri.gliffy: -------------------------------------------------------------------------------- 1 | {"contentType":"application/gliffy+json","version":"1.1","metadata":{"title":"untitled","revision":0,"exportBorder":false},"embeddedResources":{"index":0,"resources":[]},"stage":{"objects":[{"x":710,"y":362,"rotation":0,"id":34,"uid":"com.gliffy.shape.basic.basic_v1.default.image","width":170,"height":115,"lockAspectRatio":true,"lockShape":false,"order":10,"graphic":{"type":"Image","Image":{"url":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKoAAABzCAMAAAA/mWlXAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAwBQTFRF+rNZ/vz6rcLQ+Jcacpat+JEO7fL1/ePD/M2S+7tq/NGZ+JIR/vXq+ZoiWoWfgqK2+8J6/N20qsDOOm2NZY2mscXS+I0F5ezwTnyY+IkAlbDB0t7l/v7+9fj5RHSSWISe+JYY+aU6/Nip/vHhxdXe/vr1zNni8fT3orrJ9ogAQXKR+Z4r+I8I/u3Z/NmshaW4+8aB/eC8/ejN+JAJ+q1N+JQUkq7AytjgwNHa+rhkVICctcnU/urRdJiu3OXr+aEx+ahB2OLpapCoRnaU9Pf49oUA/vnx+atF3ubs8vX4Un6a/Naliai6vc3YTHuY+fv8+JUWXoihucvX1ODm95YZ+/z8+JAM+Jcb9/n6WYSf/vDemrXF1uHoV4KeYImi/NWi2uTqd5qw/ezVVoKd+rdh6O7y097m940Fpr3Mpb3LNGmKUH2aqL/Mepyx/vLkS3qWbJKpYYqk/Pz89o8I+aI0SnmW+JskSHiVwtLb4Ojt95IQ4urvfqC0SnqXnLbGVYKc95QVSHaU+75x+aAt+8iG+q9QjKu9/MqKh6a5QnORLWOF//79UoCaSHiW/uvUyNbeUHyai6m7l7LD3+js4OnuVIKceJuxUH2ZkK2/xNPd/MqNfJ6y+aQ294wBjqy++Jge/P3+5Ovv//ju6/DyPW+ObpSrY4yl/P7+mLLEPnCQ+ag+VICbVYGd+JYWfp60/vTmUoGcaJCnnrjHydbgSniVztziMGaH+IwC+JMS4+vt95gd+JUXmLPD/Neo9X0AoLjH//37//z3TXuYztrje52zMWaIv9Da+8uMaI+oZ46no7zKn7jIUH6ZXYeh+JgdXIag+JgcXIehXIah+8yO/vv5+JMT+J0oXYagZ4+nVH+c+qdAQHGQ7/P2Xoei3+ftjKq7XIeg/MyQ4enu95MU95QSgKC12OHoXYahx9bf/vjwx9jg+qxJo7vK+Zkc+JUVV4Oe7PD0/ebHU3+b4+vvS3qXSXmW0Nzl0N3j+Zofydffb5OrcJWs94YA/NOg/NSg////C9/5tgAAEFxJREFUeNrsnHtcE1e+wCkhICBBXnGCEGIR5BEFQUShKdRULRERRBNHCmoBH6ACLiE2WlERlVq8tXWJVrS6ortKdq1eFVrsVqNrpTWZJLdYW1lbe+tevfWSloW2FtvZ38k7mIBpdRk/n3v+wPH8ZibfnPM7v9c54EI+Mc3l/1FtWvGtrDrMzd+d+qjuvJjmwu5ScX1mMdVR1zQ1N0wqx1MEWfz186mNuqxkG/z84ZbutdfqTrxJaVTXv/mGoH/f9NV19wZOOjlrcnHobGqiRjbhlwxX9wKxMj77ekzAO+smu1MRNcO3xK3TcHljXeC1ioqClCzJdUHQWAoaqx8EAb6m69nF30dGruflYIqYy8nzqOcCXPl1d/tZBd8KrIe/u5hyqKsnNcn39Os7ve73WfyC/6WcYx15uIRnXEehZhUNKu8tk6x4nmoxQC5eskx/Mf8Nt9umzhtxcgXbt5hiqGRQ0+Ub6N/tWwLYoyxKXJFVH7iIYqg3ykuCDFe+f/uTZeVfKJdgOYuohUoGn/nCQHghxt+q+4XFfFnBc9RCDWoicg1XUTba6b6YLat4jlKozx0JSLUr+HYxH6t4gVJZwP4zX9gPUr7tk2B9z1MJNShGl2tfslaLlW6jEuoL5SWpjmKvXplsBZXSwLySBkeR3wq2oGAJhVDv6ZouORCFrOO/vjKEQsn17oD2kQ5E7+Zj3VEUQr0RGHCx04EslS0L/AeFShZB2PWdDqxSKC8Ly6RSdeWuGP/KgSj5OjZw4PJvRvXn5zhCDV3XowimEOrOgEyHbik5QMELpQyqe8OrcxwL27PkrpRBPc0gvhqgClPX40sZ1KiS4AOOpWtxRc4aqqBmvpo6gHT2JL54C0VQMy6+OmYg+T8kWddyqYH68mXBs+TAwyqZRA3UXdeanx04U+jJas+lCOpnBtQXz9q3rvO/kPCDqYF6wjiqPLGDKuA9Pha4hBK6OlWsT023YHUOLEHn3jJ2MCVQfzqDikC7LncLrjnYFJgVg01dRAW7uu0MGk1Xhg6ve9H+HYd44vr1VECdVLIf8uttGIOQLV5t/5bJr7xenZdBgdBaonmZJBsUV4IrAhwYped3SgRiftzBoUbdVX4miPyjG8Ym94t5DjZZim/pdKWS627fhwxtvBocwJs9z62sglyb0+QwHHw5r6/gHX5Tw5tDihpZUOI65oT4p/lknDhngJ3Br4LLC69jqauHEJX0V8R8+SU7L4QceS0mb2C9nnoqwEZl/92oIbvLeiUbk9EA40cHLgF37k4JUI4ZOlRy3vK+w/76+NpfljPIvtWc9hi269ChAqzpYgWWN8itL2TKStY/P3SolvYf8jmD3bLHLcB3HgVQydNuA1XW53e+O/JAUE7MMiqgkv/MdBRJuy8J2rm3nZFzRFBnXH5DfczmRrDduOXZqL38gJijARJZwWHfswcpgUp2TrZrfgMk8oryi8FBs0a9S5IkNVAdBAJ99fLLyUPqWB+6uWa9rlvxZKCSZ3sUZdtynwjU1etPnZIUnMx4AlDJA6k6dhafN+YJQEVuVcJnhwU9Cajk/Dm3+E2y4CcBFTKtyLijAUGPD/UTaE85DFgjQBrhxMjezqmbbIV6Ybkrah/teeDO51z9kWT5wYd9tUd87bH09PRjEz0XDn9AGOFVNOPzdNRctj5jI9kxYuuHb8X/vN3OG8fG8VMtqGcVOGqKiw/cF/c6EugU/g8JWns1iclNTEzkMoVvN3qOsxGGT0lTM5mJqHG5bbG1Hlay96O7ONlL08/bDXBTxf80oYbwMF0YtCuBo/rdFVqOIYEua9lDkb4Vy5W2iQyN1iUUxk4Jtwi9YoWJSSKTtI2+1GeEFer9pOyulmMO9ObSBwfMqM2EEhp+5eP+tY6CQg0IiM9uPQypZyudJlKLaK1cJte7gzP3z6wqizA+UcgBRk5Ha2srR6SG26TSIrN0PEukUifOcKTi7qZRnfdKGCJVEop1/YtMmP47ENUND0H6M8cbQDnM+2mbPD1jRdP2cVs3mYUjliJhW0t0VWXaVRarQ6RWiZLomx4S1ayrB+oYelRlSuAPNtKMPoEW9WvzGYOTDk+ji1SiuSzPcRHk9u3T7+y4mbbUrKzjuXQgFXJHhJ+PiIgY/haHTkOs0vFOor7JN6KGNdtGM5cKCg0CXDI4anxHtlpFY262rOKIBeYFHssVqVRcnwnmJVbpjVi9rzqJ+n09YSAiemw3jzMVRgGjLGNQ1BlAI2pNs2dvtm/aR1OppaIJlq7jV1sBjiOd6RzqnDJCqSEY8KO73LqM0Nl3hSB0BCwsRs+gJ6E+aRQCKneYPdl3NDoMePRN6773aW1IBa46hxoFi4cReEuuVYYJrA3orJxCQr4zELSDoRj0MNzwSsARtUywJxsWDSDcYwtsOmsMw5rgLKpG3pAMakCId1rPfxlBSBbxwF4RpfqvcPZW3LY43+VWt4zhQc/iWXA1oaoVUJk/2/mQ4zO4IIqOt+29yeGoVLSOrU6h3momCIEv2YuDBky1zPS3blcIXQq5slmrJAT69ebfK9fpsKlWz0+qy9cVNqFqTUQjGlXvz+35MG6SSpXk7WfbGy7aAA90uTiF6gaopevIizKtEpe52sw/tpP0TYHRTtHv0h3aqCMIeUWkxedtkRAE3oQStohKIZpQrp1hfXoa4hg9rl/3jx2g3F3/7RyqXMuonkQGsYGp16IBmWKCqEsmP8YZSkK+Ut9VXk0o8WrLdk3xYkyrbK7Qn0x1EdJU6KPHP2jGkKq2FPW3DUVt0J294SknULfX4RqccZc8CBqg7D5hyr2KeTIiX+5OrtfhSqLQgJpXCt+m1M38+KIT3Uoltld/0mvhe0lgO0XZS+P7L7haJsw0y7P/Z2/KBgvG6RrnzKiyGUocjyIz3Eo1ShwzacCeCjmhyJxNrmCADuO/N1ST68EcyI+YM8kLDLlSKwk2FMBqhRw1sLZx3/aw+YxV6fpV9YAZW9jGAdQN3zmBuhqcFR4WRZLLkQbUmzTgLMw/GyLFewUQIeC9hs4C0IAwhtmnBR2FJ+qMYXp4IwQkwMrp2JduHY3u+NEbeu8/gDozG0wAJ8nLCdTIUwxlWM4cksxFsUC3ce+4czFG6LJGwuj+XYd8gOH+j8EEExjP9PhH8OXw+gum4WsUJkEYAiELfZ9V+PeSj33Ul+bCLNCcQh0lJjT5Ry4gOhlogNigAWv+DvPvG0qSyTkIVfGyvvfgRvg2KZeNDmH2llMaZfcR8875H2rfphthudLN0wdBDXceNbIHUCuQwdFrgMSgAXn1sP5RqTY0MF+jZGAGupAjyKeZajQjeVeUmp5tVjvm342eK81GsLQkZtXMR466QgaoBf8JV8kxSAMCkQa4w/znYyhRGBsoB9QrxqV0UoE0wHhyJ7K5EFTVNhobVrlBqldZGp1Ve/4Ro0aVolE9jUYpEGxPGIbGcs3/FML8o/EKPYJQBca1cwHWIPi0tfr/pDaBqrL7nUf5JL6G3krT2wKmPllyhLoAoXK6ZjqBugxQ5Ybjmh8gDdDvyOeBG6ozaO1l5Fm7jXHMbF2hVpnPMIDn8QmlYOqN/i8dV1QlzBbpWWcMgOrHQcYqe4cTqH8SEJqUqfq9uXvIBlzp20W6N2AEzjfEA+XWqGQw0gCZ/pDRoZWYkuDvtrOlM+EbOvIH6g7pZpOx6h+tkOQvBru6ygnUPjlC1a+NtUdAA3DxHHIPA/z/3rEW1GaTNx0FDkMrc0On90aFyWEOguynhHS9P2BWwiDHQiCjbplyjuwfWoG36pI6EwMsTjGjrg7mIw3II6P4BBFj9Fvt3VqrRDCUAapbqERx36wYQllYeNr+m4uYEBKo6TUJ5PCJ4K3UzIn9Sxi1XSJzbP2QqA0wqvITBoszuQ5SFMHe5G1o/o07ChflgF/9F1Ml5w3QAEbpWeTP+FpNT8Mh+2+ePjcJhjXJZzwZMaUFruhpCf3uSEtCqJ7OoP5UrdWmTDWcx3xWmwL2Xrn3sE4r431rtE8MFFqZTxZeuA7kChjkd8tlMAMfOXr1CJT5tSWBinrdh6tsbr+Q6w4tSa3mfO3lDGoprtF2HzYu8N0bIZ1mhH2pJcy/I/cGigJ15oC68wp4r5T2H8hIPq4sfO2eo1f7tSDANojyJ0S3qVSq6BG2ci8aRy1qk/7BGVS0TgQmtz7rOkpSYRxxdqQVqgbfaC59b4E4IEzuSrrGEBrFykOOXv0LE1A7fMBsPuOD1pUwbYeN/Jh+/kc7lQbyEaopBs2VG1J/jeyw6Rd43tCBBcMxSz7VhJKws6QvpiXYjk/IH/OGT6fHQox1zjMaRpXGsjFXM1uzYf6X+v161AzfMn1BxTL/5FmIra1RO7vzlVpF8CK5TlOou21VOrV583guWCsR95heF1igAWpptpW2Hq9B6Yp3jW3J4twgqButUcmgGEOpbaN5hyuVsEWdt7+HUMovBp/6lOBnWo7OJhTFW9X9xvugQe1q3azPA75hwbCqmD/ONImf+VxKA01leVijcmvJgVHH9tqgLtHJEWp34C5Tz+0cQGXILCd4LsG3IXIKQJ97rA7MFd1nfb5p5jOoIh3u5/leImgqjVtpGCc/KWgrsP6f5/hx58hVHpuvJrbB9LNsy2veje/7jTe2hRPOk9/dXLg13G8h5JF+BtQXxTaoGXE9Gph/vuWo8R4lQi21uPqDr+D6lafFDltO7XhwEjmJ0UmNtS4uLuk+LG8UAwizTRWMEdEdiLV1n2i0S9GM2BYhqgRyXWyKlhCMqURzjW1p7XDSY5O0NmL0tFUJX482oC7JskEllx/9FOabbTn1bEC1OiWb4SbQ6PWZf9LKNtFYrTTRBjoTGrcVkXCYUnOt5dyU+0I1irmThCCWIqerahtN2qKqRH9OMjXWN+Dchgs9yLRpXi7CSgNqrphBELI+81PJ3dUEIaiwkK35ErJ/XGbpCDnZS+iNRLt1JSvB83csOs1QlFaLIA+IbrTyT08N+3oafBW12li2BlZazQjzDU+zOCLrRmPCqJKfSBPIGpdKume6ATWypI7NDmi3FFX6StjsV63OZ8/hX2ez66xPxu1B7td2UKGd94j3mRbNTKR707nM6GmjvVbZiBM8hdNYXKG3N4hZ0ehLdTDTPI2wXn+Ntm1/bYSn79z3ILkzRTVba7brUQ8tc3V19beKj5Pvurp+YPV7hV/pd1lWWP1Oz0FIVEFT2x+ouY2bsNklvaqqaqLLsAnH+wvPvfS0Z22aT5VP7MT4m1dZrTB2dGbNFH1y/VL8h/9l0+Lfh/V5bvNx8uaqpxMSfvnV+1ZjIAJX4qV29zKmH1+wYMHw6fYfPH8nHKTh4EyHf/i7Fg6CbYkdYBdru5W1/lWos+MwrfLTjbzf8Dc0UHmgKFrIEXGEUx7y/l+FuicLh7RAe/s37hqe90iLbm19j3yMqLfl7xBEteKD377FecdLeH/hY0EN6czIGJu8X9tNELqeLY9kP/Z4PPlYUF/EjwS2F+jA7OoUj4YUFvnjQV3C/0yer8MJRsorj4rUieYcKruQwWDgujJBKklx1GJenVgsljDuziepjkqSB77PHbWIHJr2BP3prX8JMAD2Y6TZV3CKkQAAAABJRU5ErkJggg==","strokeWidth":2,"strokeColor":"#000000","dropShadow":false,"shadowX":0,"shadowY":0}},"children":null,"linkMap":[]},{"x":520,"y":388,"rotation":0,"id":32,"uid":"com.gliffy.shape.basic.basic_v1.default.text","width":150,"height":14,"lockAspectRatio":false,"lockShape":false,"order":9,"graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

Simpan

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null,"linkMap":[]},{"x":300,"y":260,"rotation":270,"id":30,"uid":"com.gliffy.shape.basic.basic_v1.default.text","width":150,"height":14,"lockAspectRatio":false,"lockShape":false,"order":8,"graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

Download

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null,"linkMap":[]},{"x":380,"y":150,"rotation":0,"id":26,"uid":"com.gliffy.shape.sitemap.sitemap_v1.default.page","width":35,"height":40,"lockAspectRatio":false,"lockShape":false,"order":6,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.page.sitemap_v1","strokeWidth":2,"strokeColor":"#999999","fillColor":"#6699CC","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2.333333333333334,"y":0,"rotation":0,"id":29,"uid":null,"width":30.333333333333336,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

.png

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":319.99999999999744,"y":250,"rotation":270,"id":24,"uid":"com.gliffy.shape.basic.basic_v1.default.left_arrow","width":150,"height":40,"lockAspectRatio":false,"lockShape":false,"order":0,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.left_arrow.basic_v1","strokeWidth":2,"strokeColor":"#ffffff","fillColor":"#9fc5e8","gradient":false,"dropShadow":true,"state":0,"shadowX":4,"shadowY":4,"opacity":1}},"children":[],"linkMap":[]},{"x":522,"y":399.5,"rotation":0,"id":21,"uid":"com.gliffy.shape.basic.basic_v1.default.double_arrow","width":160,"height":40,"lockAspectRatio":false,"lockShape":false,"order":5,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.double_arrow.basic_v1","strokeWidth":2,"strokeColor":"#ffffff","fillColor":"#9fc5e8","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[],"linkMap":[]},{"x":275,"y":64.99999999999977,"rotation":0,"id":17,"uid":"com.gliffy.shape.network.network_v3.home.cloud","width":230.00000000000003,"height":140,"lockAspectRatio":false,"lockShape":false,"order":3,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.cloud.network_v3","strokeWidth":2,"strokeColor":"#000000","fillColor":"#cfe2f3","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2.5555555555555554,"y":0,"rotation":0,"id":23,"uid":null,"width":224.88888888888894,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

INTERNET

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]},{"x":705,"y":319,"rotation":0,"id":14,"uid":"com.gliffy.shape.sitemap.sitemap_v1.default.database","width":90,"height":90,"lockAspectRatio":true,"lockShape":false,"order":11,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.database.sitemap_v1","strokeWidth":2,"strokeColor":"#999999","fillColor":"#6699CC","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":null,"linkMap":[]},{"x":263,"y":385,"rotation":0,"id":11,"uid":"com.gliffy.shape.basic.basic_v1.default.text","width":230,"height":14,"lockAspectRatio":false,"lockShape":false,"order":2,"graphic":{"type":"Text","Text":{"tid":null,"valign":"middle","overflow":"none","vposition":"none","hposition":"none","html":"

$ node ./tdi.js http://uncal.no/lawang.png

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null,"linkMap":[]},{"x":260,"y":362,"rotation":0,"id":8,"uid":"com.gliffy.shape.ui.ui_v2.forms_components.dialog_box","width":240,"height":116,"lockAspectRatio":false,"lockShape":false,"order":1,"graphic":{"type":"Shape","Shape":{"tid":"com.gliffy.stencil.dialog_box.ui_v2","strokeWidth":2,"strokeColor":"#000000","fillColor":"#FFFFFF","gradient":false,"dropShadow":false,"state":0,"shadowX":0,"shadowY":0,"opacity":1}},"children":[{"x":2,"y":0,"rotation":0,"id":37,"uid":null,"width":236,"height":14,"lockAspectRatio":false,"lockShape":false,"order":"auto","graphic":{"type":"Text","Text":{"tid":null,"valign":"top","overflow":"none","vposition":"none","hposition":"none","html":"

Terminal

","paddingLeft":2,"paddingRight":2,"paddingBottom":2,"paddingTop":2}},"children":null}],"linkMap":[]}],"background":"#FFFFFF","width":880,"height":478,"maxWidth":5000,"maxHeight":5000,"nodeIndex":39,"autoFit":true,"exportBorder":false,"gridOn":true,"snapToGrid":true,"drawingGuidesOn":true,"pageBreaksOn":false,"printGridOn":false,"printPaper":"LETTER","printShrinkToFit":false,"printPortrait":true,"shapeStyles":{"com.gliffy.shape.basic.basic_v1.default":{"fill":"#9fc5e8","stroke":"#ffffff","strokeWidth":2,"gradient":false,"shadow":true},"com.gliffy.shape.network.network_v3.home":{"fill":"#cfe2f3"},"com.gliffy.shape.sitemap.sitemap_v1.default":{"fill":"#6699CC","stroke":"#999999","strokeWidth":2}},"lineStyles":{},"textStyles":{},"themeData":null}} -------------------------------------------------------------------------------- /memakai_es6.md: -------------------------------------------------------------------------------- 1 | # Memakai ES6 2 | 3 | Meskipun ECMAScript 2015 atau yang lebih dikenal ES6 sudah [diresmikan](http://www.ecma-international.org/ecma-262/6.0/) tetapi implementasi di browser dan platform Node.js masih terjadi secara _gradual_. Pada saat buku ini ditulis pada platform Node.js 4.x \(LTS\) dan 5.x sudah banyak fitur-fitur ES6 yang _built-in_ dan untuk fitur yang belum didukung anda bisa memakai tool yang bernama Babel. 4 | 5 | Untuk mempelajari ES6 banyak sekali resource online yang menyediakan jadi silahkan anda bereksplorasi dan mencoba konsep-konsep baru yang ditawarkan oleh JavaScript. Anda bisa memulai dari buku online gratis tentang ES6 6 | 7 | * [ExploringJS ES6](http://exploringjs.com/es6/) 8 | 9 | Pada dasarnya Babel berfungsi untuk mengkompilasi ES6 \(atau ES7, 8\) menjadi ES5 sehingga bisa dijalankan pada browser atau platform Node.js yang belum mendukung ES6. Salah satu pertanyaan terbesar kalau anda memakai Babel adalah bagaimana mengkompilasi hanya beberapa fitur ES6 saja jikalau browser ataupun Node.js yang akan kita pakai secara native sudah mendukung sebagian atau beberapa fitur ES6? 10 | 11 | ## Babel on The Fly 12 | 13 | Sejak di release [Babel 6](https://babeljs.io/blog/2015/10/29/6.0.0/), tool ini mendukung kompilasi ES6 berdasarkan plugin artinya anda bisa memilih fitur mana yang akan dikompilasi ke ES5 jika misalnya pada platform Node.js sudah mendukung banyak fitur ES6. 14 | 15 | Kalau anda pernah memakai `babel-node` make sekarang diganti dengan paket `babel-cli` 16 | 17 | ```text 18 | $ npm install -g babel-cli 19 | ``` 20 | 21 | Apa kegunaannya? `babel-cli` sangat berguna untuk mengkompilasi ES6 secara `on the fly` misalnya begini 22 | 23 | **lib/module.js** 24 | 25 | ```text 26 | 'use strict' 27 | export function test() { 28 | console.log('test') 29 | } 30 | ``` 31 | 32 | **main.js** 33 | 34 | ```text 35 | 'use strict' 36 | import {test} from './lib/module' 37 | test() 38 | ``` 39 | 40 | Maka untuk mengeksekusi file `main.js` bisa melalui `babel-node` 41 | 42 | ```text 43 | $ babel-node main.js 44 | ``` 45 | 46 | Jika anda memakai project dengan ES6 selain `babel-cli` maka paket berikut juga perlu di install 47 | 48 | ```text 49 | $ npm install --save-dev babel babel-core babel-loader 50 | ``` 51 | 52 | dan juga setting file `.babelrc` \(meskipun sebenarnya ada beberapa alternatif lain dimana harus menuliskan setting babel tapi cara ini lebih UNIX, tergantung selera masing masing\) 53 | 54 | **.babelrc** 55 | 56 | ```text 57 | { 58 | "plugins": ["transform-es2015-modules-commonjs"] 59 | } 60 | ``` 61 | 62 | Bisa anda lihat bahwa plugins yang akan kita gunakan adalah `transform-es2015-modules-commonjs` jadi harus di install juga 63 | 64 | ```text 65 | $ npm install --save-dev babel-plugin-transform-es2015-modules-commonjs 66 | ``` 67 | 68 | Lalu bagaimana kalau kita menginginkan semua plugin kita pakai? jawabannya adalah dengan memakai `presets` 69 | 70 | ```text 71 | $ npm install --save-dev babel-preset-es2015 72 | ``` 73 | 74 | dan `.babelrc` perlu anda rubah menjadi seperti dibawah ini 75 | 76 | ```text 77 | { 78 | "presets": ["es2015"] 79 | } 80 | ``` 81 | 82 | **Catatan** Penjelasan diatas berlaku untuk JavaScript yang digunakan pada sisi server untuk client atau JavaScript yang berjalan pada browser anda bisa memakai [webpack](https://webpack.github.io/) bersama dengan babel. 83 | 84 | -------------------------------------------------------------------------------- /nodejs/README.md: -------------------------------------------------------------------------------- 1 | # Node.js 2 | 3 | Javascript merupakan bahasa pemrograman yang lengkap hanya saja selama ini di pakai sebagai bahasa untuk pengembangan aplikasi web yang berjalan pada sisi client atau browser saja. Tetapi sejak ditemukannya Node.js oleh Ryan Dhal pada tahun 2009, Javascript bisa digunakan sebagai bahasa pemrograman di sisi server sekelas dengan PHP, ASP, C\#, Ruby dll dengan kata lain Node.js menyediakan platform untuk membuat aplikasi Javascript dapat dijalankan di sisi server. 4 | 5 | Untuk mengeksekusi Javascript sebagai bahasa server diperlukan engine yang cepat dan mempunyai performansi yang bagus. Engine Javascript dari Google bernama V8 yang dipakai oleh Node.js yang merupakan engine yang sama yang dipakai di browser Google Chrome. 6 | 7 | -------------------------------------------------------------------------------- /nodejs/javascript_di_server.md: -------------------------------------------------------------------------------- 1 | # JavaScript Di Server 2 | 3 | Tak terelakkan bahwa Javascript merupakan bahasa pemrograman yang paling populer. Jika anda sebagai developer pernah mengembangkan aplikasi web maka penggunaan Javascript pasti tidak terhindarkan. 4 | 5 | Sekarang dengan berjalannya Javascript di server lalu apa keuntungan yang anda peroleh dengan mempelajari Node.js, kurang lebih seperti ini : 6 | 7 | * Pengembang hanya memakai satu bahasa untuk mengembangkan aplikasi lengkap client & server sehingga mengurangi _Learning Curve_ untuk mempelajari bahasa server yang lain. 8 | * Sharing kode antara client dan server atau istilahnya code reuse. 9 | * Javascript secara native mendukung JSON yang merupakan standar transfer data yang banyak dipakai saat ini sehingga untuk mengkonsumsi data-data dari pihak ketiga pemrosesan di Node.js akan sangat mudah sekali. 10 | * Database NoSQL seperti MongoDB dan CouchDB mendukung langsung Javascript sehingga interfacing dengan database ini akan jauh lebih mudah. 11 | * Node.js memakai V8 yang selalu mengikuti perkembangan standar ECMAScript, jadi tidak perlu ada kekhawatiran bahwa browser tidak akan mendukung fitur-fitur di Node.js. 12 | 13 | -------------------------------------------------------------------------------- /nodejs/nodejs_show.md: -------------------------------------------------------------------------------- 1 | # Node.js In Action 2 | 3 | Supaya anda lebih tertarik dalam belajar Node.js berikut beberapa website terkenal yang sudah memakai Node.js 4 | 5 | www.myspace.com 6 | 7 | ![myspace](../.gitbook/assets/mypspace.png) 8 | 9 | www.yummly.com 10 | 11 | ![yummly](../.gitbook/assets/yummly.png) 12 | 13 | www.shutterstock.com 14 | 15 | ![shutterstock](../.gitbook/assets/shutterstock.png) 16 | 17 | www.klout.com 18 | 19 | ![klout](../.gitbook/assets/klout.png) 20 | 21 | www.geekli.st 22 | 23 | ![geeklist](../.gitbook/assets/geeklist.png) 24 | 25 | www.learnboost.com 26 | 27 | ![learnboost](../.gitbook/assets/learnboost.png) 28 | 29 | Apakah masih ragu untuk memakai Node.js ?...Kalau masih penasaran apa yang membuat Node.js berbeda dari backend pada umumnya, silahkan dilanjutkan membaca :smile: 30 | 31 | -------------------------------------------------------------------------------- /npm/README.md: -------------------------------------------------------------------------------- 1 | # Module npm 2 | 3 | `nice people matter` 4 | 5 | npm merupakan package manager untuk Node.js dan untuk nama `npm` bukanlah suatu singkatan. Hanya dalam waktu 2 tahun sejak di releasenya Node.js ke publik jumlah modul melesat jauh bahkan hampir menyamai modul java ataupun ruby gems. 6 | 7 | ![modulecount npm](../.gitbook/assets/modul-npm.png) 8 | 9 | Grafik diatas didapat dari [http://modulecounts.com](http://modulecounts.com). 10 | 11 | Banyaknya push module ke repositori npm dapat diartikan adanya kepercayaan publik terhadap platform ini dan untuk kedepannya Node.js akan menjadi platform yang prospektif untuk berinvestasi. 12 | 13 | -------------------------------------------------------------------------------- /npm/konsep.md: -------------------------------------------------------------------------------- 1 | # Paket npm 2 | 3 | Secara default data paket npm disimpan di registry npmjs.org. Sehingga untuk menginstall paket npm tertentu anda bisa mencari paket ini melalui command `npm` atau langsung melalui website. 4 | 5 | Sejak versi Node.js 0.6.3 command `npm` sudah ter-bundle dengan installer Node.js. Untuk menginstall modul npm yang anda butuhkan ketik misalnya 6 | 7 | ```text 8 | npm install express 9 | ``` 10 | 11 | perintah diatas akan mendownload paket `express` dari `http://npmjs.org` dan secara otomatis akan membuat directory `node_modules`. 12 | 13 | Untuk memakai modul `express` ini cukup dengan membuat file JavaScript baru di luar direktori `node_modules` dan load modul dengan keyword `require`. 14 | 15 | ```text 16 | var app = require('express'); 17 | 18 | // kode lainnya 19 | ``` 20 | 21 | ## Membuat Paket npm 22 | 23 | Sebelum membuat paket npm pastikan fungsionalitas yang anda cari tidak ada dalam registry npm. Caranya yaitu anda bisa menggunakan perintah 24 | 25 | ```text 26 | npm search 27 | ``` 28 | 29 | atau dengan memakai website berikut [npmjs.org](http://npmjs.org), [node-modules.com](http://node-modules.com) atau [npmsearch.com](http://npmsearch.com) 30 | 31 | Untuk membuat paket npm caranya cukup mudah. Berikut alur umum untuk membuat paket npm untuk di publish ke registry `npmjs.org`. 32 | 33 | ![alur pembuatan npm](../.gitbook/assets/npm-flow.png) 34 | 35 | Secara garis besar proses pembuatan paket npm menurut alur diatas akan dijelaskan sebagai berikut 36 | 37 | ### Registrasi 38 | 39 | Sebelum publish ke registry npmjs.org kita harus registrasi dulu melalui perintah berikut 40 | 41 | ```text 42 | npm adduser 43 | ``` 44 | 45 | ### Buat Project 46 | 47 | Untuk membuat project baru dari nol langkah pertama adalah membuat direktori 48 | 49 | ```text 50 | mkdir npmproject 51 | ``` 52 | 53 | Kemudian inisialisasi project tersebut 54 | 55 | ```text 56 | npm init 57 | ``` 58 | 59 | perintah diatas akan membuat file `package.json` yang isinya adalah info dan dependensi project. Ikuti saja tiap pertanyaan dan isi informasi sesuai dengan paket yang ingin anda buat. 60 | 61 | Contohnya pada paket `svh` berikut ini 62 | 63 | `package.json` 64 | 65 | ```text 66 | { 67 | "name": "svh", 68 | "version": "0.0.7-beta", 69 | "author": "Equan Pr.", 70 | "description": "Simple file server for html-javascript web client app development", 71 | "keywords": [ 72 | "process", 73 | "reload", 74 | "watch", 75 | "development", 76 | "restart", 77 | "server", 78 | "monitor", 79 | "auto", 80 | "static", 81 | "nodemon" 82 | ], 83 | "homepage": "https://github.com/junwatu/svh", 84 | "bugs": "https://github.com/junwatu/svh/issues", 85 | "main": "./lib/core.js", 86 | "scripts": { 87 | "test": "./node_modules/mocha/bin/mocha" 88 | }, 89 | "dependencies": { 90 | "async": "~0.2.9", 91 | "chalk": "0.2.x", 92 | "cheerio": "0.12.x", 93 | "commander": "2.0.x", 94 | "compression": "^1.0.2", 95 | "concat-stream": "1.0.x", 96 | "express": "4.x", 97 | "morgan": "^1.1.1", 98 | "send": "^0.3.0", 99 | "watch": "0.8.x", 100 | "wordgenerator": "0.0.1" 101 | }, 102 | "devDependencies": { 103 | "gulp": "^3.5.6", 104 | "gulp-uglifyjs": "^0.3.0", 105 | "gulp-util": "2.2.14", 106 | "mocha": "1.13.x", 107 | "supertest": "0.8.x" 108 | }, 109 | "repository": { 110 | "type": "git", 111 | "url": "http://github.com/junwatu/svh.git" 112 | }, 113 | "bin": { 114 | "svh": "./bin/svh" 115 | }, 116 | "license": "MIT" 117 | } 118 | ``` 119 | 120 | ### Publish Lokal 121 | 122 | Sebelum di publish pastikan paket anda bisa berjalan atau digunakan pada komputer lokal. Perintah berikut akan menginstall paket anda secara global di komputer. 123 | 124 | ```text 125 | npm publish . -g 126 | ``` 127 | 128 | atau jika diinginkan link simbolik bisa memakai perintah npm berikut 129 | 130 | ```text 131 | npm link 132 | ``` 133 | 134 | ### Publish Publik 135 | 136 | ```text 137 | npm publish 138 | ``` 139 | 140 | Untuk lebih jelasnya silahkan kunjungi dokumentasi untuk [developer npm](https://www.npmjs.org/doc/misc/npm-developers.html). 141 | 142 | -------------------------------------------------------------------------------- /npm/npm.md: -------------------------------------------------------------------------------- 1 | # Konsep 2 | 3 | npm memakai sistem modul [CommonJS](http://www.commonjs.org/specs/) yang cukup mudah dalam penggunaanya. Sistem modul ini akan meng-export objek JavaScript ke variabel `exports` yang bersifat global di modul tersebut. 4 | 5 | Sebagai contoh 6 | 7 | `band.js` 8 | 9 | ```text 10 | 'use strict'; 11 | 12 | function Band(){} 13 | 14 | Band.prototype.info = function(){ 15 | return 'Nama Band: '+this.name; 16 | } 17 | 18 | Band.prototype.add = function(name){ 19 | this.name = name; 20 | } 21 | 22 | module.exports = new Band(); 23 | ``` 24 | 25 | Untuk pemakaiannya seperti di bawah ini 26 | 27 | `app.js` 28 | 29 | ```text 30 | var band = require('./band.js'); 31 | band.add('Dewa 19'); 32 | 33 | console.log(band.info); 34 | ``` 35 | 36 | `require()` diatas adalah fungsi sinkron yang meload paket atau modul lain dari sistem file. 37 | 38 | -------------------------------------------------------------------------------- /pemrosesan_data_form_html/README.md: -------------------------------------------------------------------------------- 1 | # Pemrosesan Data Form HTML 2 | 3 | Aplikasi web memperoleh data dari pengguna umumnya melalui pengisian form HTML. Contohnya seperti ketika registrasi di media sosial atau aktifitas update status di Facebook misalnya pasti akan mengisi text field dan kemudian menekan tombol submit ataupun enter agar data bisa terkirim dan diproses oleh server. 4 | 5 | Data yang dikirim oleh form biasanya salah satu dari dua tipe mime berikut 6 | 7 | * application/x-www-form-urlencoded 8 | * multipart/form-data 9 | 10 | Node.js sendiri hanya menyediakan parsing data melalui `body` dari `request` sedangkan untuk validasi atau pemrosesan data akan diserahkan kepada komunitas. 11 | 12 | -------------------------------------------------------------------------------- /pemrosesan_data_form_html/multipart.md: -------------------------------------------------------------------------------- 1 | # Multipart Data 2 | 3 | _Parsing_ data form dan file yang di _upload_ ke server Node.js adalah pekerjaan yang cukup susah kalo dikerjakan secara manual atau dari _scratch_ karena disamping harus _parsing_ data binary yang berupa file juga harus _parsing_ data form. 4 | 5 | Protokol untuk `multipart/form-data` di definisikan secara lengkap di [RFC 2388](https://www.ietf.org/rfc/rfc2388.txt). 6 | 7 | -------------------------------------------------------------------------------- /pemrosesan_data_form_html/url_encoded.md: -------------------------------------------------------------------------------- 1 | # URL Encode 2 | 3 | Hanya akan dibahas untuk 2 metode HTTP yaitu `GET` dan `POST` saja. Metode `GET` untuk menampilkan form html dan `POST` untuk menangani data form yang dikirim 4 | 5 | Ok langsung kita lihat kode server sederhana untuk parsing data form melalui objek `request` dengan data form bertipe `application/x-www-form-urlencoded` yang merupakan default dari tag form. 6 | 7 | ```text 8 | var http = require('http'); 9 | var data = []; 10 | var qs = require('querystring'); 11 | 12 | var server = http.createServer(function(req, res){ 13 | if('/' == req.url){ 14 | switch(req.method){ 15 | case 'GET': 16 | tampilkanForm(res); 17 | break; 18 | case 'POST': 19 | prosesData(req, res); 20 | break; 21 | default: 22 | badRequest(res); 23 | } 24 | } else { 25 | notFound(res); 26 | } 27 | }); 28 | 29 | function tampilkanForm(res){ 30 | var html = 'Data Hobiku' 31 | + '

Hobiku

' 32 | + '
' 33 | + '

' 34 | + '

' 35 | + '
'; 36 | 37 | res.setHeader('Content-Type', 'text/html'); 38 | res.setHeader('Content-Length', Buffer.byteLength(html)); 39 | res.end(html); 40 | } 41 | 42 | function prosesData(req, res) { 43 | var body= ''; 44 | req.setEncoding('utf-8'); 45 | req.on('data', function(chunk){ 46 | body += chunk; 47 | }); 48 | 49 | req.on('end', function(){ 50 | var data = qs.parse(body); 51 | res.setHeader('Content-Type', 'text/plain'); 52 | res.end('Hobiku: '+data.hobi); 53 | }); 54 | } 55 | 56 | function badRequest(res){ 57 | res.statusCode = 400; 58 | res.setHeader('Content-Type', 'text/plain'); 59 | res.end('400 - Bad Request'); 60 | } 61 | 62 | function notFound(res) { 63 | res.statusCode = 404; 64 | res.setHeader('Content-Type', 'text/plain'); 65 | res.end('404 - Not Found'); 66 | } 67 | 68 | server.listen(3003); 69 | console.log('server http berjalan pada port 3003'); 70 | ``` 71 | 72 | Untuk mengetest `GET` dan `POST` bisa dilakukan melalui curl, browser atau melalui gui [Postman](http://www.getpostman.com/). 73 | 74 | ## GET 75 | 76 | ![GET form fields](../.gitbook/assets/get-form.png) 77 | 78 | ## POST 79 | 80 | ![POST](../.gitbook/assets/post-urlencoded-data.png) 81 | 82 | module `querystring` dari Node.js berfungsi untuk mengubah url encoded string menjadi objek JavaScript. Contohnya 83 | 84 | ```text 85 | querystring.parse('nama=lanadelrey&job=singer&album=borntodie&ultraviolence'); 86 | // returns 87 | { nama: 'lanadelrey', job: 'singer',album: ['borntodie', 'ultraviolence']} 88 | ``` 89 | 90 | -------------------------------------------------------------------------------- /pengarang.md: -------------------------------------------------------------------------------- 1 | # Tentang Pengarang 2 | 3 | Equan Pr. adalah developer NodeJS dan peminum kopi kelas berat. Selalu sibuk dengan yang berbau JavaScript ketika di depan komputer, penggila film & musik metal dan kadang-kadang nge-twit di [@junwatu](https://twitter.com/junwatu). Ngoding di[ Github](https://github.com/junwatu) dan nulis di [Sajen.id](https://sajen.id) 🙏 4 | 5 | -------------------------------------------------------------------------------- /person_rest_api/README.md: -------------------------------------------------------------------------------- 1 | # Person REST API 2 | 3 | Aplikasi ini merupakan contoh sederhana layanan server melalui **REST** \(**Re**presentational **S**tate **T**ransfer\) yaitu mekanisme untuk komunikasi dengan server melalui protokol HTTP yang mudah untuk digunakan daripada memakai mekanisme protokol lama sepeti CORBA, SOAP ataupun RPC. 4 | 5 | Aplikasi REST memakai metode HTTP seperti POST, PUT, GET dan DELETE untuk menambah, mengubah, mengambil ataupun menghapus resource yang ada pada server. Sehingga dalam pengembangan aplikasi khususnya dengan memakai Node.js, mekanisme REST sangat mudah untuk digunakan. 6 | 7 | ## Susunan API 8 | 9 | Berikut susunan API yang akan digunakan dalam contoh aplikasi ini. Contoh API ini mungkin tidak mengikuti _best practice_ tapi penulis rasa sudah cukup untuk menggambarkan bagaimana menyusun aplikasi REST secara sederhana. 10 | 11 | ![Person Rest API](../.gitbook/assets/persons-rest-api.png) 12 | 13 | -------------------------------------------------------------------------------- /person_rest_api/inisialisasi.md: -------------------------------------------------------------------------------- 1 | # Cara Kerja 2 | 3 | Cara kerja dari aplikasi Person REST ini cukup mudah. Hanya saja untuk antar muka dengan pengguna tidak melalui antar muka web seperti halnya kita mengakses halaman Facebook misalnya, karena secara umum aplikasi REST fungsinya lebih ke memberikan layanan data mentah sehingga developer bertanggung jawab penuh untuk apa data-data tersebut digunakan, apakah akan ditampilkan ke browser web atau digunakan pada aplikasi mobile android atau akan digunakan untuk mengaktifkan device elektronik seperti Arduino, Raspberry Pi dll. 4 | 5 | Untuk aplikasi Person REST ini, data disimpan di database MongoDB melalui operasi CRUD \(_Create, Read, Update, Delete_\) yang dapat diakses melalui _request_ API yang telah di sebutkan sebelumnya. 6 | 7 | Diagram kerja aplikasi Person REST digambarkan pada diagram dibawah ini 8 | 9 | ![](../.gitbook/assets/persons-rest-diagram.png) 10 | 11 | Pengetesan operasi CRUD untuk aplikasi bisa dengan menggunakan bantuan alat _Command Line Interface_ seperti cURL atau HTTPie ataupun tool yang lebih ramah seperti Postman dan bisa juga anda membangun antar muka web dengan memakai API yang disediakan oleh server Person ini. Contoh pengetesan untuk aplikasi Person REST ini bisa lihat pada sub-bab [**Pengetesan**](testing.md). 12 | 13 | -------------------------------------------------------------------------------- /person_rest_api/kode.md: -------------------------------------------------------------------------------- 1 | # Server 2 | 3 | Kode sumber dari aplikasi ini dapat di download di link berikut 4 | 5 | [https://github.com/junwatu/rest-node-mongoose-mongodb](https://github.com/junwatu/rest-node-mongoose-mongodb) 6 | 7 | ## Instalasi 8 | 9 | Clone kode sumber melalui git dan instal depedensi paket melalui npm 10 | 11 | ```text 12 | $ git clone https://github.com/junwatu/rest-node-mongoose-mongodb.git 13 | 14 | $ cd rest-node-mongoose-mongodb 15 | 16 | $ npm install 17 | ``` 18 | 19 | Pastikan database MongoDB sudah berjalan pada sistem anda jika menggunakan `service` **systemd** pada linux anda bisa menjalankannya dengan perintah berikut 20 | 21 | ```text 22 | $ sudo service mongod start 23 | ``` 24 | 25 | ## Kode 26 | 27 | Untuk lingkungan produksi ada baiknya untuk memecah file kode ke bagian yang lebih kecil supaya lebih mudah dalam hal _maintenance_. Untuk kemudahan dan kesederhanaan aplikasi ini maka kode utama ditulis dalam satu file. 28 | 29 | > app.js 30 | 31 | ```text 32 | /* 33 | * Koneksi Nodejs dengan MongoDB menggunakan Mongoose 34 | * 35 | * Author By Equan Pr. 36 | * http://equan.me 37 | * 38 | * License : Whatever you want! :D 39 | */ 40 | 41 | var express = require("express"), 42 | app = express(), 43 | mongoose = require('mongoose'), 44 | path = require('path'), 45 | engines = require('consolidate'); 46 | 47 | app.configure(function () { 48 | app.use(express.logger()); 49 | 50 | app.use(function(req, res, next) { 51 | res.header('Access-Control-Allow-Origin', '*'); 52 | res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE'); 53 | res.header('Access-Control-Allow-Headers', 'Content-Type') 54 | if ('OPTIONS' == req.method) { 55 | res.send(200); 56 | } 57 | else { 58 | next(); 59 | } 60 | }) 61 | 62 | app.use(express.bodyParser()); 63 | app.use(express.methodOverride()); 64 | app.use(express.static(__dirname+'/public')); 65 | 66 | app.engine('html', engines.handlebars); 67 | 68 | app.set('views', __dirname + '/views'); 69 | app.set('view engine', 'html'); 70 | 71 | app.set('PORT', process.env.PORT || 5000); 72 | app.set('MONGODB_URI', process.env.MONGOLAB_URI || 73 | process.env.MONGOHQ_URL || 'mongodb://localhost/persons'); 74 | 75 | }); 76 | 77 | /** 78 | * MongoDB connection 79 | */ 80 | var db = mongoose.createConnection(app.get('MONGODB_URI')); 81 | 82 | db.on('connected', function () { 83 | console.log('Connected to MongoDB.'); 84 | 85 | }); 86 | 87 | db.on('error', function (err) { 88 | console.error.bind(console, 'Connection to MongoDB error!.'); 89 | }); 90 | 91 | db.on('close', function () { 92 | console.log('Connection to MongoDB closed.'); 93 | }); 94 | 95 | // Schema 96 | var PersonsSchema = new mongoose.Schema({ 97 | name: 'string', 98 | username: 'string', 99 | website: 'string', 100 | createdAt: 'date', 101 | updatedAt: 'date' 102 | }), 103 | 104 | Persons = db.model('Persons', PersonsSchema); 105 | 106 | // Routes 107 | app.get("/", function (req, res) { 108 | res.render('index',{ 109 | data: 'Silly RESTful sample app built with Node.js, Express, Mongoose and MongoDB. ' + 110 | 'Maybe it\'s useful for beginners ;)' 111 | }); 112 | }); 113 | 114 | // GET /persons 115 | app.get("/persons", function (req, res) { 116 | // Find All 117 | Persons.find(function (err, persons) { 118 | if (err) res.json({error: err}) 119 | 120 | if(persons) 121 | res.json({persons: persons}); 122 | }) 123 | }); 124 | 125 | // POST /persons 126 | app.post("/persons", function(req, res){ 127 | /** 128 | * Get data from post 129 | * @type {Persons} 130 | */ 131 | var person = new Persons({ 132 | name: req.body.name, 133 | username: req.body.username, 134 | website: req.body.website, 135 | createdAt: new Date(), 136 | updatedAt: new Date() 137 | }); 138 | 139 | person.save(function (err, person) { 140 | if (err) { 141 | res.send({error:err}); 142 | }else { 143 | console.log('Save data: ' + person); 144 | res.json({message: ' save ok'}); 145 | } 146 | }) 147 | }); 148 | 149 | // GET /persons/:username 150 | app.get('/persons/:username', function(req, res){ 151 | var param_username = req.params.username; 152 | 153 | Persons.find({username:param_username}, function(err, person){ 154 | if(err) { 155 | res.json({ 156 | data:"Error finding person." 157 | }); 158 | }else { 159 | res.json({ 160 | person: person 161 | }); 162 | } 163 | }) 164 | }); 165 | 166 | // PUT /persons/:username 167 | app.put('/persons/:username', function(req, res){ 168 | var query = {username: req.params.username}, 169 | data_update = { 170 | name : req.body.name, 171 | username: req.params.username, 172 | website: req.body.website, 173 | updatedAt: new Date() 174 | } 175 | 176 | Persons.update(query, data_update, {multi:false}, function(err, numberAffected, rawResponse ){ 177 | if(err) { 178 | res.json({ 179 | error:err 180 | }) 181 | }else { 182 | res.json({ 183 | numberAffected:numberAffected, 184 | rawResponse: rawResponse 185 | }); 186 | } 187 | }); 188 | 189 | }); 190 | 191 | // DELETE /persons/:username 192 | app.delete('/persons/:username', function(req, res){ 193 | var param_username_del = req.params.username; 194 | 195 | Persons.remove({username:param_username_del}, function(err){ 196 | if(err){ res.json({ 197 | error:err 198 | }) 199 | }else { 200 | res.json({message: "delete ok"}); 201 | } 202 | }); 203 | }); 204 | 205 | 206 | app.listen(app.get('PORT')); 207 | console.log("Server Port: " + app.get('PORT')); 208 | ``` 209 | 210 | -------------------------------------------------------------------------------- /person_rest_api/testing.md: -------------------------------------------------------------------------------- 1 | # Pengetesan 2 | 3 | Untuk menggunakan atau pengetesan API ini cara termudah adalah dengan memakai [Postman](https://www.getpostman.com/) atau jika anda sudah terbiasa memakai tool terminal seperti [cURL](http://curl.haxx.se/) atau [Httpie](https://github.com/jkbrzt/httpie) silahkan saja. 4 | 5 | Demo aplikasi berada pada link berikut, 6 | 7 | > [persons-api.herokuapp.com](https://github.com/junwatu/pengenalan-nodejs-gitbook/tree/6e76b1c428229f82ce33f1967c256f2a5db3502d/person_rest_api/persons-api.herokuapp.com) 8 | 9 | ## POST /persons 10 | 11 | Untuk membuat data Person baru melalui api `/persons` cukup dengan memakai request POST. 12 | 13 | ![](../.gitbook/assets/person-rest-post.png) 14 | 15 | ## GET /persons 16 | 17 | Mengambil data dengan mengakses API `/persons` yang akan mengembalikan semua data yang telah tersimpan sebelumnya. 18 | 19 | ![](../.gitbook/assets/person-rest-get.png) 20 | 21 | ## PUT /persons/:username 22 | 23 | Update data bisa dilakukan dengan mudah dengan memakai PUT. 24 | 25 | ![](../.gitbook/assets/person-rest-update.png) 26 | 27 | ## DELETE /persons/:username 28 | 29 | Operasi penghapusan data hanya bisa dilakukan satu persatu melalui key `:username`. 30 | 31 | ![](../.gitbook/assets/person-rest-delete.png) 32 | 33 | -------------------------------------------------------------------------------- /server_file_statis.md: -------------------------------------------------------------------------------- 1 | # Server File Statis 2 | 3 | Aplikasi web memerlukan file - file statis seperti CSS, font dan gambar atau file - file library JavaScript agar aplikasi web bekerja sebagaimana mestinya. File - file ini sengaja dipisahkan agar terstruktur dan secara _best practices_ file - file ini memang harus dipisahkan. Lalu bagaimana caranya Node.js bisa menyediakan file - file ini ?...ok mari kita buat server Node.js yang fungsinya untuk menyediakan file statis. 4 | 5 | Agar server Node.js bisa mengirimkan file statis ke klien maka server perlu mengetahui `path` atau tempat dimana file tersebut berada. 6 | 7 | Node.js bisa mengirimkan file tersebut secara streaming melalui fungsi [`fs.createReadStream()`](http://nodejs.org/api/fs.html#fs_fs_createreadstream_path_options). Sebelum dijelaskan lebih lanjut mungkin bisa dilihat atau di coba saja server file Node.js dibawah ini 8 | 9 | [`server-file.js`](https://raw.github.com/idjs/belajar-nodejs/gh-pages/code/server-file/server-file.js) 10 | 11 | ```text 12 | var http = require('http'), 13 | parse = require('url').parse, 14 | join = require('path').join, 15 | fs = require('fs'), 16 | root = join(__dirname, 'www'), 17 | PORT = 3300, 18 | 19 | server = http.createServer(function(req, res){ 20 | var url = parse(req.url), 21 | path = join(root, url.pathname), 22 | stream = fs.createReadStream(path); 23 | 24 | stream.on('data', function(bagian){ 25 | res.write(bagian); 26 | }); 27 | 28 | stream.on('end', function(){ 29 | res.end(); 30 | }); 31 | 32 | stream.on('error', function(){ 33 | res.setHeader('Content-Type','text/html'); 34 | 35 | var url_demo = "http://localhost:"+PORT+"/index.html"; 36 | res.write("coba buka "+url_demo+""); 37 | res.end(); 38 | }) 39 | 40 | }); 41 | 42 | server.listen(PORT); 43 | console.log('Port '+PORT+': Server File '); 44 | ``` 45 | 46 | Berikut sedikit penjelasan dari kode diatas 47 | 48 | * [`__dirname`](http://nodejs.org/api/globals.html#globals_dirname) merupakan variabel global yang disediakan oleh Node.js yang berisi path direktori dari file yang sedang aktif mengeksekusi `__dirname`. 49 | * `root` merupakan direktori root atau referensi tempat dimana file-file yang akan dikirimkan oleh server Node.js. Pada kode server diatas direktori root di setting pada direktori `www`. 50 | * `path` adalah path file yang bisa didapatkan dengan menggabungkan path direktori root dan `pathname`. `pathname` yang dimaksud di sini misalnya jika URL yang diminta yaitu `http://localhost:3300/index.html` maka `pathname` adalah `/index.html`. Nilai variabel `path` dihasilkan dengan memakai fungsi `join()`. 51 | 52 | ```text 53 | var path = join(root, url.pathname) 54 | ``` 55 | 56 | * `stream` yang di kembalikan oleh fungsi `fs.createReadStream()` merupakan class [`stream.Readable`](http://nodejs.org/api/stream.html#stream_class_stream_readable). Objek `stream` ini mengeluarkan data secara streaming untuk di olah lebih lanjut. Perlu menjadi catatan bahwa `stream.Readable` tidak akan mengeluarkan data jikalau tidak di kehendaki. Nah...cara untuk mendeteksi data streaming ini sudah siap di konsumsi atau belum adalah melalui event. 57 | 58 | Event yang di dukung oleh class `stream.Readable` adalah sebagai berikut 59 | 60 | * Event: `readable` 61 | * Event: `data` 62 | * Event: `end` 63 | * Event: `error` 64 | * Event: `close` 65 | 66 | Mungkin anda bertanya kenapa server file statis diatas memakai stream, bukankah menyediakan file secara langsung saja sudah bisa? jawabannya memang bisa, tetapi mungkin tidak akan efisien kalau file yang akan di berikan ke client mempunyai ukuran yang besar. Coba lihat kode berikut 67 | 68 | ```text 69 | var http = require('http'); 70 | var fs = require('fs'); 71 | 72 | var server = http.createServer(function (req, res) { 73 | fs.readFile(__dirname + '/data.txt', function (err, data) { 74 | res.end(data); 75 | }); 76 | }); 77 | server.listen(8000); 78 | ``` 79 | 80 | Jika file `data.txt` terlalu besar maka buffer yang digunakan oleh sistem juga besar dan konsumsi memori juga akan bertambah besar seiring semakin banyak pengguna yang mengakses file ini. 81 | 82 | Jika anda ingin lebih banyak mendalami tentang Node.js Stream silahkan lihat resource berikut \(dalam Bahasa Inggris\): 83 | 84 | * [Node.js API Stream](http://nodejs.org/api/stream.html) 85 | * [Stream Handbook](https://github.com/substack/stream-handbook) 86 | 87 | -------------------------------------------------------------------------------- /server_file_statis/kode.md: -------------------------------------------------------------------------------- 1 | # Kode 2 | 3 | Agar server Node.js bisa mengirimkan file statis ke klien maka server perlu mengetahui `path` atau tempat dimana file tersebut berada. 4 | 5 | Node.js bisa mengirimkan file tersebut secara streaming melalui fungsi [`fs.createReadStream()`](http://nodejs.org/api/fs.html#fs_fs_createreadstream_path_options). Sebelum dijelaskan lebih lanjut mungkin bisa dilihat atau di coba saja server file Node.js dibawah ini 6 | 7 | [`server-file.js`](https://raw.github.com/idjs/belajar-nodejs/gh-pages/code/server-file/server-file.js) 8 | 9 | ``` 10 | var http = require('http'), 11 | parse = require('url').parse, 12 | join = require('path').join, 13 | fs = require('fs'), 14 | root = join(__dirname, 'www'), 15 | PORT = 3300, 16 | 17 | server = http.createServer(function(req, res){ 18 | var url = parse(req.url), 19 | path = join(root, url.pathname), 20 | stream = fs.createReadStream(path); 21 | 22 | stream.on('data', function(bagian){ 23 | res.write(bagian); 24 | }); 25 | 26 | stream.on('end', function(){ 27 | res.end(); 28 | }); 29 | 30 | stream.on('error', function(){ 31 | res.setHeader('Content-Type','text/html'); 32 | 33 | var url_demo = "http://localhost:"+PORT+"/index.html"; 34 | res.write("coba buka "+url_demo+""); 35 | res.end(); 36 | }) 37 | 38 | }); 39 | 40 | server.listen(PORT); 41 | console.log('Port '+PORT+': Server File '); 42 | 43 | ``` 44 | 45 | Berikut sedikit penjelasan dari kode diatas 46 | 47 | - [`__dirname`](http://nodejs.org/api/globals.html#globals_dirname) merupakan variabel global yang disediakan oleh Node.js yang berisi path direktori dari file yang sedang aktif mengeksekusi `__dirname`. 48 | - `root` merupakan direktori root atau referensi tempat dimana file-file yang akan dikirimkan oleh server Node.js. Pada kode server diatas direktori root di setting pada direktori `www`. 49 | - `path` adalah path file yang bisa didapatkan dengan menggabungkan path direktori root dan `pathname`. `pathname` yang dimaksud di sini misalnya jika URL yang diminta yaitu `http://localhost:3300/index.html` maka `pathname` adalah `/index.html`. Nilai variabel `path` dihasilkan dengan memakai fungsi `join()`. 50 | 51 | ``` 52 | var path = join(root, url.pathname) 53 | ``` 54 | 55 | - `stream` yang di kembalikan oleh fungsi `fs.createReadStream()` merupakan class [`stream.Readable`](http://nodejs.org/api/stream.html#stream_class_stream_readable). Objek `stream` ini mengeluarkan data secara streaming untuk di olah lebih lanjut. Perlu menjadi catatan bahwa `stream.Readable` tidak akan mengeluarkan data jikalau tidak di kehendaki. Nah...cara untuk mendeteksi data streaming ini sudah siap di konsumsi atau belum adalah melalui event. 56 | 57 | Event yang di dukung oleh class `stream.Readable` adalah sebagai berikut 58 | 59 | 60 | - Event: `readable` 61 | - Event: `data` 62 | - Event: `end` 63 | - Event: `error` 64 | - Event: `close` 65 | 66 | 67 | Mungkin anda bertanya kenapa server file statis diatas memakai metode stream, bukankah menyediakan file secara langsung saja sudah bisa? jawabannya memang bisa tetapi mungkin tidak akan efisien kalau file yang akan di berikan ke client mempunyai ukuran yang cukup besar. Coba lihat kode berikut ini 68 | 69 | ``` 70 | var http = require('http'); 71 | var fs = require('fs'); 72 | 73 | var server = http.createServer(function (req, res) { 74 | fs.readFile(__dirname + '/data.txt', function (err, data) { 75 | res.end(data); 76 | }); 77 | }); 78 | server.listen(8000); 79 | 80 | ``` 81 | Jika file `data.txt` ukurannya terlalu besar maka buffer yang digunakan oleh sistem juga besar sehingga konsumsi memori juga akan bertambah besar seiring semakin banyak pengguna yang mengakses file ini. 82 | 83 | Jika anda ingin lebih banyak mendalami tentang Node.js Stream silahkan lihat resource berikut (dalam Bahasa Inggris) 84 | 85 | - [Node.js API Stream](http://nodejs.org/api/stream.html) 86 | - [Stream Handbook](https://github.com/substack/stream-handbook) 87 | 88 | 89 |
90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /server_http_dasar/README.md: -------------------------------------------------------------------------------- 1 | # Server HTTP Dasar 2 | 3 | Penggunaan Node.js yang revolusioner yaitu sebagai server. Yup...mungkin kita terbiasa memakai server seperti Apache - PHP, Nginx - PHP, Java - Tomcat - Apache atau IIS - ASP.NET sebagai pemroses data di sisi server, tetapi sekarang semua itu bisa tergantikan dengan memakai JavaScript - Node.js!. Lihat contoh dasar dari server Node.js berikut \(kode sumber pada direktori code pada repositori ini\) 4 | 5 | [`server-http.js`](https://raw.github.com/idjs/belajar-nodejs/gh-pages/code/server-http.js) 6 | 7 | ```text 8 | var http = require('http'), 9 | PORT = 3400; 10 | 11 | var server = http.createServer(function(req, res){ 12 | var body = "
Haruskah belajar Node.js?

...Yo Mesto!

" 13 | res.writeHead(200, { 14 | 'Content-Length':body.length, 15 | 'Content-Type':'text/html', 16 | 'Pesan-Header':'Pengenalan Node.js' 17 | }); 18 | 19 | res.write(body); 20 | res.end(); 21 | }); 22 | 23 | server.listen(PORT); 24 | 25 | console.log("Port "+PORT+" : Node.js Server..."); 26 | ``` 27 | 28 | Paket [http](http://nodejs.org/api/http.html#http_http) merupakan paket bawaan dari platform Node.js yang mendukung penggunaan fitur-fitur protokol HTTP. Object `server` merupakan object yang di kembalikan dari fungsi `createServer()`. 29 | 30 | ```text 31 | var server = http.createServer([requestListener]) 32 | ``` 33 | 34 | Tiap request yang terjadi akan ditangani oleh fungsi callback `requestListener`. Cara kerja callback ini hampir sama dengan ketika kita menekan tombol button html yang mempunyai atribut event `onclick`, jika ditekan maka fungsi yang teregistrasi oleh event `onclick` yaitu `clickHandler(event)` akan dijalankan. 35 | 36 | [`onclick-button.html`](https://raw.github.com/idjs/belajar-nodejs/gh-pages/code/onclick-button.html) 37 | 38 | ```text 39 | 44 | 45 | 46 | ``` 47 | 48 | Sama halnya dengan callback `requestListener` pada object `server` ini jika ada request maka `requestListener` akan dijalankan 49 | 50 | ```text 51 | function(req, res){ 52 | var body = "
Haruskah belajar Node.js?

...Yo Mesto!

" 53 | res.writeHead(200, { 54 | 'Content-Length':body.length, 55 | 'Content-Type':'text/html', 56 | 'Pesan-Header':'Pengenalan Node.js' 57 | }); 58 | 59 | res.write(body); 60 | res.end(); 61 | } 62 | ``` 63 | 64 | Paket http Node.js memberikan keleluasan bagi developer untuk membangun server tingkat rendah. Bahkan mudah saja kalau harus men-setting nilai field header dari [HTTP](http://en.wikipedia.org/wiki/List_of_HTTP_header_fields). 65 | 66 | Seperti pada contoh diatas agar respon dari request diperlakukan sebagai HTML oleh browser maka nilai field `Content-Type` harus berupa `text/html`. Setting ini bisa dilakukan melalui metode [`writeHead()`](http://nodejs.org/api/http.html#http_response_writehead_statuscode_reasonphrase_headers), `res.setHeader(field, value)` dan beberapa metode lainnya. 67 | 68 | Untuk membaca header bisa dipakai fungsi seperti `res.getHeader(field, value)` dan untuk menghapus field header tertentu dengan memakai fungsi `res.removeHeader(field)`. Perlu diingat bahwa setting header dilakukan sebelum fungsi `res.write()` atau `res.end()` di jalankan karena jika `res.write()` dijalankan tetapi kemudian ada perubahan field header maka perubahan ini akan diabaikan. 69 | 70 | Satu hal lagi yaitu tentang [kode status dari respon HTTP](http://en.wikipedia.org/wiki/List_of_HTTP_status_codes). Kode status ini bisa disetting selain 200 \(request http sukses\), misalnya bila diperlukan halaman error dengan kode status 404. 71 | 72 | -------------------------------------------------------------------------------- /server_http_dasar/menjalankan_server.md: -------------------------------------------------------------------------------- 1 | # Menjalankan Server 2 | 3 | Untuk menjalankan server Node.js ketik perintah berikut di terminal 4 | 5 | ```text 6 | $ node server-http.js 7 | Port 3400 : Node.js Server... 8 | ``` 9 | 10 | Buka browser \(chrome\) dan buka url `http://localhost:3400` kemudian ketik `CTRL+SHIFT+I` untuk membuka Chrome Dev Tool, dengan tool ini bisa dilihat respon header dari HTTP dimana beberapa fieldnya telah diset sebelumnya \(lingkaran merah pada screenshot dibawah ini\). 11 | 12 | ![server-response-dev-tool](../.gitbook/assets/server-response-dev-tool.png) 13 | 14 | -------------------------------------------------------------------------------- /testing/README.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | 3 | Perangkat lunak tidak ada yang sempurna dan pasti mempunyai _bugs_. Salah satu cara untuk menguranginya atau mencegahnya untuk muncul di kemudian hari adalah dengan jalan melakukan pengetesan. Pengetesan memberikan keyakinan pada developer bahwa perangkat lunak bekerja sebagai mana mestinya dan jika ada perubahan misalnya penambahan atau pengurangan fitur dipastikan bahwa pengetesan akan selalu berhasil. 4 | 5 | Ada banyak tipe pengetesan tetapi dalam pengembangan aplikasi web ada dua tipe pengetesan yang penting untuk diketahui yaitu **Unit Testing** dan **Acceptance Testing**. 6 | 7 | ## Unit Testing 8 | 9 | **Unit Testing** dilakukan langsung pada level kode aplikasi yaitu pada fungsi atau metode dan ada dua metodologi yang sering digunakan yaitu **TDD** dan **BDD**. Dalam JavaScript tersedia banyak pustaka yang dibuat untuk pengetesan seperti module `assert` bawaan dari Node.js, Nodeunit, Mocha, Jasmine dll. 10 | 11 | ### Test Driven Development \(TDD\) 12 | 13 | Istilah TDD ini menjadi sangat keren beberapa tahun belakangan ini. Konsep TDD adalah melakukan pengetesan terlebih dahulu baru kemudian menulis kode dari aplikasi, jadi mindset dari pembuatan perangkat lunak dibalik kalo dalam pengembangan perangkat lunak yang konvensional alurnya yaitu menulis kode terlebih dahulu baru kemudian menulis kode untuk pengetesan sedangkan dalam **Test Driven Development** proses ini dibalik. 14 | 15 | Kelemahan pengetesan ini adalah pada proses awal biasanya dibutuhkan waktu yang relatif lebih lama untuk mengembangkan aplikasi karena harus menulis kode pengetesan terlebih dahulu tetapi keuntungan jangka panjangnya yaitu aplikasi yang dihasilkan biasanya mempunyai _bugs_ yang lebih sedikit. 16 | 17 | ### Behavior Driven Development \(BDD\) 18 | 19 | Pengetesan secara BDD memakai bahasa atau metode pengetesan yang lebih ramah yaitu dengan melakukan pengetesan dengan cara atau alur seperti **user story** sehingga pengetesan ini relatif lebih populer karena secara bahasa menjembatani atau memungkinkan kolaborasi antara developer dan klien. Ada banyak pustaka pengetesan yang memakai BDD seperti Mocha, Jasmin, Vows dll. Sebagai gambaran contoh untuk pustaka Mocha misalnya 20 | 21 | ```text 22 | describe('Upload file', function(){ 23 | it('Harus bisa menerima file jpeg', function(){ 24 | //testing disini 25 | }) 26 | 27 | it('Harus bisa menerima file png', function(){ 28 | //testing disini 29 | }) 30 | 31 | it('Harus bisa menerima file xcf', function(){ 32 | //testing disini 33 | }) 34 | }) 35 | ``` 36 | 37 | Kalau diterjemahkan secara bahasa manusia maka kode testing BDD diatas akan mudah dibaca yaitu _Upload file harus bisa menerima file jpeg, png atau xcf_. 38 | 39 | ## Acceptance Testing 40 | 41 | Untuk pengetesan dari antar muka aplikasi web beserta fungsinya contohnya seperti pengetesan penekanan button apakah berfungsi dengan baik atau tidak adalah termasuk dari **Acceptance Testing**. Testing ini bisa dilakukan dengan memakai bantuan browser dan dengan munculnya _headless browser_ seperti PhantomJS memungkinkan pengetesan dilakukan secara terintegrasi dengan kode _back-end_. 42 | 43 | > Catatan penting dari testing adalah pengetesan diusahakan berjalan secara automatis sehingga jika ada kesalahan yang terjadi maka developer bisa segera memperbaikinya, maka dari itu testing pasti mempunyai yang namanya info laporan entah itu berupa file, output terminal atau antarmuka berupa web. Pada proses pengembangan perangkat lunak modern, automasi testing merupakan bagian yang sangat penting. 44 | 45 | Dalam buku ini pengetesan akan dibatasi pada pengetesan aplikasi web khususnya aplikasi Node.js dengan REST dengan memakai Mocha. 46 | 47 | -------------------------------------------------------------------------------- /testing/automasi.md: -------------------------------------------------------------------------------- 1 | # Automasi 2 | 3 | Dalam prakteknya biasanya testing ini dilakukan secara otomatis misalnya jika anda memakai Github dalam pengembangan perangkat lunak open source maka anda bisa memakai server **Travis** yang dengan setting konfigurasi tertentu akan menjalankan pengetesan jika anda menge-_push_ kode ke repository Github atau anda bisa memakai _build server_ yang ada diluaran seperti **Jenkins**, **Bamboo**, **TeamCity** dll. 4 | 5 | ## Travis 6 | 7 | Jika anda memakai Github dan menggunanakan Travis maka secara default server travis ini akan menjalankan command 8 | 9 | ```text 10 | $ npm test 11 | ``` 12 | 13 | sehingga dalam package.json yang anda push ke Github anda perlu menulis script untuk pengetesan misalnya jika memakai Mocha 14 | 15 | ```text 16 | "scripts": { 17 | "test": "mocha" 18 | } 19 | ``` 20 | 21 | ### .travis.yml 22 | 23 | Untuk setting Travis anda cukup membuat file **.travis.yml** pada folder projek misalnya seperti dibawah ini \(contoh source code projek test ada di [sini](https://github.com/junwatu/testing-learn)\) 24 | 25 | ```text 26 | . 27 | ├── app.js 28 | ├── .travis.yml 29 | ├── node_modules 30 | ├── package.json 31 | └── test 32 | └── app.test.js 33 | ``` 34 | 35 | Dengan isi file tersebut adalah versi dari Node.js dimana test akan dijalankan. Misalnya untuk menjalankan pengetesan Node.js versi 4.1 dan 4.0 36 | 37 | ```text 38 | language: node_js 39 | node_js: 40 | - "4.1" 41 | - "4.0" 42 | ``` 43 | 44 | Kemudian anda perlu mengatur konfigurasi repo di Github \([Testing Learn](https://github.com/junwatu/testing-learn)\). Supaya Github bisa memakai service dari Travis maka anda perlu meengubah konfigurasi repo \(Masuk ke menu **Settings**\) 45 | 46 | ![](../.gitbook/assets/github-service.png) 47 | 48 | ### Enable Build 49 | 50 | Supaya build selalu dijalankan oleh Travis maka anda harus meng-**ON**-kan tombol enable di [travis-ci.org](https://travis-ci.org) pada repo yang anda inginkan. 51 | 52 | ![](../.gitbook/assets/enable.png) 53 | 54 | ### Test Build 55 | 56 | Build akan dijalankan oleh Travis setiap ada kode baru di Github atau anda bisa menggunakan tombol **Test Service** pada **Settings** -> **Webhooks & services** untuk **force build**. 57 | 58 | ![](../.gitbook/assets/testing-ci.png) 59 | 60 | ### Notifikasi 61 | 62 | Notifikasi Travis bisa di integrasikan dengan Slack, Email, dll atau biasanya dengan gambar status di README repo. Untuk konfigurasi gambar status klik tombol **Build/Passing** di sebelah nama repo di Travis dan _copy paste_ ke README repo di Github. 63 | 64 | ![](../.gitbook/assets/image-build.png) 65 | 66 | Sehingga jika anda membuka repo di Github maka akan muncul gambar status yang apakah build sukses atau dalam status error. 67 | 68 | ![](../.gitbook/assets/notif.png) 69 | 70 | -------------------------------------------------------------------------------- /testing/rest_testing.md: -------------------------------------------------------------------------------- 1 | # REST 2 | 3 | Kita ambil contoh server yang dibuat dengan ExpressJS. Server dibawah ini akan mengeluarkan data berupa JSON pada URL `/`. 4 | 5 | ```text 6 | var express = require('express') 7 | var app = express() 8 | 9 | app.get('/', function (req, res) { 10 | res.json({ 11 | message: 'hello' 12 | }) 13 | }) 14 | 15 | module.exports = app 16 | ``` 17 | 18 | Lalu bagaimana cara mengetest URL `/` diatas? dengan memakai Mocha, module `assert` dan modul [Supertest](https://github.com/visionmedia/supertest) yaitu modul npm yang khusus untuk mengetest server HTTP. Mocha termasuk pustaka pengetesan yang bisa dipakai secara BDD ataupun TDD. Pustaka ini secara default memakai style BDD dan metode yang yang biasa dipakai adalah `describe` & `it`. 19 | 20 | ```text 21 | var mocha = require('mocha') 22 | var request = require('supertest') 23 | var assert = require('assert') 24 | var app = require('../app') 25 | 26 | describe('Test REST API', function(){ 27 | describe('GET /', function(){ 28 | it('should return json with key "message" and value "hello"', function(done){ 29 | request(app).get('/') 30 | .set('Accept', 'application/json') 31 | .expect('Content-Type', /json/) 32 | .expect(200) 33 | .expect(function(res){ 34 | assert.equal(res.body.message, 'hello') 35 | }) 36 | .end(function(err, res){ 37 | if(err) return done(err) 38 | done() 39 | }) 40 | }) 41 | }) 42 | }) 43 | ``` 44 | 45 | Perlu anda ingat bahwa supertest akan secara otomatis menjalankan server ExpressJS dan mengalokasikan port sehingga anda tidak perlu mejalankan server secara langsung. 46 | 47 | ```text 48 | request(app) 49 | ``` 50 | 51 | Kalau diterjemahkan dalam bahasa manusia kode diatas akan mengetest beberapa kondisi yaitu 52 | 53 | ```text 54 | expect('Content-Type', /json/) 55 | ``` 56 | 57 | kode diatas artinya diharapkan response dari GET untuk URL `/` adalah bertipe `json` 58 | 59 | ```text 60 | expect(200) 61 | ``` 62 | 63 | kode diatas artinya **response code** dari request HTTP harus mempunyai kode 200. 64 | 65 | ```text 66 | expect(function(res){ 67 | assert.equal(res.body.message, 'hello') 68 | }) 69 | ``` 70 | 71 | dan kode diatas artinya diharapkan bahwa **response body** dengan field `message` mempunyai value `hello` dan tentu saja anda bisa menambahkan banyak kondisi untuk pengetesan yang lebih detil. 72 | 73 | Untuk melakukan pengetesan cukup dengan menginstal dan jalankan `mocha` maka secara otomatis mocha akan menjalankan berkas berkas pengetesan yang berada pada folder `test`. 74 | 75 | ```text 76 | $ npm install -g mocha 77 | ``` 78 | 79 | ![](../.gitbook/assets/testing-mocha.png) 80 | 81 | Sebenarnya banyak yang bisa dijelaskan tentang pengetesan dan sudah banyak resource online diluar sana yang membahas tentang ini tapi yang perlu anda ingat adalah pastikan pengetesan dimasukkan dalam alur kerja dalam pengembangan perangkat lunak yang sedang anda kerjakan. 82 | 83 | -------------------------------------------------------------------------------- /todatauri/README.md: -------------------------------------------------------------------------------- 1 | # To Data URI 2 | 3 | Aplikasi ini adalah aplikasi Node.js CLI yang mengubah gambar png ke format data URI dan kemudian menyimpan data tersebut ke database MySQL. Proses ini bisa digambarkan seperti gambar alur dibawah ini. 4 | 5 | ![todatauri flow diagram](../.gitbook/assets/todatauri.png) 6 | 7 | ## Data URI 8 | 9 | Bagi yang belum tahu [Data URI](http://en.wikipedia.org/wiki/Data_URI_scheme) adalah salah satu cara untuk meng-embed data secara inline alih-alih harus mengambil data tersebut dari resource luar. Data yang akan diubah ke Data URI disini bisa berupa image, file csv dll. Untuk aplikasi ini hanya dibatasi untuk gambar berformat png. 10 | 11 | Format Data URI adalah seperti berikut ini 12 | 13 | ```text 14 | data:[][;charset=][;base64], 15 | ``` 16 | 17 | Umumnya untuk gambar jenis encoding yang dipakai adalah `base64`. Sebagai contohnya lihat format gambar png yang telah dirubah ke Data URI berikut ini 18 | 19 | ```text 20 | data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFgAAAAfCAMAAABUFvrSAAAABGdBTUEAANjr9RwUqgAAACBjSFJNAABtmAAAc44AAPXqAACD0AAAfHIAAN7iAAAyWgAAI0zujJoVAAADAFBMVEXW1tYxLS6EgYKtrKy7uro/OzxoZWZMSUrk5OR2c3SfnZ7y8vJaV1iRj5DJyMgjHyD///8RERESEhITExMUFBQVFRUWFhYXFxcYGBgZGRkaGhobGxscHBwdHR0eHh4fHx8gICAhISEiIiIjIyMkJCQlJSUmJiYnJycoKCgpKSkqKiorKyssLCwtLS0uLi4vLy8wMDAxMTEyMjIzMzM0NDQ1NTU2NjY3Nzc4ODg5OTk6Ojo7Ozs8PDw9PT0+Pj4/Pz9AQEBBQUFCQkJDQ0NERERFRUVGRkZHR0dISEhJSUlKSkpLS0tMTExNTU1OTk5PT09QUFBRUVFSUlJTU1NUVFRVVVVWVlZXV1dYWFhZWVlaWlpbW1tcXFxdXV1eXl5fX19gYGBhYWFiYmJjY2NkZGRlZWVmZmZnZ2doaGhpaWlqampra2tsbGxtbW1ubm5vb29wcHBxcXFycnJzc3N0dHR1dXV2dnZ3d3d4eHh5eXl6enp7e3t8fHx9fX1+fn5/f3+AgICBgYGCgoKDg4OEhISFhYWGhoaHh4eIiIiJiYmKioqLi4uMjIyNjY2Ojo6Pj4+QkJCRkZGSkpKTk5OUlJSVlZWWlpaXl5eYmJiZmZmampqbm5ucnJydnZ2enp6fn5+goKChoaGioqKjo6OkpKSlpaWmpqanp6eoqKipqamqqqqrq6usrKytra2urq6vr6+wsLCxsbGysrKzs7O0tLS1tbW2tra3t7e4uLi5ubm6urq7u7u8vLy9vb2+vr6/v7/AwMDBwcHCwsLDw8PExMTFxcXGxsbHx8fIyMjJycnKysrLy8vMzMzNzc3Ozs7Pz8/Q0NDR0dHS0tLT09PU1NTV1dXW1tbX19fY2NjZ2dna2trb29vc3Nzd3d3e3t7f39/g4ODh4eHi4uLj4+Pk5OTl5eXm5ubn5+fo6Ojp6enq6urr6+vs7Ozt7e3u7u7v7+/w8PDx8fHy8vLz8/P09PT19fX29vb39/f4+Pj5+fn6+vr7+/v8/Pz9/f3+/v7///8EKbe0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAB/0lEQVRIx62W2W7sIBBE2Rf3UvX/X5sHYyczyb2eGRnJEjZw6C4KTOD7pQAtXHUKH4AthRabldvBIQZmm7GHm8HcOiVTErabweyF6mSJ82bwNjl2Uexe8IiyVxzlVjDnoYEdU9wEFoxVqdut4FFPU9dbwTmdscf8Cjj/6BXOwUzP85vxWLXZXwGbSRAnGQZdJZBOuqhzBJLBz34jLvL42xi/wB5T69JTS66uJEZPKXpLSaWntBR1LdAj5JjlFbCS2BLpC2yJ1C2qxtx6OzwQm9YVqWway4vgolKmq1dxZJVRcx9issmoa0CJW+hnoF7n5eKFRCqzzhASTbMya5rBWyssTX+69nt1pfR2j93W4KWAIWq6AAc/8nN/45diVxpPIO6btQMPBpWGvZjMvRKNtojl96H/9K7A3jcDwM+WhGhmZuYJmGaWgHKAKVblAtwQhWRFBTg8kKS4U890dTlYYfatwbALcInIpAMZoO0MB9jQ3d3/CeaVFG6opEL9ERzqrmz6GDywP09gMrh7BvxTMCfaROcvMElygZM2eQDnZyP/AQ4AkBe4urtvAIO7uxvgEzGXiB6RDTW7u7so4iWYCtQ9TNFlXvCopVNtdDnbvdX6X3BwIcWL7B4j5THifV8Gd/eJGMixPouPd84K3/dEfc5zv1yYyac3IVuZtvfPqi9DYJrPLQNESAAAAABJRU5ErkJggg== 21 | ``` 22 | 23 | Cukup panjang memang kalo di jadikan ke format Data URI. Coba kopi contoh data uri diatas dan _paste_ ke browser url dan jangan lupa tekan enter. 24 | 25 | -------------------------------------------------------------------------------- /todatauri/koneksi_mysql.md: -------------------------------------------------------------------------------- 1 | # Koneksi MySQL 2 | 3 | Untuk koneksi ke database MySQL cukup mudah seperti yang telah dibahas pada bab sebelumnya tentang Node dan Database MySQL. 4 | 5 | ```text 6 | /** 7 | * todatauri.js dengan Mysql 8 | * 9 | * 10 | * WTFPL 11 | * Equan Pr. 12 | * 2015 13 | */ 14 | var Util = require('./todatauri.js'); 15 | var mysql = require('mysql'); 16 | 17 | var connection = mysql.createConnection({ 18 | host: 'localhost', 19 | user: 'root', 20 | password: '' 21 | }); 22 | 23 | connection.connect(function (err) { 24 | if (err) { 25 | console.log(err); 26 | } else { 27 | console.log('Koneksi MySQL dengan id ' + connection.threadId); 28 | } 29 | }); 30 | 31 | var create_database = 'CREATE DATABASE IF NOT EXISTS data_uri '; 32 | var create_table = "CREATE TABLE IF NOT EXISTS data_uri.images (id INT AUTO_INCREMENT PRIMARY KEY, data TEXT)"; 33 | 34 | connection.query(create_database, function (err, res) { 35 | if (err) { 36 | console.log(err); 37 | } else { 38 | console.log('Create database data_uri [ok]'); 39 | 40 | connection.query(create_table, function (err, result) { 41 | if (err) { 42 | console.error(err); 43 | } else { 44 | console.log('Create table images [ok]'); 45 | main(process); 46 | } 47 | }) 48 | } 49 | }); 50 | 51 | function insertData(data, connection) { 52 | connection.query('INSERT INTO data_uri.images SET ?', { data: data }, function (err, res) { 53 | if(err) { 54 | console.log(err); 55 | } else { 56 | console.log(res); 57 | closeConnection(); 58 | } 59 | }) 60 | }; 61 | 62 | function showData(connection) { 63 | connection.query('SELECT * FROM data_uri.images', function(err, result){ 64 | if(err) { 65 | console.log(err); 66 | } else { 67 | console.log('\n\nMySQL Database\n============================\n'); 68 | result.forEach(function(element, index){ 69 | 70 | console.log('id \u2192', element.id); 71 | console.log('image \u2192', element.data); 72 | }); 73 | 74 | closeConnection(); 75 | } 76 | }) 77 | } 78 | 79 | function main(process) { 80 | if (process.argv[2]) { 81 | if (process.argv[2].toLowerCase().trim() == 'show') { 82 | showData(connection); 83 | } else { 84 | Util.toDataURI(process.argv[2], function (err, data) { 85 | if (!err) { 86 | insertData(data, connection); 87 | } 88 | }) 89 | } 90 | } else { 91 | Util.toDataURI(null, function (err, data) { 92 | if (!err) { 93 | console.log(data); 94 | closeConnection(); 95 | } 96 | }); 97 | } 98 | } 99 | 100 | function closeConnection(){ 101 | connection.end(function(err){ 102 | if(err) { 103 | console.log(err); 104 | } 105 | }); 106 | } 107 | ``` 108 | 109 | Parsing argumen dilakukan oleh `process` yang merupakan object global di [Node.js](http://nodejs.org/api/process.html). Perlu diingat bahwa JavaScript memulai array dengan index 0 sehingga argumen yang diperlukan berada pada index 2 110 | 111 | ```text 112 | process.argv[2] 113 | ``` 114 | 115 | Jika anda berada pada platform UNIX atau GNU LINUX script diatas bisa dirubah untuk `self executable` dengan menambahkan script berikut pada line 1 di file `tdi.js` 116 | 117 | ```text 118 | #!/usr/bin/env node 119 | ``` 120 | 121 | Kemudian untuk menjalankannya cukup mudah seperti berikut 122 | 123 | ```text 124 | $ ./tdi.js 125 | ``` 126 | 127 | Script `tdi.js` sebenarnya cukup sederhana dan cukup untuk melakukan tugas yang di inginkan. Mungkin kelihatan agak rumit karena banyak `callback` di sana sini tetapi kalau anda sudah terbiasa memprogram secara asinkron pasti mudah sekali untuk melihat kode diatas. 128 | 129 | Penulis sarankan untuk ke depannya jika diinginkan penulisan tanpa `callback` bisa dipelajari tentang `Promises` JavaScript ES6. 130 | 131 | -------------------------------------------------------------------------------- /todatauri/konverter_gambar_png_ke_data_uri.md: -------------------------------------------------------------------------------- 1 | # todatauri.js 2 | 3 | Mari kita lihat isi dari file `todatauri.js`. Pada dasarnya file ini merupakan pustaka sederhana yang akan mendownload image berformat `.png` di internet dan kemudian mengubahnya menjadi format **Data URI**. 4 | 5 | Jadi anda bisa menggunakan pustaka ini seperti halnya modul npm dengan bantuan `require`. 6 | 7 | ```text 8 | /** 9 | * todatauri.js 10 | * Download image and convert it to Data URI 11 | * 12 | * WTFPL 13 | * (c) 2015, Equan Pr. 14 | */ 15 | var fs = require('fs'); 16 | var http = require('http'); 17 | var https = require('https'); 18 | var url = require('url'); 19 | 20 | function Util() { 21 | 22 | var defaultImage = 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Node.js_logo.svg/320px-Node.js_logo.svg.png'; 23 | var imageDest = 'download.png'; 24 | var file; 25 | 26 | return { 27 | toDataURI: function(urlArg, cb) { 28 | var imageURL; 29 | urlArg ? imageURL = urlArg : imageURL = defaultImage; 30 | if(url.parse(imageURL).protocol === 'https:') { 31 | Util().httpsGetImage(imageURL, function(err, data){ 32 | err ? cb(err,null): cb(null, data); 33 | }) ; 34 | } else { 35 | Util().httpGetImage(imageURL, function(err, data){ 36 | err ? cb(err, null): cb(null, data); 37 | }); 38 | } 39 | }, 40 | 41 | httpGetImage: function(url, cb) { 42 | file = fs.createWriteStream(imageDest); 43 | 44 | http.get(url, function(response) { 45 | response.pipe(file); 46 | 47 | console.log('Download node.js defaultImage from', defaultImage); 48 | console.log('\n'); 49 | 50 | file.on('finish', function() { 51 | file.close(); 52 | Util().imageToDataUri(imageDest, function(err, data) { 53 | err ? cb(err, null) : cb(null,data); 54 | }); 55 | }); 56 | }) 57 | }, 58 | 59 | httpsGetImage: function(url, cb) { 60 | file = fs.createWriteStream(imageDest); 61 | 62 | https.get(url, function(response) { 63 | response.pipe(file); 64 | 65 | console.log('Download node.js defaultImage from', defaultImage); 66 | console.log('\n'); 67 | 68 | file.on('finish', function() { 69 | file.close(); 70 | Util().imageToDataUri(imageDest, function(err, data) { 71 | err ? cb(err, null) : cb(null,data); 72 | }); 73 | }); 74 | }) 75 | }, 76 | 77 | imageToDataUri: function(imageName, cb) { 78 | //TODO: lookup mime type here 79 | var mime = 'image/png'; 80 | var encoding = 'base64'; 81 | 82 | var uri = 'data:' + mime + ';' + encoding + ','; 83 | 84 | fs.readFile(imageName, function(err, buf) { 85 | if (err) return cb(err, null); 86 | cb(null, uri + buf.toString(encoding)); 87 | }) 88 | } 89 | } 90 | } 91 | 92 | module.exports = Util(); 93 | ``` 94 | 95 | Fungsi utama pada file `todatauri.js` yaitu fungsi `imageToDataUri()` dan jika dilihat isinya maka sebenarnya sangat sederhana untuk mengubah gambar png ke encoding `base64` yang akan digunakan di Data URI. 96 | 97 | ```text 98 | buf.toString(encoding)) 99 | ``` 100 | 101 | [`fs.readFile(filename[, options], callback)`](https://nodejs.org/api/fs.html#fs_fs_readfile_filename_options_callback) merupakan fungsi untuk membaca file secara asinkron dan jika encoding tidak di berikan maka hasil pembacaan file akan mengembalikan data berupa `buffer`. Sehingga untuk mengubah data `buffer` ini ke `base64` cukup dengan memakai metode `.toString(encoding)`. 102 | 103 | -------------------------------------------------------------------------------- /todatauri/penggunaan.md: -------------------------------------------------------------------------------- 1 | # Penggunaan 2 | 3 | Untuk kode sumber selengkapnya bisa di lihat di [Github](https://github.com/junwatu/todatauri) pada branch `todatauri-mysql` atau ketik perintah berikut pada command line. 4 | 5 | ```text 6 | $ git clone -b todatauri-mysql https://github.com/junwatu/todatauri todatauri-mysql 7 | 8 | $ cd todatauri-mysql 9 | 10 | $ npm install 11 | ``` 12 | 13 | Ada tiga penggunaan aplikasi ini yaitu 14 | 15 | ## Download PNG & Simpan Ke MySQL 16 | 17 | ```text 18 | $ node ./tdi.js 19 | ``` 20 | 21 | Aplikasi ini akan mendownload file image png dari internet dan mendukung protokol `http` ataupun `https`. 22 | 23 | ## Demo 24 | 25 | ```text 26 | $ node ./tdi.js 27 | ``` 28 | 29 | Jika dijalankan tanpa argumen maka hasilnya adalah keluaran demo yang tidak lain adalah contoh format Data URI. 30 | 31 | ## Tampilkan Data MySQL 32 | 33 | ```text 34 | $ node ./tdi.js show 35 | ``` 36 | 37 | Jika ada argumen `show` maka data dalam MySQL akan ditampilkan semua. Hati hati jika anda banyak mengkonversi banyak data gambar png. 38 | 39 | --------------------------------------------------------------------------------