├── .gitattributes ├── .gitignore ├── Chapter01 ├── 01_arrow_function │ ├── 01.js │ ├── 02.js │ ├── 03.js │ ├── 04.js │ ├── 05.js │ ├── 06.js │ └── README.txt ├── 02_let_const │ ├── 01.js │ ├── 02.js │ ├── 03.js │ ├── 04.js │ ├── 05.js │ └── README.txt ├── 03_class │ ├── 01.js │ ├── 02.js │ ├── 03.js │ └── README.txt ├── 04_enhanced_object_literals │ ├── 01.js │ ├── 02.js │ ├── 03.js │ ├── 04.js │ └── README.txt ├── 05_map_set │ ├── 01.js │ ├── 02.js │ ├── 03.js │ └── README.txt ├── 06_weakmap_weakset │ ├── 01.js │ ├── 02.js │ └── README.txt └── 07_template │ ├── 01.js │ └── README.txt ├── Chapter02 ├── 01_callback_sync_cont_passing │ ├── README.txt │ └── test.js ├── 02_callback_async_cont_passing │ ├── README.txt │ └── test.js ├── 03_callback_non_cont_passing │ ├── README.txt │ └── test.js ├── 04_callback_unpredictable │ ├── README.txt │ ├── data.txt │ └── test.js ├── 05_callback_sync_api │ ├── README.txt │ ├── data.txt │ └── test.js ├── 06_callback_deferred_execution │ ├── README.txt │ ├── data.txt │ └── test.js ├── 07_callback_propagating_errors │ ├── README.txt │ ├── data.txt │ ├── invalid_json.json │ ├── readJSON.js │ └── valid_json.json ├── 08_module_examples │ ├── README.txt │ ├── logger_class.js │ ├── logger_class_test.js │ ├── logger_constructor.js │ ├── logger_constructor_test.js │ ├── logger_function.js │ ├── logger_function_test.js │ ├── logger_guard.js │ ├── logger_guard_es2015.js │ ├── logger_guard_es2015_test.js │ ├── logger_guard_test.js │ ├── logger_instance.js │ └── logger_instance_test.js ├── 09_module_revealing_module │ ├── README.txt │ └── test.js ├── 10_module_loader │ ├── README.txt │ ├── loader.js │ ├── main.js │ ├── moduleA.js │ └── moduleB.js ├── 11_module_circular_dependency │ ├── README.txt │ ├── a.js │ ├── b.js │ └── main.js ├── 12_observer_event_emitter_find_pattern │ ├── README.txt │ ├── fileA.txt │ ├── fileB.json │ └── main.js ├── 13_observer_event_emitter_find_pattern_class │ ├── README │ ├── fileA.txt │ ├── fileB.json │ └── main.js ├── 14_observer_sync_emit │ ├── README.txt │ └── test.js ├── 15_observer_emitter_vs_callback │ ├── README.txt │ └── test.js └── 16_observer_event_emitter_glob │ ├── README.txt │ ├── data │ ├── file1.txt │ ├── file2.txt │ └── file3.txt │ ├── main.js │ └── package.json ├── Chapter03 ├── 01_web_spider │ ├── README.txt │ ├── index.js │ ├── package.json │ └── utilities.js ├── 02_web_spider_functions │ ├── README.txt │ ├── index.js │ ├── package.json │ └── utilities.js ├── 03_sequential_callbacks │ ├── README.txt │ └── test.js ├── 04_web_spider_v2 │ ├── README.txt │ ├── index.js │ ├── package.json │ └── utilities.js ├── 05_web_spider_v3 │ ├── README.txt │ ├── index.js │ ├── package.json │ └── utilities.js ├── 06_web_spider_v4 │ ├── README.txt │ ├── index.js │ ├── package.json │ ├── taskQueue.js │ └── utilities.js ├── 07_async_sequential_execution │ ├── README.txt │ ├── index.js │ ├── package.json │ └── utilities.js ├── 08_async_sequential_iteration │ ├── README.txt │ ├── index.js │ ├── package.json │ └── utilities.js ├── 09_async_parallel_execution │ ├── README.txt │ ├── index.js │ ├── package.json │ └── utilities.js └── 10_async_limited_parallel_execution │ ├── README.txt │ ├── index.js │ ├── package.json │ └── utilities.js ├── Chapter04 ├── 01_promisify │ ├── README.txt │ ├── promisify.js │ └── test.js ├── 02_promises_sequential_execution │ ├── README.txt │ ├── index.js │ ├── package.json │ └── utilities.js ├── 03_promises_parallel_execution │ ├── README.txt │ ├── index.js │ ├── package.json │ └── utilities.js ├── 04_promises_limited_parallel_execution │ ├── README.txt │ ├── index.js │ ├── package.json │ ├── taskQueue.js │ └── utilities.js ├── 05_exposing_callback_and_promises │ ├── README.txt │ ├── index.js │ └── test.js ├── 06_generators_simple │ ├── README.txt │ └── index.js ├── 07_generators_iterators │ ├── README.txt │ └── index.js ├── 08_generators_passing_values │ ├── README.txt │ └── index.js ├── 09_generators_passing_errors │ ├── README.txt │ └── index.js ├── 10_generators_async_flow │ ├── README.txt │ └── clone.js ├── 11_generators_async_flow_thunks │ ├── README.txt │ └── clone.js ├── 12_generators_sequential_execution │ ├── README.txt │ ├── index.js │ ├── package.json │ └── utilities.js ├── 13_generators_parallel_execution_a │ ├── README.txt │ ├── index.js │ ├── package.json │ └── utilities.js ├── 14_generators_parallel_execution_b │ ├── README.txt │ ├── index.js │ ├── package.json │ └── utilities.js ├── 15_generators_limited_parallel │ ├── README.txt │ ├── index.js │ ├── package.json │ ├── taskQueue.js │ └── utilities.js └── 16_async_await │ ├── README.txt │ ├── index.es5.js │ ├── index.js │ └── package.json ├── Chapter05 ├── 01_gzip_buffer │ ├── README.txt │ └── index.js ├── 02_gzip_streams │ ├── README.txt │ └── index.js ├── 03_gzip_server │ ├── README.txt │ ├── gzipReceive.js │ └── gzipSend.js ├── 04_gzip_crypto_server │ ├── README.txt │ ├── gzipReceive.js │ └── gzipSend.js ├── 05_streams_flowing │ ├── README.txt │ └── readStdin.js ├── 06_streams_flowing │ ├── README.txt │ └── readStdin.js ├── 07_streams_readable │ ├── README.txt │ ├── generateRandom.js │ ├── package.json │ └── randomStream.js ├── 08_streams_writable │ ├── README.txt │ ├── entropyServer.js │ └── package.json ├── 09_streams_writable_back_pressure │ ├── README.txt │ ├── entropyServer.js │ └── package.json ├── 10_streams_writable_implement │ ├── README.txt │ ├── package.json │ ├── toFileStream.js │ └── writeToFile.js ├── 11_streams_transform │ ├── README.txt │ ├── replaceStream.js │ └── replaceStreamTest.js ├── 12_streams_transform_pipes │ ├── README.txt │ ├── replace.js │ └── replaceStream.js ├── 13_streams_sequential_execution │ ├── README.txt │ ├── concat.js │ ├── concatFiles.js │ ├── package.json │ ├── part1.txt │ ├── part2.txt │ └── part3.txt ├── 14_streams_unordered_parallel_execution │ ├── README.txt │ ├── checkUrls.js │ ├── package.json │ ├── parallelStream.js │ └── urlList.txt ├── 15_streams_unordered_limited_parallel_execution │ ├── README.txt │ ├── checkUrls.js │ ├── limitedParallelStream.js │ ├── package.json │ └── urlList.txt ├── 16_streams_ordered_parallel_execution │ ├── README.txt │ ├── checkUrls.js │ ├── package.json │ └── urlList.txt ├── 17_streams_combined_a │ ├── README.txt │ ├── archive.js │ ├── combinedStreams.js │ └── package.json ├── 18_streams_combined_b │ ├── README.txt │ ├── archive.js │ ├── combinedStreams.js │ └── package.json ├── 19_streams_fork │ ├── README.txt │ └── generateHashes.js ├── 20_streams_merge │ ├── README.txt │ ├── mergeTar.js │ └── package.json └── 21_streams_mux_demux │ ├── README.txt │ ├── client.js │ ├── generateData.js │ └── server.js ├── Chapter06 ├── 01_factory_simple_a │ ├── README.txt │ ├── factory.js │ └── image.js ├── 02_factory_simple_b │ ├── README.txt │ ├── factory.js │ ├── image.js │ ├── imageGif.js │ ├── imageJpeg.js │ └── imagePng.js ├── 03_factory_encapsulation │ ├── README.txt │ └── createPerson.js ├── 04_factory_profiler │ ├── README.txt │ ├── profiler.js │ └── profilerTest.js ├── 05_factory_composable │ ├── README.txt │ ├── game.js │ └── package.json ├── 06_revealing_constructor │ ├── README.txt │ ├── example.js │ ├── roee.js │ └── ticker.js ├── 07_proxy_a │ ├── README.txt │ ├── createProxy.js │ └── test.js ├── 08_proxy_b │ ├── README.txt │ ├── createProxy.js │ └── test.js ├── 09_proxy_c │ ├── README.txt │ ├── createProxy.js │ └── test.js ├── 10_proxy_logging_writable_stream │ ├── README.txt │ └── loggingWritable.js ├── 11_proxy_es2015 │ ├── README.txt │ └── test.js ├── 11_proxy_es2015_b │ ├── README.txt │ └── test.js ├── 12_decorator_a │ ├── README.txt │ └── decorator.js ├── 13_decorator_b │ ├── README.txt │ └── decorator.js ├── 14_decorator_levelup_plugin │ ├── .gitignore │ ├── README.txt │ ├── levelSubscribe.js │ ├── levelSubscribeTest.js │ └── package.json ├── 15_adapter │ ├── .gitignore │ ├── README.txt │ ├── fsAdapter.js │ ├── package.json │ ├── testFs.js │ └── testFsAdapter.js ├── 16_strategy │ ├── README.txt │ ├── config.js │ ├── configTest.js │ ├── package.json │ ├── samples │ │ ├── conf.ini │ │ └── conf.json │ └── strategies.js ├── 17_state │ ├── README.txt │ ├── client.js │ ├── failsafeSocket.js │ ├── offlineState.js │ ├── onlineState.js │ ├── package.json │ └── server.js ├── 18_template │ ├── README.txt │ ├── configTemplate.js │ ├── configTest.js │ ├── jsonConfig.js │ ├── package.json │ └── samples │ │ └── conf.json ├── 19_middleware_zmq │ ├── README.txt │ ├── client.js │ ├── jsonMiddleware.js │ ├── package.json │ ├── server.js │ └── zmqMiddlewareManager.js ├── 20_middleware_generators │ ├── README.txt │ ├── app.js │ ├── package.json │ └── rateLimit.js └── 21_command │ ├── README.txt │ ├── command.js │ ├── package.json │ └── server.js ├── Chapter07 ├── 01_hard-coded_dependency │ ├── .gitignore │ ├── README.txt │ ├── app.js │ ├── example-db │ │ ├── 000005.ldb │ │ ├── 000008.log │ │ ├── CURRENT │ │ ├── LOCK │ │ ├── LOG │ │ ├── LOG.old │ │ └── MANIFEST-000007 │ ├── lib │ │ ├── authController.js │ │ ├── authService.js │ │ └── db.js │ ├── package.json │ └── populate_db.js ├── 02_di │ ├── .gitignore │ ├── README.txt │ ├── app.js │ ├── lib │ │ ├── authController.js │ │ ├── authService.js │ │ └── db.js │ ├── package.json │ └── populate_db.js ├── 03a_service_locator │ ├── .gitignore │ ├── README.txt │ ├── app.js │ ├── lib │ │ ├── authController.js │ │ ├── authService.js │ │ ├── db.js │ │ └── serviceLocator.js │ ├── package.json │ └── populate_db.js ├── 03b_express_service_locator │ ├── .gitignore │ ├── README.txt │ ├── app.js │ ├── lib │ │ ├── authController.js │ │ ├── authService.js │ │ └── db.js │ ├── package.json │ └── populate_db.js ├── 04_di_container │ ├── .gitignore │ ├── README.txt │ ├── app.js │ ├── lib │ │ ├── authController.js │ │ ├── authService.js │ │ ├── db.js │ │ └── diContainer.js │ ├── package.json │ └── populate_db.js ├── 05_plugin_module_impersonation │ ├── .gitignore │ ├── README.txt │ ├── app.js │ ├── lib │ │ ├── authController.js │ │ ├── authService.js │ │ └── db.js │ ├── node_modules │ │ └── authsrv-plugin-logout │ │ │ └── index.js │ ├── package.json │ └── populate_db.js ├── 06_plugin_service_locator │ ├── .gitignore │ ├── README.txt │ ├── app.js │ ├── lib │ │ ├── authController.js │ │ ├── authService.js │ │ ├── db.js │ │ └── serviceLocator.js │ ├── package.json │ └── populate_db.js ├── 07_plugin_di │ ├── .gitignore │ ├── README.txt │ ├── app.js │ ├── lib │ │ ├── authController.js │ │ ├── authService.js │ │ └── db.js │ ├── package.json │ └── populate_db.js └── 08_plugin_di_container │ ├── .gitignore │ ├── README.txt │ ├── app.js │ ├── lib │ ├── authController.js │ ├── authService.js │ ├── db.js │ └── diContainer.js │ ├── package.json │ └── populate_db.js ├── Chapter08 ├── 01_umd │ ├── README.txt │ ├── package.json │ ├── testBrowser.html │ ├── testServer.js │ └── umdModule.js ├── 02_amd │ ├── README.txt │ ├── package.json │ ├── umdModule.js │ └── using_amd.html ├── 03_webpack │ ├── .gitignore │ ├── README.txt │ ├── magic.html │ ├── main.js │ ├── package.json │ └── sayHello.js ├── 04_webpack_es2015 │ ├── .gitignore │ ├── README.txt │ ├── magic.html │ ├── package.json │ ├── src │ │ ├── main.js │ │ └── sayHello.js │ └── webpack.config.js ├── 05_runtime_code_branching │ ├── .gitignore │ ├── README.txt │ ├── magic.html │ ├── package.json │ ├── src │ │ └── main.js │ └── webpack.config.js ├── 06_buildtime_code_branching │ ├── .gitignore │ ├── README.txt │ ├── magic.html │ ├── package.json │ ├── src │ │ └── main.js │ └── webpack.config.js ├── 07_webpack_define_plugin_dynamic_variables │ ├── .gitignore │ ├── README.txt │ ├── package.json │ ├── src │ │ └── main.js │ └── webpack.config.js ├── 08_buildtime_module_swapping_a │ ├── .gitignore │ ├── README.txt │ ├── magic.html │ ├── package.json │ ├── src │ │ ├── alertBrowser.js │ │ ├── alertServer.js │ │ └── main.js │ └── webpack.config.js ├── 08_buildtime_module_swapping_b │ ├── .gitignore │ ├── README.txt │ ├── dist │ │ └── bundle.js │ ├── magic.html │ ├── package.json │ ├── src │ │ ├── alertBrowser.js │ │ ├── alertServer.js │ │ └── main.js │ └── webpack.config.js ├── 09_react_rendering_browser │ ├── .gitignore │ ├── README.txt │ ├── index.html │ ├── package.json │ ├── src │ │ ├── joyceBooks.js │ │ └── main.js │ └── webpack.config.js ├── 10_react_router │ ├── .gitignore │ ├── README.txt │ ├── index.html │ ├── package.json │ ├── src │ │ ├── components │ │ │ ├── authorsIndex.js │ │ │ ├── joyceBooks.js │ │ │ ├── notFound.js │ │ │ └── wellsBooks.js │ │ ├── main.js │ │ └── routes.js │ └── webpack.config.js ├── 11_react_reusable_components │ ├── .gitignore │ ├── README.txt │ ├── index.html │ ├── package.json │ ├── src │ │ ├── authors.js │ │ ├── components │ │ │ ├── authorPage.js │ │ │ ├── authorsIndex.js │ │ │ └── notFound.js │ │ ├── main.js │ │ └── routes.js │ └── webpack.config.js ├── 12_react_server_side_rendering │ ├── .babelrc │ ├── .gitignore │ ├── README.txt │ ├── package.json │ ├── server.js │ ├── src │ │ ├── authors.js │ │ ├── components │ │ │ ├── authorPage.js │ │ │ ├── authorsIndex.js │ │ │ └── notFound.js │ │ ├── main.js │ │ ├── routes.js │ │ └── routesConfig.js │ ├── views │ │ └── index.ejs │ └── webpack.config.js ├── 13_universal_rendering_and_routing │ ├── .babelrc │ ├── .gitignore │ ├── README.txt │ ├── package.json │ ├── server.js │ ├── src │ │ ├── authors.js │ │ ├── components │ │ │ ├── authorPage.js │ │ │ ├── authorsIndex.js │ │ │ └── notFound.js │ │ ├── main.js │ │ ├── routes.js │ │ └── routesConfig.js │ ├── views │ │ └── index.ejs │ └── webpack.config.js └── 14_universal_data_retrieval │ ├── .babelrc │ ├── .gitignore │ ├── README.txt │ ├── apiServer.js │ ├── package.json │ ├── src │ ├── authors.js │ ├── components │ │ ├── authorPage.js │ │ ├── authorsIndex.js │ │ └── notFound.js │ ├── main.js │ ├── routes.js │ ├── routesConfig.js │ └── xhrClient.js │ ├── views │ └── index.ejs │ ├── webServer.js │ └── webpack.config.js ├── Chapter09 ├── 01_async_init_wrong │ ├── README.txt │ ├── app.js │ ├── asyncModule.js │ └── routes.js ├── 02_async_init_queues │ ├── README.txt │ ├── app.js │ ├── asyncModule.js │ ├── asyncModuleWrapper.js │ └── routes.js ├── 03_batching_and_caching │ ├── .gitignore │ ├── README.txt │ ├── app.js │ ├── appPromises.js │ ├── loadTest.js │ ├── package.json │ ├── populate_db.js │ ├── totalSales.js │ ├── totalSalesBatch.js │ ├── totalSalesCache.js │ └── totalSalesPromises.js └── 04_cpu_bound │ ├── README.txt │ ├── app.js │ ├── processPool.js │ ├── subsetSum.js │ ├── subsetSumDefer.js │ ├── subsetSumFork.js │ └── subsetSumWorker.js ├── Chapter10 ├── 01_cluster │ ├── README.txt │ ├── app.js │ └── clusteredApp.js ├── 02_cluster_resiliency │ ├── README.txt │ ├── app.js │ └── clusteredApp.js ├── 03_cluster_zero_downtime │ ├── README.txt │ ├── app.js │ └── clusteredApp.js ├── 04_reverse_proxy_nginx │ ├── README.txt │ ├── app.js │ └── nginx.patch.conf ├── 05_service_registry │ ├── README.txt │ ├── app.js │ ├── loadBalancer.js │ └── package.json ├── 06_peer2peer_loadbalancing │ ├── README.txt │ ├── app.js │ ├── balancedRequest.js │ └── client.js └── 07_dynamic_peer2peer_loadbalancing │ ├── README.txt │ ├── apiRequest.js │ ├── app.js │ ├── client.js │ └── package.json ├── Chapter11 ├── 01_basic_chat │ ├── README.txt │ ├── app.js │ ├── package.json │ └── www │ │ └── index.html ├── 02_chat_redis │ ├── README.txt │ ├── app.js │ ├── package.json │ └── www │ │ └── index.html ├── 03_chat_zmq │ ├── README │ ├── app.js │ ├── package.json │ └── www │ │ └── index.html ├── 04_durable_sub │ ├── README.txt │ ├── app.js │ ├── historySvc.js │ ├── msgHistory │ │ ├── 000005.ldb │ │ ├── 000006.log │ │ ├── CURRENT │ │ ├── LOCK │ │ ├── LOG │ │ ├── LOG.old │ │ └── MANIFEST-000004 │ ├── package.json │ └── www │ │ └── index.html ├── 05_fanout_fanin │ ├── README.txt │ ├── package.json │ ├── sink.js │ ├── ventilator.js │ └── worker.js ├── 06_competing_consumers │ ├── README.txt │ ├── collector.js │ ├── package.json │ ├── producer.js │ └── worker.js ├── 07_correlation_id │ ├── README.txt │ ├── package.json │ ├── replier.js │ ├── reply.js │ ├── request.js │ └── requestor.js └── 08_return_address │ ├── README.txt │ ├── amqpReply.js │ ├── amqpRequest.js │ ├── package.json │ ├── replier.js │ └── requestor.js ├── README.md └── Software and Hardware list.pdf /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /Chapter01/01_arrow_function/01.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const numbers = [2, 6, 7, 8, 1]; 4 | const even = numbers.filter(function(x) { 5 | return x%2 === 0; 6 | }); 7 | 8 | console.log(even); -------------------------------------------------------------------------------- /Chapter01/01_arrow_function/02.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const numbers = [2, 6, 7, 8, 1]; 4 | const even = numbers.filter(x => x%2 === 0); 5 | 6 | console.log(even); -------------------------------------------------------------------------------- /Chapter01/01_arrow_function/03.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const numbers = [2, 6, 7, 8, 1]; 4 | const even = numbers.filter((x) => { 5 | if (x%2 === 0) { 6 | console.log(x + ' is even!'); 7 | return true; 8 | } 9 | }); 10 | 11 | console.log(even); -------------------------------------------------------------------------------- /Chapter01/01_arrow_function/04.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function DelayedGreeter(name) { 4 | this.name = name; 5 | } 6 | 7 | DelayedGreeter.prototype.greet = function() { 8 | setTimeout( function cb() { 9 | console.log('Hello ' + this.name); 10 | }, 500); 11 | }; 12 | 13 | const greeter = new DelayedGreeter('World'); 14 | greeter.greet(); // will print “Hello undefined” 15 | -------------------------------------------------------------------------------- /Chapter01/01_arrow_function/05.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function DelayedGreeter(name) { 4 | this.name = name; 5 | } 6 | 7 | DelayedGreeter.prototype.greet = function() { 8 | setTimeout( (function cb() { 9 | console.log('Hello ' + this.name); 10 | }).bind(this), 500); 11 | }; 12 | 13 | const greeter = new DelayedGreeter('World'); 14 | greeter.greet(); // will print “Hello World” 15 | -------------------------------------------------------------------------------- /Chapter01/01_arrow_function/06.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function DelayedGreeter(name) { 4 | this.name = name; 5 | } 6 | 7 | DelayedGreeter.prototype.greet = function() { 8 | setTimeout( () => console.log('Hello ' + this.name), 500); 9 | }; 10 | 11 | const greeter = new DelayedGreeter('World'); 12 | greeter.greet(); // will print “Hello World” 13 | -------------------------------------------------------------------------------- /Chapter01/01_arrow_function/README.txt: -------------------------------------------------------------------------------- 1 | In this folder you can find several examples that show how to use the arrow function operator. 2 | 3 | To execute them simply run: 4 | 5 | node 6 | 7 | (e.g. node 01.js) 8 | -------------------------------------------------------------------------------- /Chapter01/02_let_const/01.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | if (false) { 4 | let x = "hello"; 5 | } 6 | console.log(x); // ReferenceError: x is not defined 7 | -------------------------------------------------------------------------------- /Chapter01/02_let_const/02.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | for (let i=0; i < 10; i++) { 4 | // do something here 5 | } 6 | console.log(i); // ReferenceError: i is not defined 7 | -------------------------------------------------------------------------------- /Chapter01/02_let_const/03.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const x = 'This will never change'; 4 | //x = '...'; // TypeError: Assignment to constant variable. 5 | -------------------------------------------------------------------------------- /Chapter01/02_let_const/04.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const x = {}; 4 | x.name = 'John'; // This is allowed 5 | //x = null; // This will fail 6 | -------------------------------------------------------------------------------- /Chapter01/02_let_const/05.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const path = require('path'); 4 | 5 | // .. do stuff with the path module 6 | 7 | var path = './some/path'; // this will fail -------------------------------------------------------------------------------- /Chapter01/02_let_const/README.txt: -------------------------------------------------------------------------------- 1 | In this folder you can find several examples that show how to use the let and const keywords. 2 | 3 | To execute them simply run: 4 | 5 | node 6 | 7 | (e.g. node 01.js) 8 | -------------------------------------------------------------------------------- /Chapter01/03_class/01.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function Person(name, surname, age) { 4 | this.name = name; 5 | this.surname = surname; 6 | this.age = age; 7 | } 8 | 9 | Person.prototype.getFullName = function() { 10 | return this.name + ' ' + this.surname; 11 | }; 12 | 13 | Person.older = function(person1, person2) { 14 | return (person1.age >= person2.age) ? person1 : person2; 15 | }; 16 | 17 | const luciano = new Person('Luciano', 'Mammino', 29); 18 | console.log(luciano.getFullName()); 19 | const alan = new Person('Alan', 'Turing', 104); 20 | console.log(Person.older(luciano, alan)); 21 | -------------------------------------------------------------------------------- /Chapter01/03_class/02.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | class Person { 4 | constructor (name, surname, age) { 5 | this.name = name; 6 | this.surname = surname; 7 | this.age = age; 8 | } 9 | 10 | getFullName () { 11 | return this.name + ' ' + this.surname; 12 | } 13 | 14 | static older (person1, person2) { 15 | return (person1.age >= person2.age) ? person1 : person2; 16 | } 17 | } 18 | 19 | const luciano = new Person('Luciano', 'Mammino', 29); 20 | console.log(luciano.getFullName()); 21 | const alan = new Person('Alan', 'Turing', 104); 22 | console.log(Person.older(luciano, alan)); 23 | -------------------------------------------------------------------------------- /Chapter01/03_class/README.txt: -------------------------------------------------------------------------------- 1 | In this folder you can find several examples that show how to use the class definition. 2 | 3 | To execute them simply run: 4 | 5 | node 6 | 7 | (e.g. node 01.js) 8 | -------------------------------------------------------------------------------- /Chapter01/04_enhanced_object_literals/01.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const x = 22; 4 | const y = 17; 5 | const obj = { x, y }; 6 | 7 | console.log(obj); 8 | -------------------------------------------------------------------------------- /Chapter01/04_enhanced_object_literals/02.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = { 4 | square (x) { 5 | return x * x; 6 | }, 7 | cube (x) { 8 | return x * x * x; 9 | } 10 | }; 11 | 12 | console.log(module.exports); -------------------------------------------------------------------------------- /Chapter01/04_enhanced_object_literals/03.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | let namespace = '-webkit-'; 4 | let style = { 5 | [namespace + 'box-sizing'] : 'border-box', 6 | [namespace + 'box-shadow'] : '10px 10px 5px #888888' 7 | }; 8 | 9 | console.log(style); -------------------------------------------------------------------------------- /Chapter01/04_enhanced_object_literals/04.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | let person = { 4 | name : 'George', 5 | surname : 'Boole', 6 | 7 | get fullname () { 8 | return this.name + ' ' + this.surname; 9 | }, 10 | 11 | set fullname (fullname) { 12 | let parts = fullname.split(' '); 13 | this.name = parts[0]; 14 | this.surname = parts[1]; 15 | } 16 | }; 17 | 18 | console.log(person.fullname); // "George Boole" 19 | console.log(person.fullname = 'Alan Turing'); // "Alan Turing" 20 | console.log(person.name); // "Alan" -------------------------------------------------------------------------------- /Chapter01/04_enhanced_object_literals/README.txt: -------------------------------------------------------------------------------- 1 | In this folder you can find several examples that show how to use the enhanced object literals. 2 | 3 | To execute them simply run: 4 | 5 | node 6 | 7 | (e.g. node 01.js) 8 | -------------------------------------------------------------------------------- /Chapter01/05_map_set/01.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const profiles = new Map(); 4 | profiles.set('twitter', '@adalovelace'); 5 | profiles.set('facebook', 'adalovelace'); 6 | profiles.set('googleplus', 'ada'); 7 | 8 | profiles.size; // 3 9 | profiles.has('twitter'); // true 10 | profiles.get('twitter'); // "@adalovelace" 11 | profiles.has('youtube'); // false 12 | profiles.delete('facebook'); 13 | profiles.has('facebook'); // false 14 | profiles.get('facebook'); // undefined 15 | for (let entry of profiles) { 16 | console.log(entry); 17 | } 18 | -------------------------------------------------------------------------------- /Chapter01/05_map_set/02.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const tests = new Map(); 4 | tests.set(() => 2+2, 4); 5 | tests.set(() => 2*2, 4); 6 | tests.set(() => 2/2, 1); 7 | 8 | for (let entry of tests) { 9 | console.log((entry[0]() === entry[1]) ? 'PASS' : 'FAIL'); 10 | } 11 | -------------------------------------------------------------------------------- /Chapter01/05_map_set/03.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const s = new Set([0, 1, 2, 3]); 4 | 5 | s.add(3); // will not be added 6 | s.size; // 4 7 | s.delete(0); 8 | s.has(0); // false 9 | 10 | for (let entry of s) { 11 | console.log(entry); 12 | } 13 | -------------------------------------------------------------------------------- /Chapter01/05_map_set/README.txt: -------------------------------------------------------------------------------- 1 | In this folder you can find several examples that show how to use the map and set classes. 2 | 3 | To execute them simply run: 4 | 5 | node 6 | 7 | (e.g. node 01.js) 8 | -------------------------------------------------------------------------------- /Chapter01/06_weakmap_weakset/01.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | let obj = {}; 4 | const map = new WeakMap(); 5 | map.set(obj, {key: "some_value"}); 6 | console.log(map.get(obj)); // {key: "some_value"} 7 | obj = undefined; // now obj and the associated data in the map will be cleaned up in the next gc cycle 8 | console.log(map.get(obj)); 9 | -------------------------------------------------------------------------------- /Chapter01/06_weakmap_weakset/02.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | let obj1 = {key: "val1"}; 4 | let obj2 = {key: "val2"}; 5 | const set = new WeakSet([obj1, obj2]); 6 | 7 | console.log(set.has(obj1)); // true 8 | obj1 = undefined; // now obj1 will be removed from the set 9 | console.log(set.has(obj1)); // false 10 | -------------------------------------------------------------------------------- /Chapter01/06_weakmap_weakset/README.txt: -------------------------------------------------------------------------------- 1 | In this folder you can find several examples that show how to use the WeakMap and WeakSet operators. 2 | 3 | To execute them simply run: 4 | 5 | node 6 | 7 | (e.g. node 01.js) 8 | -------------------------------------------------------------------------------- /Chapter01/07_template/01.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const name = "Leonardo"; 4 | const interests = ["arts", "architecture", "science", "music", "mathematics"]; 5 | const birth = { year : 1452, place : 'Florence' }; 6 | const text = `${name} was an Italian polymath interested in many topics such 7 | as ${interests.join(', ')}. 8 | He was born in ${birth.year} in ${birth.place}.`; 9 | console.log(text); 10 | -------------------------------------------------------------------------------- /Chapter01/07_template/README.txt: -------------------------------------------------------------------------------- 1 | In this folder you can find several examples that show how to use the template syntax. 2 | 3 | To execute them simply run: 4 | 5 | node 6 | 7 | (e.g. node 01.js) 8 | -------------------------------------------------------------------------------- /Chapter02/01_callback_sync_cont_passing/README.txt: -------------------------------------------------------------------------------- 1 | This example shows continuous passing with callbacks. 2 | 3 | To run the example launch: 4 | 5 | node test 6 | -------------------------------------------------------------------------------- /Chapter02/01_callback_sync_cont_passing/test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function add(a, b) { 4 | return a + b; 5 | } 6 | 7 | function add(a, b, callback) { 8 | callback(a + b); 9 | } 10 | 11 | console.log('before'); 12 | add(1, 2, result => console.log('Result: ' + result)); 13 | console.log('after'); 14 | -------------------------------------------------------------------------------- /Chapter02/02_callback_async_cont_passing/README.txt: -------------------------------------------------------------------------------- 1 | This example shows asynchronous continuous passing with callbacks. 2 | 3 | To run the example launch: 4 | 5 | node test 6 | -------------------------------------------------------------------------------- /Chapter02/02_callback_async_cont_passing/test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function additionAsync(a, b, callback) { 4 | setTimeout(() => callback(a + b), 100); 5 | } 6 | 7 | console.log('before'); 8 | additionAsync(1, 2, result => console.log('Result: ' + result)); 9 | console.log('after'); 10 | -------------------------------------------------------------------------------- /Chapter02/03_callback_non_cont_passing/README.txt: -------------------------------------------------------------------------------- 1 | This example shows non continuous passing with callbacks. 2 | 3 | To run the example launch: 4 | 5 | node test 6 | -------------------------------------------------------------------------------- /Chapter02/03_callback_non_cont_passing/test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const result = [1, 5, 7].map(element => element - 1); 4 | console.log(result); // [0, 4, 6] 5 | -------------------------------------------------------------------------------- /Chapter02/04_callback_unpredictable/README.txt: -------------------------------------------------------------------------------- 1 | This example shows unpredictable sync/async callbacks. 2 | 3 | To run the example launch: 4 | 5 | node test 6 | -------------------------------------------------------------------------------- /Chapter02/04_callback_unpredictable/data.txt: -------------------------------------------------------------------------------- 1 | some data 2 | -------------------------------------------------------------------------------- /Chapter02/05_callback_sync_api/README.txt: -------------------------------------------------------------------------------- 1 | This example shows synchronous api with callbacks. 2 | 3 | To run the example launch: 4 | 5 | node test 6 | -------------------------------------------------------------------------------- /Chapter02/05_callback_sync_api/data.txt: -------------------------------------------------------------------------------- 1 | some data 2 | -------------------------------------------------------------------------------- /Chapter02/05_callback_sync_api/test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const fs = require('fs'); 4 | const cache = {}; 5 | function consistentReadSync(filename) { 6 | if(cache[filename]) { 7 | return cache[filename]; 8 | } else { 9 | cache[filename] = fs.readFileSync(filename, 'utf8'); 10 | return cache[filename]; 11 | } 12 | } 13 | 14 | console.log(consistentReadSync('data.txt')); 15 | // the next call will read from the cache 16 | console.log(consistentReadSync('data.txt')); -------------------------------------------------------------------------------- /Chapter02/06_callback_deferred_execution/README.txt: -------------------------------------------------------------------------------- 1 | This example shows deferred execution with callbacks. 2 | 3 | To run the example launch: 4 | 5 | node test 6 | -------------------------------------------------------------------------------- /Chapter02/06_callback_deferred_execution/data.txt: -------------------------------------------------------------------------------- 1 | some data 2 | -------------------------------------------------------------------------------- /Chapter02/06_callback_deferred_execution/test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const fs = require('fs'); 4 | const cache = {}; 5 | function consistentReadAsync(filename, callback) { 6 | if(cache[filename]) { 7 | process.nextTick(() => callback(cache[filename])); 8 | } else { 9 | //asynchronous function 10 | fs.readFile(filename, 'utf8', (err, data) => { 11 | cache[filename] = data; 12 | callback(data); 13 | }); 14 | } 15 | } 16 | 17 | consistentReadAsync('data.txt', (data) => { 18 | console.log(data); 19 | // the next call will read from the cache but still be async 20 | consistentReadAsync('data.txt', (data) => console.log(data)); 21 | }); 22 | -------------------------------------------------------------------------------- /Chapter02/07_callback_propagating_errors/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to propagate errors with callbacks. 2 | 3 | To run the example launch: 4 | 5 | node readJson 6 | -------------------------------------------------------------------------------- /Chapter02/07_callback_propagating_errors/data.txt: -------------------------------------------------------------------------------- 1 | Sample data -------------------------------------------------------------------------------- /Chapter02/07_callback_propagating_errors/invalid_json.json: -------------------------------------------------------------------------------- 1 | {hello:"world"} -------------------------------------------------------------------------------- /Chapter02/07_callback_propagating_errors/valid_json.json: -------------------------------------------------------------------------------- 1 | {"hello":"world"} -------------------------------------------------------------------------------- /Chapter02/08_module_examples/README.txt: -------------------------------------------------------------------------------- 1 | These examples shows different ways to expose functionality through module pattern. 2 | 3 | To run the examples launch files ending with *_test.js: 4 | 5 | node _test 6 | 7 | Real modules are stored files without the "_test" suffix 8 | -------------------------------------------------------------------------------- /Chapter02/08_module_examples/logger_class.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | class Logger { 4 | constructor(name) { 5 | this.name = name; 6 | } 7 | 8 | log(message) { 9 | console.log(`[${this.name}] ${message}`); 10 | } 11 | 12 | info(message) { 13 | this.log(`info: ${message}`); 14 | } 15 | 16 | verbose(message) { 17 | this.log(`verbose: ${message}`); 18 | } 19 | } 20 | 21 | module.exports = Logger; 22 | -------------------------------------------------------------------------------- /Chapter02/08_module_examples/logger_class_test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const Logger = require('./logger_class'); 4 | 5 | const dbLogger = new Logger('DB'); 6 | dbLogger.info('This is an informational message'); 7 | 8 | const accessLogger = new Logger('ACCESS'); 9 | accessLogger.verbose('This is a verbose message'); 10 | -------------------------------------------------------------------------------- /Chapter02/08_module_examples/logger_constructor.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function Logger(name) { 4 | this.name = name; 5 | } 6 | 7 | Logger.prototype.log = function(message) { 8 | console.log(`[${this.name}] ${message}`); 9 | }; 10 | 11 | Logger.prototype.info = function(message) { 12 | this.log(`info: ${message}`); 13 | }; 14 | 15 | Logger.prototype.verbose = function(message) { 16 | this.log(`verbose: ${message}`); 17 | }; 18 | 19 | module.exports = Logger; 20 | -------------------------------------------------------------------------------- /Chapter02/08_module_examples/logger_constructor_test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const Logger = require('./logger_constructor'); 4 | 5 | const dbLogger = new Logger('DB'); 6 | dbLogger.info('This is an informational message'); 7 | 8 | const accessLogger = new Logger('ACCESS'); 9 | accessLogger.verbose('This is a verbose message'); 10 | -------------------------------------------------------------------------------- /Chapter02/08_module_examples/logger_function.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = (message) => { 4 | console.log(`info: ${message}`); 5 | }; 6 | 7 | module.exports.verbose = (message) => { 8 | console.log(`verbose: ${message}`); 9 | }; 10 | -------------------------------------------------------------------------------- /Chapter02/08_module_examples/logger_function_test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const logger = require('./logger_function'); 4 | 5 | logger('This is an informational message'); 6 | logger.verbose('This is a verbose message'); 7 | -------------------------------------------------------------------------------- /Chapter02/08_module_examples/logger_guard.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const LoggerConstructor = require('./logger_constructor'); 4 | 5 | function Logger(name) { 6 | if(!(this instanceof Logger)) { 7 | return new LoggerConstructor(name); 8 | } 9 | this.name = name; 10 | } 11 | 12 | module.exports = Logger; 13 | -------------------------------------------------------------------------------- /Chapter02/08_module_examples/logger_guard_es2015.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const LoggerConstructor = require('./logger_constructor'); 4 | 5 | function Logger(name) { 6 | if(!new.target) { 7 | return new LoggerConstructor(name); 8 | } 9 | this.name = name; 10 | } 11 | 12 | module.exports = Logger; 13 | -------------------------------------------------------------------------------- /Chapter02/08_module_examples/logger_guard_es2015_test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const logger = require('./logger_guard_es2015'); 4 | 5 | const dbLogger = logger('DB'); 6 | dbLogger.info('This is an informational message'); 7 | 8 | const accessLogger = logger('ACCESS'); 9 | accessLogger.verbose('This is a verbose message'); 10 | -------------------------------------------------------------------------------- /Chapter02/08_module_examples/logger_guard_test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const logger = require('./logger_guard'); 4 | 5 | const dbLogger = logger('DB'); 6 | dbLogger.info('This is an informational message'); 7 | 8 | const accessLogger = logger('ACCESS'); 9 | accessLogger.verbose('This is a verbose message'); 10 | -------------------------------------------------------------------------------- /Chapter02/08_module_examples/logger_instance.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function Logger(name) { 4 | this.count = 0; 5 | this.name = name; 6 | } 7 | 8 | Logger.prototype.log = function(message) { 9 | this.count++; 10 | console.log('[' + this.name + '] ' + message); 11 | }; 12 | 13 | module.exports = new Logger('DEFAULT'); 14 | -------------------------------------------------------------------------------- /Chapter02/08_module_examples/logger_instance_test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const logger = require('./logger_instance'); 4 | 5 | logger.log('This is an informational message'); 6 | -------------------------------------------------------------------------------- /Chapter02/09_module_revealing_module/README.txt: -------------------------------------------------------------------------------- 1 | This example shows the revealing module pattern. 2 | 3 | To run the example launch: 4 | 5 | node test 6 | -------------------------------------------------------------------------------- /Chapter02/09_module_revealing_module/test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const mod = (() => { 4 | const privateFoo = () => {}; 5 | const privateBar = []; 6 | 7 | const exported = { 8 | publicFoo: () => {}, 9 | publicBar: () => {} 10 | }; 11 | 12 | return exported; 13 | })(); 14 | 15 | console.log(mod); 16 | -------------------------------------------------------------------------------- /Chapter02/10_module_loader/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const moduleA = require('./moduleA'); 4 | moduleA.run(); 5 | -------------------------------------------------------------------------------- /Chapter02/10_module_loader/moduleA.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const moduleB = require('./moduleB'); 4 | 5 | module.exports = { 6 | run: () => { 7 | moduleB.log(); 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /Chapter02/10_module_loader/moduleB.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | exports.log = () => { 4 | console.log("From module B: the homemade require works!"); 5 | }; 6 | -------------------------------------------------------------------------------- /Chapter02/11_module_circular_dependency/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates what happens when there are cycles in module 2 | dependencies. 3 | 4 | node main 5 | -------------------------------------------------------------------------------- /Chapter02/11_module_circular_dependency/a.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | exports.loaded = false; 4 | 5 | const b = require('./b'); 6 | 7 | module.exports = { 8 | bWasLoaded: b.loaded, 9 | loaded: true 10 | }; 11 | -------------------------------------------------------------------------------- /Chapter02/11_module_circular_dependency/b.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | exports.loaded = false; 4 | 5 | const a = require('./a'); 6 | 7 | module.exports = { 8 | aWasLoaded: a.loaded, 9 | loaded: true 10 | }; 11 | -------------------------------------------------------------------------------- /Chapter02/11_module_circular_dependency/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const a = require('./a'); 4 | const b = require('./b'); 5 | console.log(a); 6 | console.log(b); 7 | -------------------------------------------------------------------------------- /Chapter02/12_observer_event_emitter_find_pattern/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to create and use an EventEmitter. 2 | To run this sample, execute the following command from a terminal: 3 | 4 | node main 5 | -------------------------------------------------------------------------------- /Chapter02/12_observer_event_emitter_find_pattern/fileA.txt: -------------------------------------------------------------------------------- 1 | Look for hello world in this text 2 | -------------------------------------------------------------------------------- /Chapter02/12_observer_event_emitter_find_pattern/fileB.json: -------------------------------------------------------------------------------- 1 | { 2 | "find": "hello NodeJS", 3 | "maybe": "two hello you" 4 | } 5 | -------------------------------------------------------------------------------- /Chapter02/13_observer_event_emitter_find_pattern_class/README: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to create and use an EventEmitter. 2 | To run this sample, execute the following command from a terminal: 3 | 4 | node main 5 | -------------------------------------------------------------------------------- /Chapter02/13_observer_event_emitter_find_pattern_class/fileA.txt: -------------------------------------------------------------------------------- 1 | Look for hello world in this text 2 | -------------------------------------------------------------------------------- /Chapter02/13_observer_event_emitter_find_pattern_class/fileB.json: -------------------------------------------------------------------------------- 1 | { 2 | "find": "hello NodeJS", 3 | "maybe": "two hello you" 4 | } 5 | -------------------------------------------------------------------------------- /Chapter02/14_observer_sync_emit/README.txt: -------------------------------------------------------------------------------- 1 | This example shows a synchronous event emitter. 2 | 3 | To run the example launch: 4 | 5 | node test 6 | -------------------------------------------------------------------------------- /Chapter02/14_observer_sync_emit/test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const EventEmitter = require('events').EventEmitter; 4 | 5 | class SyncEmit extends EventEmitter { 6 | constructor() { 7 | super(); 8 | this.emit('ready'); 9 | } 10 | } 11 | 12 | const syncEmit = new SyncEmit(); 13 | syncEmit.on('ready', () => console.log('Object is ready to be used')); 14 | 15 | // nothing will be printed as the event is dispatched before the listener is added 16 | -------------------------------------------------------------------------------- /Chapter02/15_observer_emitter_vs_callback/README.txt: -------------------------------------------------------------------------------- 1 | This example shows a comparison between event emitter and callbacks. 2 | 3 | To run the example launch: 4 | 5 | node test 6 | -------------------------------------------------------------------------------- /Chapter02/15_observer_emitter_vs_callback/test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const EventEmitter = require('events').EventEmitter; 4 | 5 | function helloEvents() { 6 | let eventEmitter = new EventEmitter(); 7 | setTimeout(() => eventEmitter.emit('hello', 'hello world'), 100); 8 | return eventEmitter; 9 | } 10 | 11 | function helloCallback(callback) { 12 | setTimeout(() => callback('hello world'), 100); 13 | } 14 | 15 | helloEvents().on('hello', (message) => console.log(message)); 16 | helloCallback((message) => console.log(message)); 17 | -------------------------------------------------------------------------------- /Chapter02/16_observer_event_emitter_glob/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how the node-glob package, combines callbacks and 2 | and EventEmitter. 3 | To run the sample code first install the dependencies: 4 | 5 | npm install 6 | 7 | Then run the main program: 8 | 9 | node main 10 | -------------------------------------------------------------------------------- /Chapter02/16_observer_event_emitter_glob/data/file1.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Node.js_Design_Patterns_Second_Edition_Code/8c6b53577c507b4332a8f36ead3cac4a0c67c38c/Chapter02/16_observer_event_emitter_glob/data/file1.txt -------------------------------------------------------------------------------- /Chapter02/16_observer_event_emitter_glob/data/file2.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Node.js_Design_Patterns_Second_Edition_Code/8c6b53577c507b4332a8f36ead3cac4a0c67c38c/Chapter02/16_observer_event_emitter_glob/data/file2.txt -------------------------------------------------------------------------------- /Chapter02/16_observer_event_emitter_glob/data/file3.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Node.js_Design_Patterns_Second_Edition_Code/8c6b53577c507b4332a8f36ead3cac4a0c67c38c/Chapter02/16_observer_event_emitter_glob/data/file3.txt -------------------------------------------------------------------------------- /Chapter02/16_observer_event_emitter_glob/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const glob = require('glob'); 4 | 5 | glob('data/*.txt', (error, files) => console.log(`All files found: ${JSON.stringify(files)}`)) 6 | .on('match', match => console.log(`Match found: ${match}`)) 7 | ; 8 | -------------------------------------------------------------------------------- /Chapter02/16_observer_event_emitter_glob/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "dependencies": { 4 | "glob": "~4.0.6" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Chapter03/01_web_spider/README.txt: -------------------------------------------------------------------------------- 1 | This is an example of a simple web spider. 2 | To run this example you need to: 3 | 4 | 1. install the dependencies with: 5 | npm install 6 | 7 | 2. download a website of your choice with 8 | node index.js 9 | -------------------------------------------------------------------------------- /Chapter03/01_web_spider/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crawler", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "mkdirp": "^0.5.1", 13 | "request": "^2.67.0", 14 | "slug": "^0.9.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter03/01_web_spider/utilities.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const urlParse = require('url').parse; 4 | const slug = require('slug'); 5 | const path = require('path'); 6 | 7 | module.exports.urlToFilename = function urlToFilename(url) { 8 | const parsedUrl = urlParse(url); 9 | const urlPath = parsedUrl.path.split('/') 10 | .filter(function(component) { 11 | return component !== ''; 12 | }) 13 | .map(function(component) { 14 | return slug(component, { remove: null }); 15 | }) 16 | .join('/'); 17 | let filename = path.join(parsedUrl.hostname, urlPath); 18 | if(!path.extname(filename).match(/htm/)) { 19 | filename += '.html'; 20 | } 21 | return filename; 22 | }; 23 | -------------------------------------------------------------------------------- /Chapter03/02_web_spider_functions/README.txt: -------------------------------------------------------------------------------- 1 | This is an example of a simple web spider. 2 | To run this example you need to: 3 | 4 | 1. install the dependencies with: 5 | npm install 6 | 7 | 2. download a website of your choice with 8 | node index.js 9 | -------------------------------------------------------------------------------- /Chapter03/02_web_spider_functions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crawler", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "mkdirp": "^0.5.1", 13 | "request": "^2.67.0", 14 | "slug": "^0.9.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter03/02_web_spider_functions/utilities.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const urlParse = require('url').parse; 4 | const slug = require('slug'); 5 | const path = require('path'); 6 | 7 | module.exports.urlToFilename = function urlToFilename(url) { 8 | const parsedUrl = urlParse(url); 9 | const urlPath = parsedUrl.path.split('/') 10 | .filter(function(component) { 11 | return component !== ''; 12 | }) 13 | .map(function(component) { 14 | return slug(component); 15 | }) 16 | .join('/'); 17 | let filename = path.join(parsedUrl.hostname, urlPath); 18 | if(!path.extname(filename).match(/htm/)) { 19 | filename += '.html'; 20 | } 21 | return filename; 22 | }; 23 | -------------------------------------------------------------------------------- /Chapter03/03_sequential_callbacks/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to create a sequential execution of callbacks. 2 | 3 | To execute it launch: 4 | 5 | node test 6 | -------------------------------------------------------------------------------- /Chapter03/03_sequential_callbacks/test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function asyncOperation(callback) { 4 | process.nextTick(callback); 5 | } 6 | 7 | function task1(callback) { 8 | asyncOperation(() => { 9 | task2(callback); 10 | }); 11 | } 12 | 13 | function task2(callback) { 14 | asyncOperation(() => { 15 | task3(callback); 16 | }); 17 | } 18 | 19 | function task3(callback) { 20 | asyncOperation(() => { 21 | callback(); //finally executes the callback 22 | }); 23 | } 24 | 25 | task1(() => { 26 | //executed when task1, task2 and task3 are completed 27 | console.log('tasks 1, 2 and 3 executed'); 28 | }); 29 | -------------------------------------------------------------------------------- /Chapter03/04_web_spider_v2/README.txt: -------------------------------------------------------------------------------- 1 | This is an example of a simple web spider. 2 | To run this example you need to: 3 | 4 | 1. install the dependencies with: 5 | npm install 6 | 7 | 2. download a website of your choice with 8 | node index.js 9 | -------------------------------------------------------------------------------- /Chapter03/04_web_spider_v2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crawler", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "mkdirp": "^0.5.1", 13 | "request": "^2.67.0", 14 | "slug": "^0.9.1", 15 | "cheerio": "^0.17.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter03/05_web_spider_v3/README.txt: -------------------------------------------------------------------------------- 1 | This is an example of a simple web spider. 2 | To run this example you need to: 3 | 4 | 1. install the dependencies with: 5 | npm install 6 | 7 | 2. download a website of your choice with 8 | node index.js 9 | -------------------------------------------------------------------------------- /Chapter03/05_web_spider_v3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crawler", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "mkdirp": "^0.5.1", 13 | "request": "^2.67.0", 14 | "slug": "^0.9.1", 15 | "cheerio": "^0.17.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter03/06_web_spider_v4/README.txt: -------------------------------------------------------------------------------- 1 | This is an example of a simple web spider. 2 | To run this example you need to: 3 | 4 | 1. install the dependencies with: 5 | npm install 6 | 7 | 2. download a website of your choice with 8 | node index.js 9 | -------------------------------------------------------------------------------- /Chapter03/06_web_spider_v4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crawler", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "mkdirp": "^0.5.1", 13 | "request": "^2.67.0", 14 | "slug": "^0.9.1", 15 | "cheerio": "^0.17.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter03/06_web_spider_v4/taskQueue.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = class TaskQueue { 4 | constructor (concurrency) { 5 | this.concurrency = concurrency; 6 | this.running = 0; 7 | this.queue = []; 8 | } 9 | 10 | pushTask (task) { 11 | this.queue.push(task); 12 | this.next(); 13 | } 14 | 15 | next() { 16 | while (this.running < this.concurrency && this.queue.length) { 17 | const task = this.queue.shift(); 18 | task (() => { 19 | this.running--; 20 | this.next(); 21 | }); 22 | this.running++; 23 | } 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /Chapter03/07_async_sequential_execution/README.txt: -------------------------------------------------------------------------------- 1 | This is an example of a simple web spider. 2 | To run this example you need to: 3 | 4 | 1. install the dependencies with: 5 | npm install 6 | 7 | 2. download a website of your choice with 8 | node index.js 9 | -------------------------------------------------------------------------------- /Chapter03/07_async_sequential_execution/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crawler", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "async": "^1.5.2", 13 | "cheerio": "^0.17.0", 14 | "mkdirp": "^0.5.1", 15 | "request": "^2.67.0", 16 | "slug": "^0.9.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter03/08_async_sequential_iteration/README.txt: -------------------------------------------------------------------------------- 1 | This is an example of a simple web spider. 2 | To run this example you need to: 3 | 4 | 1. install the dependencies with: 5 | npm install 6 | 7 | 2. download a website of your choice with 8 | node index.js 9 | -------------------------------------------------------------------------------- /Chapter03/08_async_sequential_iteration/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crawler", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "async": "^1.5.2", 13 | "cheerio": "^0.17.0", 14 | "mkdirp": "^0.5.1", 15 | "request": "^2.67.0", 16 | "slug": "^0.9.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter03/09_async_parallel_execution/README.txt: -------------------------------------------------------------------------------- 1 | This is an example of a simple web spider. 2 | To run this example you need to: 3 | 4 | 1. install the dependencies with: 5 | npm install 6 | 7 | 2. download a website of your choice with 8 | node index.js 9 | -------------------------------------------------------------------------------- /Chapter03/09_async_parallel_execution/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crawler", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "async": "^1.5.2", 13 | "cheerio": "^0.17.0", 14 | "mkdirp": "^0.5.1", 15 | "request": "^2.67.0", 16 | "slug": "^0.9.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter03/10_async_limited_parallel_execution/README.txt: -------------------------------------------------------------------------------- 1 | This is an example of a simple web spider. 2 | To run this example you need to: 3 | 4 | 1. install the dependencies with: 5 | npm install 6 | 7 | 2. download a website of your choice with 8 | node index.js 9 | -------------------------------------------------------------------------------- /Chapter03/10_async_limited_parallel_execution/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crawler", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "async": "^1.5.2", 13 | "cheerio": "^0.17.0", 14 | "mkdirp": "^0.5.1", 15 | "request": "^2.67.0", 16 | "slug": "^0.9.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Chapter04/01_promisify/README.txt: -------------------------------------------------------------------------------- 1 | This example shows a function to "promisify" callback based functions. 2 | 3 | To run it launch: 4 | 5 | node test 6 | -------------------------------------------------------------------------------- /Chapter04/01_promisify/promisify.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = function(callbackBasedApi) { 4 | return function promisified() { 5 | const args = [].slice.call(arguments); 6 | return new Promise((resolve, reject) => { //[1] 7 | args.push(function(err, result) { //[2] 8 | if(err) { 9 | return reject(err); //[3] 10 | } 11 | if(arguments.length <= 2) { //[4] 12 | resolve(result); 13 | } else { 14 | resolve([].slice.call(arguments, 1)); 15 | } 16 | }); 17 | callbackBasedApi.apply(null, args); //[5] 18 | }); 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /Chapter04/02_promises_sequential_execution/README.txt: -------------------------------------------------------------------------------- 1 | This is an example of a simple web spider. 2 | To run this example you need to: 3 | 4 | 1. install the dependencies with: 5 | npm install 6 | 7 | 2. download a website of your choice with 8 | node index.js 9 | -------------------------------------------------------------------------------- /Chapter04/02_promises_sequential_execution/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crawler", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "mkdirp": "^0.5.1", 13 | "request": "^2.67.0", 14 | "slug": "^0.9.1", 15 | "cheerio": "^0.17.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter04/03_promises_parallel_execution/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to run a set of tasks in parallel 2 | using Promises. 3 | 4 | To run the sample code first install its dependencies: 5 | npm install 6 | 7 | Then execute the 'spider' module by providing a valid url (including the protocol) 8 | node index http://www.example.com 9 | 10 | -------------------------------------------------------------------------------- /Chapter04/03_promises_parallel_execution/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "cheerio": "^0.17.0", 4 | "mkdirp": "^0.5.0", 5 | "request": "^2.45.0", 6 | "slug": "^0.8.0" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Chapter04/04_promises_limited_parallel_execution/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to run a set of tasks in a limited parallel flow 2 | using Promises. 3 | 4 | To run the sample code first install its dependencies: 5 | npm install 6 | 7 | Then execute the 'spider' module by providing a valid url (including the protocol) 8 | node index http://www.example.com 9 | 10 | -------------------------------------------------------------------------------- /Chapter04/04_promises_limited_parallel_execution/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "cheerio": "^0.17.0", 4 | "mkdirp": "^0.5.0", 5 | "request": "^2.45.0", 6 | "slug": "^0.8.0" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Chapter04/04_promises_limited_parallel_execution/taskQueue.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = class TaskQueue { 4 | constructor(concurrency) { 5 | this.concurrency = concurrency; 6 | this.running = 0; 7 | this.queue = []; 8 | } 9 | 10 | pushTask(task) { 11 | this.queue.push(task); 12 | this.next(); 13 | } 14 | 15 | next() { 16 | while(this.running < this.concurrency && this.queue.length) { 17 | const task = this.queue.shift(); 18 | task().then(() => { 19 | this.running--; 20 | this.next(); 21 | }); 22 | this.running++; 23 | } 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /Chapter04/05_exposing_callback_and_promises/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to create an Api that can be used both with a callback based approach or with promises. 2 | 3 | The index.js file exports a function implemented in such way to offer both callback and promise support. 4 | The test.js file uses this function in both ways. 5 | 6 | Then execute the example run: 7 | node test 8 | -------------------------------------------------------------------------------- /Chapter04/05_exposing_callback_and_promises/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = function asyncDivision (dividend, divisor, cb) { 4 | return new Promise((resolve, reject) => { // [1] 5 | 6 | process.nextTick(() => { 7 | const result = dividend / divisor; 8 | if (isNaN(result) || !Number.isFinite(result)) { 9 | const error = new Error('Invalid operands'); 10 | if (cb) { cb(error); } // [2] 11 | return reject(error); 12 | } 13 | 14 | if (cb) { cb(null, result); } // [3] 15 | resolve(result); 16 | }); 17 | 18 | }); 19 | }; 20 | -------------------------------------------------------------------------------- /Chapter04/05_exposing_callback_and_promises/test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var asyncDivision = require('./index.js'); 4 | 5 | // callback oriented usage 6 | asyncDivision(10, 2, (error, result) => { 7 | if (error) { 8 | return console.error(error); 9 | } 10 | console.log(result); 11 | }); 12 | 13 | // promise oriented usage 14 | asyncDivision(22, 11) 15 | .then(result => console.log(result)) 16 | .catch(error => console.error(error)) 17 | ; 18 | -------------------------------------------------------------------------------- /Chapter04/06_generators_simple/README.txt: -------------------------------------------------------------------------------- 1 | This example show a simple usage of generators. 2 | 3 | To run it use: 4 | 5 | node index -------------------------------------------------------------------------------- /Chapter04/06_generators_simple/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function* fruitGenerator() { 4 | yield 'apple'; 5 | yield 'orange'; 6 | return 'watermelon'; 7 | } 8 | 9 | const newFruitGenerator = fruitGenerator(); 10 | console.log(newFruitGenerator.next()); //[1] 11 | console.log(newFruitGenerator.next()); //[2] 12 | console.log(newFruitGenerator.next()); //[3] 13 | -------------------------------------------------------------------------------- /Chapter04/07_generators_iterators/README.txt: -------------------------------------------------------------------------------- 1 | This example show a simple usage of generators. 2 | 3 | To run it use: 4 | 5 | node index -------------------------------------------------------------------------------- /Chapter04/07_generators_iterators/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function* iteratorGenerator(arr) { 4 | for (let i = 0; i < arr.length; i++) { 5 | yield arr[i]; 6 | } 7 | } 8 | 9 | const iterator = iteratorGenerator(['apple', 'orange', 'watermelon']); 10 | let currentItem = iterator.next(); 11 | while (!currentItem.done) { 12 | console.log(currentItem.value); 13 | currentItem = iterator.next(); 14 | } 15 | -------------------------------------------------------------------------------- /Chapter04/08_generators_passing_values/README.txt: -------------------------------------------------------------------------------- 1 | This example show a simple usage of generators. 2 | 3 | To run it use: 4 | 5 | node index -------------------------------------------------------------------------------- /Chapter04/08_generators_passing_values/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function* twoWayGenerator() { 4 | const what = yield null; 5 | console.log('Hello ' + what); 6 | } 7 | 8 | const twoWay = twoWayGenerator(); 9 | twoWay.next(); 10 | twoWay.next('world'); 11 | -------------------------------------------------------------------------------- /Chapter04/09_generators_passing_errors/README.txt: -------------------------------------------------------------------------------- 1 | This example show a simple usage of generators. 2 | 3 | To run it use: 4 | 5 | node index -------------------------------------------------------------------------------- /Chapter04/09_generators_passing_errors/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function* twoWayGenerator() { 4 | let what = yield null; 5 | console.log('Hello ' + what); 6 | } 7 | 8 | let twoWay = twoWayGenerator(); 9 | twoWay.next(); 10 | twoWay.throw(new Error()); 11 | -------------------------------------------------------------------------------- /Chapter04/10_generators_async_flow/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how generators can be used as a control 2 | flow mechanism. 3 | 4 | To run the sample code issue the command: 5 | node clone 6 | 7 | -------------------------------------------------------------------------------- /Chapter04/11_generators_async_flow_thunks/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how generators can be used as a control 2 | flow mechanism. 3 | 4 | To run the sample code issue the command: 5 | node clone 6 | 7 | -------------------------------------------------------------------------------- /Chapter04/12_generators_sequential_execution/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to run a set of tasks in sequence using 2 | generator-based control flow. 3 | 4 | To run the sample code first install the dependencies: 5 | npm install 6 | 7 | Then execute the 'spider' module by providing a valid url (including the protocol) 8 | node index http://www.example.com 9 | -------------------------------------------------------------------------------- /Chapter04/12_generators_sequential_execution/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "cheerio": "^0.17.0", 4 | "co": "^4.6.0", 5 | "mkdirp": "^0.5.0", 6 | "request": "^2.69.0", 7 | "slug": "^0.8.0", 8 | "thunkify": "^2.1.2" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Chapter04/13_generators_parallel_execution_a/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to run a set of tasks in parallel using 2 | generator-based control flow. 3 | 4 | To run the sample code first install the dependencies: 5 | npm install 6 | 7 | Then execute the 'spider' module by providing a valid url (including the protocol) 8 | node index http://www.example.com 9 | 10 | -------------------------------------------------------------------------------- /Chapter04/13_generators_parallel_execution_a/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "cheerio": "^0.17.0", 4 | "co": "^4.6.0", 5 | "mkdirp": "^0.5.0", 6 | "request": "^2.69.0", 7 | "slug": "^0.8.0", 8 | "thunkify": "^2.1.2" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Chapter04/14_generators_parallel_execution_b/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to run a set of tasks in parallel using 2 | generator-based control flow. 3 | 4 | To run the sample code first install the dependencies: 5 | npm install 6 | 7 | Then execute the 'spider' module by providing a valid url (including the protocol) 8 | node index http://www.example.com 9 | 10 | -------------------------------------------------------------------------------- /Chapter04/14_generators_parallel_execution_b/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "cheerio": "^0.17.0", 4 | "co": "^4.6.0", 5 | "mkdirp": "^0.5.0", 6 | "request": "^2.69.0", 7 | "slug": "^0.8.0", 8 | "thunkify": "^2.1.2" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Chapter04/15_generators_limited_parallel/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to run a set of tasks in a parallel with 2 | limited concurrency, using generator-based control flow. 3 | 4 | To run the sample code first install the dependencies: 5 | npm install 6 | 7 | Then execute the 'spider' module by providing a valid url (including the protocol) 8 | node index http://www.example.com 9 | 10 | -------------------------------------------------------------------------------- /Chapter04/15_generators_limited_parallel/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "cheerio": "^0.17.0", 4 | "co": "^4.6.0", 5 | "mkdirp": "^0.5.0", 6 | "request": "^2.69.0", 7 | "slug": "^0.8.0", 8 | "thunkify": "^2.1.2" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Chapter04/16_async_await/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to use the "futuristic" async await syntax to run asynchronous operations. 2 | 3 | install all the dependencies with: 4 | npm install 5 | 6 | To compile (or "transpile") the source code using async await you need to use Babel. 7 | You will find a compiled version called index.es5.js that you can run yourself with: 8 | node index.es5.js 9 | 10 | But if you want to compile and run the original source code with Babel you need to run: 11 | node_modules/.bin/babel-node --plugins "syntax-async-functions,transform-async-to-generator" index.js 12 | -------------------------------------------------------------------------------- /Chapter04/16_async_await/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const request = require('request'); 4 | 5 | function getPageHtml(url) { 6 | return new Promise((resolve, reject) => { 7 | request(url, (error, response, body) => { 8 | resolve(body); 9 | }); 10 | }); 11 | } 12 | 13 | async function main() { 14 | const html = await getPageHtml('http://google.com'); 15 | console.log(html); 16 | } 17 | 18 | main(); 19 | console.log('Loading...'); 20 | -------------------------------------------------------------------------------- /Chapter04/16_async_await/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "async_await", 3 | "version": "1.0.0", 4 | "description": "sample async await usage with babel", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Luciano Mammino", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "babel-cli": "^6.9.0", 13 | "babel-plugin-syntax-async-functions": "^6.3.13", 14 | "babel-plugin-transform-async-to-generator": "^6.4.0" 15 | }, 16 | "dependencies": { 17 | "request": "^2.67.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Chapter05/01_gzip_buffer/README.txt: -------------------------------------------------------------------------------- 1 | This example shows a simple file compressor built using buffers. 2 | To run it you can use: 3 | node index 4 | 5 | You can for example compress this readme file with: 6 | node index README.txt 7 | -------------------------------------------------------------------------------- /Chapter05/01_gzip_buffer/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const fs = require('fs'); 4 | const zlib = require('zlib'); 5 | 6 | const file = process.argv[2]; 7 | 8 | fs.readFile(file, (err, buffer) => { 9 | zlib.gzip(buffer, (err, buffer) => { 10 | fs.writeFile(file + '.gz', buffer, err => { 11 | console.log('File successfully compressed'); 12 | }); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /Chapter05/02_gzip_streams/README.txt: -------------------------------------------------------------------------------- 1 | This example shows a simple file compressor built using streams. 2 | To run it you can use: 3 | node index 4 | 5 | You can for example compress this readme file with: 6 | node index README.txt 7 | -------------------------------------------------------------------------------- /Chapter05/02_gzip_streams/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const fs = require('fs'); 4 | const zlib = require('zlib'); 5 | 6 | const file = process.argv[2]; 7 | 8 | fs.createReadStream(file) 9 | .pipe(zlib.createGzip()) 10 | .pipe(fs.createWriteStream(file + '.gz')) 11 | .on('finish', () => console.log('File successfully compressed')) 12 | ; 13 | -------------------------------------------------------------------------------- /Chapter05/03_gzip_server/README.txt: -------------------------------------------------------------------------------- 1 | This example shows a simple file server that accepts a gzipped file from a 2 | client, it decompresses it and stores it inside the current folder. 3 | 4 | To run the server you need to launch: 5 | node gzipReceive 6 | 7 | Than you can send any file with: 8 | node gzipSend localhost 9 | -------------------------------------------------------------------------------- /Chapter05/03_gzip_server/gzipReceive.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const http = require('http'); 4 | const fs = require('fs'); 5 | const zlib = require('zlib'); 6 | 7 | const server = http.createServer((req, res) => { 8 | const filename = req.headers.filename; 9 | console.log('File request received: ' + filename); 10 | req 11 | .pipe(zlib.createGunzip()) 12 | .pipe(fs.createWriteStream(filename)) 13 | .on('finish', () => { 14 | res.writeHead(201, {'Content-Type': 'text/plain'}); 15 | res.end('That\'s it\n'); 16 | console.log(`File saved: ${filename}`); 17 | }); 18 | }); 19 | 20 | server.listen(3000, () => console.log('Listening')); 21 | -------------------------------------------------------------------------------- /Chapter05/04_gzip_crypto_server/README.txt: -------------------------------------------------------------------------------- 1 | This example shows a simple file server that accepts a gzipped and encrypted 2 | file from a client, it decompresses it and stores it inside the current folder. 3 | 4 | To run the server you need to launch: 5 | node gzipReceive 6 | 7 | Than you can send any file with: 8 | node gzipSend localhost 9 | -------------------------------------------------------------------------------- /Chapter05/05_streams_flowing/README.txt: -------------------------------------------------------------------------------- 1 | This code shows an example about how to implement a stream that outputs whatever is sent through the 2 | standard input using the non flowing mode. 3 | 4 | You can run the example with: 5 | 6 | cat README.txt | node readStdin 7 | -------------------------------------------------------------------------------- /Chapter05/05_streams_flowing/readStdin.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | process.stdin 4 | .on('readable', () => { 5 | let chunk; 6 | console.log('New data available'); 7 | while((chunk = process.stdin.read()) !== null) { 8 | console.log( 9 | `Chunk read: (${chunk.length}) "${chunk.toString()}"` 10 | ); 11 | } 12 | }) 13 | .on('end', () => process.stdout.write('End of stream')) 14 | ; 15 | -------------------------------------------------------------------------------- /Chapter05/06_streams_flowing/README.txt: -------------------------------------------------------------------------------- 1 | This code shows an example about how to implement a stream that outputs whatever is sent through the 2 | standard input using the flowing mode. 3 | 4 | You can run the example with: 5 | 6 | cat README.txt | node readStdin 7 | -------------------------------------------------------------------------------- /Chapter05/06_streams_flowing/readStdin.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | process.stdin 4 | .on('data', chunk => { 5 | console.log('New data available'); 6 | console.log( 7 | `Chunk read: (${chunk.length}) "${chunk.toString()}"` 8 | ); 9 | }) 10 | .on('end', () => process.stdout.write('End of stream')) 11 | ; 12 | -------------------------------------------------------------------------------- /Chapter05/07_streams_readable/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to implement a readable stream by extending the Stream.Readable class. 2 | 3 | To run the example you need to: 4 | 5 | npm install 6 | node generateRandom 7 | -------------------------------------------------------------------------------- /Chapter05/07_streams_readable/generateRandom.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const RandomStream = require('./randomStream'); 4 | const randomStream = new RandomStream(); 5 | 6 | randomStream.on('readable', () => { 7 | let chunk; 8 | while((chunk = randomStream.read()) !== null) { 9 | console.log(`Chunk received: ${chunk.toString()}`); 10 | } 11 | }); 12 | -------------------------------------------------------------------------------- /Chapter05/07_streams_readable/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "07_streams_readable", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "randomStream.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "chance": "^1.0.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter05/07_streams_readable/randomStream.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const stream = require('stream'); 4 | const Chance = require('chance'); 5 | 6 | const chance = new Chance(); 7 | 8 | class RandomStream extends stream.Readable { 9 | constructor(options) { 10 | super(options); 11 | } 12 | 13 | _read(size) { 14 | const chunk = chance.string(); //[1] 15 | console.log(`Pushing chunk of size: ${chunk.length}`); 16 | this.push(chunk, 'utf8'); //[2] 17 | if(chance.bool({likelihood: 5})) { //[3] 18 | this.push(null); 19 | } 20 | } 21 | } 22 | 23 | module.exports = RandomStream; -------------------------------------------------------------------------------- /Chapter05/08_streams_writable/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to use a writable stream by building a web server that produces random strings. 2 | 3 | To run the example you need to: 4 | 5 | npm install 6 | node entropyServer 7 | 8 | than you will be able to point your browser to: 9 | 10 | http://localhost:8080 11 | -------------------------------------------------------------------------------- /Chapter05/08_streams_writable/entropyServer.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const Chance = require('chance'); 4 | const chance = new Chance(); 5 | 6 | require('http').createServer((req, res) => { 7 | res.writeHead(200, {'Content-Type': 'text/plain'}); //[1] 8 | while(chance.bool({likelihood: 95})) { //[2] 9 | res.write(chance.string() + '\n'); //[3] 10 | } 11 | res.end('\nThe end...\n'); //[4] 12 | res.on('finish', () => console.log('All data was sent')); //[5] 13 | }).listen(8080, () => console.log('Listening on http://localhost:8080')); 14 | -------------------------------------------------------------------------------- /Chapter05/08_streams_writable/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "08_streams_writable", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "entropyServer.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "chance": "^1.0.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter05/09_streams_writable_back_pressure/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to use a writable stream by building a web server that produces random strings. This example 2 | also manages back pressure. 3 | 4 | To run the example you need to: 5 | 6 | npm install 7 | node entropyServer 8 | 9 | than you will be able to point your browser to: 10 | 11 | http://localhost:8080 12 | -------------------------------------------------------------------------------- /Chapter05/09_streams_writable_back_pressure/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "08_streams_writable", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "entropyServer.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "chance": "^1.0.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter05/10_streams_writable_implement/README.txt: -------------------------------------------------------------------------------- 1 | This example shows an implementation of a custom write stream. 2 | To run the example you need to install the dependencies with 3 | 4 | npm install 5 | 6 | and then you will be able to run 7 | 8 | node writeToFile 9 | -------------------------------------------------------------------------------- /Chapter05/10_streams_writable_implement/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "10_streams_writable_implement", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "toFileStream.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "mkdirp": "^0.5.1" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter05/10_streams_writable_implement/toFileStream.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const stream = require('stream'); 4 | const fs = require('fs'); 5 | const path = require('path'); 6 | const mkdirp = require('mkdirp'); 7 | 8 | class ToFileStream extends stream.Writable { 9 | constructor() { 10 | super({objectMode: true}); 11 | } 12 | 13 | _write (chunk, encoding, callback) { 14 | mkdirp(path.dirname(chunk.path), err => { 15 | if (err) { 16 | return callback(err); 17 | } 18 | fs.writeFile(chunk.path, chunk.content, callback); 19 | }); 20 | } 21 | } 22 | module.exports = ToFileStream; -------------------------------------------------------------------------------- /Chapter05/10_streams_writable_implement/writeToFile.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const ToFileStream = require('./toFileStream.js'); 4 | const tfs = new ToFileStream(); 5 | 6 | tfs.write({path: "file1.txt", content: "Hello"}); 7 | tfs.write({path: "file2.txt", content: "Node.js"}); 8 | tfs.write({path: "file3.txt", content: "Streams"}); 9 | tfs.end(() => console.log("All files created")); 10 | -------------------------------------------------------------------------------- /Chapter05/11_streams_transform/README.txt: -------------------------------------------------------------------------------- 1 | This example implements a transform stream. To run the example you just need to run: 2 | 3 | node replaceStreamTest 4 | -------------------------------------------------------------------------------- /Chapter05/11_streams_transform/replaceStreamTest.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const ReplaceStream = require('./replaceStream'); 4 | 5 | const rs = new ReplaceStream('World', 'Node.js'); 6 | rs.on('data', chunk => console.log(chunk.toString())); 7 | 8 | rs.write('Hello W'); 9 | rs.write('orld!'); 10 | rs.end(); 11 | -------------------------------------------------------------------------------- /Chapter05/12_streams_transform_pipes/README.txt: -------------------------------------------------------------------------------- 1 | This example implements a transform stream that also uses pipes. To run the example you just need to run: 2 | 3 | echo 'Hello World!' | node replace 'World' 'Node.js' 4 | -------------------------------------------------------------------------------- /Chapter05/12_streams_transform_pipes/replace.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const ReplaceStream = require('./replaceStream'); 4 | process.stdin 5 | .pipe(new ReplaceStream(process.argv[2], process.argv[3])) 6 | .pipe(process.stdout); 7 | -------------------------------------------------------------------------------- /Chapter05/13_streams_sequential_execution/README.txt: -------------------------------------------------------------------------------- 1 | This examples illustrates how to use streams to build a sequential execution process. 2 | To run the example you need to install the dependencies with: 3 | 4 | npm install 5 | 6 | and then you can run: 7 | 8 | node concat niceBook.txt part1.txt part2.txt part3.txt 9 | -------------------------------------------------------------------------------- /Chapter05/13_streams_sequential_execution/concat.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const concatFiles = require('./concatFiles'); 4 | 5 | concatFiles(process.argv[2], process.argv.slice(3), () => { 6 | console.log('Files concatenated successfully'); 7 | }); 8 | -------------------------------------------------------------------------------- /Chapter05/13_streams_sequential_execution/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "13_streams_sequential_execution", 3 | "version": "1.0.0", 4 | "description": "This examples illustrates how to use streams to build a sequential execution process. To run the example you need to run:", 5 | "main": "concat.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "from2-array": "0.0.4", 13 | "through2": "^2.0.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter05/14_streams_unordered_parallel_execution/README.txt: -------------------------------------------------------------------------------- 1 | This example illustrates how to build a unordered parallel execution flow using streams. 2 | To run this example you need to install the dependencies with: 3 | 4 | npm install 5 | 6 | and then: 7 | 8 | node checkUrls urlList.txt 9 | -------------------------------------------------------------------------------- /Chapter05/14_streams_unordered_parallel_execution/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "14_streams_unordered_parallel_execution", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "checkUrls.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "request": "^2.69.0", 13 | "split": "^1.0.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter05/14_streams_unordered_parallel_execution/urlList.txt: -------------------------------------------------------------------------------- 1 | http://www.mariocasciaro.me 2 | http://loige.co 3 | http://thiswillbedownforsure.com -------------------------------------------------------------------------------- /Chapter05/15_streams_unordered_limited_parallel_execution/README.txt: -------------------------------------------------------------------------------- 1 | This example illustrates how to build a unordered parallel execution flow with limited concurrency using streams. 2 | To run this example you need to install the dependencies with: 3 | 4 | npm install 5 | 6 | and then: 7 | 8 | node checkUrls urlList.txt 9 | -------------------------------------------------------------------------------- /Chapter05/15_streams_unordered_limited_parallel_execution/checkUrls.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const fs = require('fs'); 4 | const split = require('split'); 5 | const request = require('request'); 6 | const LimitedParallelStream = require('./limitedParallelStream'); 7 | 8 | fs.createReadStream(process.argv[2]) 9 | .pipe(split()) 10 | .pipe(new LimitedParallelStream(2, (url, enc, push, done) => { 11 | if(!url) return done(); 12 | request.head(url, (err, response) => { 13 | push(url + ' is ' + (err ? 'down' : 'up') + '\n'); 14 | done(); 15 | }); 16 | })) 17 | .pipe(fs.createWriteStream('results.txt')) 18 | .on('finish', () => console.log('All urls were checked')) 19 | ; 20 | -------------------------------------------------------------------------------- /Chapter05/15_streams_unordered_limited_parallel_execution/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "14_streams_unordered_parallel_execution", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "checkUrls.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "request": "^2.69.0", 13 | "split": "^1.0.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter05/15_streams_unordered_limited_parallel_execution/urlList.txt: -------------------------------------------------------------------------------- 1 | http://www.mariocasciaro.me 2 | http://loige.co 3 | http://thiswillbedownforsure.com -------------------------------------------------------------------------------- /Chapter05/16_streams_ordered_parallel_execution/README.txt: -------------------------------------------------------------------------------- 1 | This example illustrates how to build an ordered parallel execution flow using streams. 2 | To run this example you need to install the dependencies with: 3 | 4 | npm install 5 | 6 | and then: 7 | 8 | node checkUrls urlList.txt -------------------------------------------------------------------------------- /Chapter05/16_streams_ordered_parallel_execution/checkUrls.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const fs = require('fs'); 4 | const split = require('split'); 5 | const request = require('request'); 6 | const throughParallel = require('through2-parallel'); 7 | 8 | fs.createReadStream(process.argv[2]) 9 | .pipe(split()) 10 | .pipe(throughParallel.obj({concurrency: 2}, function (url, enc, done) { 11 | if(!url) return done(); 12 | request.head(url, (err, response) => { 13 | this.push(url + ' is ' + (err ? 'down' : 'up') + '\n'); 14 | done(); 15 | }); 16 | })) 17 | .pipe(fs.createWriteStream('results.txt')) 18 | .on('finish', () => console.log('All urls were checked')) 19 | ; 20 | -------------------------------------------------------------------------------- /Chapter05/16_streams_ordered_parallel_execution/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "14_streams_unordered_parallel_execution", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "checkUrls.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "request": "^2.69.0", 13 | "split": "^1.0.0", 14 | "through2-parallel": "^0.1.3" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter05/16_streams_ordered_parallel_execution/urlList.txt: -------------------------------------------------------------------------------- 1 | http://www.mariocasciaro.me 2 | http://loige.co 3 | http://thiswillbedownforsure.com -------------------------------------------------------------------------------- /Chapter05/17_streams_combined_a/README.txt: -------------------------------------------------------------------------------- 1 | This example implements a combined stream that is used to compress and encrypt a file. 2 | 3 | To run the example you need to install the dependencies with: 4 | 5 | npm install 6 | 7 | Then you can run: 8 | 9 | node archive mypassword /path/to/a/file.txt 10 | -------------------------------------------------------------------------------- /Chapter05/17_streams_combined_a/archive.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const fs = require('fs'); 4 | const compressAndEncryptStream = 5 | require('./combinedStreams').compressAndEncrypt; 6 | 7 | fs.createReadStream(process.argv[3]) 8 | .pipe(compressAndEncryptStream(process.argv[2])) 9 | .pipe(fs.createWriteStream(process.argv[3] + ".gz.enc")) 10 | .on('error', err => { 11 | //Only errors from the last stream 12 | console.log(err); 13 | }) 14 | ; 15 | -------------------------------------------------------------------------------- /Chapter05/17_streams_combined_a/combinedStreams.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const zlib = require('zlib'); 4 | const crypto = require('crypto'); 5 | const combine = require('multipipe'); 6 | 7 | module.exports.compressAndEncrypt = password => { 8 | return combine( 9 | zlib.createGzip(), 10 | crypto.createCipher('aes192', password) 11 | ); 12 | }; 13 | 14 | module.exports.decryptAndDecompress = password => { 15 | return combine( 16 | crypto.createDecipher('aes192', password), 17 | zlib.createGunzip() 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /Chapter05/17_streams_combined_a/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "17_streams_combined", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "archive.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "multipipe": "^0.3.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter05/18_streams_combined_b/README.txt: -------------------------------------------------------------------------------- 1 | This example implements a combined stream that is used to compress and encrypt a file. 2 | 3 | To run the example you need to install the dependencies with: 4 | 5 | npm install 6 | 7 | Then you can run: 8 | 9 | node archive mypassword /path/to/a/file.txt 10 | -------------------------------------------------------------------------------- /Chapter05/18_streams_combined_b/archive.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const fs = require('fs'); 4 | const combine = require('multipipe'); 5 | const compressAndEncryptStream = 6 | require('./combinedStreams').compressAndEncrypt; 7 | 8 | combine( 9 | fs.createReadStream(process.argv[3]) 10 | .pipe(compressAndEncryptStream(process.argv[2])) 11 | .pipe(fs.createWriteStream(process.argv[3] + ".gz.enc")) 12 | ).on('error', err => { 13 | //this error may come from any stream in the pipeline 14 | console.log(err); 15 | }) 16 | ; 17 | -------------------------------------------------------------------------------- /Chapter05/18_streams_combined_b/combinedStreams.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const zlib = require('zlib'); 4 | const crypto = require('crypto'); 5 | const combine = require('multipipe'); 6 | 7 | module.exports.compressAndEncrypt = password => { 8 | return combine( 9 | zlib.createGzip(), 10 | crypto.createCipher('aes192', password) 11 | ); 12 | }; 13 | 14 | module.exports.decryptAndDecompress = password => { 15 | return combine( 16 | crypto.createDecipher('aes192', password), 17 | zlib.createGunzip() 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /Chapter05/18_streams_combined_b/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "17_streams_combined", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "archive.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "multipipe": "^0.3.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter05/19_streams_fork/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to fork a stream by piping a single Readable stream into 2 | multiple Writable streams. It will generate sha1 and md5 checksum files for a 3 | given input file.file 4 | 5 | To run it you can launch: 6 | node generateHash 7 | -------------------------------------------------------------------------------- /Chapter05/19_streams_fork/generateHashes.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const fs = require('fs'); 4 | const crypto = require('crypto'); 5 | 6 | const sha1Stream = crypto.createHash('sha1'); 7 | sha1Stream.setEncoding('base64'); 8 | 9 | const md5Stream = crypto.createHash('md5'); 10 | md5Stream.setEncoding('base64'); 11 | 12 | const inputFile = process.argv[2]; 13 | const inputStream = fs.createReadStream(inputFile); 14 | inputStream 15 | .pipe(sha1Stream) 16 | .pipe(fs.createWriteStream(inputFile + '.sha1')) 17 | ; 18 | 19 | inputStream 20 | .pipe(md5Stream) 21 | .pipe(fs.createWriteStream(inputFile + '.md5')) 22 | ; 23 | -------------------------------------------------------------------------------- /Chapter05/20_streams_merge/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to merge two streams. 2 | 3 | To run the example you have to launch: 4 | 5 | node mergeTar 6 | -------------------------------------------------------------------------------- /Chapter05/20_streams_merge/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "20_streams_merge", 3 | "version": "1.0.0", 4 | "description": "This example shows how to merge two streams.", 5 | "main": "mergeTar.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "fstream": "^1.0.8", 13 | "tar": "^2.2.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter05/21_streams_mux_demux/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to multiplex and demultiplex several streams to and 2 | from a single channel.channel 3 | 4 | To run the example you need to run the server first with: 5 | 6 | node server 7 | 8 | then, in another shell you can run the client with: 9 | 10 | node client generateData.js 11 | -------------------------------------------------------------------------------- /Chapter05/21_streams_mux_demux/generateData.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | console.log("out1"); 4 | console.log("out2"); 5 | console.error("err1"); 6 | console.log("out3"); 7 | console.error("err2"); 8 | -------------------------------------------------------------------------------- /Chapter06/01_factory_simple_a/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to implement a simple factory function. 2 | To run the example you have to launch: 3 | 4 | node factory 5 | -------------------------------------------------------------------------------- /Chapter06/01_factory_simple_a/factory.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const Image = require('./image'); 4 | 5 | function createImage(name) { 6 | return new Image(name); 7 | } 8 | 9 | const image = createImage('photo.jpeg'); 10 | 11 | console.log(image); 12 | -------------------------------------------------------------------------------- /Chapter06/01_factory_simple_a/image.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = class Image { 4 | constructor(path) { 5 | this.path = path; 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /Chapter06/02_factory_simple_b/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to implement a simple factory function. 2 | To run the example you have to launch: 3 | 4 | node factory 5 | -------------------------------------------------------------------------------- /Chapter06/02_factory_simple_b/image.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = class Image { 4 | constructor(path) { 5 | this.path = path; 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /Chapter06/02_factory_simple_b/imageGif.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const Image = require('./image'); 4 | 5 | module.exports = class ImageGif extends Image { 6 | constructor(path) { 7 | if (!path.match(/\.gif/)) { 8 | throw new Error(`${path} is not a GIF image`); 9 | } 10 | super(path); 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /Chapter06/02_factory_simple_b/imageJpeg.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const Image = require('./image'); 4 | 5 | module.exports = class ImageJpg extends Image { 6 | constructor(path) { 7 | if (!path.match(/\.jpe?g$/)) { 8 | throw new Error(`${path} is not a JPEG image`); 9 | } 10 | super(path); 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /Chapter06/02_factory_simple_b/imagePng.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const Image = require('./image'); 4 | 5 | module.exports = class ImagePng extends Image { 6 | constructor(path) { 7 | if (!path.match(/\.png$/)) { 8 | throw new Error(`${path} is not a PNG image`); 9 | } 10 | super(path); 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /Chapter06/03_factory_encapsulation/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to implement a factory function that encapsulates private 2 | properties or methods and exposes only a set of public properties and methods. 3 | 4 | To run the example launch: 5 | 6 | node createPerson 7 | -------------------------------------------------------------------------------- /Chapter06/03_factory_encapsulation/createPerson.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function createPerson(name) { 4 | const privateProperties = {}; 5 | 6 | const person = { 7 | setName: name => { 8 | if(!name) throw new Error('A person must have a name'); 9 | privateProperties.name = name; 10 | }, 11 | getName: () => { 12 | return privateProperties.name; 13 | } 14 | }; 15 | 16 | person.setName(name); 17 | return person; 18 | } 19 | 20 | const person = createPerson('James Joyce'); 21 | console.log(person.getName(), person); 22 | -------------------------------------------------------------------------------- /Chapter06/04_factory_profiler/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to use the factory encapsulation to build a module 2 | that exports different objects given the current NODE_ENV setting. 3 | 4 | To run the example you have to run: 5 | 6 | # development mode (with profiler) 7 | export NODE_ENV=development; node profilerTest 8 | 9 | # production mode (no profiler) 10 | export NODE_ENV=production; node profilerTest 11 | -------------------------------------------------------------------------------- /Chapter06/04_factory_profiler/profilerTest.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const profiler = require('./profiler'); 4 | 5 | function getRandomArray(len) { 6 | const p = profiler(`Generating a ${len} items long array`); 7 | p.start(); 8 | const arr = []; 9 | for (let i = 0; i < len; i++) { 10 | arr.push(Math.random()); 11 | } 12 | p.end(); 13 | } 14 | 15 | getRandomArray(1e6); 16 | console.log('Done'); 17 | -------------------------------------------------------------------------------- /Chapter06/05_factory_composable/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to implement a set of composable factory functions using 2 | the stampit module. 3 | 4 | To run the example you first need to install the dependencies with: 5 | 6 | npm install 7 | 8 | and then you will be able to launch: 9 | 10 | node game 11 | -------------------------------------------------------------------------------- /Chapter06/05_factory_composable/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "composable", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "stampit": "^2.1.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter06/06_revealing_constructor/README.txt: -------------------------------------------------------------------------------- 1 | This examples shows how to use the revealing constructor pattern to implement 2 | a read only event emitter, a special event emitter that, once is constructed, 3 | it will allow you to only use the "on" method and not the "emit" method. 4 | 5 | To run the example you can simply run: 6 | 7 | node example 8 | 9 | The example will run continuously, so you need to stop it with CTRL+C. 10 | -------------------------------------------------------------------------------- /Chapter06/06_revealing_constructor/example.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const ticker = require('./ticker'); 4 | 5 | ticker.on('tick', (tickCount) => console.log(tickCount, 'TICK')); 6 | // ticker.emit('something', {}); <-- This will fail 7 | // require('events').prototype.emit.call(ticker, 'someEvent', {}); <-- This workaround will instead work 8 | -------------------------------------------------------------------------------- /Chapter06/06_revealing_constructor/roee.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const EventEmitter = require('events'); 4 | 5 | module.exports = class Roee extends EventEmitter { 6 | constructor (executor) { 7 | super(); 8 | const emit = this.emit.bind(this); 9 | this.emit = undefined; 10 | executor(emit); 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /Chapter06/06_revealing_constructor/ticker.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const Roee = require('./roee'); 4 | 5 | const ticker = new Roee((emit) => { 6 | let tickCount = 0; 7 | setInterval(() => emit('tick', tickCount++), 1000); 8 | }); 9 | 10 | module.exports = ticker; 11 | -------------------------------------------------------------------------------- /Chapter06/07_proxy_a/README.txt: -------------------------------------------------------------------------------- 1 | This example illustrates how to create a proxy using prototypes. 2 | 3 | To run the example simply execute: 4 | 5 | node test 6 | -------------------------------------------------------------------------------- /Chapter06/07_proxy_a/createProxy.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function createProxy(subject) { 4 | const proto = Object.getPrototypeOf(subject); 5 | 6 | function Proxy(subject) { 7 | this.subject = subject; 8 | } 9 | 10 | Proxy.prototype = Object.create(proto); 11 | 12 | //proxied method 13 | Proxy.prototype.hello = function(){ 14 | return this.subject.hello() + ' world!'; 15 | }; 16 | 17 | //delegated method 18 | Proxy.prototype.goodbye = function(){ 19 | return this.subject.goodbye 20 | .apply(this.subject, arguments); 21 | }; 22 | 23 | return new Proxy(subject); 24 | } 25 | 26 | module.exports = createProxy; 27 | -------------------------------------------------------------------------------- /Chapter06/07_proxy_a/test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const createProxy = require('./createProxy'); 4 | 5 | class Greeter { 6 | hello() { 7 | return 'Hello'; 8 | } 9 | 10 | goodbye() { 11 | return 'Goodbye'; 12 | } 13 | } 14 | 15 | const greeter = new Greeter(); 16 | const proxy = createProxy(greeter); 17 | 18 | console.log(proxy.hello()); 19 | console.log(proxy.goodbye()); 20 | -------------------------------------------------------------------------------- /Chapter06/08_proxy_b/README.txt: -------------------------------------------------------------------------------- 1 | This example illustrates how to create a proxy using plain objects. 2 | 3 | To run the example simply execute: 4 | 5 | node test 6 | -------------------------------------------------------------------------------- /Chapter06/08_proxy_b/createProxy.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function createProxy(subject) { 4 | return { 5 | //proxied method 6 | hello: () => (subject.hello() + ' world!'), 7 | 8 | //delegated method 9 | goodbye: () => (subject.goodbye.apply(subject, arguments)) 10 | }; 11 | } 12 | 13 | module.exports = createProxy; 14 | -------------------------------------------------------------------------------- /Chapter06/08_proxy_b/test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const createProxy = require('./createProxy'); 4 | 5 | class Greeter { 6 | hello() { 7 | return 'Hello'; 8 | } 9 | 10 | goodbye() { 11 | return 'Goodbye'; 12 | } 13 | } 14 | 15 | const greeter = new Greeter(); 16 | const proxy = createProxy(greeter); 17 | 18 | console.log(proxy.hello()); 19 | console.log(proxy.goodbye()); 20 | -------------------------------------------------------------------------------- /Chapter06/09_proxy_c/README.txt: -------------------------------------------------------------------------------- 1 | This example illustrates how to create a proxy using monkey patching. 2 | 3 | To run the example simply execute: 4 | 5 | node test 6 | -------------------------------------------------------------------------------- /Chapter06/09_proxy_c/createProxy.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function createProxy(subject) { 4 | const helloOrig = subject.hello; 5 | subject.hello = () => (helloOrig.call(this) + ' world!'); 6 | 7 | return subject; 8 | } 9 | 10 | 11 | module.exports = createProxy; 12 | -------------------------------------------------------------------------------- /Chapter06/09_proxy_c/test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const createProxy = require('./createProxy'); 4 | 5 | class Greeter { 6 | hello() { 7 | return 'Hello'; 8 | } 9 | 10 | goodbye() { 11 | return 'Goodbye'; 12 | } 13 | } 14 | 15 | const greeter = new Greeter(); 16 | const proxy = createProxy(greeter); 17 | 18 | console.log(proxy.hello()); 19 | console.log(proxy.goodbye()); 20 | -------------------------------------------------------------------------------- /Chapter06/10_proxy_logging_writable_stream/README.txt: -------------------------------------------------------------------------------- 1 | This example illustrates how to create a proxy using prototypes. 2 | In this case we apply the proxy to a writable stream and we use it to enhance the write method and log the operation 3 | in the console. 4 | 5 | To run the example simply execute: 6 | 7 | node loggingWritable 8 | -------------------------------------------------------------------------------- /Chapter06/11_proxy_es2015/README.txt: -------------------------------------------------------------------------------- 1 | This example illustrates how to create a proxy using ES2015. 2 | 3 | To run the example simply execute: 4 | 5 | node test 6 | -------------------------------------------------------------------------------- /Chapter06/11_proxy_es2015/test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const scientist = { 4 | name: 'nikola', 5 | surname: 'tesla' 6 | }; 7 | 8 | const uppercaseScientist = new Proxy(scientist, { 9 | get: (target, property) => target[property].toUpperCase() 10 | }); 11 | 12 | console.log(uppercaseScientist.name, uppercaseScientist.surname); // NIKOLA TESLA 13 | -------------------------------------------------------------------------------- /Chapter06/11_proxy_es2015_b/README.txt: -------------------------------------------------------------------------------- 1 | This example illustrates how to create a proxy using ES2015. 2 | 3 | To run the example simply execute: 4 | 5 | node test 6 | -------------------------------------------------------------------------------- /Chapter06/11_proxy_es2015_b/test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const evenNumbers = new Proxy([], { 4 | get: (target, index) => index * 2, 5 | has: (target, number) => number % 2 === 0 6 | }); 7 | 8 | console.log(2 in evenNumbers); // true 9 | console.log(5 in evenNumbers); // false 10 | console.log(evenNumbers[7]); // 14 11 | -------------------------------------------------------------------------------- /Chapter06/12_decorator_a/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to implement the decorator pattern using prototypes. 2 | To run the example you can simply launch: 3 | 4 | node decorator 5 | -------------------------------------------------------------------------------- /Chapter06/13_decorator_b/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to implement the decorator pattern using object augmentation. 2 | To run the example you can simply launch: 3 | 4 | node decorator 5 | -------------------------------------------------------------------------------- /Chapter06/13_decorator_b/decorator.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function decorate(component) { 4 | // attaches a new method to the object 5 | component.greetings = function() { 6 | return 'Hi!'; 7 | }; 8 | 9 | return component; 10 | } 11 | 12 | class Greeter { 13 | hello(subject) { 14 | return `Hello ${subject}`; 15 | } 16 | } 17 | 18 | const decoratedGreeter = decorate(new Greeter()); 19 | console.log(decoratedGreeter.hello('world')); // uses original method 20 | console.log(decoratedGreeter.greetings()); // uses new method 21 | -------------------------------------------------------------------------------- /Chapter06/14_decorator_levelup_plugin/.gitignore: -------------------------------------------------------------------------------- 1 | db/ 2 | -------------------------------------------------------------------------------- /Chapter06/14_decorator_levelup_plugin/README.txt: -------------------------------------------------------------------------------- 1 | In this example we use the decorator pattern to build a new level up plugin. 2 | Before running the example you need to install the dependencies with 3 | 4 | npm install 5 | 6 | then you will be able to launch: 7 | 8 | node levelSubscribeTest 9 | -------------------------------------------------------------------------------- /Chapter06/14_decorator_levelup_plugin/levelSubscribe.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = function levelSubscribe(db) { 4 | db.subscribe = (pattern, listener) => { //[1] 5 | db.on('put', (key, val) => { //[2] 6 | const match = Object.keys(pattern).every( 7 | k => (pattern[k] === val[k]) //[3] 8 | ); 9 | 10 | if(match) { 11 | listener(key, val); //[4] 12 | } 13 | }); 14 | }; 15 | return db; 16 | }; 17 | -------------------------------------------------------------------------------- /Chapter06/14_decorator_levelup_plugin/levelSubscribeTest.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const level = require('level'); //[1] 4 | const levelSubscribe = require('./levelSubscribe'); //[2] 5 | 6 | let db = level(__dirname + '/db', {valueEncoding: 'json'}); 7 | 8 | db = levelSubscribe(db); 9 | db.subscribe( 10 | {doctype: 'tweet', language: 'en'}, //[3] 11 | (k, val) => console.log(val) 12 | ); 13 | 14 | db.put('1', {doctype: 'tweet', text: 'Hi', language: 'en'}); //[4] 15 | db.put('2', {doctype: 'company', name: 'ACME Co.'}); 16 | -------------------------------------------------------------------------------- /Chapter06/14_decorator_levelup_plugin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "13_decorator_levelup_plugin", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "level": "^1.4.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter06/15_adapter/.gitignore: -------------------------------------------------------------------------------- 1 | fsDB/ -------------------------------------------------------------------------------- /Chapter06/15_adapter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "14_adapter", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "fsAdapter.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "level": "^1.4.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter06/15_adapter/testFs.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const fs = require('fs'); 4 | 5 | fs.writeFile('file.txt', 'Hello!', () => { 6 | fs.readFile('file.txt', {encoding: 'utf8'}, (err, res) => { 7 | console.log(res); 8 | }); 9 | }); 10 | 11 | //try to read a missing file 12 | fs.readFile('missing.txt', {encoding: 'utf8'}, (err, res) => { 13 | console.log(err); 14 | }); 15 | -------------------------------------------------------------------------------- /Chapter06/15_adapter/testFsAdapter.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const levelup = require('level'); 4 | const fsAdapter = require('./fsAdapter'); 5 | 6 | const db = levelup('./fsDB', {valueEncoding: 'binary'}); 7 | const fs = fsAdapter(db); 8 | 9 | fs.writeFile('file.txt', 'Hello!', () => { 10 | fs.readFile('file.txt', {encoding: 'utf8'}, (err, res) => { 11 | console.log(res); 12 | }); 13 | }); 14 | 15 | //try to read a missing file 16 | fs.readFile('missing.txt', {encoding: 'utf8'}, (err, res) => { 17 | console.log(err); 18 | }); 19 | -------------------------------------------------------------------------------- /Chapter06/16_strategy/README.txt: -------------------------------------------------------------------------------- 1 | This sample shows how to use the Strategy pattern to 2 | create a configuration manager that supports various file formats. 3 | 4 | To install all the dependencies: 5 | npm install 6 | 7 | To run the sample: 8 | node configTest 9 | -------------------------------------------------------------------------------- /Chapter06/16_strategy/configTest.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const Config = require('./config'); 4 | const strategies = require('./strategies'); 5 | 6 | const jsonConfig = new Config(strategies.json); 7 | jsonConfig.read('samples/conf.json'); 8 | jsonConfig.set('book.nodejs', 'design patterns'); 9 | jsonConfig.save('samples/conf_mod.json'); 10 | 11 | const iniConfig = new Config(strategies.ini); 12 | iniConfig.read('samples/conf.ini'); 13 | iniConfig.set('book.nodejs', 'design patterns'); 14 | iniConfig.save('samples/conf_mod.ini'); 15 | -------------------------------------------------------------------------------- /Chapter06/16_strategy/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "15_strategy", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "config.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "ini": "^1.3.4", 13 | "object-path": "^0.9.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter06/16_strategy/samples/conf.ini: -------------------------------------------------------------------------------- 1 | property = test 2 | -------------------------------------------------------------------------------- /Chapter06/16_strategy/samples/conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "property": "test" 3 | } 4 | -------------------------------------------------------------------------------- /Chapter06/16_strategy/strategies.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const ini = require('ini'); 4 | 5 | module.exports.json = { 6 | deserialize: data => JSON.parse(data), 7 | serialize: data => JSON.stringify(data, null, ' ') 8 | }; 9 | 10 | module.exports.ini = { 11 | deserialize: data => ini.parse(data), 12 | serialize: data => ini.stringify(data) 13 | }; 14 | -------------------------------------------------------------------------------- /Chapter06/17_state/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to use the State pattern 2 | to create a client socket that doesn't break when it loses 3 | connection with the server. 4 | 5 | To install all the dependencies: 6 | npm install 7 | 8 | To try the sample run in two different terminals: 9 | node server 10 | And then: 11 | node client 12 | 13 | You can try to shutdown (ctrl+c) and restart the server several times to see the state in the client changing from 14 | online to offline and then back to online when the server is resurrected. 15 | -------------------------------------------------------------------------------- /Chapter06/17_state/client.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const createFailsafeSocket = require('./failsafeSocket'); 4 | 5 | const failsafeSocket = createFailsafeSocket({port: 5000}); 6 | 7 | setInterval(() => { 8 | //send current memory usage 9 | failsafeSocket.send(process.memoryUsage()); 10 | }, 1000); 11 | -------------------------------------------------------------------------------- /Chapter06/17_state/onlineState.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = class OnlineState { 4 | constructor(failsafeSocket) { 5 | this.failsafeSocket = failsafeSocket; 6 | } 7 | 8 | send(data) { //[1] 9 | this.failsafeSocket.socket.write(data); 10 | }; 11 | 12 | activate() { //[2] 13 | this.failsafeSocket.queue.forEach(data => { 14 | this.failsafeSocket.socket.write(data); 15 | }); 16 | this.failsafeSocket.queue = []; 17 | 18 | this.failsafeSocket.socket.once('error', () => { 19 | this.failsafeSocket.changeState('offline'); 20 | }); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /Chapter06/17_state/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "16_state", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "failsafeSocket.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "json-over-tcp": "^0.3.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter06/17_state/server.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const jot = require('json-over-tcp'); 4 | const server = jot.createServer(5000); 5 | server.on('connection', socket => { 6 | socket.on('data', data => { 7 | console.log('Client data', data); 8 | }); 9 | }); 10 | 11 | server.listen(5000, () => console.log('Started')); 12 | -------------------------------------------------------------------------------- /Chapter06/18_template/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to use the Template pattern to 2 | create different configuration managers supporting different file formats. 3 | 4 | To install all the dependencies: 5 | npm install 6 | 7 | To run the sample: 8 | node configTest 9 | -------------------------------------------------------------------------------- /Chapter06/18_template/configTest.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const JsonConfig = require('./jsonConfig'); 4 | 5 | const jsonConfig = new JsonConfig(); 6 | jsonConfig.read('samples/conf.json'); 7 | jsonConfig.set('nodejs', 'design patterns'); 8 | jsonConfig.save('samples/conf_mod.json'); 9 | -------------------------------------------------------------------------------- /Chapter06/18_template/jsonConfig.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const util = require('util'); 4 | const ConfigTemplate = require('./configTemplate'); 5 | 6 | class JsonConfig extends ConfigTemplate { 7 | 8 | _deserialize(data) { 9 | return JSON.parse(data); 10 | }; 11 | 12 | _serialize(data) { 13 | return JSON.stringify(data, null, ' '); 14 | } 15 | } 16 | 17 | module.exports = JsonConfig; 18 | -------------------------------------------------------------------------------- /Chapter06/18_template/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "17_template", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "config.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "object-path": "^0.9.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter06/18_template/samples/conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "property": "test" 3 | } 4 | -------------------------------------------------------------------------------- /Chapter06/19_middleware_zmq/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to build a middleware infrastructure for ZMQ. 2 | 3 | To run the sample you first need to install the ZMQ binaries as explained 4 | at this address: 5 | http://zeromq.org/intro:get-the-software 6 | 7 | Then install all the dependencies: 8 | npm install 9 | 10 | To try the sample, run in two different terminals: 11 | node server 12 | 13 | And then: 14 | node client 15 | -------------------------------------------------------------------------------- /Chapter06/19_middleware_zmq/client.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const zmq = require('zmq'); 4 | const ZmqMiddlewareManager = require('./zmqMiddlewareManager'); 5 | const jsonMiddleware = require('./jsonMiddleware'); 6 | 7 | const request = zmq.socket('req'); 8 | request.connect('tcp://127.0.0.1:5000'); 9 | 10 | const zmqm = new ZmqMiddlewareManager(request); 11 | 12 | zmqm.use(jsonMiddleware.json()); 13 | zmqm.use({ 14 | inbound: function (message, next) { 15 | console.log('Echoed back: ', message.data); 16 | next(); 17 | } 18 | }); 19 | 20 | setInterval( () => { 21 | zmqm.send({action: 'ping', echo: Date.now()}); 22 | }, 1000); 23 | -------------------------------------------------------------------------------- /Chapter06/19_middleware_zmq/jsonMiddleware.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports.json = () => { 4 | return { 5 | inbound: function (message, next) { 6 | message.data = JSON.parse(message.data.toString()); 7 | next(); 8 | }, 9 | outbound: function (message, next) { 10 | message.data = new Buffer(JSON.stringify(message.data)); 11 | next(); 12 | } 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /Chapter06/19_middleware_zmq/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zmq_middleware", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "zmqMiddlewareManager.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Mario Casciaro & Luciano Mammino", 10 | "license": "ISC", 11 | "dependencies": { 12 | "zmq": "^2.14.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter06/19_middleware_zmq/server.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const zmq = require('zmq'); 4 | const ZmqMiddlewareManager = require('./zmqMiddlewareManager'); 5 | const jsonMiddleware = require('./jsonMiddleware'); 6 | 7 | const reply = zmq.socket('rep'); 8 | reply.bind('tcp://127.0.0.1:5000'); 9 | 10 | const zmqm = new ZmqMiddlewareManager(reply); 11 | 12 | zmqm.use(jsonMiddleware.json()); 13 | zmqm.use({ 14 | inbound: function (message, next) { 15 | console.log('Received: ', message.data); 16 | if (message.data.action === 'ping') { 17 | this.send({action: 'pong', echo: message.data.echo}); 18 | } 19 | next(); 20 | } 21 | }); 22 | -------------------------------------------------------------------------------- /Chapter06/20_middleware_generators/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how use the middleware pattern with generators in a web app built with the Koa framework. 2 | To run this example you need to install the dependencies with 3 | 4 | npm install 5 | 6 | then you can start the server with 7 | 8 | node app 9 | 10 | and access it with your browser on http://localhost:3000 11 | Try to refresh the page several times very quickly to reach the rate limit error and display the error. 12 | -------------------------------------------------------------------------------- /Chapter06/20_middleware_generators/app.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const app = require('koa')(); 4 | 5 | app.use(require('./rateLimit')); 6 | 7 | app.use(function *(){ 8 | this.body = {"now": new Date()}; 9 | }); 10 | 11 | app.listen(3000); -------------------------------------------------------------------------------- /Chapter06/20_middleware_generators/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "middleware_generators", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Mario Casciaro & Luciano Mammino", 10 | "license": "ISC", 11 | "dependencies": { 12 | "koa": "^1.1.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter06/20_middleware_generators/rateLimit.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const lastCall = new Map(); 4 | 5 | module.exports = function *(next) { 6 | 7 | // inbound 8 | const now = new Date(); 9 | if (lastCall.has(this.ip) && now.getTime() - lastCall.get(this.ip).getTime() < 1000) { 10 | return this.status = 429; // Too Many Requests 11 | } 12 | 13 | yield next; 14 | 15 | // outbound 16 | lastCall.set(this.ip, now); 17 | this.set('X-RateLimit-Reset', now.getTime() + 1000); 18 | }; 19 | -------------------------------------------------------------------------------- /Chapter06/21_command/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates a simple implementation of the Command pattern. 2 | 3 | To install all the dependencies, run the following: 4 | npm install 5 | 6 | To try the sample run: 7 | node server 8 | 9 | Then: 10 | node command 11 | -------------------------------------------------------------------------------- /Chapter06/21_command/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "20_command", 3 | "version": "1.0.0", 4 | "description": "This sample demonstrates a simple implementation of the Command pattern.", 5 | "main": "command.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node server.js" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "request": "^2.69.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter06/21_command/server.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const http = require('http'); 4 | 5 | http.createServer((request, response) => { 6 | if(request.url !== '/cmd') { 7 | response.writeHead(400); 8 | response.end(); 9 | } 10 | 11 | let data = ''; 12 | 13 | request.on('data', chunk => { 14 | data += chunk; 15 | }); 16 | 17 | request.on('end', () => { 18 | console.log('Received the command: ', data); 19 | 20 | response.writeHead(200, { 'Content-Type': 'application/json' }); 21 | response.end(JSON.stringify({ok: true})); 22 | }); 23 | }).listen(3000, () => {console.log('Started')}); 24 | -------------------------------------------------------------------------------- /Chapter07/01_hard-coded_dependency/.gitignore: -------------------------------------------------------------------------------- 1 | example_db/ -------------------------------------------------------------------------------- /Chapter07/01_hard-coded_dependency/app.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const Express = require('express'); 4 | const bodyParser = require('body-parser'); 5 | const errorHandler = require('errorhandler'); 6 | const http = require('http'); 7 | 8 | const authController = require('./lib/authController'); 9 | 10 | let app = module.exports = new Express(); 11 | app.use(bodyParser.json()); 12 | 13 | app.post('/login', authController.login); 14 | app.get('/checkToken', authController.checkToken); 15 | 16 | app.use(errorHandler()); 17 | http.createServer(app).listen(3000, () => { 18 | console.log('Express server started'); 19 | }); 20 | -------------------------------------------------------------------------------- /Chapter07/01_hard-coded_dependency/example-db/000005.ldb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Node.js_Design_Patterns_Second_Edition_Code/8c6b53577c507b4332a8f36ead3cac4a0c67c38c/Chapter07/01_hard-coded_dependency/example-db/000005.ldb -------------------------------------------------------------------------------- /Chapter07/01_hard-coded_dependency/example-db/000008.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Node.js_Design_Patterns_Second_Edition_Code/8c6b53577c507b4332a8f36ead3cac4a0c67c38c/Chapter07/01_hard-coded_dependency/example-db/000008.log -------------------------------------------------------------------------------- /Chapter07/01_hard-coded_dependency/example-db/CURRENT: -------------------------------------------------------------------------------- 1 | MANIFEST-000007 2 | -------------------------------------------------------------------------------- /Chapter07/01_hard-coded_dependency/example-db/LOCK: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Node.js_Design_Patterns_Second_Edition_Code/8c6b53577c507b4332a8f36ead3cac4a0c67c38c/Chapter07/01_hard-coded_dependency/example-db/LOCK -------------------------------------------------------------------------------- /Chapter07/01_hard-coded_dependency/example-db/LOG: -------------------------------------------------------------------------------- 1 | 2016/04/18-22:17:10.975646 700000499000 Recovering log #6 2 | 2016/04/18-22:17:10.978669 700000499000 Delete type=0 #6 3 | 2016/04/18-22:17:10.978762 700000499000 Delete type=3 #4 4 | -------------------------------------------------------------------------------- /Chapter07/01_hard-coded_dependency/example-db/LOG.old: -------------------------------------------------------------------------------- 1 | 2016/04/18-22:10:49.327332 700000416000 Recovering log #3 2 | 2016/04/18-22:10:49.327810 700000416000 Level-0 table #5: started 3 | 2016/04/18-22:10:49.329801 700000416000 Level-0 table #5: 431 bytes OK 4 | 2016/04/18-22:10:49.330301 700000416000 Delete type=0 #3 5 | 2016/04/18-22:10:49.330363 700000416000 Delete type=3 #2 6 | -------------------------------------------------------------------------------- /Chapter07/01_hard-coded_dependency/example-db/MANIFEST-000007: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Node.js_Design_Patterns_Second_Edition_Code/8c6b53577c507b4332a8f36ead3cac4a0c67c38c/Chapter07/01_hard-coded_dependency/example-db/MANIFEST-000007 -------------------------------------------------------------------------------- /Chapter07/01_hard-coded_dependency/lib/db.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const level = require('level'); 4 | const sublevel = require('level-sublevel'); 5 | 6 | module.exports = sublevel( 7 | level('example-db', {valueEncoding: 'json'}) 8 | ); 9 | -------------------------------------------------------------------------------- /Chapter07/02_di/.gitignore: -------------------------------------------------------------------------------- 1 | example-db/ 2 | -------------------------------------------------------------------------------- /Chapter07/02_di/lib/db.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const level = require('level'); 4 | const sublevel = require('level-sublevel'); 5 | 6 | module.exports = function(dbName) { 7 | return sublevel( 8 | level(dbName, {valueEncoding: 'json'}) 9 | ); 10 | }; 11 | -------------------------------------------------------------------------------- /Chapter07/03a_service_locator/.gitignore: -------------------------------------------------------------------------------- 1 | example-db/ 2 | -------------------------------------------------------------------------------- /Chapter07/03a_service_locator/lib/db.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const level = require('level'); 4 | const sublevel = require('level-sublevel'); 5 | 6 | module.exports = (serviceLocator) => { 7 | const dbName = serviceLocator.get('dbName'); 8 | 9 | return sublevel( 10 | level(dbName, {valueEncoding: 'json'}) 11 | ); 12 | }; 13 | -------------------------------------------------------------------------------- /Chapter07/03b_express_service_locator/.gitignore: -------------------------------------------------------------------------------- 1 | example-db/ 2 | -------------------------------------------------------------------------------- /Chapter07/03b_express_service_locator/lib/db.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const level = require('level'); 4 | const sublevel = require('level-sublevel'); 5 | 6 | module.exports = (serviceLocator) => { 7 | const dbName = serviceLocator.get('dbName'); 8 | 9 | return sublevel( 10 | level(dbName, {valueEncoding: 'json'}) 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /Chapter07/04_di_container/.gitignore: -------------------------------------------------------------------------------- 1 | example-db/ 2 | -------------------------------------------------------------------------------- /Chapter07/04_di_container/lib/db.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const level = require('level'); 4 | const sublevel = require('level-sublevel'); 5 | 6 | module.exports = (dbName) => { 7 | return sublevel( 8 | level(dbName, {valueEncoding: 'json'}) 9 | ); 10 | }; 11 | -------------------------------------------------------------------------------- /Chapter07/05_plugin_module_impersonation/.gitignore: -------------------------------------------------------------------------------- 1 | example-db/ 2 | -------------------------------------------------------------------------------- /Chapter07/05_plugin_module_impersonation/app.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const Express = require('express'); 4 | const bodyParser = require('body-parser'); 5 | const errorHandler = require('errorhandler'); 6 | const http = require('http'); 7 | 8 | const authController = require('./lib/authController'); 9 | 10 | const app = module.exports = new Express(); 11 | app.use(bodyParser.json()); 12 | 13 | require('authsrv-plugin-logout'); 14 | 15 | app.post('/login', authController.login); 16 | app.get('/checkToken', authController.checkToken); 17 | 18 | app.use(errorHandler()); 19 | http.createServer(app).listen(3000, () => { 20 | console.log('Express server started'); 21 | }); 22 | -------------------------------------------------------------------------------- /Chapter07/05_plugin_module_impersonation/lib/db.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const level = require('level'); 4 | const sublevel = require('level-sublevel'); 5 | 6 | module.exports = sublevel( 7 | level('example-db', {valueEncoding: 'json'}) 8 | ); 9 | -------------------------------------------------------------------------------- /Chapter07/06_plugin_service_locator/.gitignore: -------------------------------------------------------------------------------- 1 | example-db/ 2 | -------------------------------------------------------------------------------- /Chapter07/06_plugin_service_locator/lib/db.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const level = require('level'); 4 | const sublevel = require('level-sublevel'); 5 | 6 | module.exports = function(serviceLocator) { 7 | const dbName = serviceLocator.get('dbName'); 8 | 9 | return sublevel( 10 | level(dbName, {valueEncoding: 'json'}) 11 | ); 12 | }; 13 | -------------------------------------------------------------------------------- /Chapter07/07_plugin_di/.gitignore: -------------------------------------------------------------------------------- 1 | example-db/ 2 | -------------------------------------------------------------------------------- /Chapter07/07_plugin_di/lib/db.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const level = require('level'); 4 | const sublevel = require('level-sublevel'); 5 | 6 | module.exports = (dbName) => { 7 | return sublevel( 8 | level(dbName, {valueEncoding: 'json'}) 9 | ); 10 | }; 11 | -------------------------------------------------------------------------------- /Chapter07/08_plugin_di_container/.gitignore: -------------------------------------------------------------------------------- 1 | example-db/ 2 | -------------------------------------------------------------------------------- /Chapter07/08_plugin_di_container/lib/db.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const level = require('level'); 4 | const sublevel = require('level-sublevel'); 5 | 6 | module.exports = (dbName) => { 7 | return sublevel( 8 | level(dbName, {valueEncoding: 'json'}) 9 | ); 10 | }; 11 | -------------------------------------------------------------------------------- /Chapter08/01_umd/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to implement an UMD module that can be used both in Node.js and in the browser. 2 | 3 | To run the example you need to install the dependencies with: 4 | 5 | npm install 6 | 7 | then you can run: 8 | 9 | node testServer 10 | 11 | to run the code on Node.js, or open the testBrowser.html page in your browser to run it client-side 12 | -------------------------------------------------------------------------------- /Chapter08/01_umd/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "01_umd", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "umdModule.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "mustache": "^2.2.1" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter08/01_umd/testBrowser.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 13 | 14 | -------------------------------------------------------------------------------- /Chapter08/01_umd/testServer.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const umdModule = require('./umdModule'); 4 | 5 | console.log(umdModule.sayHello('Server!')); 6 | -------------------------------------------------------------------------------- /Chapter08/02_amd/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to load an UMD module using AMD in the browser. 2 | 3 | First, install all dependencies with: 4 | npm install 5 | 6 | Then open with a browser the files: 7 | using_amd.html 8 | -------------------------------------------------------------------------------- /Chapter08/02_amd/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "02_amd", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "umdModule.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "mustache": "^2.2.1", 13 | "requirejs": "^2.1.22" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter08/02_amd/umdModule.js: -------------------------------------------------------------------------------- 1 | (function(root, factory) { 2 | if(typeof define === 'function' && define.amd) { 3 | define(['mustache'], factory); 4 | } else if(typeof module === 'object' && 5 | typeof module.exports === 'object') { 6 | var mustache = require('mustache'); 7 | module.exports = factory(mustache); 8 | } else { 9 | root.UmdModule = factory(root.Mustache); 10 | } 11 | }(this, function(mustache) { 12 | var template = '

Hello {{name}}

'; 13 | mustache.parse(template); 14 | 15 | return { 16 | sayHello:function(toWhom) { 17 | return mustache.render(template, {name: toWhom}); 18 | } 19 | }; 20 | })); 21 | -------------------------------------------------------------------------------- /Chapter08/03_webpack/.gitignore: -------------------------------------------------------------------------------- 1 | bundle.js 2 | -------------------------------------------------------------------------------- /Chapter08/03_webpack/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to use webpack to create a bundle for the browser containing 2 | your javascript code and your dependencies. 3 | 4 | Before running the example you need to install the dependencies with 5 | 6 | npm install 7 | 8 | Then you need to invoke webpack to generate your bundle file from the sources: 9 | 10 | node_modules/.bin/webpack main.js bundle.js 11 | 12 | or simply 13 | 14 | webpack main.js bundle.js # (if you installed webpack globally) 15 | 16 | Then you just need to open magic.html to see the example running in your browser 17 | -------------------------------------------------------------------------------- /Chapter08/03_webpack/magic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Webpack magic 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Chapter08/03_webpack/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | window.addEventListener('load', function() { 4 | var sayHello = require('./sayHello').sayHello; 5 | var hello = sayHello('Browser!'); 6 | var body = document.getElementsByTagName("body")[0]; 7 | body.innerHTML = hello; 8 | }); 9 | -------------------------------------------------------------------------------- /Chapter08/03_webpack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "03_webpack", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "sayHello.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "mustache": "^2.2.1", 13 | "webpack": "^1.12.14" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter08/03_webpack/sayHello.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var mustache = require('mustache'); 4 | var template = '

Hello {{name}}

'; 5 | mustache.parse(template); 6 | module.exports.sayHello = function(toWhom) { 7 | return mustache.render(template, {name: toWhom}); 8 | }; 9 | -------------------------------------------------------------------------------- /Chapter08/04_webpack_es2015/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | -------------------------------------------------------------------------------- /Chapter08/04_webpack_es2015/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to use webpack to create a bundle for the browser containing 2 | your javascript code and your dependencies. 3 | 4 | Before running the example you need to install the dependencies with 5 | 6 | npm install 7 | 8 | Then you need to invoke webpack to generate your bundle file from the sources: 9 | 10 | node_modules/.bin/webpack main.js bundle.js 11 | 12 | or simply 13 | 14 | webpack main.js bundle.js # (if you installed webpack globally) 15 | 16 | Then you just need to open magic.html to see the example running in your browser 17 | -------------------------------------------------------------------------------- /Chapter08/04_webpack_es2015/magic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Webpack magic 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Chapter08/04_webpack_es2015/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "04_webpack_es2015", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "sayHello.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "mustache": "^2.2.1" 13 | }, 14 | "devDependencies": { 15 | "babel-core": "^6.6.4", 16 | "babel-loader": "^6.2.4", 17 | "babel-preset-es2015": "^6.6.0", 18 | "webpack": "^1.12.14" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Chapter08/04_webpack_es2015/src/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | window.addEventListener('load', () => { 4 | const sayHello = require('./sayHello').sayHello; 5 | const hello = sayHello('Browser!'); 6 | const body = document.getElementsByTagName("body")[0]; 7 | body.innerHTML = hello; 8 | }); 9 | -------------------------------------------------------------------------------- /Chapter08/04_webpack_es2015/src/sayHello.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const mustache = require('mustache'); 4 | const template = '

Hello {{name}}

'; 5 | mustache.parse(template); 6 | module.exports.sayHello = toWhom => { 7 | return mustache.render(template, {name: toWhom}); 8 | }; 9 | -------------------------------------------------------------------------------- /Chapter08/04_webpack_es2015/webpack.config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const path = require('path'); 4 | 5 | module.exports = { 6 | entry: path.join(__dirname, "src", "main.js"), 7 | output: { 8 | path: path.join(__dirname, "dist"), 9 | filename: "bundle.js" 10 | }, 11 | module: { 12 | loaders: [ 13 | { 14 | test: path.join(__dirname, "src"), 15 | loader: 'babel-loader', 16 | query: { 17 | presets: ['es2015'] 18 | } 19 | } 20 | ] 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /Chapter08/05_runtime_code_branching/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | -------------------------------------------------------------------------------- /Chapter08/05_runtime_code_branching/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to implement runtime code branching for universal apps. 2 | 3 | We have a very simple javascript file that outputs a different message in the console whether you are running it in 4 | Node.js or in the browser. 5 | 6 | Before running the examples you need to install the dependencies with: 7 | 8 | npm install 9 | 10 | Then you need to generate the bundle file for the browser with: 11 | 12 | node_modules/.bin/webpack 13 | 14 | Finally you can run the script on the browser by just opening main.html and looking at the debug console, or run the 15 | script in Node.js with: 16 | 17 | node src/main.js 18 | -------------------------------------------------------------------------------- /Chapter08/05_runtime_code_branching/magic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Webpack magic 4 | 5 | 6 | 7 | check the output in the developer tool console! 8 | 9 | 10 | -------------------------------------------------------------------------------- /Chapter08/05_runtime_code_branching/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "05_runtime_code_branching", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "webpack.config.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "webpack": "^1.12.14" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter08/05_runtime_code_branching/src/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | if (typeof window !== "undefined" && window.document) { 4 | console.log('Hey browser!'); 5 | } else { 6 | console.log('Hey Node.js!'); 7 | } -------------------------------------------------------------------------------- /Chapter08/05_runtime_code_branching/webpack.config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const path = require('path'); 4 | 5 | module.exports = { 6 | entry: path.join(__dirname, "src", "main.js"), 7 | output: { 8 | path: path.join(__dirname, "dist"), 9 | filename: "bundle.js" 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /Chapter08/06_buildtime_code_branching/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | -------------------------------------------------------------------------------- /Chapter08/06_buildtime_code_branching/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to implement compile time code branching for universal apps. 2 | 3 | We have a very simple javascript file that outputs a different message in the console whether you are running it in 4 | Node.js or in the browser. 5 | 6 | Before running the examples you need to install the dependencies with: 7 | 8 | npm install 9 | 10 | Then you need to generate the bundle file for the browser with: 11 | 12 | node_modules/.bin/webpack 13 | 14 | Finally you can run the script on the browser by just opening main.html and looking at the debug console, or run the 15 | script in Node.js with: 16 | 17 | node src/main.js 18 | -------------------------------------------------------------------------------- /Chapter08/06_buildtime_code_branching/magic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Webpack magic 4 | 5 | 6 | 7 | check the output in the developer tool console! 8 | 9 | 10 | -------------------------------------------------------------------------------- /Chapter08/06_buildtime_code_branching/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "06_buildtime_code_branching", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "webpack.config.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "webpack": "^1.12.14" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter08/06_buildtime_code_branching/src/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | if (typeof __BROWSER__ !== "undefined") { 4 | console.log('Hey browser!'); 5 | } else { 6 | console.log('Hey Node.js!'); 7 | } -------------------------------------------------------------------------------- /Chapter08/06_buildtime_code_branching/webpack.config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const path = require('path'); 4 | const webpack = require('webpack'); 5 | 6 | const definePlugin = new webpack.DefinePlugin({ 7 | "__BROWSER__": "true" 8 | }); 9 | 10 | const uglify = new webpack.optimize.UglifyJsPlugin({ 11 | beautify: true, 12 | dead_code: true 13 | }); 14 | 15 | module.exports = { 16 | entry: path.join(__dirname, "src", "main.js"), 17 | output: { 18 | path: path.join(__dirname, "dist"), 19 | filename: "bundle.js" 20 | }, 21 | plugins: [definePlugin, uglify] 22 | }; 23 | -------------------------------------------------------------------------------- /Chapter08/07_webpack_define_plugin_dynamic_variables/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | -------------------------------------------------------------------------------- /Chapter08/07_webpack_define_plugin_dynamic_variables/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to implement build time dynamic variables with webpack. 2 | 3 | Before running the examples you need to install the dependencies with: 4 | 5 | npm install 6 | 7 | Then you need to generate the bundle file for the browser with: 8 | 9 | node_modules/.bin/webpack 10 | 11 | Finally you can run the resulting script in node with: 12 | 13 | node dist/bundle.js 14 | -------------------------------------------------------------------------------- /Chapter08/07_webpack_define_plugin_dynamic_variables/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wptest", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "webpack": "^1.12.14" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter08/07_webpack_define_plugin_dynamic_variables/src/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // This script will fail because of undefined variables. 4 | // These variables will be replaced at build time by webpack. 5 | // The runnable file will be found in dist/bundle.js 6 | 7 | const now = __NOW__; 8 | const platform = __PLATFORM__; 9 | const host = __HOST__; 10 | 11 | console.log(`Bundle compiled on "${now}" on "${platform}" by "${host}"`); 12 | -------------------------------------------------------------------------------- /Chapter08/07_webpack_define_plugin_dynamic_variables/webpack.config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const path = require('path'); 4 | const webpack = require('webpack'); 5 | const os = require('os'); 6 | 7 | let definePlugin = new webpack.DefinePlugin({ 8 | "__NOW__": JSON.stringify((new Date()).toString()), 9 | "__PLATFORM__": JSON.stringify(os.platform()), 10 | "__HOST__": JSON.stringify(os.hostname()) 11 | }); 12 | 13 | module.exports = { 14 | entry: path.join(__dirname, "src", "main.js"), 15 | output: { 16 | path: path.join(__dirname, "dist"), 17 | filename: "bundle.js" 18 | }, 19 | plugins: [definePlugin] 20 | }; 21 | -------------------------------------------------------------------------------- /Chapter08/08_buildtime_module_swapping_a/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | -------------------------------------------------------------------------------- /Chapter08/08_buildtime_module_swapping_a/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to implement compile time module swapping for universal apps. 2 | 3 | Before running the examples you need to install the dependencies with: 4 | 5 | npm install 6 | 7 | Then you need to generate the bundle file for the browser with: 8 | 9 | node_modules/.bin/webpack 10 | 11 | Finally you can run the script on the browser by just opening main.html and looking at the debug console, or run the 12 | script in Node.js with: 13 | 14 | node src/main.js 15 | -------------------------------------------------------------------------------- /Chapter08/08_buildtime_module_swapping_a/magic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Webpack magic 4 | 5 | 6 | 7 | This page will open a nasty alert! 8 | 9 | 10 | -------------------------------------------------------------------------------- /Chapter08/08_buildtime_module_swapping_a/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "08_buildtime_module_swapping_a", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "webpack": "^1.12.14" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Chapter08/08_buildtime_module_swapping_a/src/alertBrowser.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = alert; 4 | -------------------------------------------------------------------------------- /Chapter08/08_buildtime_module_swapping_a/src/alertServer.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = console.log; 4 | -------------------------------------------------------------------------------- /Chapter08/08_buildtime_module_swapping_a/src/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const alert = require('./alertServer'); 4 | alert('Morning comes whether you set the alarm or not!'); 5 | -------------------------------------------------------------------------------- /Chapter08/08_buildtime_module_swapping_a/webpack.config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const path = require('path'); 4 | const webpack = require('webpack'); 5 | 6 | let moduleReplacementPlugin = 7 | new webpack.NormalModuleReplacementPlugin(/alertServer.js$/, './alertBrowser.js'); 8 | 9 | module.exports = { 10 | entry: path.join(__dirname, "src", "main.js"), 11 | output: { 12 | path: path.join(__dirname, "dist"), 13 | filename: "bundle.js" 14 | }, 15 | plugins: [moduleReplacementPlugin] 16 | }; 17 | -------------------------------------------------------------------------------- /Chapter08/08_buildtime_module_swapping_b/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | -------------------------------------------------------------------------------- /Chapter08/08_buildtime_module_swapping_b/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to implement compile time module swapping for universal apps. 2 | 3 | Before running the examples you need to install the dependencies with: 4 | 5 | npm install 6 | 7 | Then you need to generate the bundle file for the browser with: 8 | 9 | node_modules/.bin/webpack 10 | 11 | Finally you can run the script on the browser by just opening main.html and looking at the debug console, or run the 12 | script in Node.js with: 13 | 14 | node src/main.js 15 | -------------------------------------------------------------------------------- /Chapter08/08_buildtime_module_swapping_b/magic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Webpack magic 4 | 5 | 6 | 7 | This page will open a nice "toast" alert! 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Chapter08/08_buildtime_module_swapping_b/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "09_buildtime_module_swapping_b", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "jquery": "^2.2.1", 13 | "toastr": "^2.1.2", 14 | "webpack": "^1.12.14" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter08/08_buildtime_module_swapping_b/src/alertBrowser.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const toastr = require('toastr'); 4 | module.exports = toastr.info; 5 | -------------------------------------------------------------------------------- /Chapter08/08_buildtime_module_swapping_b/src/alertServer.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = console.log; 4 | -------------------------------------------------------------------------------- /Chapter08/08_buildtime_module_swapping_b/src/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const alert = require('./alertServer'); 4 | alert('Morning comes whether you set the alarm or not!'); 5 | -------------------------------------------------------------------------------- /Chapter08/08_buildtime_module_swapping_b/webpack.config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const path = require('path'); 4 | const webpack = require('webpack'); 5 | 6 | let moduleReplacementPlugin = 7 | new webpack.NormalModuleReplacementPlugin(/alertServer.js$/, './alertBrowser.js'); 8 | 9 | module.exports = { 10 | entry: path.join(__dirname, "src", "main.js"), 11 | output: { 12 | path: path.join(__dirname, "dist"), 13 | filename: "bundle.js" 14 | }, 15 | plugins: [moduleReplacementPlugin] 16 | }; 17 | -------------------------------------------------------------------------------- /Chapter08/09_react_rendering_browser/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | babel_cache/ -------------------------------------------------------------------------------- /Chapter08/09_react_rendering_browser/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to implement a simple React component that is rendered in the browser. 2 | 3 | Before running the examples you need to install the dependencies with: 4 | 5 | npm install 6 | 7 | Then you need to generate the bundle file for the browser with: 8 | 9 | node_modules/.bin/webpack 10 | 11 | Finally you can run the script on the browser by just opening index.html 12 | -------------------------------------------------------------------------------- /Chapter08/09_react_rendering_browser/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Example - James Joyce books 6 | 7 | 8 |
9 | 10 | 11 | -------------------------------------------------------------------------------- /Chapter08/09_react_rendering_browser/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "10_react_rendering_browser", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "babel-core": "^6.7.2", 13 | "babel-loader": "^6.2.4", 14 | "babel-preset-es2015": "^6.6.0", 15 | "babel-preset-react": "^6.5.0", 16 | "react": "^15.0.0-rc.1", 17 | "react-dom": "^15.0.0-rc.1", 18 | "webpack": "^1.12.14" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Chapter08/09_react_rendering_browser/src/joyceBooks.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const React = require('react'); 4 | 5 | const books = [ 6 | 'Dubliners', 7 | 'A Portrait of the Artist as a Young Man', 8 | 'Exiles and poetry', 9 | 'Ulysses', 10 | 'Finnegans Wake' 11 | ]; 12 | 13 | class JoyceBooks extends React.Component { 14 | render() { 15 | return ( 16 |
17 |

James Joyce's major works

18 |
    { 19 | books.map( (book, key) => 20 |
  • {book}
  • 21 | ) 22 | }
23 |
24 | ); 25 | } 26 | } 27 | 28 | module.exports = JoyceBooks; 29 | -------------------------------------------------------------------------------- /Chapter08/09_react_rendering_browser/src/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const React = require('react'); 4 | const ReactDOM = require('react-dom'); 5 | const JoyceBooks = require('./joyceBooks'); 6 | 7 | window.onload = () => { 8 | ReactDOM.render(, document.getElementById('main')) 9 | }; 10 | -------------------------------------------------------------------------------- /Chapter08/09_react_rendering_browser/webpack.config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const path = require('path'); 4 | 5 | module.exports = { 6 | entry: path.join(__dirname, "src", "main.js"), 7 | output: { 8 | path: path.join(__dirname, "dist"), 9 | filename: "bundle.js" 10 | }, 11 | module: { 12 | loaders: [ 13 | { 14 | test: path.join(__dirname, "src"), 15 | loader: 'babel-loader', 16 | query: { 17 | cacheDirectory: 'babel_cache', 18 | presets: ['es2015', 'react'] 19 | } 20 | } 21 | ] 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /Chapter08/10_react_router/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | babel_cache/ -------------------------------------------------------------------------------- /Chapter08/10_react_router/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to implement a simple React application with several views 2 | using the react router. 3 | 4 | Before running the examples you need to install the dependencies with: 5 | 6 | npm install 7 | 8 | Then you need to generate the bundle file for the browser with: 9 | 10 | node_modules/.bin/webpack 11 | 12 | Finally you can run the example on the browser by just opening index.html 13 | -------------------------------------------------------------------------------- /Chapter08/10_react_router/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Example - Authors archive 6 | 7 | 8 |
9 | 10 | 11 | -------------------------------------------------------------------------------- /Chapter08/10_react_router/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "10_react_rendering_browser", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "babel-core": "^6.7.2", 13 | "babel-loader": "^6.2.4", 14 | "babel-preset-es2015": "^6.6.0", 15 | "babel-preset-react": "^6.5.0", 16 | "react": "^15.0.0-rc.1", 17 | "react-dom": "^15.0.0-rc.1", 18 | "react-router": "^2.0.1", 19 | "webpack": "^1.12.14" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter08/10_react_router/src/components/notFound.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const React = require('react'); 4 | const Link = require('react-router').Link; 5 | 6 | class NotFound extends React.Component { 7 | render() { 8 | return ( 9 |
10 |

Page not found

11 | Go back to index 12 |
13 | ); 14 | } 15 | } 16 | 17 | module.exports = NotFound; 18 | -------------------------------------------------------------------------------- /Chapter08/10_react_router/src/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const React = require('react'); 4 | const ReactDOM = require('react-dom'); 5 | const Routes = require('./routes'); 6 | 7 | window.onload = () => { 8 | ReactDOM.render(, document.getElementById('main')) 9 | }; 10 | -------------------------------------------------------------------------------- /Chapter08/10_react_router/webpack.config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const path = require('path'); 4 | 5 | module.exports = { 6 | entry: path.join(__dirname, "src", "main.js"), 7 | output: { 8 | path: path.join(__dirname, "dist"), 9 | filename: "bundle.js" 10 | }, 11 | module: { 12 | loaders: [ 13 | { 14 | test: path.join(__dirname, "src"), 15 | loader: 'babel-loader', 16 | query: { 17 | cacheDirectory: 'babel_cache', 18 | presets: ['es2015', 'react'] 19 | } 20 | } 21 | ] 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /Chapter08/11_react_reusable_components/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | babel_cache/ -------------------------------------------------------------------------------- /Chapter08/11_react_reusable_components/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to build a reusable React component and render two 2 | instance of them in the browser. 3 | 4 | Before running the examples you need to install the dependencies with: 5 | 6 | npm install 7 | 8 | Then you need to generate the bundle file for the browser with: 9 | 10 | node_modules/.bin/webpack 11 | 12 | Finally you can run the script on the browser by just opening index.html 13 | -------------------------------------------------------------------------------- /Chapter08/11_react_reusable_components/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Example - Authors archive 6 | 7 | 8 |
9 | 10 | 11 | -------------------------------------------------------------------------------- /Chapter08/11_react_reusable_components/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "10_react_rendering_browser", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "babel-core": "^6.7.2", 13 | "babel-loader": "^6.2.4", 14 | "babel-preset-es2015": "^6.6.0", 15 | "babel-preset-react": "^6.5.0", 16 | "react": "^15.0.0-rc.1", 17 | "react-dom": "^15.0.0-rc.1", 18 | "react-router": "^2.0.1", 19 | "webpack": "^1.12.14" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Chapter08/11_react_reusable_components/src/authors.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = { 4 | 5 | 'joyce': { 6 | 'name': 'James Joyce', 7 | 'books': [ 8 | 'Dubliners', 9 | 'A Portrait of the Artist as a Young Man', 10 | 'Exiles and poetry', 11 | 'Ulysses', 12 | 'Finnegans Wake' 13 | ] 14 | }, 15 | 16 | 'h-g-wells': { 17 | 'name': 'Herbert George Wells', 18 | 'books': [ 19 | 'The Time Machine', 20 | 'The War of the Worlds', 21 | 'The First Men in the Moon', 22 | 'The Invisible Man' 23 | ] 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /Chapter08/11_react_reusable_components/src/components/authorsIndex.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const React = require('react'); 4 | const Link = require('react-router').Link; 5 | const AUTHORS = require('../authors'); 6 | 7 | class AuthorsIndex extends React.Component { 8 | render() { 9 | return ( 10 |
11 |

List of authors

12 |
    { 13 | Object.keys(AUTHORS).map(id => 14 |
  • {AUTHORS[id].name}
  • 15 | ) 16 | }
17 |
18 | ) 19 | } 20 | } 21 | 22 | module.exports = AuthorsIndex; 23 | -------------------------------------------------------------------------------- /Chapter08/11_react_reusable_components/src/components/notFound.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const React = require('react'); 4 | const Link = require('react-router').Link; 5 | 6 | class NotFound extends React.Component { 7 | render() { 8 | return ( 9 |
10 |

Page not found

11 | Go back to index 12 |
13 | ); 14 | } 15 | } 16 | 17 | module.exports = NotFound; 18 | -------------------------------------------------------------------------------- /Chapter08/11_react_reusable_components/src/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const React = require('react'); 4 | const ReactDOM = require('react-dom'); 5 | const Routes = require('./routes'); 6 | 7 | window.onload = () => { 8 | ReactDOM.render(, document.getElementById('main')) 9 | }; 10 | -------------------------------------------------------------------------------- /Chapter08/11_react_reusable_components/webpack.config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const path = require('path'); 4 | 5 | module.exports = { 6 | entry: path.join(__dirname, "src", "main.js"), 7 | output: { 8 | path: path.join(__dirname, "dist"), 9 | filename: "bundle.js" 10 | }, 11 | module: { 12 | loaders: [ 13 | { 14 | test: path.join(__dirname, "src"), 15 | loader: 'babel-loader', 16 | query: { 17 | cacheDirectory: 'babel_cache', 18 | presets: ['es2015', 'react'] 19 | } 20 | } 21 | ] 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /Chapter08/12_react_server_side_rendering/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react"] 3 | } -------------------------------------------------------------------------------- /Chapter08/12_react_server_side_rendering/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | babel_cache/ -------------------------------------------------------------------------------- /Chapter08/12_react_server_side_rendering/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to render on the server a react powered application 2 | 3 | Before running the examples you need to install the dependencies with: 4 | 5 | npm install 6 | 7 | Then you need to run the server using babel-cli: 8 | 9 | node_modules/.bin/babel-node server.js 10 | 11 | Finally you can point your browser to http://localhost:3000 to see the rendered 12 | app. 13 | -------------------------------------------------------------------------------- /Chapter08/12_react_server_side_rendering/src/authors.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = { 4 | 5 | 'joyce': { 6 | 'name': 'James Joyce', 7 | 'books': [ 8 | 'Dubliners', 9 | 'A Portrait of the Artist as a Young Man', 10 | 'Exiles and poetry', 11 | 'Ulysses', 12 | 'Finnegans Wake' 13 | ] 14 | }, 15 | 16 | 'h-g-wells': { 17 | 'name': 'Herbert George Wells', 18 | 'books': [ 19 | 'The Time Machine', 20 | 'The War of the Worlds', 21 | 'The First Men in the Moon', 22 | 'The Invisible Man' 23 | ] 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /Chapter08/12_react_server_side_rendering/src/components/authorsIndex.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const React = require('react'); 4 | const Link = require('react-router').Link; 5 | const AUTHORS = require('../authors'); 6 | 7 | class AuthorsIndex extends React.Component { 8 | render() { 9 | return ( 10 |
11 |

List of authors

12 |
    { 13 | Object.keys(AUTHORS).map(id => 14 |
  • {AUTHORS[id].name}
  • 15 | ) 16 | }
17 |
18 | ) 19 | } 20 | } 21 | 22 | module.exports = AuthorsIndex; 23 | -------------------------------------------------------------------------------- /Chapter08/12_react_server_side_rendering/src/components/notFound.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const React = require('react'); 4 | const Link = require('react-router').Link; 5 | 6 | class NotFound extends React.Component { 7 | render() { 8 | return ( 9 |
10 |

Page not found

11 | Go back to index 12 |
13 | ); 14 | } 15 | } 16 | 17 | module.exports = NotFound; 18 | -------------------------------------------------------------------------------- /Chapter08/12_react_server_side_rendering/src/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const React = require('react'); 4 | const ReactDOM = require('react-dom'); 5 | const Routes = require('./routes'); 6 | 7 | window.onload = () => { 8 | ReactDOM.render(, document.getElementById('main')) 9 | }; 10 | -------------------------------------------------------------------------------- /Chapter08/12_react_server_side_rendering/src/routes.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const React = require('react'); 4 | const ReactRouter = require('react-router'); 5 | const Router = ReactRouter.Router; 6 | const hashHistory = ReactRouter.hashHistory; 7 | const routesConfig = require('./routesConfig'); 8 | 9 | class Routes extends React.Component { 10 | render() { 11 | return ; 12 | } 13 | } 14 | 15 | module.exports = Routes; -------------------------------------------------------------------------------- /Chapter08/12_react_server_side_rendering/src/routesConfig.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const AuthorsIndex = require('./components/authorsIndex'); 4 | const AuthorPage = require('./components/authorPage'); 5 | const NotFound = require('./components/notFound'); 6 | 7 | const routesConfig = [ 8 | {path: '/', component: AuthorsIndex}, 9 | {path: '/author/:id', component: AuthorPage}, 10 | {path: '*', component: NotFound} 11 | ]; 12 | 13 | module.exports = routesConfig; 14 | -------------------------------------------------------------------------------- /Chapter08/12_react_server_side_rendering/views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Example - Authors archive 6 | 7 | 8 |
9 | <%- markup -%> 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /Chapter08/12_react_server_side_rendering/webpack.config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const path = require('path'); 4 | 5 | module.exports = { 6 | entry: path.join(__dirname, "src", "main.js"), 7 | output: { 8 | path: path.join(__dirname, "dist"), 9 | filename: "bundle.js" 10 | }, 11 | module: { 12 | loaders: [ 13 | { 14 | test: path.join(__dirname, "src"), 15 | loader: 'babel-loader', 16 | query: { 17 | cacheDirectory: 'babel_cache', 18 | presets: ['es2015', 'react'] 19 | } 20 | } 21 | ] 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /Chapter08/13_universal_rendering_and_routing/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react"] 3 | } -------------------------------------------------------------------------------- /Chapter08/13_universal_rendering_and_routing/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | babel_cache/ -------------------------------------------------------------------------------- /Chapter08/13_universal_rendering_and_routing/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to implement a react app that is both rendered on the 2 | server (at first access) and on the browser (after any interaction with the page) 3 | 4 | Before running the examples you need to install the dependencies with: 5 | 6 | npm install 7 | 8 | Then you need to generate the bundle file with webpack: 9 | 10 | node_modules/.bin/webpack 11 | 12 | Then you need to run the server using babel-cli: 13 | 14 | node_modules/.bin/babel-node server.js 15 | 16 | Finally you can point your browser to http://localhost:3000 to run the app. 17 | -------------------------------------------------------------------------------- /Chapter08/13_universal_rendering_and_routing/src/authors.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = { 4 | 5 | 'joyce': { 6 | 'name': 'James Joyce', 7 | 'books': [ 8 | 'Dubliners', 9 | 'A Portrait of the Artist as a Young Man', 10 | 'Exiles and poetry', 11 | 'Ulysses', 12 | 'Finnegans Wake' 13 | ] 14 | }, 15 | 16 | 'h-g-wells': { 17 | 'name': 'Herbert George Wells', 18 | 'books': [ 19 | 'The Time Machine', 20 | 'The War of the Worlds', 21 | 'The First Men in the Moon', 22 | 'The Invisible Man' 23 | ] 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /Chapter08/13_universal_rendering_and_routing/src/components/authorsIndex.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const React = require('react'); 4 | const Link = require('react-router').Link; 5 | const AUTHORS = require('../authors'); 6 | 7 | class AuthorsIndex extends React.Component { 8 | render() { 9 | return ( 10 |
11 |

List of authors

12 |
    { 13 | Object.keys(AUTHORS).map(id => 14 |
  • {AUTHORS[id].name}
  • 15 | ) 16 | }
17 |
18 | ) 19 | } 20 | } 21 | 22 | module.exports = AuthorsIndex; 23 | -------------------------------------------------------------------------------- /Chapter08/13_universal_rendering_and_routing/src/components/notFound.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const React = require('react'); 4 | const Link = require('react-router').Link; 5 | 6 | class NotFound extends React.Component { 7 | render() { 8 | return ( 9 |
10 |

Page not found

11 | Go back to index 12 |
13 | ); 14 | } 15 | } 16 | 17 | module.exports = NotFound; 18 | -------------------------------------------------------------------------------- /Chapter08/13_universal_rendering_and_routing/src/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const React = require('react'); 4 | const ReactDOM = require('react-dom'); 5 | const Routes = require('./routes'); 6 | 7 | window.onload = () => { 8 | ReactDOM.render(, document.getElementById('main')) 9 | }; 10 | -------------------------------------------------------------------------------- /Chapter08/13_universal_rendering_and_routing/src/routes.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const React = require('react'); 4 | const ReactRouter = require('react-router'); 5 | const Router = ReactRouter.Router; 6 | const browserHistory = ReactRouter.browserHistory; 7 | const routesConfig = require('./routesConfig'); 8 | 9 | class Routes extends React.Component { 10 | render() { 11 | return ; 12 | } 13 | } 14 | 15 | module.exports = Routes; -------------------------------------------------------------------------------- /Chapter08/13_universal_rendering_and_routing/src/routesConfig.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const AuthorsIndex = require('./components/authorsIndex'); 4 | const AuthorPage = require('./components/authorPage'); 5 | const NotFound = require('./components/notFound'); 6 | 7 | const routesConfig = [ 8 | {path: '/', component: AuthorsIndex}, 9 | {path: '/author/:id', component: AuthorPage}, 10 | {path: '*', component: NotFound} 11 | ]; 12 | 13 | module.exports = routesConfig; 14 | -------------------------------------------------------------------------------- /Chapter08/13_universal_rendering_and_routing/views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Example - Authors archive 6 | 7 | 8 |
<%- markup %>
9 | 10 | 11 | -------------------------------------------------------------------------------- /Chapter08/13_universal_rendering_and_routing/webpack.config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const path = require('path'); 4 | 5 | module.exports = { 6 | entry: path.join(__dirname, "src", "main.js"), 7 | output: { 8 | path: path.join(__dirname, "dist"), 9 | filename: "bundle.js" 10 | }, 11 | module: { 12 | loaders: [ 13 | { 14 | test: path.join(__dirname, "src"), 15 | loader: 'babel-loader', 16 | query: { 17 | cacheDirectory: 'babel_cache', 18 | presets: ['es2015', 'react'] 19 | } 20 | } 21 | ] 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /Chapter08/14_universal_data_retrieval/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react"] 3 | } -------------------------------------------------------------------------------- /Chapter08/14_universal_data_retrieval/.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | babel_cache/ -------------------------------------------------------------------------------- /Chapter08/14_universal_data_retrieval/README.txt: -------------------------------------------------------------------------------- 1 | This example shows how to implement a react app that is able to load asynchronous 2 | components and to make API request both from the server and the client to 3 | render them. 4 | 5 | Before running the examples you need to install the dependencies with: 6 | 7 | npm install 8 | 9 | Then you need to generate the bundle file with webpack: 10 | 11 | node_modules/.bin/webpack 12 | 13 | Then you need to run the webServer using babel-cli: 14 | 15 | node_modules/.bin/babel-node webServer 16 | 17 | Finally you need to run the apiServer using 18 | 19 | node apiServer 20 | 21 | Now you can point your browser to http://localhost:3000 to run the app. 22 | -------------------------------------------------------------------------------- /Chapter08/14_universal_data_retrieval/src/authors.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = { 4 | 5 | 'joyce': { 6 | 'name': 'James Joyce', 7 | 'books': [ 8 | 'Dubliners', 9 | 'A Portrait of the Artist as a Young Man', 10 | 'Exiles and poetry', 11 | 'Ulysses', 12 | 'Finnegans Wake' 13 | ] 14 | }, 15 | 16 | 'h-g-wells': { 17 | 'name': 'Herbert George Wells', 18 | 'books': [ 19 | 'The Time Machine', 20 | 'The War of the Worlds', 21 | 'The First Men in the Moon', 22 | 'The Invisible Man' 23 | ] 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /Chapter08/14_universal_data_retrieval/src/components/notFound.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const React = require('react'); 4 | const Link = require('react-router').Link; 5 | 6 | class NotFound extends React.Component { 7 | render() { 8 | return ( 9 |
10 |

Page not found

11 | Go back to index 12 |
13 | ); 14 | } 15 | } 16 | 17 | module.exports = NotFound; 18 | -------------------------------------------------------------------------------- /Chapter08/14_universal_data_retrieval/src/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const React = require('react'); 4 | const ReactDOM = require('react-dom'); 5 | const Routes = require('./routes'); 6 | 7 | window.onload = () => { 8 | ReactDOM.render(, document.getElementById('main')) 9 | }; 10 | -------------------------------------------------------------------------------- /Chapter08/14_universal_data_retrieval/src/routes.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const React = require('react'); 4 | const AsyncProps = require('async-props').default; 5 | const ReactRouter = require('react-router'); 6 | const Router = ReactRouter.Router; 7 | const browserHistory = ReactRouter.browserHistory; 8 | const routesConfig = require('./routesConfig'); 9 | 10 | class Routes extends React.Component { 11 | render() { 12 | return } 16 | />; 17 | } 18 | } 19 | 20 | module.exports = Routes; 21 | -------------------------------------------------------------------------------- /Chapter08/14_universal_data_retrieval/src/routesConfig.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const AuthorsIndex = require('./components/authorsIndex'); 4 | const AuthorPage = require('./components/authorPage'); 5 | const NotFound = require('./components/notFound'); 6 | 7 | const routesConfig = [ 8 | {path: '/', component: AuthorsIndex}, 9 | {path: '/author/:id', component: AuthorPage}, 10 | {path: '*', component: NotFound} 11 | ]; 12 | 13 | module.exports = routesConfig; 14 | -------------------------------------------------------------------------------- /Chapter08/14_universal_data_retrieval/src/xhrClient.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const Axios = require('axios'); 4 | 5 | const baseURL = typeof window !== 'undefined' ? '/api' : 'http://localhost:3001'; 6 | const xhrClient = Axios.create({baseURL}); 7 | 8 | module.exports = xhrClient; 9 | -------------------------------------------------------------------------------- /Chapter08/14_universal_data_retrieval/views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Example - Authors archive 6 | 7 | 8 |
<%- markup %>
9 | 10 | <%- scriptTag %> 11 | 12 | -------------------------------------------------------------------------------- /Chapter08/14_universal_data_retrieval/webpack.config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const path = require('path'); 4 | 5 | module.exports = { 6 | entry: path.join(__dirname, "src", "main.js"), 7 | output: { 8 | path: path.join(__dirname, "dist"), 9 | filename: "bundle.js" 10 | }, 11 | module: { 12 | loaders: [ 13 | { 14 | test: path.join(__dirname, "src"), 15 | loader: 'babel-loader', 16 | query: { 17 | cacheDirectory: 'babel_cache', 18 | presets: ['es2015', 'react'] 19 | } 20 | } 21 | ] 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /Chapter09/01_async_init_wrong/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates the problems we can have when using an asynchronously 2 | initialized module without considering its initialization state. 3 | 4 | To try the sample, first start the server: 5 | node app 6 | 7 | Then with a browser navigate to the url: 8 | http://localhost:8000/say 9 | 10 | Within 10 seconds from the startup of the server, 11 | the expected result should be an error message like the following: 12 | Error:I don't have anything to say right now 13 | 14 | After 10 seconds, the the async module is fully initialized and 15 | the server should start returning the current time: 16 | I say: Current time is: 17 | -------------------------------------------------------------------------------- /Chapter09/01_async_init_wrong/app.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const http = require('http'); 4 | const routes = require('./routes'); 5 | const asyncModule = require('./asyncModule'); 6 | 7 | asyncModule.initialize(() => { 8 | console.log('Async module initialized'); 9 | }); 10 | 11 | http.createServer((req, res) => { 12 | if (req.method === 'GET' && req.url === '/say') { 13 | return routes.say(req, res); 14 | } 15 | res.writeHead(404); 16 | res.end('Not found'); 17 | }).listen(8000, () => console.log('Started')); 18 | 19 | -------------------------------------------------------------------------------- /Chapter09/01_async_init_wrong/asyncModule.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const asyncModule = module.exports; 4 | 5 | asyncModule.initialized = false; 6 | asyncModule.initialize = callback => { 7 | setTimeout(() => { 8 | asyncModule.initialized = true; 9 | callback(); 10 | }, 10000); 11 | }; 12 | 13 | asyncModule.tellMeSomething = callback => { 14 | process.nextTick(() => { 15 | if(!asyncModule.initialized) { 16 | return callback( 17 | new Error('I don\'t have anything to say right now') 18 | ); 19 | } 20 | callback(null, 'Current time is: ' + new Date()); 21 | }); 22 | }; 23 | -------------------------------------------------------------------------------- /Chapter09/01_async_init_wrong/routes.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const asyncModule = require('./asyncModule'); 4 | 5 | module.exports.say = (req, res) => { 6 | asyncModule.tellMeSomething((err, something) => { 7 | if(err) { 8 | res.writeHead(500); 9 | return res.end('Error:' + err.message); 10 | } 11 | res.writeHead(200); 12 | res.end('I say: ' + something); 13 | }); 14 | }; 15 | -------------------------------------------------------------------------------- /Chapter09/02_async_init_queues/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrate how to shield an asynchronously initialized module 2 | from improper usage, by implementing pre-initialization queues. 3 | 4 | To try the sample, first start the server: 5 | node app 6 | 7 | Then with a browser navigate to the url: 8 | http://localhost:8000/say 9 | 10 | The expected result should always be a message containing the current 11 | time, like the following: 12 | I say: Current time is: 13 | -------------------------------------------------------------------------------- /Chapter09/02_async_init_queues/app.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const http = require('http'); 4 | const routes = require('./routes'); 5 | const asyncModule = require('./asyncModuleWrapper'); 6 | 7 | asyncModule.initialize(() => { 8 | console.log('Async module initialized'); 9 | }); 10 | 11 | http.createServer((req, res) => { 12 | if (req.method === 'GET' && req.url === '/say') { 13 | return routes.say(req, res); 14 | } 15 | res.writeHead(404); 16 | res.end('Not found'); 17 | }).listen(8000, () => console.log('Started')); 18 | -------------------------------------------------------------------------------- /Chapter09/02_async_init_queues/asyncModule.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const asyncModule = module.exports; 4 | 5 | asyncModule.initialized = false; 6 | asyncModule.initialize = callback => { 7 | setTimeout(() => { 8 | asyncModule.initialized = true; 9 | callback(); 10 | }, 10000); 11 | }; 12 | 13 | asyncModule.tellMeSomething = callback => { 14 | process.nextTick(() => { 15 | if(!asyncModule.initialized) { 16 | return callback( 17 | new Error('I don\'t have anything to say right now') 18 | ); 19 | } 20 | callback(null, 'Current time is: ' + new Date()); 21 | }); 22 | }; 23 | -------------------------------------------------------------------------------- /Chapter09/02_async_init_queues/routes.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const asyncModule = require('./asyncModuleWrapper'); 4 | 5 | module.exports.say = (req, res) => { 6 | asyncModule.tellMeSomething((err, something) => { 7 | if(err) { 8 | res.writeHead(500); 9 | return res.end('Error:' + err.message); 10 | } 11 | res.writeHead(200); 12 | res.end('I say: ' + something); 13 | }); 14 | }; 15 | -------------------------------------------------------------------------------- /Chapter09/03_batching_and_caching/.gitignore: -------------------------------------------------------------------------------- 1 | example-db/ 2 | -------------------------------------------------------------------------------- /Chapter09/03_batching_and_caching/app.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const http = require('http'); 4 | const url = require('url'); 5 | const totalSales = require('./totalSales'); 6 | //const totalSales = require('./totalSalesBatch'); 7 | //const totalSales = require('./totalSalesCache'); 8 | 9 | http.createServer((req, res) => { 10 | const query = url.parse(req.url, true).query; 11 | totalSales(query.item, (err, sum) => { 12 | res.writeHead(200); 13 | res.end(`Total sales for item ${query.item} is ${sum}`); 14 | }); 15 | }).listen(8000, () => console.log('Started')); 16 | -------------------------------------------------------------------------------- /Chapter09/03_batching_and_caching/appPromises.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const http = require('http'); 4 | const url = require('url'); 5 | const totalSales = require('./totalSalesPromises'); 6 | 7 | http.createServer(function(req, res) { 8 | const query = url.parse(req.url, true).query; 9 | totalSales(query.item).then(function(sum) { 10 | res.writeHead(200); 11 | res.end(`Total sales for item ${query.item} is ${sum}`); 12 | }); 13 | }).listen(8000, function() {console.log('Started')}); 14 | -------------------------------------------------------------------------------- /Chapter09/03_batching_and_caching/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "async": "^0.9.0", 4 | "level": "^0.18.0", 5 | "level-sublevel": "^6.3.15", 6 | "node-uuid": "^1.4.1", 7 | "pify": "^2.3.0", 8 | "request": "^2.47.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Chapter09/03_batching_and_caching/totalSales.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const level = require('level'); 4 | const sublevel = require('level-sublevel'); 5 | 6 | const db = sublevel(level('example-db', {valueEncoding: 'json'})); 7 | const salesDb = db.sublevel('sales'); 8 | 9 | module.exports = function totalSales(item, callback) { 10 | console.log('totalSales() invoked'); 11 | let sum = 0; 12 | salesDb.createValueStream() // [1] 13 | .on('data', data => { 14 | if(!item || data.item === item) { // [2] 15 | sum += data.amount; 16 | } 17 | }) 18 | .on('end', () => { 19 | callback(null, sum); // [3] 20 | }); 21 | }; 22 | -------------------------------------------------------------------------------- /Chapter09/03_batching_and_caching/totalSalesBatch.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const totalSales = require('./totalSales'); 4 | 5 | const queues = {}; 6 | module.exports = function totalSalesBatch(item, callback) { 7 | if(queues[item]) { // [1] 8 | console.log('Batching operation'); 9 | return queues[item].push(callback); 10 | } 11 | 12 | queues[item] = [callback]; // [2] 13 | totalSales(item, (err, res) => { 14 | const queue = queues[item]; // [3] 15 | queues[item] = null; 16 | queue.forEach(cb => cb(err, res)); 17 | }); 18 | }; 19 | -------------------------------------------------------------------------------- /Chapter09/03_batching_and_caching/totalSalesPromises.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const pify = require('pify'); // [1] 4 | const totalSales = pify(require('./totalSales')); 5 | 6 | const cache = {}; 7 | module.exports = function totalSalesPromises(item) { 8 | if (cache[item]) { // [2] 9 | return cache[item]; 10 | } 11 | 12 | cache[item] = totalSales(item) // [3] 13 | .then(res => { // [4] 14 | setTimeout(() => {delete cache[item]}, 30 * 1000); //30 seconds expiry 15 | return res; 16 | }) 17 | .catch(err => { // [5] 18 | delete cache[item]; 19 | throw err; 20 | }); 21 | return cache[item]; // [6] 22 | }; 23 | -------------------------------------------------------------------------------- /Chapter09/04_cpu_bound/subsetSumWorker.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const SubsetSum = require('./subsetSum'); 4 | 5 | process.on('message', msg => { // [1] 6 | const subsetSum = new SubsetSum(msg.sum, msg.set); 7 | 8 | subsetSum.on('match', data => { // [2] 9 | process.send({event: 'match', data: data}); 10 | }); 11 | 12 | subsetSum.on('end', data => { 13 | process.send({event: 'end', data: data}); 14 | }); 15 | 16 | subsetSum.start(); 17 | }); 18 | -------------------------------------------------------------------------------- /Chapter10/01_cluster/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to scale a Node.js application using the cluster module 2 | 3 | To try the sample simply run: 4 | node clusteredApp 5 | -------------------------------------------------------------------------------- /Chapter10/01_cluster/app.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const http = require('http'); 4 | const pid = process.pid; 5 | 6 | http.createServer((req, res) => { 7 | for (let i = 1e7; i > 0; i--) {} 8 | console.log(`Handling request from ${pid}`); 9 | res.end(`Hello from ${pid}\n`); 10 | }).listen(8080, () => { 11 | console.log(`Started ${pid}`); 12 | }); 13 | -------------------------------------------------------------------------------- /Chapter10/01_cluster/clusteredApp.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const cluster = require('cluster'); 4 | const os = require('os'); 5 | 6 | if(cluster.isMaster) { 7 | const cpus = os.cpus().length; 8 | for (let i = 0; i < cpus; i++) { // [1] 9 | cluster.fork(); 10 | } 11 | } else { 12 | require('./app'); // [2] 13 | } 14 | -------------------------------------------------------------------------------- /Chapter10/02_cluster_resiliency/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how a cluster of Node.js processes 2 | can maintain a high availability even in presence of crashes. 3 | 4 | To try the sample simply run: 5 | node clusteredApp 6 | -------------------------------------------------------------------------------- /Chapter10/02_cluster_resiliency/app.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const http = require('http'); 4 | const pid = process.pid; 5 | 6 | http.createServer((req, res) => { 7 | for (let i = 1e7; i > 0; i--) {} 8 | console.log(`Handling request from ${pid}`); 9 | res.end(`Hello from ${pid}\n`); 10 | }).listen(8080, () => { 11 | console.log(`Started ${pid}`); 12 | }); 13 | 14 | //Crash randomly 15 | setTimeout(() => { 16 | throw new Error('Ooops'); 17 | }, Math.ceil(Math.random() * 3) * 1000); 18 | -------------------------------------------------------------------------------- /Chapter10/02_cluster_resiliency/clusteredApp.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const cluster = require('cluster'); 4 | const os = require('os'); 5 | 6 | if (cluster.isMaster) { 7 | const cpus = os.cpus().length; 8 | for (let i = 0; i < cpus; i++) { 9 | cluster.fork(); 10 | } 11 | 12 | cluster.on('exit', (worker, code) => { 13 | if(code != 0) { 14 | console.log('Worker crashed. Starting a new worker'); 15 | cluster.fork(); 16 | } 17 | }); 18 | } else { 19 | require('./app'); 20 | } 21 | -------------------------------------------------------------------------------- /Chapter10/03_cluster_zero_downtime/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to restart a clustered Node.js app 2 | without any interruption in the service (Zero-downtime restart) 3 | 4 | To try the sample run: 5 | node clusteredApp 6 | 7 | To trigger a restart use the command (works only on Linux/MacOS/*nix) 8 | kill -SIGUSR2 9 | -------------------------------------------------------------------------------- /Chapter10/03_cluster_zero_downtime/app.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const http = require('http'); 4 | const pid = process.pid; 5 | 6 | http.createServer((req, res) => { 7 | for (let i = 1e7; i > 0; i--) {} 8 | console.log(`Handling request from ${pid}`); 9 | res.end(`Hello from ${pid}\n`); 10 | }).listen(8080, function() { 11 | console.log(`Started ${pid}`); 12 | }); 13 | -------------------------------------------------------------------------------- /Chapter10/04_reverse_proxy_nginx/README.txt: -------------------------------------------------------------------------------- 1 | This sample shows how to load balance a Node.js application 2 | using Nginx. 3 | 4 | To try the sample, first start multiple instances of the same HTTP server, using different ports: 5 | node app 8081 6 | node app 8082 7 | node app 8083 8 | node app 8084 9 | 10 | Then, use the provided configuration (nginx.patch.conf) as reference to modify the global Nginx configuration file 11 | (usually located into /etc/nginx/nginx.conf). 12 | Then reload the server with: 13 | nginx -s reload 14 | 15 | Access the server at: 16 | http://localhost 17 | -------------------------------------------------------------------------------- /Chapter10/04_reverse_proxy_nginx/app.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const http = require('http'); 4 | const pid = process.pid; 5 | 6 | http.createServer((req, res) => { 7 | for (let i = 1e7; i > 0; i--) {} 8 | console.log(`Handling request from ${pid}`); 9 | res.end(`Hello from ${pid}\n`); 10 | }).listen(process.env.PORT || process.argv[2] || 8080, () => { 11 | console.log(`Started ${pid}`); 12 | }); 13 | -------------------------------------------------------------------------------- /Chapter10/04_reverse_proxy_nginx/nginx.patch.conf: -------------------------------------------------------------------------------- 1 | #Include the following lines into the global nginx.conf 2 | #configuration file 3 | 4 | http { 5 | # [...] 6 | 7 | upstream nodejs_design_patterns_app { 8 | server 127.0.0.1:8081; 9 | server 127.0.0.1:8082; 10 | server 127.0.0.1:8083; 11 | server 127.0.0.1:8084; 12 | } 13 | 14 | # [...] 15 | 16 | server { 17 | listen 80; 18 | 19 | location / { 20 | proxy_pass http://nodejs_design_patterns_app; 21 | } 22 | } 23 | 24 | # [...] 25 | } 26 | -------------------------------------------------------------------------------- /Chapter10/05_service_registry/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "05_service_registry", 3 | "version": "1.0.0", 4 | "description": "This sample shows how to build a Node.js-based load balancer which works in combination with a service registry.", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "consul": "^0.25.0", 13 | "http-proxy": "^1.13.2", 14 | "portfinder": "^1.0.3" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter10/06_peer2peer_loadbalancing/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to distribute the traffic 2 | across multiple servers without the need of a standalone load balancer. 3 | 4 | Start two instances of our sample HTTP server: 5 | node app 8081 6 | node app 8082 7 | 8 | Run the client application with: 9 | node client 10 | -------------------------------------------------------------------------------- /Chapter10/06_peer2peer_loadbalancing/app.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const http = require('http'); 4 | const pid = process.pid; 5 | 6 | http.createServer((req, res) => { 7 | for (let i = 1e7; i > 0; i--) {} 8 | console.log(`Handling request from ${pid}`); 9 | res.end(`Hello from ${pid}\n`); 10 | }).listen(process.argv[2] || 8080, () => { 11 | console.log(`Started ${pid}`); 12 | }); 13 | -------------------------------------------------------------------------------- /Chapter10/06_peer2peer_loadbalancing/balancedRequest.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const http = require('http'); 4 | const servers = [ 5 | {host: 'localhost', port: '8081'}, 6 | {host: 'localhost', port: '8082'} 7 | ]; 8 | 9 | let i = 0; 10 | 11 | module.exports = (options, callback) => { 12 | i = (i + 1) % servers.length; 13 | options.hostname = servers[i].host; 14 | options.port = servers[i].port; 15 | 16 | return http.request(options, callback); 17 | }; 18 | -------------------------------------------------------------------------------- /Chapter10/06_peer2peer_loadbalancing/client.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const request = require('./balancedRequest'); 4 | 5 | for (let i = 10; i >= 0; i--) { 6 | request({method: 'GET', path: '/'}, res => { 7 | let str = ''; 8 | res 9 | .on('data', chunk => { 10 | str += chunk; 11 | }) 12 | .on('end', () => console.log(str)) 13 | ; 14 | }).end(); 15 | } 16 | -------------------------------------------------------------------------------- /Chapter10/07_dynamic_peer2peer_loadbalancing/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to distribute the traffic 2 | across multiple servers without the need of a standalone load balancer. 3 | This is a variation of the previous sample, using a service registry. 4 | 5 | First install the dependencies: 6 | npm install 7 | 8 | Make sure you have a seaport server running 9 | seaport listen 9090 10 | 11 | Start some instances of an api-service server: 12 | node app api-service 13 | node app api-service 14 | 15 | Run the client application with: 16 | node client 17 | -------------------------------------------------------------------------------- /Chapter10/07_dynamic_peer2peer_loadbalancing/app.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const http = require('http'); 4 | const pid = process.pid; 5 | const ports = require('seaport').connect('localhost', 9090); 6 | let serviceType = process.argv[2]; 7 | 8 | console.log(ports.registerMeta(serviceType)); 9 | process.exit(0); 10 | 11 | http.createServer((req, res) => { 12 | for (let i = 1e7; i > 0; i--) {} 13 | console.log(`Handling request from ${pid}`); 14 | res.end(`${serviceType} response from ${pid}\n`); 15 | }).listen(ports.register(serviceType), () => { 16 | console.log(`Started ${pid}`); 17 | }); 18 | -------------------------------------------------------------------------------- /Chapter10/07_dynamic_peer2peer_loadbalancing/client.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const apiRequest = require('./apiRequest'); 4 | 5 | for (let i = 10; i >= 0; i--) { 6 | apiRequest('/api', (err, res, body) => { 7 | if (err) { 8 | return console.log(err); 9 | } 10 | console.log(`Response: ${body}`); 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /Chapter10/07_dynamic_peer2peer_loadbalancing/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "07_dynamic_peer2peer_loadbalancing", 3 | "version": "1.0.0", 4 | "description": "This sample demonstrates how to distribute the traffic across multiple servers without the need of a standalone load balancer. This is a variation of the previous sample, using a service registry.", 5 | "main": "apiRequest.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "request": "^2.69.0", 13 | "seaport": "^2.0.9" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Chapter11/01_basic_chat/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to implement a basic chat application in Node.js 2 | 3 | To try the sample first install the dependencies: 4 | npm install 5 | 6 | Then run: 7 | node app 8 | 9 | To access the application open a browser at the address: 10 | http://localhost:8080 11 | -------------------------------------------------------------------------------- /Chapter11/01_basic_chat/app.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const WebSocketServer = require('ws').Server; 4 | 5 | //static file server 6 | const server = require('http').createServer( //[1] 7 | require('ecstatic')({root: `${__dirname}/www`}) 8 | ); 9 | 10 | const wss = new WebSocketServer({server: server}); //[2] 11 | wss.on('connection', ws => { 12 | console.log('Client connected'); 13 | ws.on('message', msg => { //[3] 14 | console.log(`Message: ${msg}`); 15 | broadcast(msg); 16 | }); 17 | }); 18 | 19 | function broadcast(msg) { //[4] 20 | wss.clients.forEach(client => { 21 | client.send(msg); 22 | }); 23 | } 24 | 25 | server.listen(process.argv[2] || 8080); 26 | -------------------------------------------------------------------------------- /Chapter11/01_basic_chat/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "ecstatic": "^1.4.0", 4 | "ws": "^1.0.1" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Chapter11/02_chat_redis/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to integrate a chat application using Redis as message broker 2 | 3 | As pre-requisite to this sample, you first need to install Redis. 4 | http://redis.io/download 5 | 6 | To try the sample install the dependencies: 7 | npm install 8 | 9 | Then run (in two separate terminals): 10 | node app 8081 11 | node app 8082 12 | 13 | To access the application open a browser at the address: 14 | http://localhost:8081 15 | 16 | And then at the same time open another browser at the following address: 17 | http://localhost:8082 18 | -------------------------------------------------------------------------------- /Chapter11/02_chat_redis/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "ecstatic": "^1.4.0", 4 | "redis": "^2.6.0-1", 5 | "ws": "^1.0.1" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Chapter11/03_chat_zmq/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "ecstatic": "^1.4.0", 4 | "minimist": "^1.2.0", 5 | "ws": "^1.0.1", 6 | "zmq": "^2.14.0" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Chapter11/04_durable_sub/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to integrate a chat application and a history service using AMQP 2 | 3 | As pre-requisite to this sample, you first need to install RabbitMQ 4 | http://www.rabbitmq.com/download.html 5 | 6 | To try the sample, install the dependencies: 7 | npm install 8 | 9 | Then run (in separate terminals): 10 | node app 8080 11 | node app 8081 12 | node historySvc 13 | 14 | You can try to access at the same time those addresses: 15 | http://localhost:8080 16 | http://localhost:8081 17 | -------------------------------------------------------------------------------- /Chapter11/04_durable_sub/msgHistory/000005.ldb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Node.js_Design_Patterns_Second_Edition_Code/8c6b53577c507b4332a8f36ead3cac4a0c67c38c/Chapter11/04_durable_sub/msgHistory/000005.ldb -------------------------------------------------------------------------------- /Chapter11/04_durable_sub/msgHistory/000006.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Node.js_Design_Patterns_Second_Edition_Code/8c6b53577c507b4332a8f36ead3cac4a0c67c38c/Chapter11/04_durable_sub/msgHistory/000006.log -------------------------------------------------------------------------------- /Chapter11/04_durable_sub/msgHistory/CURRENT: -------------------------------------------------------------------------------- 1 | MANIFEST-000004 2 | -------------------------------------------------------------------------------- /Chapter11/04_durable_sub/msgHistory/LOCK: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Node.js_Design_Patterns_Second_Edition_Code/8c6b53577c507b4332a8f36ead3cac4a0c67c38c/Chapter11/04_durable_sub/msgHistory/LOCK -------------------------------------------------------------------------------- /Chapter11/04_durable_sub/msgHistory/LOG: -------------------------------------------------------------------------------- 1 | 2016/04/07-00:34:18.541144 70000051c000 Recovering log #3 2 | 2016/04/07-00:34:18.541697 70000051c000 Level-0 table #5: started 3 | 2016/04/07-00:34:18.543630 70000051c000 Level-0 table #5: 197 bytes OK 4 | 2016/04/07-00:34:18.544573 70000051c000 Delete type=0 #3 5 | 2016/04/07-00:34:18.544657 70000051c000 Delete type=3 #2 6 | -------------------------------------------------------------------------------- /Chapter11/04_durable_sub/msgHistory/LOG.old: -------------------------------------------------------------------------------- 1 | 2016/04/07-00:33:16.573128 700000499000 Delete type=3 #1 2 | -------------------------------------------------------------------------------- /Chapter11/04_durable_sub/msgHistory/MANIFEST-000004: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Node.js_Design_Patterns_Second_Edition_Code/8c6b53577c507b4332a8f36ead3cac4a0c67c38c/Chapter11/04_durable_sub/msgHistory/MANIFEST-000004 -------------------------------------------------------------------------------- /Chapter11/04_durable_sub/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "JSONStream": "^1.1.1", 4 | "amqplib": "^0.4.1", 5 | "ecstatic": "^1.4.0", 6 | "level": "^1.4.0", 7 | "monotonic-timestamp": "0.0.9", 8 | "request": "^2.70.0", 9 | "ws": "^1.0.1" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Chapter11/05_fanout_fanin/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how run parallel tasks using ZMQ 2 | 3 | As pre-requisite to this sample, you first need to install the ZMQ binaries: 4 | http://zeromq.org/intro:get-the-software 5 | 6 | To try the sample, install its dependencies: 7 | npm install 8 | 9 | Then run (in separate terminals): 10 | node worker 11 | node worker 12 | node sink 13 | node ventilator 4 f8e966d1e207d02c44511a58dccff2f5429e9a3b 14 | -------------------------------------------------------------------------------- /Chapter11/05_fanout_fanin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "variations-stream": "^0.1.3", 4 | "zmq": "^2.14.0" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Chapter11/05_fanout_fanin/sink.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const zmq = require('zmq'); 4 | const sink = zmq.socket('pull'); 5 | sink.bindSync("tcp://*:5017"); 6 | 7 | sink.on('message', buffer => { 8 | console.log('Message from worker: ', buffer.toString()); 9 | }); 10 | -------------------------------------------------------------------------------- /Chapter11/06_competing_consumers/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrate how run parallel tasks using AMQP 2 | 3 | As pre-requisite to this sample, you first need to install RabbitMQ 4 | http://www.rabbitmq.com/download.html 5 | 6 | To try the sample install the dependencies: 7 | npm install 8 | 9 | Then run (in separate terminals): 10 | node worker 11 | node worker 12 | node collector 13 | node producer 4 f8e966d1e207d02c44511a58dccff2f5429e9a3b 14 | -------------------------------------------------------------------------------- /Chapter11/06_competing_consumers/collector.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const amqp = require('amqplib'); 4 | 5 | let channel, queue; 6 | amqp 7 | .connect('amqp://localhost') 8 | .then(conn => conn.createChannel()) 9 | .then(ch => { 10 | channel = ch; 11 | return channel.assertQueue('results_queue'); 12 | }) 13 | .then(q => { 14 | queue = q.queue; 15 | channel.consume(queue, msg => { 16 | console.log('Message from worker: ', msg.content.toString()); 17 | }); 18 | }) 19 | .catch(err => console.log(err.stack)) 20 | ; 21 | -------------------------------------------------------------------------------- /Chapter11/06_competing_consumers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "amqplib": "^0.4.1", 4 | "variations-stream": "^0.1.3" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Chapter11/07_correlation_id/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to implement a request/reply pattern on top of a simple point-to-point one-way asynchronous channel. 2 | 3 | To try the sample simply run: 4 | node requestor 5 | -------------------------------------------------------------------------------- /Chapter11/07_correlation_id/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "node-uuid": "^1.4.7" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /Chapter11/07_correlation_id/replier.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const reply = require('./reply')(process); 4 | 5 | reply((req, cb) => { 6 | setTimeout(() => { 7 | cb({sum: req.a + req.b}); 8 | }, req.delay); 9 | }); 10 | -------------------------------------------------------------------------------- /Chapter11/07_correlation_id/reply.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = channel => 4 | { 5 | return function registerHandler(handler) { 6 | channel.on('message', message => { 7 | if (message.type !== 'request') return; 8 | handler(message.data, reply => { 9 | channel.send({ 10 | type: 'response', 11 | data: reply, 12 | inReplyTo: message.id 13 | }); 14 | }); 15 | }); 16 | }; 17 | }; 18 | -------------------------------------------------------------------------------- /Chapter11/07_correlation_id/request.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const uuid = require('node-uuid'); 4 | 5 | module.exports = channel => { 6 | const idToCallbackMap = {}; // [1] 7 | 8 | channel.on('message', message => { // [2] 9 | const handler = idToCallbackMap[message.inReplyTo]; 10 | if(handler) { 11 | handler(message.data); 12 | } 13 | }); 14 | 15 | return function sendRequest(req, callback) { // [3] 16 | const correlationId = uuid.v4(); 17 | idToCallbackMap[correlationId] = callback; 18 | channel.send({ 19 | type: 'request', 20 | data: req, 21 | id: correlationId 22 | }); 23 | }; 24 | }; 25 | -------------------------------------------------------------------------------- /Chapter11/07_correlation_id/requestor.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const replier = require('child_process') 4 | .fork(`${__dirname}/replier.js`); 5 | const request = require('./request')(replier); 6 | 7 | request({a: 1, b: 2, delay: 500}, res => { 8 | console.log('1 + 2 = ', res.sum); 9 | //this should be the last reply we receive, so we close the channel 10 | replier.disconnect(); 11 | }); 12 | 13 | request({a: 6, b: 1, delay: 100}, res => { 14 | console.log('6 + 1 = ', res.sum); 15 | }); 16 | -------------------------------------------------------------------------------- /Chapter11/08_return_address/README.txt: -------------------------------------------------------------------------------- 1 | This sample demonstrates how to implement a request/reply pattern with return address on top of AMQP. 2 | 3 | As pre-requisite to this sample, you first need to install RabbitMQ 4 | http://www.rabbitmq.com/download.html 5 | 6 | To try the sample install the dependencies: 7 | npm install 8 | 9 | Then run (in separate terminals): 10 | node replier 11 | node requestor 12 | -------------------------------------------------------------------------------- /Chapter11/08_return_address/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "amqplib": "^0.4.1", 4 | "node-uuid": "^1.4.7" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Chapter11/08_return_address/replier.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const Reply = require('./amqpReply'); 4 | const reply = Reply('requests_queue'); 5 | 6 | reply.initialize().then(() => { 7 | reply.handleRequest((req, cb) => { 8 | console.log('Request received', req); 9 | cb({sum: req.a + req.b}); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /Chapter11/08_return_address/requestor.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const req = require('./amqpRequest')(); 4 | 5 | req.initialize().then(() => { 6 | for (let i = 100; i > 0; i--) { 7 | sendRandomRequest(); 8 | } 9 | }); 10 | 11 | function sendRandomRequest() { 12 | const a = Math.round(Math.random() * 100); 13 | const b = Math.round(Math.random() * 100); 14 | req.request('requests_queue', {a: a, b: b}, 15 | res => { 16 | console.log(`${a} + ${b} = ${res.sum}`); 17 | } 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /Software and Hardware list.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Node.js_Design_Patterns_Second_Edition_Code/8c6b53577c507b4332a8f36ead3cac4a0c67c38c/Software and Hardware list.pdf --------------------------------------------------------------------------------