├── ch4 ├── cdn-site │ ├── dist │ │ ├── robots.txt │ │ ├── favicon.ico │ │ └── phenomic │ │ │ └── content │ │ │ └── posts │ │ │ ├── item │ │ │ ├── third-post.json │ │ │ ├── fourth-post.json │ │ │ ├── second-post.json │ │ │ └── fifth-post.json │ │ │ └── by-default │ │ │ └── 1 │ │ │ └── desc │ │ │ └── date │ │ │ ├── limit-2.json │ │ │ └── limit-2 │ │ │ ├── after-Zmlyc3QtcG9zdA==.json │ │ │ ├── after-ZmlmdGgtcG9zdA==.json │ │ │ ├── after-Zm91cnRoLXBvc3Q=.json │ │ │ ├── after-dGhpcmQtcG9zdA==.json │ │ │ └── after-c2Vjb25kLXBvc3Q=.json │ ├── .gitignore │ ├── content │ │ └── posts │ │ │ ├── fourth-post.md │ │ │ ├── second-post.md │ │ │ ├── third-post.md │ │ │ ├── fifth-post.md │ │ │ └── first-post.md │ ├── README.md │ └── serverless.yml ├── cdn-json │ ├── .gitignore │ └── package.json ├── cdn-lambda │ ├── .gitignore │ ├── package.json │ └── README.md ├── cdn-service │ ├── .gitignore │ ├── package.json │ ├── README.md │ └── handler.js ├── cdn-invalidate │ ├── .gitignore │ ├── package.json │ └── includes.yml ├── cdn-dns │ ├── .gitignore │ ├── src │ │ ├── index.css │ │ ├── index.js │ │ ├── App.test.js │ │ ├── App.css │ │ └── App.js │ ├── public │ │ ├── favicon.ico │ │ └── manifest.json │ ├── README.md │ ├── serverless.yml │ └── package.json ├── cdn-spa │ ├── .gitignore │ ├── src │ │ ├── index.css │ │ ├── index.js │ │ ├── App.test.js │ │ ├── App.css │ │ └── App.js │ ├── public │ │ ├── favicon.ico │ │ └── manifest.json │ ├── README.md │ ├── serverless.yml │ └── package.json └── README.md ├── ch11 ├── azure │ ├── .gitignore │ ├── handler.js │ ├── package.json │ └── README.md ├── gcp │ ├── .gitignore │ ├── index.js │ ├── package.json │ └── README.md └── README.md ├── ch3 ├── saga │ ├── .gitignore │ ├── data │ │ ├── order.json │ │ └── reservation.json │ └── package.json ├── esg-inbound │ ├── .gitignore │ ├── package.json │ ├── README.md │ └── serverless.yml ├── bff-graphql-crud │ ├── .gitignore │ ├── schema │ │ ├── thing │ │ │ ├── index.js │ │ │ ├── resolvers.js │ │ │ └── typedefs.js │ │ └── index.js │ └── package.json ├── bff-rest-search │ ├── .gitignore │ ├── includes.yml │ └── package.json ├── esg-outbound │ ├── .gitignore │ ├── package.json │ ├── serverless.yml │ └── README.md ├── esg-sqs-inbound │ ├── .gitignore │ ├── package.json │ └── README.md ├── bff-rest-analytics │ ├── .gitignore │ └── package.json ├── event-orchestration │ ├── .gitignore │ ├── data │ │ ├── order.json │ │ └── reservation.json │ ├── package.json │ └── serverless.yml └── README.md ├── ch5 ├── dr │ ├── .gitignore │ ├── recovery-account │ │ └── package.json │ ├── src1-account │ │ └── package.json │ └── README.md ├── waf │ ├── .gitignore │ ├── build │ │ └── index.html │ ├── README.md │ └── package.json ├── graphql-jwt │ ├── .gitignore │ ├── schema │ │ ├── thing │ │ │ ├── index.js │ │ │ ├── resolvers.js │ │ │ ├── model.js │ │ │ └── typedefs.js │ │ └── directives.js │ ├── serverless.yml │ ├── lib │ │ └── fixtures.js │ └── package.json ├── jwt-filter │ ├── .gitignore │ └── package.json ├── ssl-cert │ ├── .gitignore │ ├── build │ │ └── index.html │ ├── README.md │ └── package.json ├── account-as-code │ ├── .gitignore │ ├── package.json │ └── README.md ├── cognito-pool │ ├── .gitignore │ ├── package.json │ └── README.md ├── cognito-authorizer │ ├── .gitignore │ ├── package.json │ ├── handler.js │ ├── serverless.yml │ └── README.md ├── custom-authorizer │ ├── .gitignore │ ├── package.json │ └── README.md ├── envelope-encryption │ ├── .gitignore │ └── package.json ├── cognito-signin │ ├── .gitignore │ ├── src │ │ ├── index.css │ │ ├── index.js │ │ ├── authenticate │ │ │ └── index.js │ │ ├── App.test.js │ │ └── Home.css │ ├── public │ │ ├── favicon.ico │ │ └── manifest.json │ ├── README.md │ └── package.json └── README.md ├── ch2 ├── event-first │ ├── .gitignore │ ├── package.json │ ├── serverless.yml │ └── README.md ├── data-lake-es │ ├── .gitignore │ ├── README.md │ └── package.json ├── data-lake-s3 │ ├── .gitignore │ ├── package.json │ └── README.md ├── db-first-cognito │ ├── .gitignore │ ├── package.json │ └── README.md ├── replaying-events │ ├── .gitignore │ ├── index.js │ ├── handler.js │ ├── serverless.yml │ ├── README.md │ └── package.json ├── bi-directional-sync │ ├── .gitignore │ └── package.json ├── db-first-dynamodb │ ├── .gitignore │ ├── package.json │ └── README.md ├── materialized-view-es │ ├── .gitignore │ └── package.json ├── materialized-view-s3 │ ├── .gitignore │ └── package.json ├── micro-event-store │ ├── .gitignore │ └── package.json ├── materialized-view-cognito │ ├── .gitignore │ └── package.json └── materialized-view-dynamodb │ ├── .gitignore │ ├── package.json │ └── README.md ├── ch6 ├── pipeline │ ├── .gitignore │ ├── .npmrc-conf │ ├── README.md │ ├── serverless.yml │ ├── package.json │ └── .gitlab-ci.yml ├── unit-testing │ ├── .eslintignore │ ├── test │ │ ├── helper.js │ │ └── unit │ │ │ └── utils │ │ │ └── index.test.js │ ├── .npmrc-conf │ ├── .gitignore │ ├── README.md │ ├── .editorconfig │ ├── .nycrc │ ├── src │ │ ├── connector │ │ │ └── stream.js │ │ └── get │ │ │ └── index.js │ ├── .babelrc │ └── .gitlab-ci.yml ├── integration-testing │ ├── .eslintignore │ ├── test │ │ ├── helper.js │ │ ├── int │ │ │ ├── mocks.js │ │ │ └── save │ │ │ │ └── index.test.js │ │ └── unit │ │ │ └── utils │ │ │ └── index.test.js │ ├── .npmrc-conf │ ├── .gitignore │ ├── README.md │ ├── .editorconfig │ ├── .nycrc │ ├── src │ │ ├── connector │ │ │ └── stream.js │ │ └── get │ │ │ └── index.js │ ├── .babelrc │ └── fixtures │ │ └── dynamodb.us-east-1.amazonaws.com-443 │ │ ├── save │ │ └── get ├── feature-flag │ ├── .gitignore │ ├── src │ │ ├── index.css │ │ ├── index.js │ │ ├── authenticate │ │ │ └── index.js │ │ ├── App.test.js │ │ └── Home.css │ ├── public │ │ ├── favicon.ico │ │ └── manifest.json │ ├── README.md │ └── package.json ├── contract-testing-sync │ ├── bff │ │ ├── .eslintignore │ │ ├── test │ │ │ ├── helper.js │ │ │ ├── int │ │ │ │ ├── mocks.js │ │ │ │ └── save │ │ │ │ │ └── index.test.js │ │ │ └── unit │ │ │ │ └── utils │ │ │ │ └── index.test.js │ │ ├── .npmrc-conf │ │ ├── .gitignore │ │ ├── fixtures │ │ │ ├── frontend │ │ │ │ ├── get │ │ │ │ └── save │ │ │ └── dynamodb.us-east-1.amazonaws.com-443 │ │ │ │ ├── save │ │ │ │ └── get │ │ ├── .editorconfig │ │ ├── .nycrc │ │ ├── .babelrc │ │ └── src │ │ │ └── get │ │ │ └── index.js │ ├── frontend │ │ ├── .gitignore │ │ ├── package.json │ │ └── fixtures │ │ │ └── 0.0.0.0-3001 │ │ │ ├── get │ │ │ └── save │ └── README.md ├── transitive-testing │ ├── author-bff │ │ ├── .eslintignore │ │ ├── test │ │ │ ├── helper.js │ │ │ ├── int │ │ │ │ └── mocks.js │ │ │ └── unit │ │ │ │ └── utils │ │ │ │ └── index.test.js │ │ ├── .npmrc-conf │ │ ├── .gitignore │ │ ├── fixtures │ │ │ ├── author-frontend │ │ │ │ ├── get-thing0 │ │ │ │ └── save-thing0 │ │ │ └── dynamodb.us-east-1.amazonaws.com-443 │ │ │ │ ├── save-thing0 │ │ │ │ └── get-thing0 │ │ ├── .editorconfig │ │ ├── .nycrc │ │ ├── src │ │ │ ├── connector │ │ │ │ └── stream.js │ │ │ └── get │ │ │ │ └── index.js │ │ └── .babelrc │ ├── customer-bff │ │ ├── .eslintignore │ │ ├── test │ │ │ ├── helper.js │ │ │ ├── int │ │ │ │ ├── mocks.js │ │ │ │ └── upstream-author-bff │ │ │ │ │ └── e2e.test.js │ │ │ └── unit │ │ │ │ └── utils │ │ │ │ └── index.test.js │ │ ├── .npmrc-conf │ │ ├── .gitignore │ │ ├── fixtures │ │ │ ├── customer-frontend │ │ │ │ └── get-thing0 │ │ │ └── dynamodb.us-east-1.amazonaws.com-443 │ │ │ │ └── save-thing0 │ │ ├── .editorconfig │ │ ├── .nycrc │ │ ├── .babelrc │ │ └── src │ │ │ └── get │ │ │ └── index.js │ ├── author-frontend │ │ ├── .gitignore │ │ ├── package.json │ │ └── fixtures │ │ │ └── 0.0.0.0-3001 │ │ │ ├── get-thing0 │ │ │ └── save-thing0 │ └── customer-frontend │ │ ├── .gitignore │ │ ├── package.json │ │ └── fixtures │ │ └── 0.0.0.0-3001 │ │ └── get-thing0 ├── contract-testing-async │ ├── downstream │ │ ├── .eslintignore │ │ ├── test │ │ │ ├── helper.js │ │ │ ├── int │ │ │ │ ├── mocks.js │ │ │ │ └── upstream-provider-y │ │ │ │ │ └── contract.test.js │ │ │ └── unit │ │ │ │ └── utils │ │ │ │ └── index.test.js │ │ ├── .npmrc-conf │ │ ├── .gitignore │ │ ├── .editorconfig │ │ ├── .nycrc │ │ ├── .babelrc │ │ ├── src │ │ │ └── get │ │ │ │ └── index.js │ │ └── fixtures │ │ │ └── dynamodb.us-east-1.amazonaws.com-443 │ │ │ └── save │ ├── upstream │ │ ├── .eslintignore │ │ ├── test │ │ │ ├── helper.js │ │ │ ├── int │ │ │ │ ├── mocks.js │ │ │ │ └── save │ │ │ │ │ └── index.test.js │ │ │ └── unit │ │ │ │ └── utils │ │ │ │ └── index.test.js │ │ ├── .npmrc-conf │ │ ├── .gitignore │ │ ├── .editorconfig │ │ ├── .nycrc │ │ ├── .babelrc │ │ ├── src │ │ │ └── connector │ │ │ │ └── stream.js │ │ └── fixtures │ │ │ └── dynamodb.us-east-1.amazonaws.com-443 │ │ │ └── save │ └── README.md └── README.md ├── ch1 ├── create-function │ ├── .gitignore │ ├── serverless.yml │ ├── handler.js │ ├── package.json │ └── README.md ├── create-stack │ ├── .gitignore │ ├── serverless.yml │ ├── README.md │ └── package.json ├── event-stream │ ├── .gitignore │ ├── package.json │ └── README.md ├── create-api-gateway │ ├── .gitignore │ ├── serverless.yml │ ├── package.json │ ├── handler.js │ └── README.md ├── create-stream-processor │ ├── .gitignore │ ├── serverless.yml │ ├── package.json │ ├── README.md │ └── handler.js ├── deploy-spa │ ├── .gitignore │ ├── src │ │ ├── index.css │ │ ├── index.js │ │ ├── App.test.js │ │ ├── App.css │ │ └── App.js │ ├── public │ │ ├── favicon.ico │ │ └── manifest.json │ ├── README.md │ └── package.json └── README.md ├── ch7 ├── custom-metrics │ ├── .gitignore │ ├── README.md │ ├── serverless.yml │ ├── package.json │ └── handler.js ├── datadog-account │ ├── .gitignore │ ├── handler.js │ ├── package.json │ └── README.md ├── event-metrics │ ├── .gitignore │ ├── README.md │ └── package.json ├── synthetics │ ├── .gitignore │ ├── src │ │ ├── index.css │ │ ├── index.js │ │ ├── authenticate │ │ │ └── index.js │ │ ├── App.test.js │ │ └── Home.css │ ├── public │ │ ├── favicon.ico │ │ └── manifest.json │ ├── serverless.yml │ ├── README.md │ └── package.json └── README.md ├── ch8 ├── handling-faults │ ├── .gitignore │ ├── package.json │ └── README.md ├── idempotence-es │ ├── .gitignore │ ├── package.json │ └── README.md ├── timeout-retry │ ├── .gitignore │ ├── package.json │ ├── README.md │ └── handler.js ├── resubmitting-faults │ ├── .gitignore │ ├── cli │ │ ├── serverless.yml │ │ ├── index.js │ │ └── package.json │ ├── simulator │ │ └── package.json │ └── monitor │ │ └── package.json ├── backpressure-ratelimit │ ├── .gitignore │ ├── package.json │ └── README.md ├── idempotence-inverse-oplock │ ├── .gitignore │ ├── package.json │ └── README.md └── README.md ├── ch9 ├── cache-control │ ├── .gitignore │ ├── package.json │ └── README.md ├── frp-batching │ ├── .gitignore │ ├── README.md │ └── package.json ├── frp-grouping │ ├── .gitignore │ ├── README.md │ └── package.json ├── dynamodb-autoscaling │ ├── .gitignore │ ├── README.md │ └── package.json ├── frp-async-non-blocking-io │ ├── .gitignore │ ├── package.json │ └── README.md ├── session-consistency │ ├── service │ │ ├── .gitignore │ │ ├── schema │ │ │ ├── thing │ │ │ │ ├── index.js │ │ │ │ ├── resolvers.js │ │ │ │ └── typedefs.js │ │ │ └── index.js │ │ └── package.json │ └── spa │ │ ├── .gitignore │ │ ├── src │ │ ├── index.css │ │ ├── App.test.js │ │ ├── App.css │ │ └── index.js │ │ ├── public │ │ ├── favicon.ico │ │ └── manifest.json │ │ └── package.json ├── tuning-faas │ ├── .gitignore │ ├── README.md │ ├── src │ │ ├── connector │ │ │ └── stream.js │ │ └── get │ │ │ └── index.js │ └── .babelrc └── README.md └── ch10 ├── regional-failover ├── .gitignore ├── check │ ├── handler.js │ └── package.json └── service │ ├── package.json │ └── handler.js ├── dynamodb-global-table ├── .gitignore └── package.json ├── latency-based-routing ├── .gitignore ├── package.json ├── handler.js └── README.md ├── regional-health-check ├── .gitignore ├── package.json └── README.md ├── round-robin-replication ├── .gitignore ├── includes.yml └── package.json └── README.md /ch4/cdn-site/dist/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /ch11/azure/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch11/gcp/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch3/saga/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch5/dr/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch5/waf/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch2/event-first/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch3/esg-inbound/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch4/cdn-json/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch4/cdn-lambda/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch4/cdn-service/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch5/graphql-jwt/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch5/jwt-filter/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch5/ssl-cert/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch6/pipeline/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch1/create-function/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch1/create-stack/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch1/event-stream/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch2/data-lake-es/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch2/data-lake-s3/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch2/db-first-cognito/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch2/replaying-events/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch3/bff-graphql-crud/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch3/bff-rest-search/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch3/esg-outbound/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch3/esg-sqs-inbound/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch4/cdn-invalidate/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch4/cdn-site/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log 5 | -------------------------------------------------------------------------------- /ch5/account-as-code/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch5/cognito-pool/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch7/custom-metrics/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch7/datadog-account/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch7/event-metrics/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch8/handling-faults/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch8/idempotence-es/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch8/timeout-retry/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch9/cache-control/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch9/frp-batching/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch9/frp-grouping/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch1/create-api-gateway/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch10/regional-failover/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch2/bi-directional-sync/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch2/db-first-dynamodb/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch2/materialized-view-es/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch2/materialized-view-s3/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch2/micro-event-store/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch3/bff-rest-analytics/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch3/event-orchestration/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch5/cognito-authorizer/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch5/custom-authorizer/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch5/envelope-encryption/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch6/unit-testing/.eslintignore: -------------------------------------------------------------------------------- 1 | tools/ 2 | lib/ 3 | coverage/ 4 | webpack.config.js 5 | -------------------------------------------------------------------------------- /ch8/resubmitting-faults/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch8/resubmitting-faults/cli/serverless.yml: -------------------------------------------------------------------------------- 1 | service: cncb-resubmitting-faults-cli 2 | -------------------------------------------------------------------------------- /ch9/dynamodb-autoscaling/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch1/create-stream-processor/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch1/deploy-spa/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | .serverless 4 | .DS_Store 5 | *.log 6 | -------------------------------------------------------------------------------- /ch10/dynamodb-global-table/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch10/latency-based-routing/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch10/regional-health-check/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch10/round-robin-replication/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch2/materialized-view-cognito/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch2/materialized-view-dynamodb/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch4/cdn-dns/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | .serverless 4 | .DS_Store 5 | *.log 6 | -------------------------------------------------------------------------------- /ch4/cdn-spa/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | .serverless 4 | .DS_Store 5 | *.log 6 | -------------------------------------------------------------------------------- /ch6/integration-testing/.eslintignore: -------------------------------------------------------------------------------- 1 | tools/ 2 | lib/ 3 | coverage/ 4 | webpack.config.js 5 | -------------------------------------------------------------------------------- /ch7/synthetics/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | .serverless 4 | .DS_Store 5 | *.log 6 | -------------------------------------------------------------------------------- /ch8/backpressure-ratelimit/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch8/idempotence-inverse-oplock/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch9/frp-async-non-blocking-io/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch1/create-stack/serverless.yml: -------------------------------------------------------------------------------- 1 | service: cncb-create-stack 2 | 3 | provider: 4 | name: aws 5 | -------------------------------------------------------------------------------- /ch5/cognito-signin/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | .serverless 4 | .DS_Store 5 | *.log 6 | -------------------------------------------------------------------------------- /ch6/feature-flag/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | .serverless 4 | .DS_Store 5 | *.log 6 | -------------------------------------------------------------------------------- /ch9/session-consistency/service/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .serverless 3 | .DS_Store 4 | *.log -------------------------------------------------------------------------------- /ch6/contract-testing-sync/bff/.eslintignore: -------------------------------------------------------------------------------- 1 | tools/ 2 | lib/ 3 | coverage/ 4 | webpack.config.js 5 | -------------------------------------------------------------------------------- /ch6/transitive-testing/author-bff/.eslintignore: -------------------------------------------------------------------------------- 1 | tools/ 2 | lib/ 3 | coverage/ 4 | webpack.config.js 5 | -------------------------------------------------------------------------------- /ch4/cdn-dns/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /ch4/cdn-spa/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/downstream/.eslintignore: -------------------------------------------------------------------------------- 1 | tools/ 2 | lib/ 3 | coverage/ 4 | webpack.config.js 5 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/upstream/.eslintignore: -------------------------------------------------------------------------------- 1 | tools/ 2 | lib/ 3 | coverage/ 4 | webpack.config.js 5 | -------------------------------------------------------------------------------- /ch6/transitive-testing/customer-bff/.eslintignore: -------------------------------------------------------------------------------- 1 | tools/ 2 | lib/ 3 | coverage/ 4 | webpack.config.js 5 | -------------------------------------------------------------------------------- /ch9/session-consistency/spa/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | .serverless 4 | .DS_Store 5 | *.log 6 | -------------------------------------------------------------------------------- /ch1/deploy-spa/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /ch6/feature-flag/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /ch7/synthetics/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /ch5/cognito-signin/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /ch3/saga/data/order.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "33333333-7777-1111-1111-111111111111", 3 | "sku": "1", 4 | "quantity": 1 5 | } -------------------------------------------------------------------------------- /ch4/cdn-site/content/posts/fourth-post.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Fourth post" 3 | date: "2017-01-04" 4 | --- 5 | 6 | Another post 7 | -------------------------------------------------------------------------------- /ch4/cdn-site/content/posts/second-post.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Second post" 3 | date: "2017-01-02" 4 | --- 5 | 6 | Another post 7 | -------------------------------------------------------------------------------- /ch4/cdn-site/dist/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanteInc/js-cloud-native-cookbook/HEAD/ch4/cdn-site/dist/favicon.ico -------------------------------------------------------------------------------- /ch9/session-consistency/spa/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /ch4/cdn-dns/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanteInc/js-cloud-native-cookbook/HEAD/ch4/cdn-dns/public/favicon.ico -------------------------------------------------------------------------------- /ch4/cdn-spa/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanteInc/js-cloud-native-cookbook/HEAD/ch4/cdn-spa/public/favicon.ico -------------------------------------------------------------------------------- /ch6/unit-testing/test/helper.js: -------------------------------------------------------------------------------- 1 | import chai from 'chai'; 2 | import sinonChai from 'sinon-chai'; 3 | 4 | chai.use(sinonChai); 5 | -------------------------------------------------------------------------------- /ch1/deploy-spa/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanteInc/js-cloud-native-cookbook/HEAD/ch1/deploy-spa/public/favicon.ico -------------------------------------------------------------------------------- /ch4/cdn-site/content/posts/third-post.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Third post" 3 | date: "2017-01-03" 4 | --- 5 | 6 | Another postttttttttttt 7 | -------------------------------------------------------------------------------- /ch6/integration-testing/test/helper.js: -------------------------------------------------------------------------------- 1 | import chai from 'chai'; 2 | import sinonChai from 'sinon-chai'; 3 | 4 | chai.use(sinonChai); 5 | -------------------------------------------------------------------------------- /ch7/synthetics/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanteInc/js-cloud-native-cookbook/HEAD/ch7/synthetics/public/favicon.ico -------------------------------------------------------------------------------- /ch2/replaying-events/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('yargs') 3 | .commandDir('lib') 4 | .demandCommand() 5 | .help() 6 | .argv -------------------------------------------------------------------------------- /ch5/cognito-signin/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanteInc/js-cloud-native-cookbook/HEAD/ch5/cognito-signin/public/favicon.ico -------------------------------------------------------------------------------- /ch6/contract-testing-sync/bff/test/helper.js: -------------------------------------------------------------------------------- 1 | import chai from 'chai'; 2 | import sinonChai from 'sinon-chai'; 3 | 4 | chai.use(sinonChai); 5 | -------------------------------------------------------------------------------- /ch6/feature-flag/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanteInc/js-cloud-native-cookbook/HEAD/ch6/feature-flag/public/favicon.ico -------------------------------------------------------------------------------- /ch6/transitive-testing/author-bff/test/helper.js: -------------------------------------------------------------------------------- 1 | import chai from 'chai'; 2 | import sinonChai from 'sinon-chai'; 3 | 4 | chai.use(sinonChai); 5 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/downstream/test/helper.js: -------------------------------------------------------------------------------- 1 | import chai from 'chai'; 2 | import sinonChai from 'sinon-chai'; 3 | 4 | chai.use(sinonChai); 5 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/upstream/test/helper.js: -------------------------------------------------------------------------------- 1 | import chai from 'chai'; 2 | import sinonChai from 'sinon-chai'; 3 | 4 | chai.use(sinonChai); 5 | -------------------------------------------------------------------------------- /ch6/transitive-testing/customer-bff/test/helper.js: -------------------------------------------------------------------------------- 1 | import chai from 'chai'; 2 | import sinonChai from 'sinon-chai'; 3 | 4 | chai.use(sinonChai); 5 | -------------------------------------------------------------------------------- /ch8/resubmitting-faults/cli/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('yargs') 3 | .commandDir('lib') 4 | .demandCommand() 5 | .help() 6 | .argv -------------------------------------------------------------------------------- /ch6/pipeline/.npmrc-conf: -------------------------------------------------------------------------------- 1 | @my:registry=https://npm.my.example.com/ 2 | //npm.my.example.com/:_authToken=${NPM_TOKEN} 3 | //npm.my.example.com/:always-auth=true 4 | -------------------------------------------------------------------------------- /ch9/session-consistency/spa/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DanteInc/js-cloud-native-cookbook/HEAD/ch9/session-consistency/spa/public/favicon.ico -------------------------------------------------------------------------------- /ch11/README.md: -------------------------------------------------------------------------------- 1 | # Welcoming Polycloud 2 | 3 | 1. [Creating a service with Google Cloud Functions](./gcp) 4 | 2. [Creating a service with Azure Functions](./azure) 5 | -------------------------------------------------------------------------------- /ch4/cdn-site/dist/phenomic/content/posts/item/third-post.json: -------------------------------------------------------------------------------- 1 | {"filename":"third-post.md","title":"Third post","date":"2017-01-03","body":{"t":"p","c":["Another post"]}} -------------------------------------------------------------------------------- /ch6/unit-testing/.npmrc-conf: -------------------------------------------------------------------------------- 1 | @my:registry=https://npm.my.example.com/ 2 | //npm.my.example.com/:_authToken=${NPM_TOKEN} 3 | //npm.my.example.com/:always-auth=true 4 | -------------------------------------------------------------------------------- /ch4/cdn-site/dist/phenomic/content/posts/item/fourth-post.json: -------------------------------------------------------------------------------- 1 | {"filename":"fourth-post.md","title":"Fourth post","date":"2017-01-04","body":{"t":"p","c":["Another post"]}} -------------------------------------------------------------------------------- /ch4/cdn-site/dist/phenomic/content/posts/item/second-post.json: -------------------------------------------------------------------------------- 1 | {"filename":"second-post.md","title":"Second post","date":"2017-01-02","body":{"t":"p","c":["Another post"]}} -------------------------------------------------------------------------------- /ch6/integration-testing/.npmrc-conf: -------------------------------------------------------------------------------- 1 | @my:registry=https://npm.my.example.com/ 2 | //npm.my.example.com/:_authToken=${NPM_TOKEN} 3 | //npm.my.example.com/:always-auth=true 4 | -------------------------------------------------------------------------------- /ch6/unit-testing/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .serverless 5 | .webpack 6 | *.log 7 | .vscode 8 | .eslintcache 9 | .DS_Store 10 | 11 | -------------------------------------------------------------------------------- /ch7/datadog-account/handler.js: -------------------------------------------------------------------------------- 1 | module.exports.hello = (event, context, callback) => { 2 | console.log('event: %j', event); 3 | callback(null, 'success'); 4 | }; 5 | -------------------------------------------------------------------------------- /ch9/tuning-faas/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .serverless 5 | .webpack 6 | *.log 7 | .vscode 8 | .eslintcache 9 | .DS_Store 10 | 11 | -------------------------------------------------------------------------------- /ch6/integration-testing/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .serverless 5 | .webpack 6 | *.log 7 | .vscode 8 | .eslintcache 9 | .DS_Store 10 | 11 | -------------------------------------------------------------------------------- /ch2/replaying-events/handler.js: -------------------------------------------------------------------------------- 1 | module.exports.listener = (event, context, callback) => { 2 | console.log('event: %j', event); 3 | 4 | callback(null, 'success'); 5 | }; 6 | -------------------------------------------------------------------------------- /ch6/contract-testing-sync/bff/.npmrc-conf: -------------------------------------------------------------------------------- 1 | @my:registry=https://npm.my.example.com/ 2 | //npm.my.example.com/:_authToken=${NPM_TOKEN} 3 | //npm.my.example.com/:always-auth=true 4 | -------------------------------------------------------------------------------- /ch6/transitive-testing/author-bff/.npmrc-conf: -------------------------------------------------------------------------------- 1 | @my:registry=https://npm.my.example.com/ 2 | //npm.my.example.com/:_authToken=${NPM_TOKEN} 3 | //npm.my.example.com/:always-auth=true 4 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/downstream/.npmrc-conf: -------------------------------------------------------------------------------- 1 | @my:registry=https://npm.my.example.com/ 2 | //npm.my.example.com/:_authToken=${NPM_TOKEN} 3 | //npm.my.example.com/:always-auth=true 4 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/upstream/.npmrc-conf: -------------------------------------------------------------------------------- 1 | @my:registry=https://npm.my.example.com/ 2 | //npm.my.example.com/:_authToken=${NPM_TOKEN} 3 | //npm.my.example.com/:always-auth=true 4 | -------------------------------------------------------------------------------- /ch6/contract-testing-sync/bff/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .serverless 5 | .webpack 6 | *.log 7 | .vscode 8 | .eslintcache 9 | .DS_Store 10 | 11 | -------------------------------------------------------------------------------- /ch6/transitive-testing/author-bff/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .serverless 5 | .webpack 6 | *.log 7 | .vscode 8 | .eslintcache 9 | .DS_Store 10 | 11 | -------------------------------------------------------------------------------- /ch6/transitive-testing/customer-bff/.npmrc-conf: -------------------------------------------------------------------------------- 1 | @my:registry=https://npm.my.example.com/ 2 | //npm.my.example.com/:_authToken=${NPM_TOKEN} 3 | //npm.my.example.com/:always-auth=true 4 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/downstream/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .serverless 5 | .webpack 6 | *.log 7 | .vscode 8 | .eslintcache 9 | .DS_Store 10 | 11 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/upstream/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .serverless 5 | .webpack 6 | *.log 7 | .vscode 8 | .eslintcache 9 | .DS_Store 10 | 11 | -------------------------------------------------------------------------------- /ch6/contract-testing-sync/frontend/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .serverless 5 | .webpack 6 | *.log 7 | .vscode 8 | .eslintcache 9 | .DS_Store 10 | 11 | -------------------------------------------------------------------------------- /ch6/transitive-testing/author-frontend/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .serverless 5 | .webpack 6 | *.log 7 | .vscode 8 | .eslintcache 9 | .DS_Store 10 | 11 | -------------------------------------------------------------------------------- /ch6/transitive-testing/customer-bff/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .serverless 5 | .webpack 6 | *.log 7 | .vscode 8 | .eslintcache 9 | .DS_Store 10 | 11 | -------------------------------------------------------------------------------- /ch6/transitive-testing/customer-frontend/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .serverless 5 | .webpack 6 | *.log 7 | .vscode 8 | .eslintcache 9 | .DS_Store 10 | 11 | -------------------------------------------------------------------------------- /ch5/graphql-jwt/schema/thing/index.js: -------------------------------------------------------------------------------- 1 | module.exports.thingTypeDefs = require('./typedefs'); 2 | module.exports.thingResolvers = require('./resolvers'); 3 | module.exports.Thing = require('./model'); 4 | -------------------------------------------------------------------------------- /ch3/bff-graphql-crud/schema/thing/index.js: -------------------------------------------------------------------------------- 1 | module.exports.thingTypeDefs = require('./typedefs'); 2 | module.exports.thingResolvers = require('./resolvers'); 3 | module.exports.Thing = require('./model'); 4 | -------------------------------------------------------------------------------- /ch5/waf/build/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

JavaScript Cloud Native Development Cookbook!

5 |

Your WAF allowed you to successfully access this page!

6 | 7 | 8 | -------------------------------------------------------------------------------- /ch2/replaying-events/serverless.yml: -------------------------------------------------------------------------------- 1 | service: cncb-replaying-events 2 | 3 | provider: 4 | name: aws 5 | runtime: nodejs8.10 6 | 7 | functions: 8 | listener: 9 | handler: handler.listener 10 | -------------------------------------------------------------------------------- /ch5/ssl-cert/build/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

JavaScript Cloud Native Development Cookbook!

5 |

Your secure single page application loaded successfully!

6 | 7 | 8 | -------------------------------------------------------------------------------- /ch6/integration-testing/test/int/mocks.js: -------------------------------------------------------------------------------- 1 | import * as sinon from 'sinon'; 2 | import * as utils from '../../src/utils'; 3 | 4 | sinon.stub(utils, 'uuidv4') 5 | .returns('00000000-0000-0000-0000-000000000000'); 6 | -------------------------------------------------------------------------------- /ch9/session-consistency/service/schema/thing/index.js: -------------------------------------------------------------------------------- 1 | module.exports.thingTypeDefs = require('./typedefs'); 2 | module.exports.thingResolvers = require('./resolvers'); 3 | module.exports.Thing = require('./model'); 4 | -------------------------------------------------------------------------------- /ch1/deploy-spa/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | -------------------------------------------------------------------------------- /ch5/cognito-signin/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | -------------------------------------------------------------------------------- /ch6/contract-testing-sync/bff/test/int/mocks.js: -------------------------------------------------------------------------------- 1 | import * as sinon from 'sinon'; 2 | import * as utils from '../../src/utils'; 3 | 4 | sinon.stub(utils, 'uuidv4') 5 | .returns('00000000-0000-0000-0000-000000000000'); 6 | -------------------------------------------------------------------------------- /ch6/feature-flag/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | -------------------------------------------------------------------------------- /ch7/synthetics/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/upstream/test/int/mocks.js: -------------------------------------------------------------------------------- 1 | import * as sinon from 'sinon'; 2 | import * as utils from '../../src/utils'; 3 | 4 | sinon.stub(utils, 'uuidv4') 5 | .returns('00000000-0000-0000-0000-000000000000'); 6 | -------------------------------------------------------------------------------- /ch6/transitive-testing/author-bff/test/int/mocks.js: -------------------------------------------------------------------------------- 1 | import * as sinon from 'sinon'; 2 | import * as utils from '../../src/utils'; 3 | 4 | sinon.stub(utils, 'uuidv4') 5 | .returns('00000000-0000-0000-0000-000000000000'); 6 | -------------------------------------------------------------------------------- /ch6/transitive-testing/customer-bff/test/int/mocks.js: -------------------------------------------------------------------------------- 1 | import * as sinon from 'sinon'; 2 | import * as utils from '../../src/utils'; 3 | 4 | sinon.stub(utils, 'uuidv4') 5 | .returns('00000000-0000-0000-0000-000000000000'); 6 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/downstream/test/int/mocks.js: -------------------------------------------------------------------------------- 1 | import * as sinon from 'sinon'; 2 | import * as utils from '../../src/utils'; 3 | 4 | sinon.stub(utils, 'uuidv4') 5 | .returns('00000000-0000-0000-0000-000000000000'); 6 | -------------------------------------------------------------------------------- /ch1/create-function/serverless.yml: -------------------------------------------------------------------------------- 1 | service: cncb-create-function 2 | 3 | provider: 4 | name: aws 5 | runtime: nodejs8.10 6 | environment: 7 | V1: value1 8 | 9 | functions: 10 | hello: 11 | handler: handler.hello 12 | -------------------------------------------------------------------------------- /ch1/create-function/handler.js: -------------------------------------------------------------------------------- 1 | module.exports.hello = (event, context, callback) => { 2 | console.log('event: %j', event); 3 | console.log('context: %j', context); 4 | console.log('env: %j', process.env); 5 | 6 | callback(null, 'success'); 7 | }; 8 | -------------------------------------------------------------------------------- /ch3/event-orchestration/data/order.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "33333333-6666-0000-1111-111111111111", 3 | "type": "order-submitted", 4 | "order": { 5 | "id": "33333333-6666-1111-1111-111111111111", 6 | "sku": "1", 7 | "quantity": 1 8 | } 9 | } -------------------------------------------------------------------------------- /ch6/feature-flag/src/authenticate/index.js: -------------------------------------------------------------------------------- 1 | export { default as CognitoSecurity } from './auth'; 2 | export { default as withAuth } from './withAuth'; 3 | export { default as SecureRoute } from './secureRoute'; 4 | export { default as ImplicitCallback } from './implicitCallback'; 5 | -------------------------------------------------------------------------------- /ch6/unit-testing/README.md: -------------------------------------------------------------------------------- 1 | # Writing unit tests 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch6/unit-testing --path cncb-unit-testing 5 | 2. cd cncb-unit-testing 6 | 3. npm install 7 | 4. npm test 8 | -------------------------------------------------------------------------------- /ch7/synthetics/src/authenticate/index.js: -------------------------------------------------------------------------------- 1 | export { default as CognitoSecurity } from './auth'; 2 | export { default as withAuth } from './withAuth'; 3 | export { default as SecureRoute } from './secureRoute'; 4 | export { default as ImplicitCallback } from './implicitCallback'; 5 | -------------------------------------------------------------------------------- /ch5/cognito-signin/src/authenticate/index.js: -------------------------------------------------------------------------------- 1 | export { default as CognitoSecurity } from './auth'; 2 | export { default as withAuth } from './withAuth'; 3 | export { default as SecureRoute } from './secureRoute'; 4 | export { default as ImplicitCallback } from './implicitCallback'; 5 | -------------------------------------------------------------------------------- /ch6/unit-testing/test/unit/utils/index.test.js: -------------------------------------------------------------------------------- 1 | import 'mocha'; 2 | import { expect } from 'chai'; 3 | import { uuidv4 } from '../../../src/utils'; 4 | 5 | describe('utils/index.js', () => { 6 | it('should create a uuid', () => { 7 | expect(uuidv4()).to.not.equal(null); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /ch4/cdn-dns/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import registerServiceWorker from './registerServiceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | registerServiceWorker(); 9 | -------------------------------------------------------------------------------- /ch4/cdn-spa/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import registerServiceWorker from './registerServiceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | registerServiceWorker(); 9 | -------------------------------------------------------------------------------- /ch7/README.md: -------------------------------------------------------------------------------- 1 | # Optimizing Observability 2 | 3 | 1. [Monitoring a cloud-native system](./datadog-account) 4 | 2. [Implementing custom metrics](./custom-metrics) 5 | 3. [Monitoring domain events](./event-metrics) 6 | 4. [Creating alerts](README.md) 7 | 5. [Creating synthetic transaction tests](./synthetics) 8 | -------------------------------------------------------------------------------- /ch6/integration-testing/test/unit/utils/index.test.js: -------------------------------------------------------------------------------- 1 | import 'mocha'; 2 | import { expect } from 'chai'; 3 | import { uuidv4 } from '../../../src/utils'; 4 | 5 | describe('utils/index.js', () => { 6 | it('should create a uuid', () => { 7 | expect(uuidv4()).to.not.equal(null); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /ch4/cdn-dns/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /ch4/cdn-spa/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /ch6/contract-testing-sync/bff/test/unit/utils/index.test.js: -------------------------------------------------------------------------------- 1 | import 'mocha'; 2 | import { expect } from 'chai'; 3 | import { uuidv4 } from '../../../src/utils'; 4 | 5 | describe('utils/index.js', () => { 6 | it('should create a uuid', () => { 7 | expect(uuidv4()).to.not.equal(null); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /ch1/create-api-gateway/serverless.yml: -------------------------------------------------------------------------------- 1 | service: cncb-create-api-gateway 2 | 3 | provider: 4 | name: aws 5 | runtime: nodejs8.10 6 | 7 | functions: 8 | hello: 9 | handler: handler.hello 10 | events: 11 | - http: 12 | path: hello 13 | method: get 14 | cors: true 15 | -------------------------------------------------------------------------------- /ch1/deploy-spa/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /ch5/cognito-signin/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/upstream/test/unit/utils/index.test.js: -------------------------------------------------------------------------------- 1 | import 'mocha'; 2 | import { expect } from 'chai'; 3 | import { uuidv4 } from '../../../src/utils'; 4 | 5 | describe('utils/index.js', () => { 6 | it('should create a uuid', () => { 7 | expect(uuidv4()).to.not.equal(null); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /ch6/feature-flag/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /ch6/transitive-testing/author-bff/test/unit/utils/index.test.js: -------------------------------------------------------------------------------- 1 | import 'mocha'; 2 | import { expect } from 'chai'; 3 | import { uuidv4 } from '../../../src/utils'; 4 | 5 | describe('utils/index.js', () => { 6 | it('should create a uuid', () => { 7 | expect(uuidv4()).to.not.equal(null); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /ch6/transitive-testing/customer-bff/test/unit/utils/index.test.js: -------------------------------------------------------------------------------- 1 | import 'mocha'; 2 | import { expect } from 'chai'; 3 | import { uuidv4 } from '../../../src/utils'; 4 | 5 | describe('utils/index.js', () => { 6 | it('should create a uuid', () => { 7 | expect(uuidv4()).to.not.equal(null); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /ch7/synthetics/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/downstream/test/unit/utils/index.test.js: -------------------------------------------------------------------------------- 1 | import 'mocha'; 2 | import { expect } from 'chai'; 3 | import { uuidv4 } from '../../../src/utils'; 4 | 5 | describe('utils/index.js', () => { 6 | it('should create a uuid', () => { 7 | expect(uuidv4()).to.not.equal(null); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /ch4/cdn-site/dist/phenomic/content/posts/by-default/1/desc/date/limit-2.json: -------------------------------------------------------------------------------- 1 | {"previousPageIsFirst":true,"next":"dGhpcmQtcG9zdA==","list":[{"id":"fifth-post","filename":"fifth-post.md","title":"Fifth post","date":"2017-01-05","layout":"hero"},{"id":"fourth-post","filename":"fourth-post.md","title":"Fourth post","date":"2017-01-04"}]} -------------------------------------------------------------------------------- /ch9/session-consistency/spa/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /ch11/gcp/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.hello = (request, response) => { 4 | console.log('env: %j', process.env); 5 | 6 | response.status(200).send('JavaScript Cloud Native Development Cookbook! Your function executed successfully!'); 7 | }; 8 | 9 | exports.trigger = (event, callback) => { 10 | callback(); 11 | }; 12 | -------------------------------------------------------------------------------- /ch4/cdn-site/dist/phenomic/content/posts/by-default/1/desc/date/limit-2/after-Zmlyc3QtcG9zdA==.json: -------------------------------------------------------------------------------- 1 | {"previousPageIsFirst":false,"previous":"dGhpcmQtcG9zdA==","list":[{"id":"first-post","filename":"first-post.md","title":"First post","headings":[{"level":1,"text":"This is a Markdown file","id":"this-is-a-markdown-file"}],"date":"2017-01-01"}]} -------------------------------------------------------------------------------- /ch6/pipeline/README.md: -------------------------------------------------------------------------------- 1 | # Creating a CI/CD pipeline 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch6/pipeline --path cncb-pipeline 5 | 2. cd cncb-pipeline 6 | 3. npm install 7 | 4. npm test 8 | 6. npm run dp:lcl -- -s $MY_STAGE 9 | 7. npm run rm:lcl -- -s $MY_STAGE -------------------------------------------------------------------------------- /ch1/create-stack/README.md: -------------------------------------------------------------------------------- 1 | # Creating a stack 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch1/create-stack --path cncb-create-stack 5 | 2. cd cncb-create-stack 6 | 3. npm install 7 | 4. npm test 8 | 6. npm run dp:lcl -- -s $MY_STAGE 9 | 7. npm run rm:lcl -- -s $MY_STAGE -------------------------------------------------------------------------------- /ch6/pipeline/serverless.yml: -------------------------------------------------------------------------------- 1 | service: cncb-pipeline 2 | 3 | provider: 4 | name: aws 5 | # cfnRole: arn:aws:iam::${self:custom.accounts.${opt:acct}.accountNumber}:role/${opt:stage}-cfnRole 6 | 7 | custom: 8 | accounts: 9 | dev: 10 | accountNumber: 123456789012 11 | prod: 12 | accountNumber: 210987654321 13 | 14 | -------------------------------------------------------------------------------- /ch4/cdn-site/dist/phenomic/content/posts/by-default/1/desc/date/limit-2/after-ZmlmdGgtcG9zdA==.json: -------------------------------------------------------------------------------- 1 | {"previousPageIsFirst":true,"next":"dGhpcmQtcG9zdA==","list":[{"id":"fifth-post","filename":"fifth-post.md","title":"Fifth post","date":"2017-01-05","layout":"hero"},{"id":"fourth-post","filename":"fourth-post.md","title":"Fourth post","date":"2017-01-04"}]} -------------------------------------------------------------------------------- /ch3/esg-inbound/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-esg-inbound", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0" 12 | } 13 | } -------------------------------------------------------------------------------- /ch6/integration-testing/README.md: -------------------------------------------------------------------------------- 1 | # Writing integration tests 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch6/integration-testing --path cncb-integration-testing 5 | 2. cd cncb-integration-testing 6 | 3. npm install 7 | 4. npm test 8 | 5. DEBUG=replay REPLAY=record npm run test:int 9 | -------------------------------------------------------------------------------- /ch4/cdn-json/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-cdn-json", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ch4/cdn-site/dist/phenomic/content/posts/by-default/1/desc/date/limit-2/after-Zm91cnRoLXBvc3Q=.json: -------------------------------------------------------------------------------- 1 | {"previousPageIsFirst":true,"previous":"ZmlmdGgtcG9zdA==","next":"c2Vjb25kLXBvc3Q=","list":[{"id":"fourth-post","filename":"fourth-post.md","title":"Fourth post","date":"2017-01-04"},{"id":"third-post","filename":"third-post.md","title":"Third post","date":"2017-01-03"}]} -------------------------------------------------------------------------------- /ch4/cdn-site/dist/phenomic/content/posts/by-default/1/desc/date/limit-2/after-dGhpcmQtcG9zdA==.json: -------------------------------------------------------------------------------- 1 | {"previousPageIsFirst":true,"previous":"ZmlmdGgtcG9zdA==","next":"Zmlyc3QtcG9zdA==","list":[{"id":"third-post","filename":"third-post.md","title":"Third post","date":"2017-01-03"},{"id":"second-post","filename":"second-post.md","title":"Second post","date":"2017-01-02"}]} -------------------------------------------------------------------------------- /ch1/create-function/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-create-function", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0" 12 | } 13 | } -------------------------------------------------------------------------------- /ch1/create-stack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-create-stack", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -v -r us-east-1 -s test", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -v -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0" 12 | } 13 | } -------------------------------------------------------------------------------- /ch4/cdn-service/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-cdn-service", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ch5/cognito-authorizer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-cognito-authorizer", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0" 12 | } 13 | } -------------------------------------------------------------------------------- /ch9/tuning-faas/README.md: -------------------------------------------------------------------------------- 1 | # Tuning function-as-a-service 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch9/tuning-faas --path cncb-tuning-faas 5 | 2. cd cncb-tuning-faas 6 | 3. npm install 7 | 4. npm test 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. npm run rm:lcl -- -s $MY_STAGE 10 | -------------------------------------------------------------------------------- /ch1/create-api-gateway/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-create-api-gateway", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0" 12 | } 13 | } -------------------------------------------------------------------------------- /ch11/azure/handler.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports.hello = function (context) { 4 | context.log('context: %j', context); 5 | context.log('env: %j', process.env); 6 | 7 | context.res = { 8 | status: 200, 9 | body: 'JavaScript Cloud Native Development Cookbook! Your function executed successfully!', 10 | }; 11 | 12 | context.done(); 13 | }; 14 | -------------------------------------------------------------------------------- /ch5/account-as-code/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-account-as-code", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ch7/datadog-account/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-datadog-account", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ch9/cache-control/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-cache-control", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ch5/waf/README.md: -------------------------------------------------------------------------------- 1 | # Configuring a web application firewall 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch5/waf --path cncb-waf 5 | 2. cd cncb-waf 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. Access cdn endpoint 10 | 7. npm run rm:lcl -- -s $MY_STAGE 11 | -------------------------------------------------------------------------------- /ch6/contract-testing-sync/README.md: -------------------------------------------------------------------------------- 1 | # Writing contract tests for a synchronous api 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch6/contract-testing-sync --path cncb-contract-testing-sync 5 | 2. cd cncb-contract-testing-sync 6 | 3. npm install 7 | 4. npm test 8 | 5. DEBUG=replay REPLAY=record npm run test:int 9 | -------------------------------------------------------------------------------- /ch10/README.md: -------------------------------------------------------------------------------- 1 | # Deploying to Multiple Regions 2 | 3 | 1. [Implementing latency based routing](./latency-based-routing) 4 | 2. [Creating a regional health check](./regional-health-check) 5 | 3. [Triggering regional failover](./regional-failover) 6 | 4. [Implement regional replication with DynamoDB](./dynamodb-global-table) 7 | 5. [Implementing round robin replication](./round-robin-replication) 8 | -------------------------------------------------------------------------------- /ch6/feature-flag/README.md: -------------------------------------------------------------------------------- 1 | # Leveraging feature flags 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch6/feature-flag --path cncb-feature-flag 5 | 2. cd cncb-feature-flag 6 | 3. npm install 7 | 4. Update src/configuration.js 8 | 5. npm start 9 | 6. Click Sign In and complete form 10 | 7. Note rendered data 11 | -------------------------------------------------------------------------------- /ch4/cdn-site/content/posts/fifth-post.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Fifth post" 3 | date: "2017-01-05" 4 | layout: hero 5 | --- 6 | 7 | Another post that have a [link to the first one](../first-post/). 8 | 9 | An wrong link to [a post that does not exist](../unknown-post/) and another one 10 | to [a page that does not exist](/unknown-page/). 11 | 12 | Here is an [external link](http://phenomic.io). 13 | -------------------------------------------------------------------------------- /ch5/cognito-pool/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-cognito-pool", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "lodash": "^4.17.10", 12 | "serverless": "1.26.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ch11/azure/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-azure", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r 'East US' -s test", 7 | "dp:lcl": "sls deploy -v -r 'East US'", 8 | "rm:lcl": "sls remove -v -r 'East US'" 9 | }, 10 | "devDependencies": { 11 | "serverless": "^1.30.1", 12 | "serverless-azure-functions": "^0.6.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ch11/gcp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-gcp", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "test": "sls package -r us-east1 -s test", 7 | "dp:lcl": "sls deploy -v --r us-east1", 8 | "rm:lcl": "sls remove -r us-east1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "^1.30.1", 12 | "serverless-google-cloudfunctions": "^2.0.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ch1/deploy-spa/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /ch2/event-first/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-event-first", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0" 12 | }, 13 | "dependencies": { 14 | "uuid": "^3.2.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch4/cdn-dns/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /ch4/cdn-spa/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /ch5/jwt-filter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-jwt-filter", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "dependencies": { 11 | "uuid": "^3.1.0" 12 | }, 13 | "devDependencies": { 14 | "serverless": "1.26.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch7/synthetics/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /ch10/regional-failover/check/handler.js: -------------------------------------------------------------------------------- 1 | module.exports.check = (request, context, callback) => { 2 | callback(null, { 3 | statusCode: process.env.UNHEALTHY === 'true' ? 503 : 200, 4 | body: JSON.stringify({ 5 | timestamp: Date.now(), 6 | region: process.env.AWS_REGION, 7 | }), 8 | headers: { 9 | 'Cache-Control': 'no-cache, no-store, must-revalidate', 10 | }, 11 | }); 12 | }; 13 | -------------------------------------------------------------------------------- /ch2/data-lake-s3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-data-lake-s3", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0" 12 | }, 13 | "dependencies": { 14 | "uuid": "^3.2.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch5/cognito-signin/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /ch5/ssl-cert/README.md: -------------------------------------------------------------------------------- 1 | # Creating an SSL certificate for encryption in transit 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch5/ssl-cert --path cncb-ssl-cert 5 | 2. cd cncb-ssl-cert 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. Access cdn endpoint 10 | 7. npm run rm:lcl -- -s $MY_STAGE 11 | -------------------------------------------------------------------------------- /ch6/feature-flag/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /ch1/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Cloud-Native 2 | 3 | 1. [Creating a stack](./create-stack) 4 | 2. [Creating a function and working with metrics and logs](./create-function) 5 | 3. [Creating an event stream and publishing an event](./event-stream) 6 | 4. [Creating a stream processor](./create-stream-processor) 7 | 5. [Creating an API Gateway](./create-api-gateway) 8 | 6. [Deploying a single page application](./deploy-spa) 9 | -------------------------------------------------------------------------------- /ch1/event-stream/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-event-stream", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0" 12 | }, 13 | "dependencies": { 14 | "uuid": "^3.2.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch4/cdn-lambda/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-cdn-lambda", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0", 12 | "serverless-plugin-cloudfront-lambda-edge": "^2.0.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ch4/cdn-site/dist/phenomic/content/posts/by-default/1/desc/date/limit-2/after-c2Vjb25kLXBvc3Q=.json: -------------------------------------------------------------------------------- 1 | {"previousPageIsFirst":false,"previous":"Zm91cnRoLXBvc3Q=","list":[{"id":"second-post","filename":"second-post.md","title":"Second post","date":"2017-01-02"},{"id":"first-post","filename":"first-post.md","title":"First post","headings":[{"level":1,"text":"This is a Markdown file","id":"this-is-a-markdown-file"}],"date":"2017-01-01"}]} -------------------------------------------------------------------------------- /ch1/create-stream-processor/serverless.yml: -------------------------------------------------------------------------------- 1 | service: cncb-create-stream-processor 2 | 3 | provider: 4 | name: aws 5 | runtime: nodejs8.10 6 | 7 | functions: 8 | listener: 9 | handler: handler.listener 10 | events: 11 | - stream: 12 | type: kinesis 13 | arn: ${cf:cncb-event-stream-${opt:stage}.streamArn} 14 | batchSize: 100 15 | startingPosition: TRIM_HORIZON 16 | -------------------------------------------------------------------------------- /ch3/esg-sqs-inbound/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-esg-sqs-inbound", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.32.0" 12 | }, 13 | "dependencies": { 14 | "highland": "^2.13.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch5/dr/recovery-account/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-dr-recovery-account", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-west-1 -s test", 7 | "dp:lcl": "sls deploy -v -r us-west-1", 8 | "rm:lcl": "sls remove -r us-west-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0", 12 | "serverless-pseudo-parameters": "^1.6.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ch8/timeout-retry/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-timeout-retry", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "dependencies": { 11 | "uuid": "^3.1.0" 12 | }, 13 | "devDependencies": { 14 | "serverless": "1.26.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch9/session-consistency/spa/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /ch3/saga/data/reservation.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "33333333-7777-0000-2222-111111111111", 3 | "type": "reservation-violation", 4 | "reservation": { 5 | "id": "33333333-7777-2222-1111-111111111111" 6 | }, 7 | "context": { 8 | "order": { 9 | "id": "33333333-7777-1111-1111-111111111111", 10 | "sku": "1", 11 | "quanity": 1 12 | }, 13 | "trigger": "33333333-7777-0000-1111-111111111111" 14 | } 15 | } -------------------------------------------------------------------------------- /ch5/waf/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-waf", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0", 12 | "serverless-spa-config": "1.0.2", 13 | "serverless-spa-deploy": "1.0.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch8/README.md: -------------------------------------------------------------------------------- 1 | # Designing for Failure 2 | 3 | 1. [Employing proper timeouts and retries](./timeout-retry) 4 | 2. [Implementing backpressure and rate limiting](./backpressure-ratelimit) 5 | 3. [Handling Faults](./handling-faults) 6 | 4. [Resubmitting fault events](./resubmitting-faults) 7 | 5. [Implementing idempotency with an inverse oplock](./idempotence-inverse-oplock) 8 | 6. [Implementing idempotency with event sourcing](./idempotence-es) 9 | -------------------------------------------------------------------------------- /ch1/create-stream-processor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-create-stream-processor", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0" 12 | }, 13 | "dependencies": { 14 | "highland": "^2.11.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch5/ssl-cert/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-ssl-cert", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0", 12 | "serverless-spa-config": "1.0.2", 13 | "serverless-spa-deploy": "1.0.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch11/gcp/README.md: -------------------------------------------------------------------------------- 1 | # Creating a service in GCP 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch11/gcp --path cncb-gcp 5 | 2. cd cncb-gcp 6 | 3. npm install 7 | 4. npm test 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. curl -v https://us-east1-cncb-project.cloudfunctions.net/hello 10 | 7. sls logs -f hello -r us-east1 -s $MY_STAGE 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch3/event-orchestration/data/reservation.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "33333333-6666-0000-3333-111111111111", 3 | "type": "reservation-confirmed", 4 | "reservation": { 5 | "id": "33333333-6666-2222-1111-111111111111" 6 | }, 7 | "context": { 8 | "order": { 9 | "id": "33333333-6666-1111-1111-111111111111", 10 | "sku": "1", 11 | "quanity": 1 12 | }, 13 | "trigger": "33333333-6666-0000-2222-111111111111" 14 | } 15 | } -------------------------------------------------------------------------------- /ch8/resubmitting-faults/cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-resubmitting-faults-cli", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "resubmit": "node index.js" 7 | }, 8 | "dependencies": { 9 | "aws-sdk": "^2.45.0", 10 | "bluebird": "^3.5.0", 11 | "debug": "^2.6.4", 12 | "highland": "^2.11.1", 13 | "lodash": "^4.17.4", 14 | "moment": "^2.18.1", 15 | "yargs": "^7.1.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ch9/README.md: -------------------------------------------------------------------------------- 1 | # Optimizing Performance 2 | 3 | 1. [Tuning function-as-a-service](./tuning-faas) 4 | 2. [Batching requests](./frp-batching) 5 | 3. [Leveraging asynchronous non-blocking IO](./frp-async-non-blocking-io) 6 | 4. [Grouping events in stream processors](./frp-grouping) 7 | 5. [Autoscaling DynamoDB](./dynamodb-autoscaling) 8 | 6. [Utilizing cache-control](./cache-control) 9 | 7. [Leveraging session consistency](./session-consistency) 10 | -------------------------------------------------------------------------------- /ch4/cdn-spa/README.md: -------------------------------------------------------------------------------- 1 | # Serving a single page app from the cdn 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch4/cdn-spa --path cncb-cdn-spa 5 | 2. cd cncb-cdn-spa 6 | 3. npm install 7 | 4. npm test 8 | 5. npm run build 9 | 6. npm run dp:lcl -- -s $MY_STAGE 10 | 7. browse https://.cloudfront.net 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch8/idempotence-es/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-idempotence-es", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "dependencies": { 11 | "highland": "^2.11.1", 12 | "uuid": "^3.1.0" 13 | }, 14 | "devDependencies": { 15 | "serverless": "1.26.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ch5/custom-authorizer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-custom-authorizer", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0" 12 | }, 13 | "dependencies": { 14 | "jsonwebtoken": "^8.2.1", 15 | "jwks-rsa": "^1.2.1" 16 | } 17 | } -------------------------------------------------------------------------------- /ch2/event-first/serverless.yml: -------------------------------------------------------------------------------- 1 | service: cncb-event-first 2 | 3 | provider: 4 | name: aws 5 | runtime: nodejs8.10 6 | iamRoleStatements: 7 | - Effect: Allow 8 | Action: 9 | - kinesis:PutRecord 10 | Resource: ${cf:cncb-event-stream-${opt:stage}.streamArn} 11 | 12 | functions: 13 | submit: 14 | handler: handler.submit 15 | environment: 16 | STREAM_NAME: ${cf:cncb-event-stream-${opt:stage}.streamName} 17 | 18 | -------------------------------------------------------------------------------- /ch3/saga/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-saga", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "highland": "^2.11.1", 16 | "uuid": "^3.1.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch4/cdn-invalidate/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-cdn-invalidate", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0" 12 | }, 13 | "dependencies": { 14 | "highland": "^2.13.0", 15 | "uuid": "^3.2.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ch4/cdn-site/README.md: -------------------------------------------------------------------------------- 1 | # Serving a website from the cdn 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch4/cdn-site --path cncb-cdn-site 5 | 2. cd cncb-cdn-site 6 | 3. npm install 7 | 4. update serverless.yml with hosted zone id and domain name 8 | 5. npm test 9 | 7. npm run dp:lcl -- -s $MY_STAGE 10 | 8. browse see stack output 11 | 9. npm run rm:lcl -- -s $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch11/azure/README.md: -------------------------------------------------------------------------------- 1 | # Creating a service in Azure 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch11/azure --path cncb-azure 5 | 2. cd cncb-azure 6 | 3. npm install 7 | 4. npm test 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. sls logs -f hello -r 'East US' -s $MY_STAGE 10 | 7. curl -v https://cncb-azure-$MY_STAGE.azurewebsites.net/api/hello 11 | 8. npm run rm:lcl -- --stage $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/README.md: -------------------------------------------------------------------------------- 1 | # Writing contract tests for a asynchronous api 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch6/contract-testing-async --path cncb-contract-testing-async 5 | 2. cd cncb-contract-testing-async/upstream 6 | 3. npm install 7 | 4. npm test 8 | 5. DEBUG=replay REPLAY=record npm run test:int 9 | 6. repeat for cd cncb-contract-testing-async/downstream 10 | -------------------------------------------------------------------------------- /ch6/contract-testing-sync/bff/fixtures/frontend/get: -------------------------------------------------------------------------------- 1 | GET /things/00000000-0000-0000-0000-000000000000 2 | accept-encoding: gzip, deflate 3 | 4 | HTTP/1.1 200 OK 5 | content-type: application/json; charset=utf-8 6 | access-control-allow-origin: * 7 | cache-control: max-age=3 8 | vary: origin,accept-encoding 9 | date: Sun, 17 Jun 2018 21:26:46 GMT 10 | connection: close 11 | transfer-encoding: chunked 12 | 13 | {"id":"00000000-0000-0000-0000-000000000000","name":"thing0"} -------------------------------------------------------------------------------- /ch5/envelope-encryption/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-envelope-encryption", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "dependencies": { 11 | "crypto-js": "^3.1.9-1", 12 | "uuid": "^3.1.0" 13 | }, 14 | "devDependencies": { 15 | "serverless": "1.26.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ch6/contract-testing-sync/frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-contract-testing-sync-frontend", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test:int": "mocha --timeout 20000 ./test/int/**/*.test.js" 7 | }, 8 | "devDependencies": { 9 | "aws-sdk": "^2.94.0", 10 | "aws-sdk-mock": "^1.7.0", 11 | "chai": "^4.1.2", 12 | "mocha": "^5.2.0", 13 | "replay": "^2.3.0", 14 | "supertest": "^3.1.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch4/cdn-spa/serverless.yml: -------------------------------------------------------------------------------- 1 | service: cncb-cdn-spa 2 | 3 | provider: 4 | name: aws 5 | 6 | plugins: 7 | - serverless-spa-deploy 8 | - serverless-spa-config 9 | 10 | custom: 11 | spa: 12 | files: 13 | - source: ./build 14 | globs: '**/*' 15 | headers: 16 | CacheControl: max-age=31536000 # 1 year 17 | - source: ./build 18 | globs: 'index.html' 19 | headers: 20 | CacheControl: max-age=300 # 5 minutes 21 | -------------------------------------------------------------------------------- /ch5/account-as-code/README.md: -------------------------------------------------------------------------------- 1 | # Securing your cloud account 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch5/account-as-code --path cncb-account-as-code 5 | 2. cd cncb-account-as-code 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 10 | ## References 11 | * [IAM Best Practices](http://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html) 12 | -------------------------------------------------------------------------------- /ch5/graphql-jwt/serverless.yml: -------------------------------------------------------------------------------- 1 | service: cncb-graphql-jwt 2 | 3 | provider: 4 | name: aws 5 | runtime: nodejs8.10 6 | # cfnRole: arn:aws:iam:::role/${opt:stage}-cfnRole 7 | 8 | functions: 9 | graphql: 10 | handler: handler.graphql 11 | events: 12 | - http: 13 | path: graphql 14 | method: post 15 | cors: true 16 | authorizer: 17 | arn: ${cf:cncb-cognito-pool-${opt:stage}.userPoolArn} 18 | -------------------------------------------------------------------------------- /ch6/contract-testing-sync/frontend/fixtures/0.0.0.0-3001/get: -------------------------------------------------------------------------------- 1 | GET /things/00000000-0000-0000-0000-000000000000 2 | accept-encoding: gzip, deflate 3 | 4 | HTTP/1.1 200 OK 5 | content-type: application/json; charset=utf-8 6 | access-control-allow-origin: * 7 | cache-control: max-age=3 8 | vary: origin,accept-encoding 9 | date: Sun, 17 Jun 2018 21:26:46 GMT 10 | connection: close 11 | transfer-encoding: chunked 12 | 13 | {"id":"00000000-0000-0000-0000-000000000000","name":"thing0"} -------------------------------------------------------------------------------- /ch6/transitive-testing/author-frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-transitive-testing-author-frontend", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test:int": "mocha --timeout 20000 ./test/int/**/*.test.js" 7 | }, 8 | "devDependencies": { 9 | "aws-sdk": "^2.94.0", 10 | "aws-sdk-mock": "^1.7.0", 11 | "chai": "^4.1.2", 12 | "mocha": "^5.2.0", 13 | "replay": "^2.3.0", 14 | "supertest": "^3.1.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch8/idempotence-inverse-oplock/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-idempotence-inverse-oplock", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "dependencies": { 11 | "highland": "^2.11.1", 12 | "uuid": "^3.1.0" 13 | }, 14 | "devDependencies": { 15 | "serverless": "1.26.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ch6/transitive-testing/customer-frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-transitive-testing-customer-frontend", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test:int": "mocha --timeout 20000 ./test/int/**/*.test.js" 7 | }, 8 | "devDependencies": { 9 | "aws-sdk": "^2.94.0", 10 | "aws-sdk-mock": "^1.7.0", 11 | "chai": "^4.1.2", 12 | "mocha": "^5.2.0", 13 | "replay": "^2.3.0", 14 | "supertest": "^3.1.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch10/regional-health-check/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-regional-health-check", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test", 7 | "dp:lcl:e": "sls deploy -v -r us-east-1", 8 | "dp:lcl:w": "sls deploy -v -r us-west-2", 9 | "rm:lcl:e": "sls remove -r us-east-1", 10 | "rm:lcl:w": "sls remove -r us-west-2" 11 | }, 12 | "devDependencies": { 13 | "serverless": "1.26.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch2/db-first-cognito/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-db-first-cognito", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "highland": "^2.11.1", 16 | "uuid": "^3.1.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch3/esg-inbound/README.md: -------------------------------------------------------------------------------- 1 | # Implementing an inbound external service gateway 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch3/esg-inbound --path cncb-esg-inbound 5 | 2. cd cncb-esg-inbound 6 | 3. npm install 7 | 4. npm test 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. https://developer.github.com/webhooks/creating 10 | 7. sls logs -f webhook -r us-east-1 -s $MY_STAGE 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch3/event-orchestration/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-event-orchestration", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "highland": "^2.11.1", 16 | "uuid": "^3.1.0" 17 | } 18 | } -------------------------------------------------------------------------------- /ch4/README.md: -------------------------------------------------------------------------------- 1 | # Leveraging the Edge of the Cloud 2 | 3 | 1. [Serving a single page application from the CDN](./cdn-spa) 4 | 2. [Associating a custom domain name with a service](./cdn-dns) 5 | 3. [Serving a website from the CDN](./cdn-site) 6 | 4. [Deploying a service behind a CDN](./cdn-service) 7 | 5. [Serving static JSON from a CDN](./cdn-json) 8 | 6. [Trigging the invalidation of content in a CDN](./cdn-invalidate) 9 | 7. [Executing code at the edge of the cloud](./cdn-lambda) 10 | -------------------------------------------------------------------------------- /ch6/transitive-testing/author-bff/fixtures/author-frontend/get-thing0: -------------------------------------------------------------------------------- 1 | GET /things/00000000-0000-0000-0000-000000000000 2 | accept-encoding: gzip, deflate 3 | 4 | HTTP/1.1 200 OK 5 | content-type: application/json; charset=utf-8 6 | access-control-allow-origin: * 7 | cache-control: max-age=3 8 | vary: origin,accept-encoding 9 | date: Sun, 17 Jun 2018 21:26:46 GMT 10 | connection: close 11 | transfer-encoding: chunked 12 | 13 | {"id":"00000000-0000-0000-0000-000000000000","name":"thing0"} -------------------------------------------------------------------------------- /ch6/transitive-testing/author-frontend/fixtures/0.0.0.0-3001/get-thing0: -------------------------------------------------------------------------------- 1 | GET /things/00000000-0000-0000-0000-000000000000 2 | accept-encoding: gzip, deflate 3 | 4 | HTTP/1.1 200 OK 5 | content-type: application/json; charset=utf-8 6 | access-control-allow-origin: * 7 | cache-control: max-age=3 8 | vary: origin,accept-encoding 9 | date: Sun, 17 Jun 2018 21:26:46 GMT 10 | connection: close 11 | transfer-encoding: chunked 12 | 13 | {"id":"00000000-0000-0000-0000-000000000000","name":"thing0"} -------------------------------------------------------------------------------- /ch7/datadog-account/README.md: -------------------------------------------------------------------------------- 1 | # Monitoring a cloud-native system 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch7/datadog-account --path cncb-datadog-account 5 | 2. cd cncb-datadog-account 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 10 | ## References 11 | * [Datadog AWS Integration](https://docs.datadoghq.com/integrations/amazon_web_services/#setup) 12 | -------------------------------------------------------------------------------- /ch7/event-metrics/README.md: -------------------------------------------------------------------------------- 1 | # Monitoring events 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch7/event-monitor --path cncb-event-monitor 5 | 2. cd cncb-event-monitor 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. sls invoke -f simulate -r us-east-1 -s $MY_STAGE 10 | 7. sls logs -f listener -r us-east-1 -s $MY_STAGE 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch1/create-api-gateway/handler.js: -------------------------------------------------------------------------------- 1 | module.exports.hello = (event, context, callback) => { 2 | console.log('event: %j', event); 3 | 4 | const response = { 5 | statusCode: 200, 6 | headers: { 7 | 'Access-Control-Allow-Origin': '*', 8 | }, 9 | body: JSON.stringify({ 10 | message: 'JavaScript Cloud Native Development Cookbook! Your function executed successfully!', 11 | input: event, 12 | }), 13 | }; 14 | 15 | callback(null, response); 16 | }; 17 | -------------------------------------------------------------------------------- /ch1/create-function/README.md: -------------------------------------------------------------------------------- 1 | # Creating a function 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch1/create-function --path cncb-create-function 5 | 2. cd cncb-create-function 6 | 3. npm install 7 | 4. npm test 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. sls invoke -r us-east-1 -f hello -s $MY_STAGE -d '{"hello":"world"}' 10 | 7. sls logs -f hello -r us-east-1 -s $MY_STAGE 11 | 8. npm run rm:lcl -- -s $MY_STAGE -------------------------------------------------------------------------------- /ch2/bi-directional-sync/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-bi-directional-sync", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "highland": "^2.11.1", 16 | "uuid": "^3.1.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch2/db-first-dynamodb/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-db-first-dynamodb", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "highland": "^2.11.1", 16 | "uuid": "^3.1.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch2/micro-event-store/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-micro-event-store", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "highland": "^2.11.1", 16 | "uuid": "^3.1.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch3/README.md: -------------------------------------------------------------------------------- 1 | # Implementing Autonomous Services 2 | 3 | 1. [Implementing a GraphQL CRUD BFF](./bff-graphql-crud) 4 | 2. [Implementing a search BFF](./bff-rest-search) 5 | 3. [Implementing an analytics BFF](./bff-rest-analytics) 6 | 4. [Implementing an inbound external service gateway](./esg-inbound) 7 | 5. [Implementing an outbound external service gateway](./esg-outbound) 8 | 6. [Orchestrating collaboration between services](./event-orchestration) 9 | 7. [Implementing a saga](./saga) 10 | -------------------------------------------------------------------------------- /ch4/cdn-dns/README.md: -------------------------------------------------------------------------------- 1 | # Associating a custom domain name with a cdn 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch4/cdn-dns --path cncb-cdn-dns 5 | 2. cd cncb-cdn-dns 6 | 3. npm install 7 | 4. update serverless.yml with hosted zone id and domain name 8 | 5. npm test 9 | 6. npm run build 10 | 7. npm run dp:lcl -- -s $MY_STAGE 11 | 8. browse see stack output 12 | 9. npm run rm:lcl -- -s $MY_STAGE 13 | -------------------------------------------------------------------------------- /ch6/README.md: -------------------------------------------------------------------------------- 1 | # Building a Continuous Deployment Pipeline 2 | 3 | 1. [Creating the CI/CD pipeline](./pipeline) 4 | 2. [Writing unit tests](./unit-testing) 5 | 3. [Writing integration tests](./integration-testing) 6 | 4. [Writing contract tests for a synchronous API](./contract-testing-sync) 7 | 5. [Writing contract tests for an asynchronous API](./contract-testing-async) 8 | 6. [Assembling transitive end-to-end tests](./transitive-testing) 9 | 7. [Leveraging feature flags](./feature-flag) 10 | -------------------------------------------------------------------------------- /ch8/handling-faults/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-handling-faults", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -v -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -v -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "highland": "^2.13.0", 16 | "uuid": "^3.2.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch9/cache-control/README.md: -------------------------------------------------------------------------------- 1 | # Utilizing cache-control 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch9/cache-control --path cncb-cache-control 5 | 2. cd cncb-cache-control 6 | 3. npm install 7 | 4. npm test 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. curl -s -w "%{time_total}\n" -o /dev/null https://xyz.cloudfront.net/get 10 | 7. sls logs -f get -r us-east-1 -s $MY_STAGE 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch10/regional-failover/check/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-regional-failover-check", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test", 7 | "dp:lcl:e": "sls deploy -v -r us-east-1", 8 | "dp:lcl:w": "sls deploy -v -r us-west-2", 9 | "rm:lcl:e": "sls remove -v -r us-east-1", 10 | "rm:lcl:w": "sls remove -v -r us-west-2" 11 | }, 12 | "devDependencies": { 13 | "serverless": "1.26.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ch2/materialized-view-s3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-materialized-view-s3", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "highland": "^2.11.1", 16 | "uuid": "^3.1.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch3/bff-rest-analytics/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-bff-rest-analytics", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "highland": "^2.11.1", 16 | "moment": "^2.22.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch4/cdn-service/README.md: -------------------------------------------------------------------------------- 1 | # Deploying a service behind a cdn 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch4/cdn-service --path cncb-cdn-service 5 | 2. cd cncb-cdn-service 6 | 3. npm install 7 | 4. npm test 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. curl -s -w "%{time_total}\n" -o /dev/null https://xyz.cloudfront.net/hello 10 | 7. sls logs -f hello -r us-east-1 -s $MY_STAGE 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch5/cognito-authorizer/handler.js: -------------------------------------------------------------------------------- 1 | module.exports.hello = (request, context, callback) => { 2 | console.log('request: %j', request); 3 | 4 | const response = { 5 | statusCode: 200, 6 | headers: { 7 | 'Access-Control-Allow-Origin': '*', 8 | }, 9 | body: JSON.stringify({ 10 | message: 'JavaScript Cloud Native Development Cookbook! Your function executed successfully!', 11 | input: request, 12 | }), 13 | }; 14 | 15 | callback(null, response); 16 | }; 17 | -------------------------------------------------------------------------------- /ch4/cdn-site/serverless.yml: -------------------------------------------------------------------------------- 1 | service: cncb-cdn-site 2 | 3 | provider: 4 | name: aws 5 | 6 | plugins: 7 | - serverless-spa-deploy 8 | - serverless-spa-config 9 | 10 | custom: 11 | spa: 12 | files: 13 | - source: ./dist 14 | globs: '**/*' 15 | headers: 16 | CacheControl: max-age=31536000 # 1 year 17 | redirect: true 18 | dns: 19 | hostedZoneId: Z1234567890123 20 | domainName: example.com 21 | endpoint: www.${self:custom.dns.domainName} 22 | -------------------------------------------------------------------------------- /ch9/frp-batching/README.md: -------------------------------------------------------------------------------- 1 | # Batching requests 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch9/frp-batching --path cncb-frp-batching 5 | 2. cd cncb-frp-batching 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. sls invoke -f simulate -r us-east-1 -s $MY_STAGE 10 | 7. sls logs -f listener -r us-east-1 -s $MY_STAGE --filter 'event count' 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch1/deploy-spa/README.md: -------------------------------------------------------------------------------- 1 | # Deploying a single page application 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch1/deploy-spa --path cncb-deploy-spa 5 | 2. cd cncb-deploy-spa 6 | 3. npm install 7 | 4. npm start 8 | 5. npm test 9 | 6. npm run build 10 | 7. npm run dp:lcl -- -s $MY_STAGE 11 | 8. browse http://cncb-deploy-spa-$MY_STAGE-websitebucket-xxxx.s3-website-us-east-1.amazonaws.com 12 | 9. npm run rm:lcl -- -s $MY_STAGE 13 | -------------------------------------------------------------------------------- /ch2/materialized-view-cognito/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-materialized-view-cognito", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "highland": "^2.11.1", 16 | "uuid": "^3.1.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch2/materialized-view-dynamodb/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-materialized-view-dynamodb", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "highland": "^2.11.1", 16 | "uuid": "^3.1.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch4/cdn-invalidate/includes.yml: -------------------------------------------------------------------------------- 1 | BucketTopicPolicy: 2 | Type: AWS::SNS::TopicPolicy 3 | Properties: 4 | Topics: 5 | - Ref: BucketTopic 6 | PolicyDocument: 7 | Statement: 8 | - Effect: Allow 9 | Principal: 10 | Service: s3.amazonaws.com 11 | Action: sns:Publish 12 | Resource: 13 | Ref: BucketTopic 14 | Condition: 15 | ArnLike: 16 | aws:SourceArn: arn:aws:s3:::${self:service}-${opt:stage}-bucket-* -------------------------------------------------------------------------------- /ch5/cognito-authorizer/serverless.yml: -------------------------------------------------------------------------------- 1 | service: cncb-cognito-authorizer 2 | 3 | provider: 4 | name: aws 5 | # cfnRole: arn:aws:iam:::role/${opt:stage}-cfnRole 6 | runtime: nodejs8.10 7 | endpointType: REGIONAL 8 | 9 | functions: 10 | hello: 11 | handler: handler.hello 12 | events: 13 | - http: 14 | path: hello 15 | method: get 16 | cors: true 17 | authorizer: 18 | arn: ${cf:cncb-cognito-pool-${opt:stage}.userPoolArn} 19 | -------------------------------------------------------------------------------- /ch5/dr/src1-account/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-dr-src1-account", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "serverless": "1.26.0", 12 | "serverless-pseudo-parameters": "^1.6.0" 13 | }, 14 | "dependencies": { 15 | "moment": "^2.22.2", 16 | "uuid": "^3.2.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch6/transitive-testing/customer-bff/fixtures/customer-frontend/get-thing0: -------------------------------------------------------------------------------- 1 | GET /things/00000000-0000-0000-0000-000000000000 2 | accept-encoding: gzip, deflate 3 | 4 | HTTP/1.1 200 OK 5 | content-type: application/json; charset=utf-8 6 | access-control-allow-origin: * 7 | cache-control: max-age=3 8 | vary: origin,accept-encoding 9 | date: Tue, 26 Jun 2018 02:21:25 GMT 10 | connection: close 11 | transfer-encoding: chunked 12 | 13 | {"id":"00000000-0000-0000-0000-000000000000","name":"thing0","asOf":1529179380000} -------------------------------------------------------------------------------- /ch6/transitive-testing/customer-frontend/fixtures/0.0.0.0-3001/get-thing0: -------------------------------------------------------------------------------- 1 | GET /things/00000000-0000-0000-0000-000000000000 2 | accept-encoding: gzip, deflate 3 | 4 | HTTP/1.1 200 OK 5 | content-type: application/json; charset=utf-8 6 | access-control-allow-origin: * 7 | cache-control: max-age=3 8 | vary: origin,accept-encoding 9 | date: Tue, 26 Jun 2018 02:21:25 GMT 10 | connection: close 11 | transfer-encoding: chunked 12 | 13 | {"id":"00000000-0000-0000-0000-000000000000","name":"thing0","asOf":1529179380000} -------------------------------------------------------------------------------- /ch7/custom-metrics/README.md: -------------------------------------------------------------------------------- 1 | # Implementing custom metrics 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch7/custom-metrics --path cncb-custom-metrics 5 | 2. cd cncb-custom-metrics 6 | 3. npm install 7 | 4. npm test 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. curl -v https://xyz.execute-api.us-east-1.amazonaws.com/$MY_STAGE/hello | json_pp 10 | 7. sls logs -f hello -r us-east-1 -s $MY_STAGE 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch8/resubmitting-faults/simulator/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-resubmitting-faults-simulator", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "highland": "^2.11.1", 16 | "uuid": "^3.1.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch3/bff-rest-search/includes.yml: -------------------------------------------------------------------------------- 1 | BucketTopicPolicy: 2 | Type: AWS::SNS::TopicPolicy 3 | Properties: 4 | Topics: 5 | - Ref: BucketTopic 6 | PolicyDocument: 7 | Statement: 8 | - Effect: Allow 9 | Principal: 10 | Service: s3.amazonaws.com 11 | Action: sns:Publish 12 | Resource: 13 | Ref: BucketTopic 14 | Condition: 15 | ArnLike: 16 | aws:SourceArn: arn:aws:s3:::${self:service}-${opt:stage}-bucket-* -------------------------------------------------------------------------------- /ch3/esg-outbound/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-esg-outbound", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "highland": "^2.11.1", 16 | "isomorphic-fetch": "^2.2.1", 17 | "uuid": "^3.1.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /ch7/custom-metrics/serverless.yml: -------------------------------------------------------------------------------- 1 | service: cncb-custom-metrics 2 | 3 | provider: 4 | name: aws 5 | runtime: nodejs8.10 6 | 7 | functions: 8 | hello: 9 | handler: handler.hello 10 | events: 11 | - http: 12 | path: hello 13 | method: get 14 | cors: true 15 | environment: 16 | ACCOUNT_NAME: ${opt:account} 17 | SERVERLESS_STAGE: ${opt:stage} 18 | SERVERLESS_PROJECT: ${self:service} 19 | MONITOR_ADVANCED: false 20 | DEBUG: '*' 21 | -------------------------------------------------------------------------------- /ch8/handling-faults/README.md: -------------------------------------------------------------------------------- 1 | # Handling Faults 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch8/handling-faults --path cncb-handling-faults 5 | 2. cd cncb-handling-faults 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. sls invoke -f simulate -r us-east-1 -s $MY_STAGE 10 | 7. sls logs -f listener -r us-east-1 -s $MY_STAGE --filter 'publishing fault' 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch8/idempotence-es/README.md: -------------------------------------------------------------------------------- 1 | # Implementing idempotency with event sourcing 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch8/idempotence-es --path cncb-idempotence-es 5 | 2. cd cncb-idempotence-es 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. sls invoke -f simulate -r us-east-1 -s $MY_STAGE 10 | 7. sls logs -f trigger -r us-east-1 -s $MY_STAGE 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch8/resubmitting-faults/monitor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-resubmitting-faults-monitor", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -v -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "highland": "^2.11.1", 16 | "moment": "^2.22.2" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch10/round-robin-replication/includes.yml: -------------------------------------------------------------------------------- 1 | BucketTopicPolicy: 2 | Type: AWS::SNS::TopicPolicy 3 | Properties: 4 | Topics: 5 | - Ref: BucketTopic 6 | PolicyDocument: 7 | Statement: 8 | - Effect: Allow 9 | Principal: 10 | Service: s3.amazonaws.com 11 | Action: sns:Publish 12 | Resource: 13 | Ref: BucketTopic 14 | Condition: 15 | ArnLike: 16 | aws:SourceArn: arn:aws:s3:::${self:service}-${opt:stage}-bucket-* -------------------------------------------------------------------------------- /ch5/cognito-pool/README.md: -------------------------------------------------------------------------------- 1 | # Creating a federated identity pool 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch5/cognito-pool --path cncb-cognito-pool 5 | 2. cd cncb-cognito-pool 6 | 3. npm install 7 | 4. npm test 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. https://cncb-$MY_STAGE.auth.us-east-1.amazoncognito.com/login?redirect_uri=http://localhost:3000/signin&response_type=token&client_id= 10 | 7. npm run rm:lcl -- -s $MY_STAGE 11 | -------------------------------------------------------------------------------- /ch6/contract-testing-sync/bff/fixtures/frontend/save: -------------------------------------------------------------------------------- 1 | POST /things 2 | accept-encoding: gzip, deflate 3 | content-type: application/json 4 | body: {\"name\":\"thing0\"} 5 | 6 | HTTP/1.1 201 Created 7 | content-type: application/json; charset=utf-8 8 | access-control-allow-origin: * 9 | cache-control: no-cache 10 | location: https://0.0.0.0:3001/stg/things/00000000-0000-0000-0000-000000000000 11 | vary: origin,accept-encoding 12 | content-length: 0 13 | date: Sun, 17 Jun 2018 21:26:46 GMT 14 | connection: close 15 | 16 | -------------------------------------------------------------------------------- /ch9/frp-grouping/README.md: -------------------------------------------------------------------------------- 1 | # Grouping events in stream processors 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch9/frp-grouping --path cncb-frp-grouping 5 | 2. cd cncb-frp-grouping 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. sls invoke -f simulate -r us-east-1 -s $MY_STAGE 10 | 7. sls logs -f listener -r us-east-1 -s $MY_STAGE --filter 'event count' 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch1/create-api-gateway/README.md: -------------------------------------------------------------------------------- 1 | # Creating an api gateway 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch1/create-api-gateway --path cncb-create-api-gateway 5 | 2. cd cncb-create-api-gateway 6 | 3. npm install 7 | 4. npm test 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. curl -v https://xyz.execute-api.us-east-1.amazonaws.com/$MY_STAGE/hello | json_pp 10 | 7. sls logs -f hello -r us-east-1 -s $MY_STAGE 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch4/cdn-dns/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-title { 18 | font-size: 1.5em; 19 | } 20 | 21 | .App-intro { 22 | font-size: large; 23 | } 24 | 25 | @keyframes App-logo-spin { 26 | from { transform: rotate(0deg); } 27 | to { transform: rotate(360deg); } 28 | } 29 | -------------------------------------------------------------------------------- /ch4/cdn-spa/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-title { 18 | font-size: 1.5em; 19 | } 20 | 21 | .App-intro { 22 | font-size: large; 23 | } 24 | 25 | @keyframes App-logo-spin { 26 | from { transform: rotate(0deg); } 27 | to { transform: rotate(360deg); } 28 | } 29 | -------------------------------------------------------------------------------- /ch8/timeout-retry/README.md: -------------------------------------------------------------------------------- 1 | # Employing proper timeouts and retries 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch8/timeout-retry --path cncb-timeout-retry 5 | 2. cd cncb-timeout-retry 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. sls invoke -f command -r us-east-1 -s $MY_STAGE -d '{"name":"thing one"}' 10 | 7. sls logs -f command -r us-east-1 -s $MY_STAGE 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch1/deploy-spa/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-title { 18 | font-size: 1.5em; 19 | } 20 | 21 | .App-intro { 22 | font-size: large; 23 | } 24 | 25 | @keyframes App-logo-spin { 26 | from { transform: rotate(0deg); } 27 | to { transform: rotate(360deg); } 28 | } 29 | -------------------------------------------------------------------------------- /ch4/cdn-service/handler.js: -------------------------------------------------------------------------------- 1 | module.exports.hello = (request, context, callback) => { 2 | console.log('request: %j', request); 3 | 4 | const response = { 5 | statusCode: 200, 6 | headers: { 7 | 'Access-Control-Allow-Origin': '*', 8 | 'Cache-Control': 'max-age=5', 9 | }, 10 | body: JSON.stringify({ 11 | message: 'JavaScript Cloud Native Development Cookbook! Your function executed successfully!', 12 | input: request, 13 | }), 14 | }; 15 | 16 | callback(null, response); 17 | }; 18 | -------------------------------------------------------------------------------- /ch6/contract-testing-sync/frontend/fixtures/0.0.0.0-3001/save: -------------------------------------------------------------------------------- 1 | POST /things 2 | accept-encoding: gzip, deflate 3 | content-type: application/json 4 | body: {\"name\":\"thing0\"} 5 | 6 | HTTP/1.1 201 Created 7 | content-type: application/json; charset=utf-8 8 | access-control-allow-origin: * 9 | cache-control: no-cache 10 | location: https://0.0.0.0:3001/stg/things/00000000-0000-0000-0000-000000000000 11 | vary: origin,accept-encoding 12 | content-length: 0 13 | date: Sun, 17 Jun 2018 21:26:46 GMT 14 | connection: close 15 | 16 | -------------------------------------------------------------------------------- /ch6/feature-flag/src/Home.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-title { 18 | font-size: 1.5em; 19 | } 20 | 21 | .App-intro { 22 | font-size: large; 23 | } 24 | 25 | @keyframes App-logo-spin { 26 | from { transform: rotate(0deg); } 27 | to { transform: rotate(360deg); } 28 | } 29 | -------------------------------------------------------------------------------- /ch7/synthetics/src/Home.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-title { 18 | font-size: 1.5em; 19 | } 20 | 21 | .App-intro { 22 | font-size: large; 23 | } 24 | 25 | @keyframes App-logo-spin { 26 | from { transform: rotate(0deg); } 27 | to { transform: rotate(360deg); } 28 | } 29 | -------------------------------------------------------------------------------- /ch1/event-stream/README.md: -------------------------------------------------------------------------------- 1 | # Creating an event stream and publishing an event 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch1/event-stream --path cncb-event-stream 5 | 2. cd cncb-event-stream 6 | 3. npm install 7 | 4. npm test 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. sls invoke -r us-east-1 -f publish -s $MY_STAGE -d '{"type":"thing-created"}' 10 | 7. sls logs -f publish -r us-east-1 -s $MY_STAGE 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | 13 | 14 | -------------------------------------------------------------------------------- /ch3/esg-outbound/serverless.yml: -------------------------------------------------------------------------------- 1 | service: cncb-esg-outbound 2 | 3 | provider: 4 | name: aws 5 | runtime: nodejs8.10 6 | environment: 7 | REPO: enter-your-github-project 8 | OWNER: enter-your-github-id 9 | TOKEN: enter-your-github-token 10 | 11 | functions: 12 | listener: 13 | handler: handler.listener 14 | events: 15 | - stream: 16 | type: kinesis 17 | arn: ${cf:cncb-event-stream-${opt:stage}.streamArn} 18 | batchSize: 100 19 | startingPosition: TRIM_HORIZON 20 | -------------------------------------------------------------------------------- /ch5/cognito-signin/README.md: -------------------------------------------------------------------------------- 1 | # Implementing sign up, sign in and sign out 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch5/cognito-signin --path cncb-cognito-signin 5 | 2. cd cncb-cognito-signin 6 | 3. npm install 7 | 4. Update src/App.js 8 | 4. npm start 9 | 6. npm run build 10 | 7. Browse to http://localhost:3000 11 | 8. Click Sign Up and complete form 12 | 9. Click Sign Out 13 | 10. Click Sign In again 14 | 11. Review the idToken displayed on the page 15 | -------------------------------------------------------------------------------- /ch5/cognito-signin/src/Home.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-title { 18 | font-size: 1.5em; 19 | } 20 | 21 | .App-intro { 22 | font-size: large; 23 | } 24 | 25 | @keyframes App-logo-spin { 26 | from { transform: rotate(0deg); } 27 | to { transform: rotate(360deg); } 28 | } 29 | -------------------------------------------------------------------------------- /ch6/transitive-testing/author-bff/fixtures/author-frontend/save-thing0: -------------------------------------------------------------------------------- 1 | POST /things 2 | accept-encoding: gzip, deflate 3 | content-type: application/json 4 | body: {\"name\":\"thing0\"} 5 | 6 | HTTP/1.1 201 Created 7 | content-type: application/json; charset=utf-8 8 | access-control-allow-origin: * 9 | cache-control: no-cache 10 | location: https://0.0.0.0:3001/stg/things/00000000-0000-0000-0000-000000000000 11 | vary: origin,accept-encoding 12 | content-length: 0 13 | date: Sun, 17 Jun 2018 21:26:46 GMT 14 | connection: close 15 | 16 | -------------------------------------------------------------------------------- /ch9/dynamodb-autoscaling/README.md: -------------------------------------------------------------------------------- 1 | # Autoscaling DynamoDB 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch9/dynamodb-autoscaling --path cncb-dynamodb-autoscaling 5 | 2. cd cncb-dynamodb-autoscaling 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. sls invoke -f simulate -r us-east-1 -s $MY_STAGE 10 | 7. sls logs -f listener -r us-east-1 -s $MY_STAGE --filter 'event count' 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch9/tuning-faas/src/connector/stream.js: -------------------------------------------------------------------------------- 1 | import { Kinesis } from 'aws-sdk'; 2 | 3 | class Connector { 4 | constructor(streamName) { 5 | this.streamName = streamName; 6 | this.stream = new Kinesis(); 7 | } 8 | 9 | publish(event) { 10 | const params = { 11 | StreamName: this.streamName, 12 | PartitionKey: event.partitionKey, 13 | Data: Buffer.from(JSON.stringify(event)), 14 | }; 15 | 16 | return this.stream.putRecord(params).promise(); 17 | } 18 | } 19 | 20 | export default Connector; 21 | -------------------------------------------------------------------------------- /ch3/esg-inbound/serverless.yml: -------------------------------------------------------------------------------- 1 | service: cncb-esg-inbound 2 | 3 | provider: 4 | name: aws 5 | runtime: nodejs8.10 6 | iamRoleStatements: 7 | - Effect: Allow 8 | Action: 9 | - kinesis:PutRecord 10 | Resource: ${cf:cncb-event-stream-${opt:stage}.streamArn} 11 | 12 | functions: 13 | webhook: 14 | handler: handler.webhook 15 | events: 16 | - http: 17 | path: webhook 18 | method: post 19 | environment: 20 | STREAM_NAME: ${cf:cncb-event-stream-${opt:stage}.streamName} 21 | -------------------------------------------------------------------------------- /ch6/transitive-testing/author-frontend/fixtures/0.0.0.0-3001/save-thing0: -------------------------------------------------------------------------------- 1 | POST /things 2 | accept-encoding: gzip, deflate 3 | content-type: application/json 4 | body: {\"name\":\"thing0\"} 5 | 6 | HTTP/1.1 201 Created 7 | content-type: application/json; charset=utf-8 8 | access-control-allow-origin: * 9 | cache-control: no-cache 10 | location: https://0.0.0.0:3001/stg/things/00000000-0000-0000-0000-000000000000 11 | vary: origin,accept-encoding 12 | content-length: 0 13 | date: Sun, 17 Jun 2018 21:26:46 GMT 14 | connection: close 15 | 16 | -------------------------------------------------------------------------------- /ch9/session-consistency/spa/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-title { 18 | font-size: 1.5em; 19 | } 20 | 21 | .App-intro { 22 | font-size: large; 23 | } 24 | 25 | @keyframes App-logo-spin { 26 | from { transform: rotate(0deg); } 27 | to { transform: rotate(360deg); } 28 | } 29 | -------------------------------------------------------------------------------- /ch10/latency-based-routing/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-latency-based-routing", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test", 7 | "dp:lcl:e": "sls deploy -v -r us-east-1", 8 | "dp:lcl:w": "sls deploy -v -r us-west-2", 9 | "rm:lcl:e": "sls remove -v -r us-east-1", 10 | "rm:lcl:w": "sls remove -v -r us-west-2" 11 | }, 12 | "devDependencies": { 13 | "serverless": "1.26.0", 14 | "serverless-multi-regional-plugin": "^1.0.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch9/frp-batching/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-frp-batching", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -v -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -v -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "bluebird": "^3.5.1", 16 | "highland": "^2.13.0", 17 | "moment": "^2.22.1", 18 | "uuid": "^3.2.1" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ch9/frp-grouping/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-frp-grouping", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -v -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -v -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "bluebird": "^3.5.1", 16 | "highland": "^2.13.0", 17 | "moment": "^2.22.1", 18 | "uuid": "^3.2.1" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ch10/latency-based-routing/handler.js: -------------------------------------------------------------------------------- 1 | module.exports.hello = (request, context, callback) => { 2 | console.log('Request: %j', request); 3 | console.log('Context: %j', context); 4 | console.log('Env: %j', process.env); 5 | 6 | const response = { 7 | statusCode: 200, 8 | body: JSON.stringify({ 9 | timestamp: Date.now(), 10 | message: `Your function executed successfully in ${process.env.AWS_REGION}!`, 11 | }), 12 | }; 13 | 14 | console.log('Response: %j', response); 15 | 16 | callback(null, response); 17 | }; 18 | -------------------------------------------------------------------------------- /ch10/regional-failover/service/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-regional-failover-service", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test", 7 | "dp:lcl:e": "sls deploy -v -r us-east-1", 8 | "dp:lcl:w": "sls deploy -v -r us-west-2", 9 | "rm:lcl:e": "sls remove -v -r us-east-1", 10 | "rm:lcl:w": "sls remove -v -r us-west-2" 11 | }, 12 | "devDependencies": { 13 | "serverless": "1.26.0", 14 | "serverless-multi-regional-plugin": "^1.0.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch2/db-first-cognito/README.md: -------------------------------------------------------------------------------- 1 | # Applying the database-first variant of the event sourcing pattern with Cognito Datasets 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch2/db-first-cognito --path cncb-db-first-cognito 5 | 2. cd cncb-db-first-dynamodb 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. update, open and execute index.html 10 | 7. sls logs -f trigger -r us-east-1 -s $MY_STAGE 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch2/replaying-events/README.md: -------------------------------------------------------------------------------- 1 | # Replaying events 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch2/replaying-events --path cncb-replaying-events 5 | 2. cd cncb-replaying-events 6 | 3. npm install 7 | 4. npm test 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. node index.js replay --bucket --prefix --function --dry false 10 | 7. sls logs -f listener -r us-east-1 -s $MY_STAGE 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch10/regional-failover/service/handler.js: -------------------------------------------------------------------------------- 1 | module.exports.hello = (request, context, callback) => { 2 | console.log('Request: %j', request); 3 | console.log('Context: %j', context); 4 | console.log('Env: %j', process.env); 5 | 6 | const response = { 7 | statusCode: 200, 8 | body: JSON.stringify({ 9 | timestamp: Date.now(), 10 | message: `Your function executed successfully in ${process.env.AWS_REGION}!`, 11 | }), 12 | }; 13 | 14 | console.log('Response: %j', response); 15 | 16 | callback(null, response); 17 | }; 18 | -------------------------------------------------------------------------------- /ch5/graphql-jwt/lib/fixtures.js: -------------------------------------------------------------------------------- 1 | const thingsData = [ 2 | { 3 | id: '55555555-6666-1111-0000-000000000000', 4 | name: 'thing0', 5 | description: 'Thing none of two.', 6 | }, 7 | { 8 | id: '55555555-6666-1111-1111-000000000000', 9 | name: 'thing1', 10 | description: 'Thing one of two.', 11 | }, 12 | { 13 | id: '55555555-6666-1111-2222-000000000000', 14 | name: 'thing2', 15 | description: 'Thing two of two.', 16 | }, 17 | ]; 18 | 19 | module.exports = thingsData; -------------------------------------------------------------------------------- /ch7/custom-metrics/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-custom-metrics", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1 -s test --account cncb", 7 | "dp:lcl": "sls deploy -v -r us-east-1 --account cncb", 8 | "rm:lcl": "sls remove -r us-east-1 --account cncb" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "debug": "^3.1.0", 16 | "serverless-datadog-metrics": "^1.0.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch7/synthetics/serverless.yml: -------------------------------------------------------------------------------- 1 | service: cncb-synthetics 2 | 3 | provider: 4 | name: aws 5 | # cfnRole: arn:aws:iam:::role/${opt:stage}-cfnRole 6 | 7 | plugins: 8 | - serverless-spa-deploy 9 | - serverless-spa-config 10 | 11 | custom: 12 | spa: 13 | files: 14 | - source: ./build 15 | globs: '**/*' 16 | headers: 17 | CacheControl: max-age=31536000 # 1 year 18 | - source: ./build 19 | globs: 'index.html' 20 | headers: 21 | CacheControl: max-age=300 # 5 minutes 22 | -------------------------------------------------------------------------------- /ch5/graphql-jwt/schema/thing/resolvers.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | Query: { 3 | thing(_, { id }, ctx) { 4 | return ctx.models.Thing.getById(id); 5 | }, 6 | things(_, { name, limit, cursor }, ctx) { 7 | return ctx.models.Thing.queryByName(name, limit, cursor); 8 | }, 9 | }, 10 | Mutation: { 11 | saveThing: (_, { input }, ctx) => { 12 | return ctx.models.Thing.save(input.id, input); 13 | }, 14 | deleteThing: (_, args, ctx) => { 15 | return ctx.models.Thing.delete(args.id); 16 | }, 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /ch6/unit-testing/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | trim_trailing_whitespace = true 9 | end_of_line = lf 10 | insert_final_newline = true 11 | 12 | # Set default charset 13 | [*.{js,ts,css,json}] 14 | charset = utf-8 15 | indent_style = space 16 | indent_size = 2 17 | 18 | # Matches the exact files package.json 19 | [{package.json}] 20 | indent_style = space 21 | indent_size = 2 22 | -------------------------------------------------------------------------------- /ch3/bff-graphql-crud/schema/thing/resolvers.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | Query: { 3 | thing(_, { id }, ctx) { 4 | return ctx.models.Thing.getById(id); 5 | }, 6 | things(_, { name, limit, cursor }, ctx) { 7 | return ctx.models.Thing.queryByName(name, limit, cursor); 8 | }, 9 | }, 10 | Mutation: { 11 | saveThing: (_, { input }, ctx) => { 12 | return ctx.models.Thing.save(input.id, input); 13 | }, 14 | deleteThing: (_, args, ctx) => { 15 | return ctx.models.Thing.delete(args.id); 16 | }, 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /ch4/cdn-site/content/posts/first-post.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "First post" 3 | date: "2017-01-01" 4 | --- 5 | 6 | # This is a [Markdown](https://en.wikipedia.org/wiki/Markdown#Example) file 7 | 8 | If you are new to Markdown, you might want to check those links: 9 | 10 | * [What is Markdown?](http://whatismarkdown.com/) 11 | * [Mastering Markdown, a GitHub guide](https://guides.github.com/features/mastering-markdown/) 12 | * [wikipedia.org/wiki/Markdown](https://en.wikipedia.org/wiki/Markdown#Example) 13 | * [masteringmarkdown.com](http://masteringmarkdown.com/) 14 | -------------------------------------------------------------------------------- /ch6/pipeline/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-pipeline", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "echo running unit tests...", 7 | "test:int": "echo running integration tests...", 8 | "dp:lcl": "sls deploy -v -r us-east-1 --acct dev", 9 | "rm:lcl": "sls remove -r us-east-1 --acct dev", 10 | "dp:stg:e": "sls deploy -v -r us-east-1 -s stg --acct dev", 11 | "dp:prd:e": "sls deploy -v -r us-east-1 -s prd --acct prod" 12 | }, 13 | "devDependencies": { 14 | "serverless": "1.26.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ch8/backpressure-ratelimit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-backpressure-ratelimit", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -v -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -v -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "bluebird": "^3.5.1", 16 | "highland": "^2.13.0", 17 | "moment": "^2.22.1", 18 | "uuid": "^3.2.1" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ch8/idempotence-inverse-oplock/README.md: -------------------------------------------------------------------------------- 1 | # Implementing idempotency with an inverse oplock 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch8/idempotence-inverse-oplock --path cncb-idempotence-inverse-oplock 5 | 2. cd cncb-idempotence-inverse-oplock 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. sls invoke -f simulate -r us-east-1 -s $MY_STAGE 10 | 7. sls logs -f listener -r us-east-1 -s $MY_STAGE 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch6/integration-testing/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | trim_trailing_whitespace = true 9 | end_of_line = lf 10 | insert_final_newline = true 11 | 12 | # Set default charset 13 | [*.{js,ts,css,json}] 14 | charset = utf-8 15 | indent_style = space 16 | indent_size = 2 17 | 18 | # Matches the exact files package.json 19 | [{package.json}] 20 | indent_style = space 21 | indent_size = 2 22 | -------------------------------------------------------------------------------- /ch6/unit-testing/.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "lines": 100, 3 | "statements": 100, 4 | "functions": 100, 5 | "branches": 100, 6 | "include": [ 7 | "src/**/*.js" 8 | ], 9 | "exclude": [ 10 | "test/int/**/*.test.js", 11 | "test/unit/**/*.test.js" 12 | ], 13 | "require": [], 14 | "reporter": [ 15 | "text", 16 | "lcov", 17 | "html", 18 | "text-summary" 19 | ], 20 | "sourceMap": false, 21 | "instrument": false, 22 | "cache": false, 23 | "check-coverage": true, 24 | "all": true 25 | } 26 | -------------------------------------------------------------------------------- /ch8/backpressure-ratelimit/README.md: -------------------------------------------------------------------------------- 1 | # Implementing backpressure and rate limiting 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch8/backpressure-ratelimit --path cncb-backpressure-ratelimit 5 | 2. cd cncb-backpressure-ratelimit 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. sls invoke -f simulate -r us-east-1 -s $MY_STAGE 10 | 7. sls logs -f listener -r us-east-1 -s $MY_STAGE --filter 'event count' 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch9/frp-async-non-blocking-io/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-frp-async-non-blocking-io", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -v -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -v -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "bluebird": "^3.5.1", 16 | "highland": "^2.13.0", 17 | "moment": "^2.22.1", 18 | "uuid": "^3.2.1" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ch6/contract-testing-sync/bff/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | trim_trailing_whitespace = true 9 | end_of_line = lf 10 | insert_final_newline = true 11 | 12 | # Set default charset 13 | [*.{js,ts,css,json}] 14 | charset = utf-8 15 | indent_style = space 16 | indent_size = 2 17 | 18 | # Matches the exact files package.json 19 | [{package.json}] 20 | indent_style = space 21 | indent_size = 2 22 | -------------------------------------------------------------------------------- /ch9/frp-async-non-blocking-io/README.md: -------------------------------------------------------------------------------- 1 | # Leveraging asynchronous non-blocking IO 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch9/frp-async-non-blocking-io --path cncb-frp-async-non-blocking-io 5 | 2. cd cncb-frp-async-non-blocking-io 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. sls invoke -f simulate -r us-east-1 -s $MY_STAGE 10 | 7. sls logs -f listener -r us-east-1 -s $MY_STAGE --filter 'event count' 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | -------------------------------------------------------------------------------- /ch9/session-consistency/service/schema/thing/resolvers.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | Query: { 3 | thing(_, { id }, ctx) { 4 | return ctx.models.Thing.getById(id); 5 | }, 6 | things(_, { name, limit, cursor }, ctx) { 7 | return ctx.models.Thing.queryByName(name, limit, cursor); 8 | }, 9 | }, 10 | Mutation: { 11 | saveThing: (_, { input }, ctx) => { 12 | return ctx.models.Thing.save(input.id, input); 13 | }, 14 | deleteThing: (_, args, ctx) => { 15 | return ctx.models.Thing.delete(args.id); 16 | }, 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/upstream/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | trim_trailing_whitespace = true 9 | end_of_line = lf 10 | insert_final_newline = true 11 | 12 | # Set default charset 13 | [*.{js,ts,css,json}] 14 | charset = utf-8 15 | indent_style = space 16 | indent_size = 2 17 | 18 | # Matches the exact files package.json 19 | [{package.json}] 20 | indent_style = space 21 | indent_size = 2 22 | -------------------------------------------------------------------------------- /ch6/integration-testing/.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "lines": 100, 3 | "statements": 100, 4 | "functions": 100, 5 | "branches": 100, 6 | "include": [ 7 | "src/**/*.js" 8 | ], 9 | "exclude": [ 10 | "test/int/**/*.test.js", 11 | "test/unit/**/*.test.js" 12 | ], 13 | "require": [], 14 | "reporter": [ 15 | "text", 16 | "lcov", 17 | "html", 18 | "text-summary" 19 | ], 20 | "sourceMap": false, 21 | "instrument": false, 22 | "cache": false, 23 | "check-coverage": true, 24 | "all": true 25 | } 26 | -------------------------------------------------------------------------------- /ch6/transitive-testing/author-bff/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | trim_trailing_whitespace = true 9 | end_of_line = lf 10 | insert_final_newline = true 11 | 12 | # Set default charset 13 | [*.{js,ts,css,json}] 14 | charset = utf-8 15 | indent_style = space 16 | indent_size = 2 17 | 18 | # Matches the exact files package.json 19 | [{package.json}] 20 | indent_style = space 21 | indent_size = 2 22 | -------------------------------------------------------------------------------- /ch6/transitive-testing/customer-bff/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | trim_trailing_whitespace = true 9 | end_of_line = lf 10 | insert_final_newline = true 11 | 12 | # Set default charset 13 | [*.{js,ts,css,json}] 14 | charset = utf-8 15 | indent_style = space 16 | indent_size = 2 17 | 18 | # Matches the exact files package.json 19 | [{package.json}] 20 | indent_style = space 21 | indent_size = 2 22 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/downstream/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | trim_trailing_whitespace = true 9 | end_of_line = lf 10 | insert_final_newline = true 11 | 12 | # Set default charset 13 | [*.{js,ts,css,json}] 14 | charset = utf-8 15 | indent_style = space 16 | indent_size = 2 17 | 18 | # Matches the exact files package.json 19 | [{package.json}] 20 | indent_style = space 21 | indent_size = 2 22 | -------------------------------------------------------------------------------- /ch6/contract-testing-sync/bff/.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "lines": 100, 3 | "statements": 100, 4 | "functions": 100, 5 | "branches": 100, 6 | "include": [ 7 | "src/**/*.js" 8 | ], 9 | "exclude": [ 10 | "test/int/**/*.test.js", 11 | "test/unit/**/*.test.js" 12 | ], 13 | "require": [], 14 | "reporter": [ 15 | "text", 16 | "lcov", 17 | "html", 18 | "text-summary" 19 | ], 20 | "sourceMap": false, 21 | "instrument": false, 22 | "cache": false, 23 | "check-coverage": true, 24 | "all": true 25 | } 26 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/downstream/.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "lines": 100, 3 | "statements": 100, 4 | "functions": 100, 5 | "branches": 100, 6 | "include": [ 7 | "src/**/*.js" 8 | ], 9 | "exclude": [ 10 | "test/int/**/*.test.js", 11 | "test/unit/**/*.test.js" 12 | ], 13 | "require": [], 14 | "reporter": [ 15 | "text", 16 | "lcov", 17 | "html", 18 | "text-summary" 19 | ], 20 | "sourceMap": false, 21 | "instrument": false, 22 | "cache": false, 23 | "check-coverage": true, 24 | "all": true 25 | } 26 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/upstream/.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "lines": 100, 3 | "statements": 100, 4 | "functions": 100, 5 | "branches": 100, 6 | "include": [ 7 | "src/**/*.js" 8 | ], 9 | "exclude": [ 10 | "test/int/**/*.test.js", 11 | "test/unit/**/*.test.js" 12 | ], 13 | "require": [], 14 | "reporter": [ 15 | "text", 16 | "lcov", 17 | "html", 18 | "text-summary" 19 | ], 20 | "sourceMap": false, 21 | "instrument": false, 22 | "cache": false, 23 | "check-coverage": true, 24 | "all": true 25 | } 26 | -------------------------------------------------------------------------------- /ch6/transitive-testing/author-bff/.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "lines": 100, 3 | "statements": 100, 4 | "functions": 100, 5 | "branches": 100, 6 | "include": [ 7 | "src/**/*.js" 8 | ], 9 | "exclude": [ 10 | "test/int/**/*.test.js", 11 | "test/unit/**/*.test.js" 12 | ], 13 | "require": [], 14 | "reporter": [ 15 | "text", 16 | "lcov", 17 | "html", 18 | "text-summary" 19 | ], 20 | "sourceMap": false, 21 | "instrument": false, 22 | "cache": false, 23 | "check-coverage": true, 24 | "all": true 25 | } 26 | -------------------------------------------------------------------------------- /ch6/transitive-testing/customer-bff/.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "lines": 100, 3 | "statements": 100, 4 | "functions": 100, 5 | "branches": 100, 6 | "include": [ 7 | "src/**/*.js" 8 | ], 9 | "exclude": [ 10 | "test/int/**/*.test.js", 11 | "test/unit/**/*.test.js" 12 | ], 13 | "require": [], 14 | "reporter": [ 15 | "text", 16 | "lcov", 17 | "html", 18 | "text-summary" 19 | ], 20 | "sourceMap": false, 21 | "instrument": false, 22 | "cache": false, 23 | "check-coverage": true, 24 | "all": true 25 | } 26 | -------------------------------------------------------------------------------- /ch8/timeout-retry/handler.js: -------------------------------------------------------------------------------- 1 | const aws = require('aws-sdk'); 2 | const uuid = require('uuid'); 3 | 4 | module.exports.command = (request, context, callback) => { 5 | console.log('request: %j', request); 6 | 7 | const db = new aws.DynamoDB.DocumentClient({ 8 | httpOptions: { timeout: 1000 }, 9 | logger: console, 10 | // logger: { log: msg => debug(msg) }, 11 | }); 12 | 13 | const params = { 14 | TableName: process.env.TABLE_NAME, 15 | Item: { 16 | id: uuid.v4(), 17 | ...request, 18 | }, 19 | }; 20 | 21 | db.put(params, callback); 22 | }; 23 | -------------------------------------------------------------------------------- /ch2/data-lake-es/README.md: -------------------------------------------------------------------------------- 1 | # Indexing the data lake 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch2/data-lake-es --path cncb-data-lake-es 5 | 2. cd cncb-data-lake-es 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. publish an event from a separate terminal 10 | * cd ../cncb-event-stream 11 | * sls invoke -r us-east-1 -f publish -s $MY_STAGE -d '{"type":"thing-created"}' 12 | 7. sls logs -f transformer -r us-east-1 -s $MY_STAGE 13 | 8. npm run rm:lcl -- -s $MY_STAGE 14 | -------------------------------------------------------------------------------- /ch2/data-lake-es/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-data-lake-es", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.211.0", 12 | "bluebird": "^3.5.1", 13 | "serverless": "^1.26.0", 14 | "serverless-pseudo-parameters": "1.4.2" 15 | }, 16 | "dependencies": { 17 | "elasticsearch": "^14.2.1", 18 | "http-aws-es": "^4.0.0", 19 | "uuid": "3.2.1" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ch2/data-lake-s3/README.md: -------------------------------------------------------------------------------- 1 | # Creating a data lake 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch2/data-lake-s3 --path cncb-data-lake-s3 5 | 2. cd cncb-data-lake-s3 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. publish an event from a separate terminal 10 | * cd ../cncb-event-stream 11 | * sls invoke -r us-east-1 -f publish -s $MY_STAGE -d '{"type":"thing-created"}' 12 | 7. sls logs -f transformer -r us-east-1 -s $MY_STAGE 13 | 8. npm run rm:lcl -- -s $MY_STAGE 14 | -------------------------------------------------------------------------------- /ch4/cdn-site/dist/phenomic/content/posts/item/fifth-post.json: -------------------------------------------------------------------------------- 1 | {"filename":"fifth-post.md","title":"Fifth post","date":"2017-01-05","layout":"hero","body":{"t":"div","c":[{"t":"p","c":["Another post that have a ",{"t":"a","p":{"href":"../first-post/"},"c":["link to the first one"]},"."]},"\n",{"t":"p","c":["An wrong link to ",{"t":"a","p":{"href":"../unknown-post/"},"c":["a post that does not exist"]}," and another one\nto ",{"t":"a","p":{"href":"/unknown-page/"},"c":["a page that does not exist"]},"."]},"\n",{"t":"p","c":["Here is an ",{"t":"a","p":{"href":"http://phenomic.io"},"c":["external link"]},"."]}]}} -------------------------------------------------------------------------------- /ch10/regional-health-check/README.md: -------------------------------------------------------------------------------- 1 | # Creating a regional health check 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch10/regional-health-check --path cncb-regional-health-check 5 | 2. cd cncb-regional-health-check 6 | 3. npm install 7 | 4. npm test 8 | 5. npm run dp:lcl:e -- -s $MY_STAGE 9 | 6. npm run dp:lcl:w -- -s $MY_STAGE 10 | 7. curl -v https://xyz.execute-api.us-east-1.amazonaws.com/$MY_STAGE/check 11 | 8. curl -v https://zyx.execute-api.us-west-2.amazonaws.com/$MY_STAGE/check 12 | 9. npm run rm:lcl -- -s $MY_STAGE 13 | -------------------------------------------------------------------------------- /ch3/bff-rest-search/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-bff-rest-search", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0", 13 | "serverless-pseudo-parameters": "^1.4.2" 14 | }, 15 | "dependencies": { 16 | "elasticsearch": "^14.2.2", 17 | "highland": "^2.11.1", 18 | "http-aws-es": "^4.0.0", 19 | "uuid": "^3.1.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ch1/deploy-spa/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-deploy-spa", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "react-scripts start", 7 | "build": "react-scripts build", 8 | "test": "sls package -r us-east-1 -s test", 9 | "dp:lcl": "sls deploy -v -r us-east-1", 10 | "rm:lcl": "sls remove -r us-east-1" 11 | }, 12 | "dependencies": { 13 | "react": "16.2.0", 14 | "react-dom": "16.2.0" 15 | }, 16 | "devDependencies": { 17 | "react-scripts": "1.1.1", 18 | "serverless": "1.26.0", 19 | "serverless-spa-deploy": "^1.0.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ch2/event-first/README.md: -------------------------------------------------------------------------------- 1 | # Applying the event-first variant of the event sourcing pattern 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch2/event-first --path cncb-event-first 5 | 2. cd cncb-event-first 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. sls invoke -r us-east-1 -f submit -s $MY_STAGE -d '{"id":"11111111-1111-1111-1111-111111111111","name":"thing one","kind":"other"}' 10 | 7. sls logs -f submit -r us-east-1 -s $MY_STAGE 11 | 8. npm run rm:lcl -- -s $MY_STAGE 12 | 13 | 14 | -------------------------------------------------------------------------------- /ch2/materialized-view-es/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-materialized-view-es", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0", 13 | "serverless-pseudo-parameters": "^1.4.2" 14 | }, 15 | "dependencies": { 16 | "elasticsearch": "^14.2.2", 17 | "highland": "^2.11.1", 18 | "http-aws-es": "^4.0.0", 19 | "uuid": "^3.1.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ch4/cdn-dns/serverless.yml: -------------------------------------------------------------------------------- 1 | service: cncb-cdn-dns 2 | 3 | provider: 4 | name: aws 5 | 6 | plugins: 7 | - serverless-spa-deploy 8 | - serverless-spa-config 9 | 10 | custom: 11 | spa: 12 | files: 13 | - source: ./build 14 | globs: '**/*' 15 | headers: 16 | CacheControl: max-age=31536000 # 1 year 17 | - source: ./build 18 | globs: 'index.html' 19 | headers: 20 | CacheControl: max-age=300 # 5 minutes 21 | dns: 22 | hostedZoneId: Z1234567890123 23 | domainName: example.com 24 | endpoint: app.${self:custom.dns.domainName} 25 | -------------------------------------------------------------------------------- /ch9/dynamodb-autoscaling/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-dynamodb-autoscaling", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -v -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -v -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0", 13 | "serverless-dynamodb-autoscaling-plugin": "^1.0.0" 14 | }, 15 | "dependencies": { 16 | "bluebird": "^3.5.1", 17 | "highland": "^2.13.0", 18 | "moment": "^2.22.1", 19 | "uuid": "^3.2.1" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ch5/graphql-jwt/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-graphql-jwt", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "graphql": "^0.13.2", 16 | "graphql-errors": "^2.1.0", 17 | "graphql-server-lambda": "^1.3.6", 18 | "graphql-tools": "^3.0.0", 19 | "lodash": "^4.17.10", 20 | "uuid": "^3.1.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ch6/unit-testing/src/connector/stream.js: -------------------------------------------------------------------------------- 1 | /* eslint import/no-extraneous-dependencies: ["error", {"devDependencies": true}] */ 2 | import { Kinesis } from 'aws-sdk'; 3 | 4 | class Connector { 5 | constructor(streamName) { 6 | this.streamName = streamName; 7 | this.stream = new Kinesis(); 8 | } 9 | 10 | publish(event) { 11 | const params = { 12 | StreamName: this.streamName, 13 | PartitionKey: event.partitionKey, 14 | Data: Buffer.from(JSON.stringify(event)), 15 | }; 16 | 17 | return this.stream.putRecord(params).promise(); 18 | } 19 | } 20 | 21 | export default Connector; 22 | -------------------------------------------------------------------------------- /ch3/bff-graphql-crud/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-bff-graphql-crud", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "graphql": "^0.13.2", 16 | "graphql-server-lambda": "^1.3.6", 17 | "graphql-tools": "^3.0.0", 18 | "highland": "^2.11.1", 19 | "lodash": "^4.17.10", 20 | "uuid": "^3.1.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ch6/integration-testing/src/connector/stream.js: -------------------------------------------------------------------------------- 1 | /* eslint import/no-extraneous-dependencies: ["error", {"devDependencies": true}] */ 2 | import { Kinesis } from 'aws-sdk'; 3 | 4 | class Connector { 5 | constructor(streamName) { 6 | this.streamName = streamName; 7 | this.stream = new Kinesis(); 8 | } 9 | 10 | publish(event) { 11 | const params = { 12 | StreamName: this.streamName, 13 | PartitionKey: event.partitionKey, 14 | Data: Buffer.from(JSON.stringify(event)), 15 | }; 16 | 17 | return this.stream.putRecord(params).promise(); 18 | } 19 | } 20 | 21 | export default Connector; 22 | -------------------------------------------------------------------------------- /ch6/unit-testing/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "transform-runtime", 4 | [ 5 | "transform-async-to-module-method", 6 | { 7 | "module": "bluebird", 8 | "method": "coroutine" 9 | } 10 | ] 11 | ], 12 | "presets": [ 13 | [ 14 | "env", { 15 | "useBuiltIns": true, 16 | "debug": false 17 | }], 18 | "stage-2" 19 | ], 20 | "env": { 21 | "test": { 22 | "plugins": [ 23 | "istanbul" 24 | ] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ch2/replaying-events/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-replaying-events", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "replay": "node index.js", 7 | "test": "sls package -r us-east-1", 8 | "dp:lcl": "sls deploy -v -r us-east-1", 9 | "rm:lcl": "sls remove -r us-east-1" 10 | }, 11 | "devDependencies": { 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "aws-sdk": "^2.45.0", 16 | "bluebird": "^3.5.0", 17 | "debug": "^2.6.4", 18 | "highland": "^2.11.1", 19 | "lodash": "^4.17.4", 20 | "moment": "^2.18.1", 21 | "yargs": "^7.1.0" 22 | } 23 | } -------------------------------------------------------------------------------- /ch4/cdn-dns/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | 5 | class App extends Component { 6 | render() { 7 | return ( 8 |
9 |
10 | logo 11 |

Welcome to React

12 |
13 |

14 | To get started, edit src/App.js and save to reload. 15 |

16 |
17 | ); 18 | } 19 | } 20 | 21 | export default App; 22 | -------------------------------------------------------------------------------- /ch4/cdn-spa/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | 5 | class App extends Component { 6 | render() { 7 | return ( 8 |
9 |
10 | logo 11 |

Welcome to React

12 |
13 |

14 | To get started, edit src/App.js and save to reload. 15 |

16 |
17 | ); 18 | } 19 | } 20 | 21 | export default App; 22 | -------------------------------------------------------------------------------- /ch6/integration-testing/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "transform-runtime", 4 | [ 5 | "transform-async-to-module-method", 6 | { 7 | "module": "bluebird", 8 | "method": "coroutine" 9 | } 10 | ] 11 | ], 12 | "presets": [ 13 | [ 14 | "env", { 15 | "useBuiltIns": true, 16 | "debug": false 17 | }], 18 | "stage-2" 19 | ], 20 | "env": { 21 | "test": { 22 | "plugins": [ 23 | "istanbul" 24 | ] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ch1/deploy-spa/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | 5 | class App extends Component { 6 | render() { 7 | return ( 8 |
9 |
10 | logo 11 |

Welcome to React

12 |
13 |

14 | To get started, edit src/App.js and save to reload. 15 |

16 |
17 | ); 18 | } 19 | } 20 | 21 | export default App; 22 | -------------------------------------------------------------------------------- /ch2/db-first-dynamodb/README.md: -------------------------------------------------------------------------------- 1 | # Applying the database-first variant of the event sourcing pattern with DynamoDB 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch2/db-first-dynamodb --path cncb-db-first-dynamodb 5 | 2. cd cncb-db-first-dynamodb 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. sls invoke -r us-east-1 -f command -s $MY_STAGE -d '{"name":"thing one"}' 10 | 7. sls logs -f command -r us-east-1 -s $MY_STAGE 11 | 8. sls logs -f trigger -r us-east-1 -s $MY_STAGE 12 | 9. npm run rm:lcl -- -s $MY_STAGE 13 | -------------------------------------------------------------------------------- /ch6/contract-testing-sync/bff/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "transform-runtime", 4 | [ 5 | "transform-async-to-module-method", 6 | { 7 | "module": "bluebird", 8 | "method": "coroutine" 9 | } 10 | ] 11 | ], 12 | "presets": [ 13 | [ 14 | "env", { 15 | "useBuiltIns": true, 16 | "debug": false 17 | }], 18 | "stage-2" 19 | ], 20 | "env": { 21 | "test": { 22 | "plugins": [ 23 | "istanbul" 24 | ] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ch6/transitive-testing/author-bff/src/connector/stream.js: -------------------------------------------------------------------------------- 1 | /* eslint import/no-extraneous-dependencies: ["error", {"devDependencies": true}] */ 2 | import { Kinesis } from 'aws-sdk'; 3 | 4 | class Connector { 5 | constructor(streamName) { 6 | this.streamName = streamName; 7 | this.stream = new Kinesis(); 8 | } 9 | 10 | publish(event) { 11 | const params = { 12 | StreamName: this.streamName, 13 | PartitionKey: event.partitionKey, 14 | Data: Buffer.from(JSON.stringify(event)), 15 | }; 16 | 17 | return this.stream.putRecord(params).promise(); 18 | } 19 | } 20 | 21 | export default Connector; 22 | -------------------------------------------------------------------------------- /ch5/graphql-jwt/schema/thing/model.js: -------------------------------------------------------------------------------- 1 | const uuid = require('uuid'); 2 | const { merge } = require('lodash'); 3 | 4 | class Thing { 5 | 6 | constructor(connector) { 7 | this.connector = connector; 8 | } 9 | 10 | getById(id) { 11 | return this.connector.getById(id); 12 | } 13 | 14 | queryByName(name, limit, cursor) { 15 | return this.connector.queryByName(name, cursor, limit); 16 | } 17 | 18 | save(id, body) { 19 | id = id ? id : uuid.v4(); 20 | return this.connector.save(id, body); 21 | } 22 | 23 | delete(id) { 24 | return this.connector.delete(id); 25 | } 26 | } 27 | 28 | module.exports = Thing -------------------------------------------------------------------------------- /ch6/contract-testing-async/upstream/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "transform-runtime", 4 | [ 5 | "transform-async-to-module-method", 6 | { 7 | "module": "bluebird", 8 | "method": "coroutine" 9 | } 10 | ] 11 | ], 12 | "presets": [ 13 | [ 14 | "env", { 15 | "useBuiltIns": true, 16 | "debug": false 17 | }], 18 | "stage-2" 19 | ], 20 | "env": { 21 | "test": { 22 | "plugins": [ 23 | "istanbul" 24 | ] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/upstream/src/connector/stream.js: -------------------------------------------------------------------------------- 1 | /* eslint import/no-extraneous-dependencies: ["error", {"devDependencies": true}] */ 2 | import { Kinesis } from 'aws-sdk'; 3 | 4 | class Connector { 5 | constructor(streamName) { 6 | this.streamName = streamName; 7 | this.stream = new Kinesis(); 8 | } 9 | 10 | publish(event) { 11 | const params = { 12 | StreamName: this.streamName, 13 | PartitionKey: event.partitionKey, 14 | Data: Buffer.from(JSON.stringify(event)), 15 | }; 16 | 17 | return this.stream.putRecord(params).promise(); 18 | } 19 | } 20 | 21 | export default Connector; 22 | -------------------------------------------------------------------------------- /ch6/transitive-testing/author-bff/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "transform-runtime", 4 | [ 5 | "transform-async-to-module-method", 6 | { 7 | "module": "bluebird", 8 | "method": "coroutine" 9 | } 10 | ] 11 | ], 12 | "presets": [ 13 | [ 14 | "env", { 15 | "useBuiltIns": true, 16 | "debug": false 17 | }], 18 | "stage-2" 19 | ], 20 | "env": { 21 | "test": { 22 | "plugins": [ 23 | "istanbul" 24 | ] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ch6/transitive-testing/customer-bff/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "transform-runtime", 4 | [ 5 | "transform-async-to-module-method", 6 | { 7 | "module": "bluebird", 8 | "method": "coroutine" 9 | } 10 | ] 11 | ], 12 | "presets": [ 13 | [ 14 | "env", { 15 | "useBuiltIns": true, 16 | "debug": false 17 | }], 18 | "stage-2" 19 | ], 20 | "env": { 21 | "test": { 22 | "plugins": [ 23 | "istanbul" 24 | ] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ch1/create-stream-processor/README.md: -------------------------------------------------------------------------------- 1 | # Creating a stream processor 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch1/create-stream-processor --path cncb-create-stream-processor 5 | 2. cd cncb-create-stream-processor 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. publish an event from a separate terminal 10 | * cd ../cncb-event-stream 11 | * sls invoke -r us-east-1 -f publish -s $MY_STAGE -d '{"type":"thing-created"}' 12 | 7. sls logs -f listener -r us-east-1 -s $MY_STAGE 13 | 8. npm run rm:lcl -- -s $MY_STAGE 14 | -------------------------------------------------------------------------------- /ch10/latency-based-routing/README.md: -------------------------------------------------------------------------------- 1 | # Implementing latency based routing 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch10/regional-health-check --path cncb-regional-health-check 5 | 2. cd cncb-regional-health-check 6 | 3. npm install 7 | 4. npm test 8 | 5. npm run dp:lcl:w -- -s $MY_STAGE 9 | 6. curl -v https://$MY_STAGE-cncb-latency-based-routing.example.com/$MY_STAGE/hello 10 | 7. npm run dp:lcl:e -- -s $MY_STAGE 11 | 8. curl -v https://cncb-latency-based-routing.example.com/hello 12 | 9. npm run rm:lcl:w -- -s $MY_STAGE 13 | 10. npm run rm:lcl:e -- -s $MY_STAGE 14 | -------------------------------------------------------------------------------- /ch4/cdn-dns/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-cdn-dns", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "react-scripts start", 7 | "build": "react-scripts build", 8 | "test": "sls package -r us-east-1 -s test", 9 | "dp:lcl": "sls deploy -v -r us-east-1", 10 | "rm:lcl": "sls remove -r us-east-1" 11 | }, 12 | "dependencies": { 13 | "react": "16.2.0", 14 | "react-dom": "16.2.0" 15 | }, 16 | "devDependencies": { 17 | "react-scripts": "1.1.1", 18 | "serverless": "1.26.0", 19 | "serverless-spa-config": "1.0.2", 20 | "serverless-spa-deploy": "1.0.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ch4/cdn-spa/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-cdn-spa", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "react-scripts start", 7 | "build": "react-scripts build", 8 | "test": "sls package -r us-east-1 -s test", 9 | "dp:lcl": "sls deploy -v -r us-east-1", 10 | "rm:lcl": "sls remove -r us-east-1" 11 | }, 12 | "dependencies": { 13 | "react": "16.2.0", 14 | "react-dom": "16.2.0" 15 | }, 16 | "devDependencies": { 17 | "react-scripts": "1.1.1", 18 | "serverless": "1.26.0", 19 | "serverless-spa-config": "1.0.2", 20 | "serverless-spa-deploy": "1.0.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/downstream/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "transform-runtime", 4 | [ 5 | "transform-async-to-module-method", 6 | { 7 | "module": "bluebird", 8 | "method": "coroutine" 9 | } 10 | ] 11 | ], 12 | "presets": [ 13 | [ 14 | "env", { 15 | "useBuiltIns": true, 16 | "debug": false 17 | }], 18 | "stage-2" 19 | ], 20 | "env": { 21 | "test": { 22 | "plugins": [ 23 | "istanbul" 24 | ] 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ch9/session-consistency/service/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-session-consistency-service", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl": "sls deploy -v -r us-east-1", 8 | "rm:lcl": "sls remove -r us-east-1" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "graphql": "^0.13.2", 16 | "graphql-server-lambda": "^1.3.6", 17 | "graphql-tools": "^3.0.0", 18 | "highland": "^2.11.1", 19 | "lodash": "^4.17.10", 20 | "uuid": "^3.1.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ch5/dr/README.md: -------------------------------------------------------------------------------- 1 | # Replicating the data lake for disaster recovery 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch5/dr --path cncb-dr 5 | 2. cd cncb-dr/recovery-account 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. cd ../src1-account 10 | 7. npm install 11 | 8. npm test -- -s $MY_STAGE 12 | 9. npm run dp:lcl -- -s $MY_STAGE 13 | 10. sls invoke -r us-east-1 -f load -s $MY_STAGE 14 | 11. review source and target buckets 15 | 12. npm run rm:lcl -- -s $MY_STAGE 16 | 13. cd ../recovery-account 17 | 14. npm run rm:lcl -- -s $MY_STAGE 18 | -------------------------------------------------------------------------------- /ch7/synthetics/README.md: -------------------------------------------------------------------------------- 1 | # Creating synthetic transaction tests 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch5/cognito-signin --path cncb-cognito-signin 5 | 2. cd cncb-cognito-signin 6 | 3. npm install 7 | 4. Update src/configuration.js 8 | 4. npm start 9 | 5. npm test 10 | 6. npm run build 11 | 7. npm run dp:lcl -- -s $MY_STAGE 12 | 8. browse http://cncb-cognito-signin-$MY_STAGE-websitebucket-xxxx.s3-website-us-east-1.amazonaws.com 13 | 9. Click Sign Up and complete form 14 | 10. Click Sign Out 15 | 11. Click Sign In and complete form 16 | 12. npm run rm:lcl -- -s $MY_STAGE 17 | -------------------------------------------------------------------------------- /ch1/create-stream-processor/handler.js: -------------------------------------------------------------------------------- 1 | const _ = require('highland'); 2 | 3 | module.exports.listener = (event, context, cb) => { 4 | console.log('event: %j', event); 5 | 6 | _(event.Records) 7 | .map(recordToEvent) 8 | .tap(printEvent) 9 | .filter(forThingCreated) 10 | .collect() 11 | .tap(printCount) 12 | .toCallback(cb); 13 | }; 14 | 15 | const recordToEvent = r => JSON.parse(Buffer.from(r.kinesis.data, 'base64')); 16 | 17 | const forThingCreated = e => e.type === 'thing-created'; 18 | 19 | const printEvent = e => console.log('event: %j', e); 20 | 21 | const printCount = events => console.log('count: %d', events.length); 22 | -------------------------------------------------------------------------------- /ch6/integration-testing/fixtures/dynamodb.us-east-1.amazonaws.com-443/save: -------------------------------------------------------------------------------- 1 | POST / 2 | content-type: application/x-amz-json-1.0 3 | x-amz-target: DynamoDB_20120810.PutItem 4 | host: dynamodb.us-east-1.amazonaws.com 5 | body: {\"TableName\":\"stg-cncb-integration-testing-things\",\"Item\":{\"id\":{\"S\":\"00000000-0000-0000-0000-000000000000\"},\"name\":{\"S\":\"thing0\"}}} 6 | 7 | HTTP/1.1 200 OK 8 | server: Server 9 | date: Fri, 15 Jun 2018 05:59:44 GMT 10 | content-type: application/x-amz-json-1.0 11 | content-length: 2 12 | connection: keep-alive 13 | x-amzn-requestid: ECUGR6AOBDC45NLA4SI4UMN4RRVV4KQNSO5AEMVJF66Q9ASUAAJG 14 | x-amz-crc32: 2745614147 15 | 16 | {} -------------------------------------------------------------------------------- /ch9/tuning-faas/src/get/index.js: -------------------------------------------------------------------------------- 1 | import { response200, response404, response500 } from '../utils'; 2 | import Connector from '../connector/db'; 3 | 4 | export class Handler { 5 | constructor(tableName) { 6 | this.connector = new Connector(tableName); 7 | } 8 | 9 | handle(request) { 10 | const { id } = request.pathParameters; 11 | return this.connector.getById(id); 12 | } 13 | } 14 | 15 | export const handle = (request, context, cb) => { 16 | new Handler(process.env.TABLE_NAME) 17 | .handle(request) 18 | .then(data => (data ? 19 | response200(cb, data) : 20 | response404(cb))) 21 | .catch(response500(cb)); 22 | }; 23 | -------------------------------------------------------------------------------- /ch6/unit-testing/src/get/index.js: -------------------------------------------------------------------------------- 1 | import { response200, response404, response500 } from '../utils'; 2 | import Connector from '../connector/db'; 3 | 4 | export class Handler { 5 | constructor(tableName) { 6 | this.connector = new Connector(tableName); 7 | } 8 | 9 | handle(request) { 10 | const { id } = request.pathParameters; 11 | return this.connector.getById(id); 12 | } 13 | } 14 | 15 | export const handle = (request, context, cb) => { 16 | new Handler(process.env.TABLE_NAME) 17 | .handle(request) 18 | .then(data => (data ? 19 | response200(cb, data) : 20 | response404(cb))) 21 | .catch(response500(cb)); 22 | }; 23 | -------------------------------------------------------------------------------- /ch7/custom-metrics/handler.js: -------------------------------------------------------------------------------- 1 | const { monitor, count } = require('serverless-datadog-metrics'); 2 | const debug = require('debug')('handler'); 3 | 4 | module.exports.hello = monitor((request, context, callback) => { 5 | debug('request: %j', request); 6 | debug('context: %j', context); 7 | 8 | count('hello.count', 1); 9 | 10 | const response = { 11 | statusCode: 200, 12 | headers: { 13 | 'Access-Control-Allow-Origin': '*', 14 | }, 15 | body: JSON.stringify({ 16 | message: 'JavaScript Cloud Native Development Cookbook! Your function executed successfully!', 17 | }), 18 | }; 19 | 20 | callback(null, response); 21 | }); 22 | -------------------------------------------------------------------------------- /ch9/tuning-faas/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | [ 4 | "transform-async-to-module-method", 5 | { 6 | "module": "bluebird", 7 | "method": "coroutine" 8 | } 9 | ] 10 | ], 11 | "presets": [ 12 | [ 13 | "env", { 14 | "node": "8.10", 15 | "useBuiltIns": true, 16 | "debug": false 17 | }], 18 | "stage-2" 19 | ], 20 | "env": { 21 | "test": { 22 | "plugins": [ 23 | "istanbul", 24 | "transform-runtime" 25 | ] 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ch3/event-orchestration/serverless.yml: -------------------------------------------------------------------------------- 1 | service: cncb-event-orchestration 2 | 3 | provider: 4 | name: aws 5 | runtime: nodejs8.10 6 | iamRoleStatements: 7 | - Effect: Allow 8 | Action: 9 | - kinesis:PutRecord 10 | Resource: ${cf:cncb-event-stream-${opt:stage}.streamArn} 11 | 12 | functions: 13 | listener: 14 | handler: handler.listener 15 | events: 16 | - stream: 17 | type: kinesis 18 | arn: ${cf:cncb-event-stream-${opt:stage}.streamArn} 19 | batchSize: 100 20 | startingPosition: TRIM_HORIZON 21 | environment: 22 | STREAM_NAME: ${cf:cncb-event-stream-${opt:stage}.streamName} 23 | -------------------------------------------------------------------------------- /ch5/graphql-jwt/schema/directives.js: -------------------------------------------------------------------------------- 1 | const { get, intersection } = require('lodash'); 2 | const { UserError } = require('graphql-errors'); 3 | 4 | const getGroups = ctx => get(ctx.event, 'requestContext.authorizer.claims.cognito:groups', ''); 5 | 6 | const directiveResolvers = { 7 | hasRole: (next, source, { roles }, ctx) => { 8 | const groups = getGroups(ctx).split(','); 9 | if (groups && intersection(groups, roles).length > 0) { 10 | return next(); 11 | } 12 | console.log('hasRole: (%s) does not intersect (%s)', groups, roles); 13 | throw new UserError('Access Denied'); 14 | }, 15 | } 16 | 17 | module.exports = { directiveResolvers }; 18 | -------------------------------------------------------------------------------- /ch6/contract-testing-sync/bff/fixtures/dynamodb.us-east-1.amazonaws.com-443/save: -------------------------------------------------------------------------------- 1 | POST / 2 | content-type: application/x-amz-json-1.0 3 | x-amz-target: DynamoDB_20120810.PutItem 4 | host: dynamodb.us-east-1.amazonaws.com 5 | body: {\"TableName\":\"stg-cncb-contract-testing-sync-things\",\"Item\":{\"id\":{\"S\":\"00000000-0000-0000-0000-000000000000\"},\"name\":{\"S\":\"thing0\"}}} 6 | 7 | HTTP/1.1 200 OK 8 | server: Server 9 | date: Sun, 17 Jun 2018 21:26:46 GMT 10 | content-type: application/x-amz-json-1.0 11 | content-length: 2 12 | connection: keep-alive 13 | x-amzn-requestid: MI2E1841TID76J3RE8ITB2RIPBVV4KQNSO5AEMVJF66Q9ASUAAJG 14 | x-amz-crc32: 2745614147 15 | 16 | {} -------------------------------------------------------------------------------- /ch6/integration-testing/src/get/index.js: -------------------------------------------------------------------------------- 1 | import { response200, response404, response500 } from '../utils'; 2 | import Connector from '../connector/db'; 3 | 4 | export class Handler { 5 | constructor(tableName) { 6 | this.connector = new Connector(tableName); 7 | } 8 | 9 | handle(request) { 10 | const { id } = request.pathParameters; 11 | return this.connector.getById(id); 12 | } 13 | } 14 | 15 | export const handle = (request, context, cb) => { 16 | new Handler(process.env.TABLE_NAME) 17 | .handle(request) 18 | .then(data => (data ? 19 | response200(cb, data) : 20 | response404(cb))) 21 | .catch(response500(cb)); 22 | }; 23 | -------------------------------------------------------------------------------- /ch7/event-metrics/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-event-metrics", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -v -r us-east-1 -s test --account cncb", 7 | "dp:lcl": "sls deploy -v -r us-east-1 --account cncb", 8 | "rm:lcl": "sls remove -v -r us-east-1 --account cncb" 9 | }, 10 | "devDependencies": { 11 | "aws-sdk": "^2.218.1", 12 | "serverless": "1.26.0" 13 | }, 14 | "dependencies": { 15 | "bluebird": "^3.5.1", 16 | "debug": "^3.1.0", 17 | "highland": "^2.13.0", 18 | "moment": "^2.22.1", 19 | "serverless-datadog-metrics": "^1.0.1", 20 | "uuid": "^3.2.1" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ch6/contract-testing-sync/bff/src/get/index.js: -------------------------------------------------------------------------------- 1 | import { response200, response404, response500 } from '../utils'; 2 | import Connector from '../connector/db'; 3 | 4 | export class Handler { 5 | constructor(tableName) { 6 | this.connector = new Connector(tableName); 7 | } 8 | 9 | handle(request) { 10 | const { id } = request.pathParameters; 11 | return this.connector.getById(id); 12 | } 13 | } 14 | 15 | export const handle = (request, context, cb) => { 16 | new Handler(process.env.TABLE_NAME) 17 | .handle(request) 18 | .then(data => (data ? 19 | response200(cb, data) : 20 | response404(cb))) 21 | .catch(response500(cb)); 22 | }; 23 | -------------------------------------------------------------------------------- /ch6/transitive-testing/author-bff/src/get/index.js: -------------------------------------------------------------------------------- 1 | import { response200, response404, response500 } from '../utils'; 2 | import Connector from '../connector/db'; 3 | 4 | export class Handler { 5 | constructor(tableName) { 6 | this.connector = new Connector(tableName); 7 | } 8 | 9 | handle(request) { 10 | const { id } = request.pathParameters; 11 | return this.connector.getById(id); 12 | } 13 | } 14 | 15 | export const handle = (request, context, cb) => { 16 | new Handler(process.env.TABLE_NAME) 17 | .handle(request) 18 | .then(data => (data ? 19 | response200(cb, data) : 20 | response404(cb))) 21 | .catch(response500(cb)); 22 | }; 23 | -------------------------------------------------------------------------------- /ch6/transitive-testing/customer-bff/src/get/index.js: -------------------------------------------------------------------------------- 1 | import { response200, response404, response500 } from '../utils'; 2 | import Connector from '../connector/db'; 3 | 4 | export class Handler { 5 | constructor(tableName) { 6 | this.connector = new Connector(tableName); 7 | } 8 | 9 | handle(request) { 10 | const { id } = request.pathParameters; 11 | return this.connector.getById(id); 12 | } 13 | } 14 | 15 | export const handle = (request, context, cb) => { 16 | new Handler(process.env.TABLE_NAME) 17 | .handle(request) 18 | .then(data => (data ? 19 | response200(cb, data) : 20 | response404(cb))) 21 | .catch(response500(cb)); 22 | }; 23 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/downstream/src/get/index.js: -------------------------------------------------------------------------------- 1 | import { response200, response404, response500 } from '../utils'; 2 | import Connector from '../connector/db'; 3 | 4 | export class Handler { 5 | constructor(tableName) { 6 | this.connector = new Connector(tableName); 7 | } 8 | 9 | handle(request) { 10 | const { id } = request.pathParameters; 11 | return this.connector.getById(id); 12 | } 13 | } 14 | 15 | export const handle = (request, context, cb) => { 16 | new Handler(process.env.TABLE_NAME) 17 | .handle(request) 18 | .then(data => (data ? 19 | response200(cb, data) : 20 | response404(cb))) 21 | .catch(response500(cb)); 22 | }; 23 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/upstream/fixtures/dynamodb.us-east-1.amazonaws.com-443/save: -------------------------------------------------------------------------------- 1 | POST / 2 | content-type: application/x-amz-json-1.0 3 | x-amz-target: DynamoDB_20120810.PutItem 4 | host: dynamodb.us-east-1.amazonaws.com 5 | body: {\"TableName\":\"stg-cncb-contract-testing-async-upstream-things\",\"Item\":{\"id\":{\"S\":\"00000000-0000-0000-0000-000000000000\"},\"name\":{\"S\":\"thing0\"}}} 6 | 7 | HTTP/1.1 200 OK 8 | server: Server 9 | date: Wed, 20 Jun 2018 03:38:06 GMT 10 | content-type: application/x-amz-json-1.0 11 | content-length: 2 12 | connection: keep-alive 13 | x-amzn-requestid: 94BULVS95GCK7O79DT618VIL0NVV4KQNSO5AEMVJF66Q9ASUAAJG 14 | x-amz-crc32: 2745614147 15 | 16 | {} -------------------------------------------------------------------------------- /ch3/bff-graphql-crud/schema/index.js: -------------------------------------------------------------------------------- 1 | const { merge } = require('lodash'); 2 | const { makeExecutableSchema } = require('graphql-tools'); 3 | const { thingTypeDefs, thingResolvers } = require('./thing'); 4 | 5 | const query = ` 6 | type Query { 7 | _empty: String 8 | } 9 | `; 10 | 11 | const mutation = ` 12 | type Mutation { 13 | _empty: String 14 | } 15 | `; 16 | 17 | const schemaDefinition = ` 18 | schema { 19 | query: Query 20 | mutation: Mutation 21 | } 22 | `; 23 | 24 | module.exports = makeExecutableSchema({ 25 | typeDefs: [schemaDefinition, query, mutation, thingTypeDefs], 26 | resolvers: merge({}, thingResolvers), 27 | logger: console, 28 | }); 29 | -------------------------------------------------------------------------------- /ch3/bff-graphql-crud/schema/thing/typedefs.js: -------------------------------------------------------------------------------- 1 | module.exports = ` 2 | type Thing { 3 | id: String! 4 | name: String 5 | description: String 6 | } 7 | 8 | type ThingConnection { 9 | items: [Thing!]! 10 | cursor: String 11 | } 12 | 13 | extend type Query { 14 | thing(id: String!): Thing 15 | things(name: String, limit: Int, cursor: String): ThingConnection 16 | } 17 | 18 | input ThingInput { 19 | id: String 20 | name: String! 21 | description: String 22 | } 23 | 24 | extend type Mutation { 25 | saveThing( 26 | input: ThingInput 27 | ): Thing 28 | deleteThing( 29 | id: ID! 30 | ): Thing 31 | } 32 | `; 33 | -------------------------------------------------------------------------------- /ch5/cognito-signin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-cognito-signin", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "react-scripts start", 7 | "build": "react-scripts build", 8 | "test": "sls package -r us-east-1 -s test", 9 | "dp:lcl": "sls deploy -v -r us-east-1", 10 | "rm:lcl": "sls remove -r us-east-1" 11 | }, 12 | "dependencies": { 13 | "amazon-cognito-auth-js": "1.2.4", 14 | "react": "16.3.2", 15 | "react-dom": "16.3.2" 16 | }, 17 | "devDependencies": { 18 | "react-scripts": "1.1.5", 19 | "react-router-dom": "4.3.1", 20 | "serverless": "1.26.0", 21 | "serverless-spa-deploy": "^1.0.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ch6/transitive-testing/author-bff/fixtures/dynamodb.us-east-1.amazonaws.com-443/save-thing0: -------------------------------------------------------------------------------- 1 | POST / 2 | content-type: application/x-amz-json-1.0 3 | x-amz-target: DynamoDB_20120810.PutItem 4 | host: dynamodb.us-east-1.amazonaws.com 5 | body: {\"TableName\":\"stg-cncb-transitive-testing-author-bff-things\",\"Item\":{\"id\":{\"S\":\"00000000-0000-0000-0000-000000000000\"},\"name\":{\"S\":\"thing0\"}}} 6 | 7 | HTTP/1.1 200 OK 8 | server: Server 9 | date: Sun, 17 Jun 2018 21:26:46 GMT 10 | content-type: application/x-amz-json-1.0 11 | content-length: 2 12 | connection: keep-alive 13 | x-amzn-requestid: MI2E1841TID76J3RE8ITB2RIPBVV4KQNSO5AEMVJF66Q9ASUAAJG 14 | x-amz-crc32: 2745614147 15 | 16 | {} 17 | -------------------------------------------------------------------------------- /ch9/session-consistency/service/schema/index.js: -------------------------------------------------------------------------------- 1 | const { merge } = require('lodash'); 2 | const { makeExecutableSchema } = require('graphql-tools'); 3 | const { thingTypeDefs, thingResolvers } = require('./thing'); 4 | 5 | const query = ` 6 | type Query { 7 | _empty: String 8 | } 9 | `; 10 | 11 | const mutation = ` 12 | type Mutation { 13 | _empty: String 14 | } 15 | `; 16 | 17 | const schemaDefinition = ` 18 | schema { 19 | query: Query 20 | mutation: Mutation 21 | } 22 | `; 23 | 24 | module.exports = makeExecutableSchema({ 25 | typeDefs: [schemaDefinition, query, mutation, thingTypeDefs], 26 | resolvers: merge({}, thingResolvers), 27 | logger: console, 28 | }); 29 | -------------------------------------------------------------------------------- /ch9/session-consistency/service/schema/thing/typedefs.js: -------------------------------------------------------------------------------- 1 | module.exports = ` 2 | type Thing { 3 | id: String! 4 | name: String 5 | description: String 6 | } 7 | 8 | type ThingConnection { 9 | items: [Thing!]! 10 | cursor: String 11 | } 12 | 13 | extend type Query { 14 | thing(id: String!): Thing 15 | things(name: String, limit: Int, cursor: String): ThingConnection 16 | } 17 | 18 | input ThingInput { 19 | id: String 20 | name: String! 21 | description: String 22 | } 23 | 24 | extend type Mutation { 25 | saveThing( 26 | input: ThingInput 27 | ): Thing 28 | deleteThing( 29 | id: ID! 30 | ): Thing 31 | } 32 | `; 33 | -------------------------------------------------------------------------------- /ch9/session-consistency/spa/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | 6 | import { ApolloProvider } from "react-apollo"; 7 | import { ApolloClient, HttpLink, InMemoryCache } from "apollo-boost"; 8 | 9 | const client = new ApolloClient({ 10 | link: new HttpLink({ 11 | // CHANGE ME 12 | uri: 'https://r281sep4o7.execute-api.us-east-1.amazonaws.com/john/graphql', 13 | }), 14 | cache: new InMemoryCache(), 15 | }); 16 | 17 | ReactDOM.render( 18 | 19 | 20 | , 21 | document.getElementById('root') 22 | ); 23 | -------------------------------------------------------------------------------- /ch6/transitive-testing/customer-bff/test/int/upstream-author-bff/e2e.test.js: -------------------------------------------------------------------------------- 1 | import 'mocha'; 2 | import * as aws from 'aws-sdk'; 3 | 4 | import { handle } from '../../../src/listener'; 5 | 6 | const relay = require('baton-event-relay'); 7 | require('baton-vcr-replay-for-aws-sdk'); 8 | 9 | describe('e2e/upstream-author-bff', () => { 10 | before(() => { 11 | process.env.TABLE_NAME = 'stg-cncb-transitive-testing-customer-bff-things'; 12 | aws.config.update({ region: 'us-east-1' }); 13 | }); 14 | 15 | it('should process the thing0-created event', (done) => { 16 | const rec = relay('./fixtures/upstream-author-bff/thing0-created'); 17 | handle(rec.event, {}, done); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /ch5/cognito-authorizer/README.md: -------------------------------------------------------------------------------- 1 | # Securing an API gateway with OAuth 2.0 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch5/cognito-authorizer --path cncb-cognito-authorizer 5 | 2. cd cncb-cognito-authorizer 6 | 3. npm install 7 | 4. npm test 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. curl -v https://xyz.execute-api.us-east-1.amazonaws.com/$MY_STAGE/hello | json_pp 10 | 7. export CNCB_TOKEN=1234567890.1234567890 11 | 8. curl -v -H "Authorization: Bearer $CNCB_TOKEN" https://xyz.execute-api.us-east-1.amazonaws.com/$MY_STAGE/hello | json_pp 12 | 9. sls logs -f hello -r us-east-1 -s $MY_STAGE 13 | 10. npm run rm:lcl -- -s $MY_STAGE 14 | -------------------------------------------------------------------------------- /ch6/integration-testing/fixtures/dynamodb.us-east-1.amazonaws.com-443/get: -------------------------------------------------------------------------------- 1 | POST / 2 | content-type: application/x-amz-json-1.0 3 | x-amz-target: DynamoDB_20120810.GetItem 4 | host: dynamodb.us-east-1.amazonaws.com 5 | body: {\"TableName\":\"stg-cncb-integration-testing-things\",\"Key\":{\"id\":{\"S\":\"00000000-0000-0000-0000-000000000000\"}}} 6 | 7 | HTTP/1.1 200 OK 8 | server: Server 9 | date: Sat, 16 Jun 2018 04:09:37 GMT 10 | content-type: application/x-amz-json-1.0 11 | content-length: 82 12 | connection: keep-alive 13 | x-amzn-requestid: 4IPLUULPC0GEH3BQ7GS43U9JK7VV4KQNSO5AEMVJF66Q9ASUAAJG 14 | x-amz-crc32: 3235158845 15 | 16 | {"Item":{"id":{"S":"00000000-0000-0000-0000-000000000000"},"name":{"S":"thing0"}}} -------------------------------------------------------------------------------- /ch4/cdn-lambda/README.md: -------------------------------------------------------------------------------- 1 | # Executing code at the edge of the cloud 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch4/cdn-lambda --path cncb-cdn-lambda 5 | 2. cd cncb-cdn-lambda 6 | 3. npm install 7 | 4. npm test 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. sls invoke -r us-east-1 -f load -s $MY_STAGE -d '{"id":"44444444-7777-1111-1111-000000000000","name":"thing one"}' 10 | 7. curl -v https://xyz.cloudfront.net/things/44444444-7777-1111-1111-000000000000 | json_pp 11 | 8. curl -v -H "Authorization: Bearer 1234567890" https://xyz.cloudfront.net/things/44444444-7777-1111-1111-000000000000 | json_pp 12 | 9. npm run rm:lcl -- -s $MY_STAGE 13 | -------------------------------------------------------------------------------- /ch6/pipeline/.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: node:8 2 | 3 | before_script: 4 | - cp .npmrc-conf .npmrc 5 | - npm install --unsafe-perm 6 | 7 | test: 8 | stage: test 9 | script: 10 | - npm test 11 | - npm run test:int 12 | 13 | stg-east: 14 | stage: deploy 15 | variables: 16 | AWS_ACCESS_KEY_ID: $DEV_AWS_ACCESS_KEY_ID 17 | AWS_SECRET_ACCESS_KEY: $DEV_AWS_SECRET_ACCESS_KEY 18 | script: 19 | - npm run dp:stg:e 20 | except: 21 | - master 22 | 23 | production-east: 24 | stage: deploy 25 | variables: 26 | AWS_ACCESS_KEY_ID: $PROD_AWS_ACCESS_KEY_ID 27 | AWS_SECRET_ACCESS_KEY: $PROD_AWS_SECRET_ACCESS_KEY 28 | script: 29 | - npm run dp:prd:e 30 | only: 31 | - master 32 | -------------------------------------------------------------------------------- /ch6/contract-testing-sync/bff/fixtures/dynamodb.us-east-1.amazonaws.com-443/get: -------------------------------------------------------------------------------- 1 | POST / 2 | content-type: application/x-amz-json-1.0 3 | x-amz-target: DynamoDB_20120810.GetItem 4 | host: dynamodb.us-east-1.amazonaws.com 5 | body: {\"TableName\":\"stg-cncb-contract-testing-sync-things\",\"Key\":{\"id\":{\"S\":\"00000000-0000-0000-0000-000000000000\"}}} 6 | 7 | HTTP/1.1 200 OK 8 | server: Server 9 | date: Sun, 17 Jun 2018 21:26:46 GMT 10 | content-type: application/x-amz-json-1.0 11 | content-length: 82 12 | connection: keep-alive 13 | x-amzn-requestid: AQRBJO9RV5EKDR4R7K0G9G92L7VV4KQNSO5AEMVJF66Q9ASUAAJG 14 | x-amz-crc32: 3235158845 15 | 16 | {"Item":{"id":{"S":"00000000-0000-0000-0000-000000000000"},"name":{"S":"thing0"}}} -------------------------------------------------------------------------------- /ch6/unit-testing/.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: node:8 2 | 3 | before_script: 4 | - cp .npmrc-conf .npmrc 5 | - npm install --unsafe-perm 6 | 7 | test: 8 | stage: test 9 | script: 10 | - npm test 11 | - npm run test:int 12 | 13 | stg-east: 14 | stage: deploy 15 | variables: 16 | AWS_ACCESS_KEY_ID: $DEV_AWS_ACCESS_KEY_ID 17 | AWS_SECRET_ACCESS_KEY: $DEV_AWS_SECRET_ACCESS_KEY 18 | script: 19 | - npm run dp:stg:e 20 | except: 21 | - master 22 | 23 | production-east: 24 | stage: deploy 25 | variables: 26 | AWS_ACCESS_KEY_ID: $PROD_AWS_ACCESS_KEY_ID 27 | AWS_SECRET_ACCESS_KEY: $PROD_AWS_SECRET_ACCESS_KEY 28 | script: 29 | - npm run dp:prd:e 30 | only: 31 | - master 32 | -------------------------------------------------------------------------------- /ch10/dynamodb-global-table/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-dynamodb-global-table", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl:e": "sls deploy -v -r us-east-1", 8 | "dp:lcl:w": "sls deploy -v -r us-west-2", 9 | "rm:lcl:e": "sls remove -v -r us-east-1", 10 | "rm:lcl:w": "sls remove -v -r us-west-2" 11 | }, 12 | "devDependencies": { 13 | "aws-sdk": "^2.218.1", 14 | "serverless": "1.26.0", 15 | "serverless-dynamodb-autoscaling-plugin": "^1.0.0", 16 | "serverless-dynamodb-global-table-plugin": "^1.0.1" 17 | }, 18 | "dependencies": { 19 | "highland": "^2.11.1", 20 | "uuid": "^3.1.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ch10/round-robin-replication/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-round-robin-replication", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "sls package -r us-east-1", 7 | "dp:lcl:e": "sls deploy -v -r us-east-1", 8 | "dp:lcl:w": "sls deploy -v -r us-west-2", 9 | "rm:lcl:e": "sls remove -v -r us-east-1", 10 | "rm:lcl:w": "sls remove -v -r us-west-2" 11 | }, 12 | "devDependencies": { 13 | "aws-sdk": "^2.218.1", 14 | "serverless": "1.26.0", 15 | "serverless-pseudo-parameters": "^1.4.2" 16 | }, 17 | "dependencies": { 18 | "elasticsearch": "^14.2.2", 19 | "highland": "^2.11.1", 20 | "http-aws-es": "^4.0.0", 21 | "uuid": "^3.1.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/downstream/fixtures/dynamodb.us-east-1.amazonaws.com-443/save: -------------------------------------------------------------------------------- 1 | POST / 2 | content-type: application/x-amz-json-1.0 3 | x-amz-target: DynamoDB_20120810.PutItem 4 | host: dynamodb.us-east-1.amazonaws.com 5 | body: {\"TableName\":\"stg-cncb-contract-testing-async-downstream-things\",\"Item\":{\"id\":{\"S\":\"00000000-0000-0000-0000-000000000000\"},\"name\":{\"S\":\"thing0\"},\"asOf\":{\"N\":\"1529179380000\"}}} 6 | 7 | HTTP/1.1 200 OK 8 | server: Server 9 | date: Wed, 20 Jun 2018 05:05:21 GMT 10 | content-type: application/x-amz-json-1.0 11 | content-length: 2 12 | connection: keep-alive 13 | x-amzn-requestid: B2804F055G85Q4U9QBB086EIFFVV4KQNSO5AEMVJF66Q9ASUAAJG 14 | x-amz-crc32: 2745614147 15 | 16 | {} -------------------------------------------------------------------------------- /ch6/contract-testing-async/downstream/test/int/upstream-provider-y/contract.test.js: -------------------------------------------------------------------------------- 1 | import 'mocha'; 2 | import * as aws from 'aws-sdk'; 3 | 4 | import { handle } from '../../../src/listener'; 5 | 6 | const relay = require('baton-event-relay'); 7 | 8 | require('baton-vcr-replay-for-aws-sdk'); 9 | 10 | describe('contract/upstream-provider-y', () => { 11 | before(() => { 12 | process.env.TABLE_NAME = 'stg-cncb-contract-testing-async-downstream-things'; 13 | aws.config.update({ region: 'us-east-1' }); 14 | }); 15 | 16 | it('should process the thing-created event', (done) => { 17 | const rec = relay('./fixtures/upstream-provider-y/thing-created'); 18 | handle(rec.event, {}, done); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /ch6/feature-flag/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-feature-flag", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "react-scripts start", 7 | "build": "react-scripts build", 8 | "test": "sls package -r us-east-1 -s test", 9 | "dp:lcl": "sls deploy -v -r us-east-1", 10 | "rm:lcl": "sls remove -r us-east-1" 11 | }, 12 | "dependencies": { 13 | "amazon-cognito-auth-js": "1.2.4", 14 | "lodash": "^4.17.10", 15 | "react": "16.3.2", 16 | "react-dom": "16.3.2" 17 | }, 18 | "devDependencies": { 19 | "react-scripts": "1.1.5", 20 | "react-router-dom": "4.3.1", 21 | "serverless": "1.26.0", 22 | "serverless-spa-deploy": "^1.0.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ch6/transitive-testing/customer-bff/fixtures/dynamodb.us-east-1.amazonaws.com-443/save-thing0: -------------------------------------------------------------------------------- 1 | POST / 2 | content-type: application/x-amz-json-1.0 3 | x-amz-target: DynamoDB_20120810.PutItem 4 | host: dynamodb.us-east-1.amazonaws.com 5 | body: {\"TableName\":\"stg-cncb-transitive-testing-customer-bff-things\",\"Item\":{\"id\":{\"S\":\"00000000-0000-0000-0000-000000000000\"},\"name\":{\"S\":\"thing0\"},\"asOf\":{\"N\":\"1529179380000\"}}} 6 | 7 | HTTP/1.1 200 OK 8 | server: Server 9 | date: Tue, 26 Jun 2018 02:17:26 GMT 10 | content-type: application/x-amz-json-1.0 11 | content-length: 2 12 | connection: keep-alive 13 | x-amzn-requestid: 2Q2FFGLM6D11KAEKJBDH4SFK1FVV4KQNSO5AEMVJF66Q9ASUAAJG 14 | x-amz-crc32: 2745614147 15 | 16 | {} -------------------------------------------------------------------------------- /ch7/synthetics/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-synthetics", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "react-scripts start", 7 | "build": "react-scripts build", 8 | "test": "sls package -r us-east-1 -s test", 9 | "dp:lcl": "sls deploy -v -r us-east-1", 10 | "rm:lcl": "sls remove -r us-east-1" 11 | }, 12 | "dependencies": { 13 | "amazon-cognito-auth-js": "1.2.4", 14 | "react": "16.3.2", 15 | "react-dom": "16.3.2" 16 | }, 17 | "devDependencies": { 18 | "react-scripts": "1.1.5", 19 | "react-router-dom": "4.3.1", 20 | "serverless": "1.26.0", 21 | "serverless-spa-config": "1.0.2", 22 | "serverless-spa-deploy": "1.0.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ch5/README.md: -------------------------------------------------------------------------------- 1 | # Securing Cloud-Native Systems 2 | 3 | 1. [Securing your cloud account](./account-as-code) 4 | 2. [Creating a federated identity pool](./cognito-pool) 5 | 3. [Implementing sign up, sign in and sign out](./cognito-signin) 6 | 4. [Securing an API gateway with OpenID Connect](./cognito-authorizer) 7 | 5. [Implementing a custom authorizer](./custom-authorizer) 8 | 6. [Authorizing a GraphQL based service](./graphql-jwt) 9 | 7. [Implementing a JWT filter](./jwt-filter) 10 | 8. [Using envelope encryption](./envelope-encryption) 11 | 9. [Creating an SSL certificate for encryption in transit](./ssl-cert) 12 | 10. [Configuring a web application firewall](./waf) 13 | 11. [Replicating the data lake for disaster recovery](./dr) 14 | -------------------------------------------------------------------------------- /ch9/session-consistency/spa/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cncb-session-consistency-spa", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "react-scripts start", 7 | "build": "react-scripts build", 8 | "test": "sls package -r us-east-1 -s test", 9 | "dp:lcl": "sls deploy -v -r us-east-1", 10 | "rm:lcl": "sls remove -r us-east-1" 11 | }, 12 | "dependencies": { 13 | "apollo-boost": "^0.1.12", 14 | "graphql": "^0.13.2", 15 | "react": "16.2.0", 16 | "react-apollo": "^2.1.9", 17 | "react-dom": "16.2.0" 18 | }, 19 | "devDependencies": { 20 | "react-scripts": "1.1.1", 21 | "serverless": "1.26.0", 22 | "serverless-spa-deploy": "^1.0.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ch2/materialized-view-dynamodb/README.md: -------------------------------------------------------------------------------- 1 | # Creating a materialized view in DynamoDB 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch2/materialized-view-dynamodb --path cncb-materialized-view-dynamodb 5 | 2. cd cncb-materialized-view-dynamodb 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. publish an event from a separate terminal 10 | * cd ../cncb-event-stream 11 | * sls invoke -r us-east-1 -f publish -s $MY_STAGE -d '{"type":"thing-created"}' 12 | 7. sls logs -f listener -r us-east-1 -s $MY_STAGE 13 | 8. sls invoke -r us-east-1 -f query -s $MY_STAGE -d 14 | 9. npm run rm:lcl -- -s $MY_STAGE 15 | -------------------------------------------------------------------------------- /ch3/esg-outbound/README.md: -------------------------------------------------------------------------------- 1 | # Implementing an outbound external service gateway 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch3/esg-outbound --path cncb-esg-outbound 5 | 2. cd cncb-esg-outbound 6 | 3. npm install 7 | 4. npm test -- -s $MY_STAGE 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. publish an event from a separate terminal 10 | * cd ../cncb-event-stream 11 | * sls invoke -r us-east-1 -f publish -s $MY_STAGE -d '{"type":"issue-created","issue":{"new":{"title":"issue one","description":"this is issue one.","id":"33333333-55555-1111-1111-111111111111"}}}' 12 | 7. sls logs -f listener -r us-east-1 -s $MY_STAGE 13 | 9. npm run rm:lcl -- -s $MY_STAGE 14 | -------------------------------------------------------------------------------- /ch5/graphql-jwt/schema/thing/typedefs.js: -------------------------------------------------------------------------------- 1 | module.exports = ` 2 | type Thing { 3 | id: String! 4 | name: String 5 | description: String 6 | } 7 | 8 | type ThingConnection { 9 | items: [Thing!]! 10 | cursor: String 11 | } 12 | 13 | extend type Query { 14 | thing(id: String!): Thing 15 | things(name: String, limit: Int, cursor: String): ThingConnection 16 | } 17 | 18 | input ThingInput { 19 | id: String 20 | name: String! 21 | description: String 22 | } 23 | 24 | extend type Mutation { 25 | saveThing( 26 | input: ThingInput 27 | ): Thing @hasRole(roles: ["Author"]) 28 | deleteThing( 29 | id: ID! 30 | ): Thing @hasRole(roles: ["Manager"]) 31 | } 32 | `; 33 | -------------------------------------------------------------------------------- /ch6/transitive-testing/author-bff/fixtures/dynamodb.us-east-1.amazonaws.com-443/get-thing0: -------------------------------------------------------------------------------- 1 | POST / 2 | content-type: application/x-amz-json-1.0 3 | x-amz-target: DynamoDB_20120810.GetItem 4 | host: dynamodb.us-east-1.amazonaws.com 5 | body: {\"TableName\":\"stg-cncb-transitive-testing-author-bff-things\",\"Key\":{\"id\":{\"S\":\"00000000-0000-0000-0000-000000000000\"}}} 6 | 7 | HTTP/1.1 200 OK 8 | server: Server 9 | date: Sun, 17 Jun 2018 21:26:46 GMT 10 | content-type: application/x-amz-json-1.0 11 | content-length: 82 12 | connection: keep-alive 13 | x-amzn-requestid: AQRBJO9RV5EKDR4R7K0G9G92L7VV4KQNSO5AEMVJF66Q9ASUAAJG 14 | x-amz-crc32: 3235158845 15 | 16 | {"Item":{"id":{"S":"00000000-0000-0000-0000-000000000000"},"name":{"S":"thing0"}}} 17 | -------------------------------------------------------------------------------- /ch3/esg-sqs-inbound/README.md: -------------------------------------------------------------------------------- 1 | # Implementing an inbound external service gateway from SQS 2 | 3 | This is a bonus recipe as Lambda SQS support was not available at the time the book outline was approved. 4 | 5 | ## How to do it... 6 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch3/esg-sqs-inbound --path cncb-esg-sqs-inbound 7 | 2. cd cncb-esg-sqs-inbound 8 | 3. npm install 9 | 4. npm test 10 | 5. npm run dp:lcl -- -s $MY_STAGE 11 | 6. sls invoke -r us-east-1 -f submit -s $MY_STAGE -d '{"id":"33333333-8888-0000-0000-111111111111","name":"thing eight"}' 12 | 7. sls logs -f submit -r us-east-1 -s $MY_STAGE 13 | 8. sls logs -f trigger -r us-east-1 -s $MY_STAGE 14 | 9. npm run rm:lcl -- -s $MY_STAGE 15 | -------------------------------------------------------------------------------- /ch6/integration-testing/test/int/save/index.test.js: -------------------------------------------------------------------------------- 1 | import 'mocha'; 2 | import { expect } from 'chai'; 3 | 4 | const supertest = require('supertest'); 5 | 6 | const endpoint = process.env.ENDPOINT ? process.env.ENDPOINT : 'http://localhost:3001'; 7 | const client = supertest(endpoint); 8 | 9 | const THING = { name: 'thing0' }; 10 | 11 | describe('save/index.js', () => { 12 | it('should save', () => client.post('/things') 13 | .send(THING) 14 | // .set('Authorization', JWT) 15 | .expect(201) 16 | .expect((res) => { 17 | // console.log('RES: %s', JSON.stringify(res, null, 2)); 18 | expect(res.header.location).to.equal('https://localhost:3001/stg/things/00000000-0000-0000-0000-000000000000'); 19 | })); 20 | }); 21 | -------------------------------------------------------------------------------- /ch6/contract-testing-sync/bff/test/int/save/index.test.js: -------------------------------------------------------------------------------- 1 | import 'mocha'; 2 | import { expect } from 'chai'; 3 | 4 | const supertest = require('supertest'); 5 | 6 | const endpoint = process.env.ENDPOINT ? process.env.ENDPOINT : 'http://localhost:3001'; 7 | const client = supertest(endpoint); 8 | 9 | const THING = { name: 'thing0' }; 10 | 11 | describe('save/index.js', () => { 12 | it('should save', () => client.post('/things') 13 | .send(THING) 14 | // .set('Authorization', JWT) 15 | .expect(201) 16 | .expect((res) => { 17 | // console.log('RES: %s', JSON.stringify(res, null, 2)); 18 | expect(res.header.location).to.equal('https://localhost:3001/stg/things/00000000-0000-0000-0000-000000000000'); 19 | })); 20 | }); 21 | -------------------------------------------------------------------------------- /ch5/custom-authorizer/README.md: -------------------------------------------------------------------------------- 1 | # Implementing a custom authorizer 2 | 3 | ## How to do it... 4 | 1. sls create --template-url https://github.com/danteinc/js-cloud-native-cookbook/tree/master/ch5/custom-authorizer --path cncb-custom-authorizer 5 | 2. cd cncb-custom-authorizer 6 | 3. npm install 7 | 4. npm test 8 | 5. npm run dp:lcl -- -s $MY_STAGE 9 | 6. curl -v https://xyz.execute-api.us-east-1.amazonaws.com/$MY_STAGE/hello | json_pp 10 | 7. export CNCB_TOKEN=1234567890.1234567890 11 | 8. curl -v -H "Authorization: Bearer $CNCB_TOKEN" https://xyz.execute-api.us-east-1.amazonaws.com/$MY_STAGE/hello | json_pp 12 | 9. sls logs -f authorizer -r us-east-1 -s $MY_STAGE 13 | 10. sls logs -f hello -r us-east-1 -s $MY_STAGE 14 | 11. npm run rm:lcl -- -s $MY_STAGE 15 | -------------------------------------------------------------------------------- /ch6/contract-testing-async/upstream/test/int/save/index.test.js: -------------------------------------------------------------------------------- 1 | import 'mocha'; 2 | import { expect } from 'chai'; 3 | 4 | const supertest = require('supertest'); 5 | 6 | const endpoint = process.env.ENDPOINT ? process.env.ENDPOINT : 'http://localhost:3001'; 7 | const client = supertest(endpoint); 8 | 9 | const THING = { name: 'thing0' }; 10 | 11 | describe('save/index.js', () => { 12 | it('should save', () => client.post('/things') 13 | .send(THING) 14 | // .set('Authorization', JWT) 15 | .expect(201) 16 | .expect((res) => { 17 | // console.log('RES: %s', JSON.stringify(res, null, 2)); 18 | expect(res.header.location).to.equal('https://localhost:3001/stg/things/00000000-0000-0000-0000-000000000000'); 19 | })); 20 | }); 21 | --------------------------------------------------------------------------------