From 1a1e295e3030597d61ff3b9c7b17b545f139b2c2 Mon Sep 17 00:00:00 2001 From: michaelact <86778470+michaelact@users.noreply.github.com> Date: Sat, 14 May 2022 01:44:08 +0700 Subject: [PATCH 1/5] ref: restructure service folder naming --- booking/.eslintrc.json | 3 + booking/Dockerfile | 25 + booking/env | 6 + booking/integration-test/index.js | 41 + booking/mock/index.js | 43 + booking/npm-shrinkwrap.json | 738 ++++++++++++++++++ booking/package.json | 48 ++ booking/src/api/booking.js | 63 ++ booking/src/api/booking.spec.js | 103 +++ booking/src/config/config.js | 45 ++ booking/src/config/db/index.js | 4 + booking/src/config/db/mongo.js | 32 + booking/src/config/db/mongo.spec.js | 29 + booking/src/config/di/di.js | 33 + booking/src/config/di/di.proto.js | 82 ++ booking/src/config/di/index.js | 3 + booking/src/config/index.di.spec.js | 24 + booking/src/config/index.js | 9 + booking/src/config/ssl/index.js | 6 + booking/src/index.js | 36 + booking/src/models/booking.model.js | 14 + booking/src/models/index.js | 26 + booking/src/models/index.spec.js | 81 ++ booking/src/models/ticket.model.js | 11 + booking/src/models/user.model.js | 15 + booking/src/repository/repository.js | 79 ++ booking/src/repository/repository.spec.js | 9 + booking/src/server/server.js | 43 + booking/src/server/server.spec.js | 12 + booking/src/services/index.js | 4 + booking/src/services/notification.service.js | 17 + booking/src/services/payment.service.js | 17 + build.sh | 24 + cinema-catalog/.eslintrc.json | 3 + cinema-catalog/Dockerfile | 25 + cinema-catalog/env | 6 + ...cinema-catalog-service-api.jmeter.test.jmx | 182 +++++ cinema-catalog/integration-test/index.js | 10 + cinema-catalog/npm-shrinkwrap.json | 520 ++++++++++++ cinema-catalog/package.json | 45 ++ cinema-catalog/src/api/cinema-catalog.js | 34 + cinema-catalog/src/api/cinema-catalog.spec.js | 126 +++ cinema-catalog/src/config/config.js | 45 ++ cinema-catalog/src/config/index.js | 5 + cinema-catalog/src/config/mongo.js | 32 + cinema-catalog/src/config/mongo.spec.js | 29 + cinema-catalog/src/config/ssl/index.js | 6 + cinema-catalog/src/index.js | 45 ++ cinema-catalog/src/mock/cinemas.json | 326 ++++++++ cinema-catalog/src/mock/cities.json | 36 + cinema-catalog/src/mock/countries.json | 19 + cinema-catalog/src/mock/index.js | 0 cinema-catalog/src/mock/states.json | 36 + cinema-catalog/src/repository/repository.js | 98 +++ .../src/repository/repository.spec.js | 10 + cinema-catalog/src/server/server.js | 29 + cinema-catalog/src/server/server.spec.js | 16 + deploy.sh | 12 + movies/.eslintrc.json | 3 + movies/Dockerfile | 25 + movies/integration-test/index.js | 10 + .../movie-service-api.jmeter.test.jmx | 118 +++ movies/npm-shrinkwrap.json | 520 ++++++++++++ movies/package.json | 44 ++ movies/src/api/movies.js | 24 + movies/src/api/movies.spec.js | 103 +++ movies/src/config/config.js | 45 ++ movies/src/config/index.js | 4 + movies/src/config/mongo.js | 32 + movies/src/config/mongo.spec.js | 29 + movies/src/config/ssl/index.js | 6 + movies/src/index.js | 45 ++ movies/src/mock/movies.js | 46 ++ movies/src/repository/repository.js | 88 +++ movies/src/repository/repository.spec.js | 10 + movies/src/server/server.js | 29 + movies/src/server/server.spec.js | 16 + notification/.eslintrc.json | 3 + notification/Dockerfile | 25 + notification/env | 6 + notification/integration-test/index.js | 36 + notification/npm-shrinkwrap.json | 726 +++++++++++++++++ notification/package.json | 51 ++ notification/src/api/notification.js | 30 + notification/src/api/notification.spec.js | 122 +++ notification/src/config/config.js | 13 + notification/src/config/di/di.js | 21 + notification/src/config/di/di.proto.js | 82 ++ notification/src/config/di/index.js | 3 + notification/src/config/index.di.spec.js | 25 + notification/src/config/index.js | 7 + notification/src/config/ssl/index.js | 6 + notification/src/index.js | 36 + notification/src/models/index.js | 24 + notification/src/models/index.spec.js | 42 + notification/src/models/notification.model.js | 25 + notification/src/repository/repository.js | 65 ++ .../src/repository/repository.spec.js | 9 + notification/src/server/server.js | 42 + notification/src/server/server.spec.js | 16 + payment/.eslintrc.json | 3 + payment/Dockerfile | 25 + payment/env | 6 + payment/integration-test/index.js | 28 + payment/npm-shrinkwrap.json | 708 +++++++++++++++++ payment/package.json | 50 ++ payment/src/api/payment.js | 25 + payment/src/api/payment.spec.js | 115 +++ payment/src/config/config.js | 50 ++ payment/src/config/db/index.js | 4 + payment/src/config/db/mongo.js | 32 + payment/src/config/db/mongo.spec.js | 29 + payment/src/config/di/di.js | 30 + payment/src/config/di/di.proto.js | 82 ++ payment/src/config/di/index.js | 3 + payment/src/config/index.di.spec.js | 24 + payment/src/config/index.js | 8 + payment/src/config/ssl/index.js | 6 + payment/src/index.js | 36 + payment/src/models/index.js | 24 + payment/src/models/index.spec.js | 34 + payment/src/models/payment.model.js | 12 + payment/src/repository/repository.js | 76 ++ payment/src/repository/repository.spec.js | 9 + payment/src/server/server.js | 42 + payment/src/server/server.spec.js | 16 + 126 files changed, 7509 insertions(+) create mode 100644 booking/.eslintrc.json create mode 100644 booking/Dockerfile create mode 100644 booking/env create mode 100644 booking/integration-test/index.js create mode 100644 booking/mock/index.js create mode 100644 booking/npm-shrinkwrap.json create mode 100644 booking/package.json create mode 100644 booking/src/api/booking.js create mode 100644 booking/src/api/booking.spec.js create mode 100644 booking/src/config/config.js create mode 100644 booking/src/config/db/index.js create mode 100644 booking/src/config/db/mongo.js create mode 100644 booking/src/config/db/mongo.spec.js create mode 100644 booking/src/config/di/di.js create mode 100644 booking/src/config/di/di.proto.js create mode 100644 booking/src/config/di/index.js create mode 100644 booking/src/config/index.di.spec.js create mode 100644 booking/src/config/index.js create mode 100644 booking/src/config/ssl/index.js create mode 100644 booking/src/index.js create mode 100644 booking/src/models/booking.model.js create mode 100644 booking/src/models/index.js create mode 100644 booking/src/models/index.spec.js create mode 100644 booking/src/models/ticket.model.js create mode 100644 booking/src/models/user.model.js create mode 100644 booking/src/repository/repository.js create mode 100644 booking/src/repository/repository.spec.js create mode 100644 booking/src/server/server.js create mode 100644 booking/src/server/server.spec.js create mode 100644 booking/src/services/index.js create mode 100644 booking/src/services/notification.service.js create mode 100644 booking/src/services/payment.service.js create mode 100644 build.sh create mode 100644 cinema-catalog/.eslintrc.json create mode 100644 cinema-catalog/Dockerfile create mode 100644 cinema-catalog/env create mode 100644 cinema-catalog/integration-test/cinema-catalog-service-api.jmeter.test.jmx create mode 100644 cinema-catalog/integration-test/index.js create mode 100644 cinema-catalog/npm-shrinkwrap.json create mode 100644 cinema-catalog/package.json create mode 100644 cinema-catalog/src/api/cinema-catalog.js create mode 100644 cinema-catalog/src/api/cinema-catalog.spec.js create mode 100644 cinema-catalog/src/config/config.js create mode 100644 cinema-catalog/src/config/index.js create mode 100644 cinema-catalog/src/config/mongo.js create mode 100644 cinema-catalog/src/config/mongo.spec.js create mode 100644 cinema-catalog/src/config/ssl/index.js create mode 100644 cinema-catalog/src/index.js create mode 100644 cinema-catalog/src/mock/cinemas.json create mode 100644 cinema-catalog/src/mock/cities.json create mode 100644 cinema-catalog/src/mock/countries.json create mode 100644 cinema-catalog/src/mock/index.js create mode 100644 cinema-catalog/src/mock/states.json create mode 100644 cinema-catalog/src/repository/repository.js create mode 100644 cinema-catalog/src/repository/repository.spec.js create mode 100644 cinema-catalog/src/server/server.js create mode 100644 cinema-catalog/src/server/server.spec.js create mode 100644 deploy.sh create mode 100644 movies/.eslintrc.json create mode 100644 movies/Dockerfile create mode 100644 movies/integration-test/index.js create mode 100644 movies/integration-test/movie-service-api.jmeter.test.jmx create mode 100644 movies/npm-shrinkwrap.json create mode 100644 movies/package.json create mode 100644 movies/src/api/movies.js create mode 100644 movies/src/api/movies.spec.js create mode 100644 movies/src/config/config.js create mode 100644 movies/src/config/index.js create mode 100644 movies/src/config/mongo.js create mode 100644 movies/src/config/mongo.spec.js create mode 100644 movies/src/config/ssl/index.js create mode 100644 movies/src/index.js create mode 100644 movies/src/mock/movies.js create mode 100644 movies/src/repository/repository.js create mode 100644 movies/src/repository/repository.spec.js create mode 100644 movies/src/server/server.js create mode 100644 movies/src/server/server.spec.js create mode 100644 notification/.eslintrc.json create mode 100644 notification/Dockerfile create mode 100644 notification/env create mode 100644 notification/integration-test/index.js create mode 100644 notification/npm-shrinkwrap.json create mode 100644 notification/package.json create mode 100644 notification/src/api/notification.js create mode 100644 notification/src/api/notification.spec.js create mode 100644 notification/src/config/config.js create mode 100644 notification/src/config/di/di.js create mode 100644 notification/src/config/di/di.proto.js create mode 100644 notification/src/config/di/index.js create mode 100644 notification/src/config/index.di.spec.js create mode 100644 notification/src/config/index.js create mode 100644 notification/src/config/ssl/index.js create mode 100644 notification/src/index.js create mode 100644 notification/src/models/index.js create mode 100644 notification/src/models/index.spec.js create mode 100644 notification/src/models/notification.model.js create mode 100644 notification/src/repository/repository.js create mode 100644 notification/src/repository/repository.spec.js create mode 100644 notification/src/server/server.js create mode 100644 notification/src/server/server.spec.js create mode 100644 payment/.eslintrc.json create mode 100644 payment/Dockerfile create mode 100644 payment/env create mode 100644 payment/integration-test/index.js create mode 100644 payment/npm-shrinkwrap.json create mode 100644 payment/package.json create mode 100644 payment/src/api/payment.js create mode 100644 payment/src/api/payment.spec.js create mode 100644 payment/src/config/config.js create mode 100644 payment/src/config/db/index.js create mode 100644 payment/src/config/db/mongo.js create mode 100644 payment/src/config/db/mongo.spec.js create mode 100644 payment/src/config/di/di.js create mode 100644 payment/src/config/di/di.proto.js create mode 100644 payment/src/config/di/index.js create mode 100644 payment/src/config/index.di.spec.js create mode 100644 payment/src/config/index.js create mode 100644 payment/src/config/ssl/index.js create mode 100644 payment/src/index.js create mode 100644 payment/src/models/index.js create mode 100644 payment/src/models/index.spec.js create mode 100644 payment/src/models/payment.model.js create mode 100644 payment/src/repository/repository.js create mode 100644 payment/src/repository/repository.spec.js create mode 100644 payment/src/server/server.js create mode 100644 payment/src/server/server.spec.js diff --git a/booking/.eslintrc.json b/booking/.eslintrc.json new file mode 100644 index 0000000..a755cdb --- /dev/null +++ b/booking/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": ["standard"] +} diff --git a/booking/Dockerfile b/booking/Dockerfile new file mode 100644 index 0000000..523816b --- /dev/null +++ b/booking/Dockerfile @@ -0,0 +1,25 @@ +FROM node:7.5.0-alpine + +RUN addgroup -S nupp && adduser -S -g nupp nupp + +ENV HOME=/home/nupp + +COPY package.json npm-shrinkwrap.json $HOME/app/ + +COPY src/ $HOME/app/src + +ADD https://github.com/Yelp/dumb-init/releases/download/v1.1.1/dumb-init_1.1.1_amd64 /usr/local/bin/dumb-init + +WORKDIR $HOME/app + +RUN chown -R nupp:nupp $HOME/* /usr/local/ && \ + chmod +x /usr/local/bin/dumb-init && \ + npm cache clean && \ + npm install --silent --progress=false --production && \ + chown -R nupp:nupp $HOME/* + +USER nupp + +EXPOSE 3000 + +CMD ["dumb-init", "npm", "start"] diff --git a/booking/env b/booking/env new file mode 100644 index 0000000..ac29194 --- /dev/null +++ b/booking/env @@ -0,0 +1,6 @@ +DB=booking +DB_USER=cristian +DB_PASS=cristianPassword2017 +DB_REPLS=rs1 +DB_SERVERS='192.168.99.100:27017 192.168.99.101:27017 192.168.99.102:27017' +PORT=3000 diff --git a/booking/integration-test/index.js b/booking/integration-test/index.js new file mode 100644 index 0000000..4aaebb3 --- /dev/null +++ b/booking/integration-test/index.js @@ -0,0 +1,41 @@ +/* eslint-env mocha */ +const supertest = require('supertest') + +describe('Booking Service', () => { + const api = supertest('http://192.168.99.100:3002') + const now = new Date() + now.setDate(now.getDate() + 1) + const user = { + name: 'Cristian', + lastName: 'Ramirez', + email: 'cristiano@gmail.com', + creditCard: { + number: '4242424242424242', + cvc: '123', + exp_month: '12', + exp_year: '2017', + }, + membership: '7777888899990000' + } + + const booking = { + city: 'Morelia', + cinema: 'Plaza Morelia', + movie: { + title: 'Assasins Creed', + format: 'IMAX' + }, + schedule: now.toString(), + cinemaRoom: 7, + seats: ['45'], + totalAmount: 71 + } + it('can make a booking', (done) => { + api.post('/booking') + .send({user, booking}) + .expect((res) => { + console.log(res.body) + }) + .expect(200, done) + }) +}) diff --git a/booking/mock/index.js b/booking/mock/index.js new file mode 100644 index 0000000..b46daad --- /dev/null +++ b/booking/mock/index.js @@ -0,0 +1,43 @@ +/* + -------------------------------------- + | | + | v + | Jane ------(went to)----- + | | | + | | (loyal vistor) | + | v v + Joe --(common user)--> Movie Name <--(displayed)-- Plaza Morelia + | | + | (format) | (city) + v v + 4DX Morelia + + city + | + cinema + | + movie + | + --- | --------- + | | +visitor format + | | +--- | ---- --- | --- +| | | | | +normal loyal 4Dx 3D normal + +const nodes = { +movie: '', +visitor: '', +cinema: '', +city: '', +format: '' +} + +const edges = { +wentTo: '', +displayed: '', +available: '' +} + +*/ diff --git a/booking/npm-shrinkwrap.json b/booking/npm-shrinkwrap.json new file mode 100644 index 0000000..82bde98 --- /dev/null +++ b/booking/npm-shrinkwrap.json @@ -0,0 +1,738 @@ +{ + "name": "booking-service", + "version": "1.0.0", + "dependencies": { + "accepts": { + "version": "1.3.3", + "from": "accepts@>=1.3.3 <1.4.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz" + }, + "array-flatten": { + "version": "1.1.1", + "from": "array-flatten@1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" + }, + "asynckit": { + "version": "0.4.0", + "from": "asynckit@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" + }, + "awilix": { + "version": "2.2.2", + "from": "awilix@latest", + "resolved": "https://registry.npmjs.org/awilix/-/awilix-2.2.2.tgz" + }, + "balanced-match": { + "version": "0.4.2", + "from": "balanced-match@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz" + }, + "basic-auth": { + "version": "1.0.4", + "from": "basic-auth@>=1.0.3 <1.1.0", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz" + }, + "body-parser": { + "version": "1.16.0", + "from": "body-parser@latest", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.16.0.tgz", + "dependencies": { + "qs": { + "version": "6.2.1", + "from": "qs@6.2.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.1.tgz" + } + } + }, + "brace-expansion": { + "version": "1.1.6", + "from": "brace-expansion@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz" + }, + "bson": { + "version": "0.4.23", + "from": "bson@>=0.4.23 <0.5.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-0.4.23.tgz" + }, + "buffer-shims": { + "version": "1.0.0", + "from": "buffer-shims@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" + }, + "bytes": { + "version": "2.4.0", + "from": "bytes@2.4.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz" + }, + "camel-case": { + "version": "3.0.0", + "from": "camel-case@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz" + }, + "camelize": { + "version": "1.0.0", + "from": "camelize@1.0.0", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz" + }, + "combined-stream": { + "version": "1.0.5", + "from": "combined-stream@>=1.0.5 <1.1.0", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz" + }, + "concat-map": { + "version": "0.0.1", + "from": "concat-map@0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + }, + "connect": { + "version": "3.5.0", + "from": "connect@3.5.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.5.0.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + } + }, + "content-disposition": { + "version": "0.5.1", + "from": "content-disposition@0.5.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz" + }, + "content-security-policy-builder": { + "version": "1.1.0", + "from": "content-security-policy-builder@1.1.0", + "resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-1.1.0.tgz" + }, + "content-type": { + "version": "1.0.2", + "from": "content-type@>=1.0.2 <1.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz" + }, + "cookie": { + "version": "0.3.1", + "from": "cookie@0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz" + }, + "cookie-signature": { + "version": "1.0.6", + "from": "cookie-signature@1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + }, + "cookiejar": { + "version": "2.1.0", + "from": "cookiejar@>=2.0.6 <3.0.0", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.0.tgz" + }, + "core-util-is": { + "version": "1.0.2", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "cors": { + "version": "2.8.1", + "from": "cors@latest", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.1.tgz" + }, + "dasherize": { + "version": "2.0.0", + "from": "dasherize@2.0.0", + "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz" + }, + "dashify": { + "version": "0.2.2", + "from": "dashify@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/dashify/-/dashify-0.2.2.tgz" + }, + "debug": { + "version": "2.6.0", + "from": "debug@>=2.1.1 <3.0.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz" + }, + "delayed-stream": { + "version": "1.0.0", + "from": "delayed-stream@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + }, + "depd": { + "version": "1.1.0", + "from": "depd@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz" + }, + "destroy": { + "version": "1.0.4", + "from": "destroy@>=1.0.4 <1.1.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" + }, + "dns-prefetch-control": { + "version": "0.1.0", + "from": "dns-prefetch-control@0.1.0", + "resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz" + }, + "dont-sniff-mimetype": { + "version": "1.0.0", + "from": "dont-sniff-mimetype@1.0.0", + "resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.0.0.tgz" + }, + "ee-first": { + "version": "1.1.1", + "from": "ee-first@1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + }, + "encodeurl": { + "version": "1.0.1", + "from": "encodeurl@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz" + }, + "es6-promise": { + "version": "3.0.2", + "from": "es6-promise@3.0.2", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz" + }, + "escape-html": { + "version": "1.0.3", + "from": "escape-html@>=1.0.3 <1.1.0", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + }, + "etag": { + "version": "1.7.0", + "from": "etag@>=1.7.0 <1.8.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz" + }, + "express": { + "version": "4.14.0", + "from": "express@latest", + "resolved": "https://registry.npmjs.org/express/-/express-4.14.0.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + }, + "qs": { + "version": "6.2.0", + "from": "qs@6.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz" + } + } + }, + "extend": { + "version": "3.0.0", + "from": "extend@>=3.0.0 <3.1.0", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz" + }, + "finalhandler": { + "version": "0.5.0", + "from": "finalhandler@0.5.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.0.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@~2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + } + }, + "form-data": { + "version": "2.1.2", + "from": "form-data@>=2.1.1 <2.2.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.2.tgz" + }, + "formidable": { + "version": "1.1.1", + "from": "formidable@>=1.0.17 <2.0.0", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.1.1.tgz" + }, + "forwarded": { + "version": "0.1.0", + "from": "forwarded@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz" + }, + "frameguard": { + "version": "3.0.0", + "from": "frameguard@3.0.0", + "resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.0.0.tgz" + }, + "fresh": { + "version": "0.3.0", + "from": "fresh@0.3.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz" + }, + "fs.realpath": { + "version": "1.0.0", + "from": "fs.realpath@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + }, + "glob": { + "version": "7.1.1", + "from": "glob@>=7.0.3 <8.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz" + }, + "handle-thing": { + "version": "1.2.5", + "from": "handle-thing@>=1.2.4 <2.0.0", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz" + }, + "helmet": { + "version": "3.4.0", + "from": "helmet@>=3.4.0 <4.0.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.4.0.tgz" + }, + "helmet-csp": { + "version": "2.3.0", + "from": "helmet-csp@2.3.0", + "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.3.0.tgz" + }, + "hide-powered-by": { + "version": "1.0.0", + "from": "hide-powered-by@1.0.0", + "resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.0.0.tgz" + }, + "hpack.js": { + "version": "2.1.6", + "from": "hpack.js@>=2.1.6 <3.0.0", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz" + }, + "hpkp": { + "version": "2.0.0", + "from": "hpkp@2.0.0", + "resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz" + }, + "hsts": { + "version": "2.0.0", + "from": "hsts@2.0.0", + "resolved": "https://registry.npmjs.org/hsts/-/hsts-2.0.0.tgz" + }, + "http-deceiver": { + "version": "1.2.7", + "from": "http-deceiver@>=1.2.4 <2.0.0", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" + }, + "http-errors": { + "version": "1.5.1", + "from": "http-errors@>=1.5.0 <1.6.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz" + }, + "http-status": { + "version": "0.2.5", + "from": "http-status@latest", + "resolved": "https://registry.npmjs.org/http-status/-/http-status-0.2.5.tgz" + }, + "iconv-lite": { + "version": "0.4.15", + "from": "iconv-lite@0.4.15", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz" + }, + "ienoopen": { + "version": "1.0.0", + "from": "ienoopen@1.0.0", + "resolved": "https://registry.npmjs.org/ienoopen/-/ienoopen-1.0.0.tgz" + }, + "inflight": { + "version": "1.0.6", + "from": "inflight@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + }, + "inherits": { + "version": "2.0.3", + "from": "inherits@>=2.0.3 <3.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + }, + "ipaddr.js": { + "version": "1.2.0", + "from": "ipaddr.js@1.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.2.0.tgz" + }, + "is-class": { + "version": "0.0.4", + "from": "is-class@0.0.4", + "resolved": "https://registry.npmjs.org/is-class/-/is-class-0.0.4.tgz" + }, + "is-plain-object": { + "version": "2.0.1", + "from": "is-plain-object@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.1.tgz" + }, + "is-string": { + "version": "1.0.4", + "from": "is-string@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.4.tgz" + }, + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, + "isemail": { + "version": "2.2.1", + "from": "isemail@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-2.2.1.tgz" + }, + "isobject": { + "version": "1.0.2", + "from": "isobject@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-1.0.2.tgz" + }, + "items": { + "version": "2.1.1", + "from": "items@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/items/-/items-2.1.1.tgz" + }, + "joi": { + "version": "10.2.0", + "from": "joi@latest", + "resolved": "https://registry.npmjs.org/joi/-/joi-10.2.0.tgz", + "dependencies": { + "hoek": { + "version": "4.1.0", + "from": "hoek@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.1.0.tgz" + } + } + }, + "lodash.reduce": { + "version": "4.6.0", + "from": "lodash.reduce@4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz" + }, + "lower-case": { + "version": "1.1.3", + "from": "lower-case@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.3.tgz" + }, + "media-typer": { + "version": "0.3.0", + "from": "media-typer@0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + }, + "merge-descriptors": { + "version": "1.0.1", + "from": "merge-descriptors@1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" + }, + "methods": { + "version": "1.1.2", + "from": "methods@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + }, + "mime": { + "version": "1.3.4", + "from": "mime@>=1.3.4 <2.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" + }, + "mime-db": { + "version": "1.26.0", + "from": "mime-db@>=1.26.0 <1.27.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.26.0.tgz" + }, + "mime-types": { + "version": "2.1.14", + "from": "mime-types@>=2.1.10 <3.0.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.14.tgz" + }, + "minimalistic-assert": { + "version": "1.0.0", + "from": "minimalistic-assert@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" + }, + "minimatch": { + "version": "3.0.3", + "from": "minimatch@>=3.0.2 <4.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz" + }, + "mongodb": { + "version": "2.1.18", + "from": "mongodb@2.1.18", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.1.18.tgz", + "dependencies": { + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "readable-stream": { + "version": "1.0.31", + "from": "readable-stream@1.0.31", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.31.tgz" + } + } + }, + "mongodb-core": { + "version": "1.3.18", + "from": "mongodb-core@1.3.18", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-1.3.18.tgz" + }, + "morgan": { + "version": "1.7.0", + "from": "morgan@latest", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.7.0.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@~2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + } + }, + "ms": { + "version": "0.7.2", + "from": "ms@0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz" + }, + "negotiator": { + "version": "0.6.1", + "from": "negotiator@0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz" + }, + "no-case": { + "version": "2.3.1", + "from": "no-case@>=2.2.0 <3.0.0", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.1.tgz" + }, + "nocache": { + "version": "2.0.0", + "from": "nocache@2.0.0", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.0.0.tgz" + }, + "obuf": { + "version": "1.1.1", + "from": "obuf@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz" + }, + "on-finished": { + "version": "2.3.0", + "from": "on-finished@>=2.3.0 <2.4.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" + }, + "on-headers": { + "version": "1.0.1", + "from": "on-headers@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" + }, + "once": { + "version": "1.4.0", + "from": "once@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + }, + "parseurl": { + "version": "1.3.1", + "from": "parseurl@>=1.3.1 <1.4.0", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz" + }, + "path-is-absolute": { + "version": "1.0.1", + "from": "path-is-absolute@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + }, + "path-to-regexp": { + "version": "0.1.7", + "from": "path-to-regexp@0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" + }, + "platform": { + "version": "1.3.3", + "from": "platform@1.3.3", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.3.tgz" + }, + "process-nextick-args": { + "version": "1.0.7", + "from": "process-nextick-args@>=1.0.6 <1.1.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" + }, + "proxy-addr": { + "version": "1.1.3", + "from": "proxy-addr@>=1.1.2 <1.2.0", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.3.tgz" + }, + "qs": { + "version": "6.3.0", + "from": "qs@>=6.3.0 <6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.0.tgz" + }, + "range-parser": { + "version": "1.2.0", + "from": "range-parser@>=1.2.0 <1.3.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz" + }, + "raw-body": { + "version": "2.2.0", + "from": "raw-body@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz" + }, + "readable-stream": { + "version": "2.2.2", + "from": "readable-stream@>=2.2.2 <3.0.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.2.tgz" + }, + "referrer-policy": { + "version": "1.1.0", + "from": "referrer-policy@1.1.0", + "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.1.0.tgz" + }, + "require_optional": { + "version": "1.0.0", + "from": "require_optional@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.0.tgz", + "dependencies": { + "resolve-from": { + "version": "2.0.0", + "from": "resolve-from@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz" + } + } + }, + "select-hose": { + "version": "2.0.0", + "from": "select-hose@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" + }, + "semver": { + "version": "5.3.0", + "from": "semver@>=5.1.0 <6.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz" + }, + "send": { + "version": "0.14.1", + "from": "send@0.14.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.14.1.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@~2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + } + }, + "serve-static": { + "version": "1.11.1", + "from": "serve-static@>=1.11.1 <1.12.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.11.1.tgz" + }, + "setprototypeof": { + "version": "1.0.2", + "from": "setprototypeof@1.0.2", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz" + }, + "spdy": { + "version": "3.4.4", + "from": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz" + }, + "spdy-transport": { + "version": "2.0.18", + "from": "spdy-transport@>=2.0.15 <3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.18.tgz" + }, + "statuses": { + "version": "1.3.1", + "from": "statuses@>=1.3.0 <1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "superagent": { + "version": "3.4.1", + "from": "superagent@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.4.1.tgz", + "dependencies": { + "component-emitter": { + "version": "1.2.1", + "from": "component-emitter@>=1.2.0 <2.0.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz" + } + } + }, + "supertest": { + "version": "3.0.0", + "from": "supertest@latest", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.0.0.tgz" + }, + "topo": { + "version": "2.0.2", + "from": "topo@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", + "dependencies": { + "hoek": { + "version": "4.1.0", + "from": "hoek@4.x.x", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.1.0.tgz" + } + } + }, + "type-is": { + "version": "1.6.14", + "from": "type-is@>=1.6.13 <1.7.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.14.tgz" + }, + "unpipe": { + "version": "1.0.0", + "from": "unpipe@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + }, + "upper-case": { + "version": "1.1.3", + "from": "upper-case@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz" + }, + "util-deprecate": { + "version": "1.0.2", + "from": "util-deprecate@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + }, + "utils-merge": { + "version": "1.0.0", + "from": "utils-merge@1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" + }, + "vary": { + "version": "1.1.0", + "from": "vary@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.0.tgz" + }, + "wbuf": { + "version": "1.7.2", + "from": "wbuf@>=1.4.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz" + }, + "wrappy": { + "version": "1.0.2", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + }, + "x-xss-protection": { + "version": "1.0.0", + "from": "x-xss-protection@1.0.0", + "resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.0.0.tgz" + } + } +} diff --git a/booking/package.json b/booking/package.json new file mode 100644 index 0000000..50216ed --- /dev/null +++ b/booking/package.json @@ -0,0 +1,48 @@ +{ + "name": "booking-service", + "version": "1.0.0", + "description": "A Booking service, microservice example with nodejs", + "author": "Cristian Ramirez Rosas ", + "license": "ISC", + "main": "index.js", + "standard": { + "ignore": [ + "mock/**.js" + ] + }, + "scripts": { + "test": "mocha -R spec src/**/*.spec.js", + "start": "node src/index.js", + "lint": "standard --verbose | snazzy", + "node-debug": "DEBUG=express* node src/index.js", + "chrome-debug": "node --debug-brk --inspect src/index.js", + "coverage": "istanbul cover _mocha $(find ./src -name \"*.spec.js\" -not -path \"./node_modules/*\") ", + "metric": "nodejs-dashboard -- node -r nodejs-dashboard src/index.js" + }, + "keywords": [ + "express", + "mongodb", + "docker", + "microservice" + ], + "devDependencies": { + "eslint": "^3.13.1", + "mocha": "^3.2.0", + "nodejs-dashboard": "^0.3.0", + "should": "^11.1.2", + "snazzy": "^6.0.0" + }, + "dependencies": { + "awilix": "^2.2.2", + "body-parser": "^1.16.0", + "cors": "^2.8.1", + "express": "^4.14.0", + "helmet": "^3.4.0", + "http-status": "^0.2.5", + "joi": "^10.2.0", + "mongodb": "^2.1.18", + "morgan": "^1.7.0", + "spdy": "^3.4.4", + "supertest": "^3.0.0" + } +} diff --git a/booking/src/api/booking.js b/booking/src/api/booking.js new file mode 100644 index 0000000..e916439 --- /dev/null +++ b/booking/src/api/booking.js @@ -0,0 +1,63 @@ +'use strict' +const status = require('http-status') + +module.exports = ({repo}, app) => { + app.post('/booking', (req, res, next) => { + const validate = req.container.cradle.validate + const paymentService = req.container.resolve('paymentService') + const notificationService = req.container.resolve('notificationService') + + Promise.all([ + validate(req.body.user, 'user'), + validate(req.body.booking, 'booking') + ]) + .then(([user, booking]) => { + const payment = { + userName: user.name + ' ' + user.lastName, + currency: 'mxn', + number: user.creditCard.number, + cvc: user.creditCard.cvc, + exp_month: user.creditCard.exp_month, + exp_year: user.creditCard.exp_year, + amount: booking.totalAmount, + description: ` + Tickect(s) for movie ${booking.movie}, + with seat(s) ${booking.seats.toString()} + at time ${booking.schedule}` + } + + return Promise.all([ + paymentService(payment), + Promise.resolve(user), + Promise.resolve(booking) + ]) + }) + .then(([paid, user, booking]) => { + return Promise.all([ + repo.makeBooking(user, booking), + Promise.resolve(paid), + Promise.resolve(user) + ]) + }) + .then(([booking, paid, user]) => { + return Promise.all([ + repo.generateTicket(paid, booking), + Promise.resolve(user) + ]) + }) + .then(([ticket, user]) => { + const payload = Object.assign({}, ticket, {user: {name: user.name + user.lastName, email: user.email}}) + notificationService(payload) + res.status(status.OK).json(ticket) + }) + .catch(next) + }) + + app.get('/booking/verify/:orderId', (req, res, next) => { + repo.getOrderById(req.params.orderId) + .then(order => { + res.status(status.OK).json(order) + }) + .catch(next) + }) +} diff --git a/booking/src/api/booking.spec.js b/booking/src/api/booking.spec.js new file mode 100644 index 0000000..33b767f --- /dev/null +++ b/booking/src/api/booking.spec.js @@ -0,0 +1,103 @@ +/* eslint-env mocha */ +const { createContainer, asValue } = require('awilix') +const should = require('should') +const request = require('supertest') +const server = require('../server/server') +const models = require('../models') +const services = require('../services') + +describe('Booking API', () => { + let app = null + + const serverSettings = { + port: 3000 + } + + let testRepo = { + makeBooking (user, booking) { + return Promise.resolve('booking made successfully') + }, + generateTicket (paid, booking) { + const testTicket = { + cinema: booking.cinema, + schedule: booking.schedule.toString(), + movie: booking.movie, + seats: booking.seats, + cinemaRoom: booking.cinemaRoom, + orderId: 123 + } + return Promise.resolve(testTicket) + }, + getOrderById (orderId) { + return Promise.resolve('orderId: ' + orderId) + } + } + + beforeEach(() => { + const container = createContainer() + + container.register({ + validate: asValue(models.validate), + booking: asValue(models.booking), + user: asValue(models.booking), + ticket: asValue(models.booking), + serverSettings: asValue(serverSettings), + paymentService: asValue(services.paymentService), + notificationService: asValue(services.notificationService), + repo: asValue(testRepo) + }) + + return server.start(container) + .then(serv => { + app = serv + }) + }) + + afterEach(() => { + app.close() + app = null + }) + + it('can make a booking and return the ticket(s)', (done) => { + const now = new Date() + now.setDate(now.getDate() + 1) + + const user = { + name: 'Cristian', + lastName: 'Ramirez', + email: 'cristiano@nupp.com', + creditCard: { + number: '1111222233334444', + cvc: '123', + exp_month: '07', + exp_year: '2017' + }, + membership: '7777888899990000' + } + + const booking = { + city: 'Morelia', + cinema: 'Plaza Morelia', + movie: 'Assasins Creed', + schedule: now.toString(), + cinemaRoom: 7, + seats: ['45'], + totalAmount: 71 + } + + request(app) + .post('/booking') + .send({user, booking}) + .expect((res) => { + res.body.should.containEql({ + cinema: booking.cinema, + schedule: now.toString(), + movie: booking.movie, + seats: booking.seats, + cinemaRoom: booking.cinemaRoom, + orderId: 123 + }) + }) + .expect(200, done) + }) +}) diff --git a/booking/src/config/config.js b/booking/src/config/config.js new file mode 100644 index 0000000..64540e2 --- /dev/null +++ b/booking/src/config/config.js @@ -0,0 +1,45 @@ +const dbSettings = { + db: process.env.DB || 'booking', + user: process.env.DB_USER || 'cristian', + pass: process.env.DB_PASS || 'cristianPassword2017', + repl: process.env.DB_REPLS || 'rs1', + servers: (process.env.DB_SERVERS) ? process.env.DB_SERVERS.substr(1, process.env.DB_SERVERS.length - 2).split(' ') : [ + '192.168.99.100:27017', + '192.168.99.101:27017', + '192.168.99.102:27017' + ], + dbParameters: () => ({ + w: 'majority', + wtimeout: 10000, + j: true, + readPreference: 'ReadPreference.SECONDARY_PREFERRED', + native_parser: false + }), + serverParameters: () => ({ + autoReconnect: true, + poolSize: 10, + socketoptions: { + keepAlive: 300, + connectTimeoutMS: 30000, + socketTimeoutMS: 30000 + } + }), + replsetParameters: (replset = 'rs1') => ({ + replicaSet: replset, + ha: true, + haInterval: 10000, + poolSize: 10, + socketoptions: { + keepAlive: 300, + connectTimeoutMS: 30000, + socketTimeoutMS: 30000 + } + }) +} + +const serverSettings = { + port: process.env.PORT || 3000, + ssl: require('./ssl') +} + +module.exports = Object.assign({}, { dbSettings, serverSettings }) diff --git a/booking/src/config/db/index.js b/booking/src/config/db/index.js new file mode 100644 index 0000000..8a1a1d3 --- /dev/null +++ b/booking/src/config/db/index.js @@ -0,0 +1,4 @@ +const {ObjectID} = require('mongodb') +const {connect} = require('./mongo') + +module.exports = Object.assign({}, {connect, ObjectID}) diff --git a/booking/src/config/db/mongo.js b/booking/src/config/db/mongo.js new file mode 100644 index 0000000..18fce0f --- /dev/null +++ b/booking/src/config/db/mongo.js @@ -0,0 +1,32 @@ +const MongoClient = require('mongodb') + +const getMongoURL = (options) => { + const url = options.servers + .reduce((prev, cur) => prev + cur + ',', 'mongodb://') + + return `${url.substr(0, url.length - 1)}/${options.db}` +} + +const connect = (options, mediator) => { + mediator.once('boot.ready', () => { + MongoClient.connect( + getMongoURL(options), { + db: options.dbParameters(), + server: options.serverParameters(), + replset: options.replsetParameters(options.repl) + }, (err, db) => { + if (err) { + mediator.emit('db.error', err) + } + + db.admin().authenticate(options.user, options.pass, (err, result) => { + if (err) { + mediator.emit('db.error', err) + } + mediator.emit('db.ready', db) + }) + }) + }) +} + +module.exports = Object.assign({}, {connect}) diff --git a/booking/src/config/db/mongo.spec.js b/booking/src/config/db/mongo.spec.js new file mode 100644 index 0000000..6226394 --- /dev/null +++ b/booking/src/config/db/mongo.spec.js @@ -0,0 +1,29 @@ +/* eslint-env mocha */ +const {EventEmitter} = require('events') +const test = require('assert') +const mongo = require('./mongo') +const {dbSettings} = require('./config') + +describe('Mongo Connection', () => { + it('should emit db Object with an EventEmitter', (done) => { + const mediator = new EventEmitter() + + mediator.on('db.ready', (db) => { + db.admin().listDatabases((err, dbs) => { + test.equal(null, err) + test.ok(dbs.databases.length > 0) + console.log(dbs.databases) + db.close() + done() + }) + }) + + mediator.on('db.error', (err) => { + console.log(err) + }) + + mongo.connect(dbSettings, mediator) + + mediator.emit('boot.ready') + }) +}) diff --git a/booking/src/config/di/di.js b/booking/src/config/di/di.js new file mode 100644 index 0000000..339306d --- /dev/null +++ b/booking/src/config/di/di.js @@ -0,0 +1,33 @@ +const { createContainer, asValue } = require('awilix') + +function initDI ({serverSettings, dbSettings, database, models, services}, mediator) { + mediator.once('init', () => { + mediator.on('db.ready', (db) => { + const container = createContainer() + + container.register({ + database: asValue(db), + validate: asValue(models.validate), + booking: asValue(models.booking), + user: asValue(models.user), + ticket: asValue(models.ticket), + ObjectID: asValue(database.ObjectID), + serverSettings: asValue(serverSettings), + paymentService: asValue(services.paymentService), + notificationService: asValue(services.notificationService) + }) + + mediator.emit('di.ready', container) + }) + + mediator.on('db.error', (err) => { + mediator.emit('di.error', err) + }) + + database.connect(dbSettings, mediator) + + mediator.emit('boot.ready') + }) +} + +module.exports.initDI = initDI diff --git a/booking/src/config/di/di.proto.js b/booking/src/config/di/di.proto.js new file mode 100644 index 0000000..82e6df1 --- /dev/null +++ b/booking/src/config/di/di.proto.js @@ -0,0 +1,82 @@ +/* + const container = createContainer() + + container.register({ + transient(user), + transient(ticket), + transient(booking), + singleton(objectID), + singleton(notifications), + singleton(payments) + }) + + function ({ User, Booking }) { + make some stuff with the user + Promise.all([ + user.validate(object), + booking.validate(object) + ]) + .then([user, booking] => { + + }) + } + +*/ + +const createContainer = () => { + // DI store + const registrations = {} + // returns the DI + const container = { + get registrations () { + return Object.assign({}, registrations) + } + } + + // DI cache systems + container.cache = {} + + const getDI = new Proxy({}, { + get: (taget, name) => resolve(name), + set: (target, name, value) => { + throw new Error('cannot set a value to the container') + } + }) + + container.getDI = getDI + + const register = (name, registration, opts) => { + const key = Symbol(name) + registrations[key] = Object.assign({}, {fn: registration}, {lifetime: opts}) + return container + } + + container.register = register + + const resolve = (name) => { + const di = registrations[name] + switch (di.lifetime) { + case 'TRANSIENT': + return container.registrations[name].fn + case 'SINGLETON': + if (!container.cache[name]) { + container.cache[name] = container.registrations[name] + } + return container.cache[name].fn + } + } + + const listDependencies = () => { + const list = [] + for (var key in registrations) { + if (registrations.hasOwnProperty(key)) { + list.push(key) + } + } + return list + } + + return Object.create(container) +} + +module.exports.createContainer = createContainer diff --git a/booking/src/config/di/index.js b/booking/src/config/di/index.js new file mode 100644 index 0000000..ff2d63c --- /dev/null +++ b/booking/src/config/di/index.js @@ -0,0 +1,3 @@ +const di = require('./di') + +module.exports = Object.assign({}, di) diff --git a/booking/src/config/index.di.spec.js b/booking/src/config/index.di.spec.js new file mode 100644 index 0000000..e3dfa51 --- /dev/null +++ b/booking/src/config/index.di.spec.js @@ -0,0 +1,24 @@ +/* eslint-env mocha */ +const {EventEmitter} = require('events') +const test = require('assert') +const {init} = require('./') + +describe('DI configuration', () => { + it('can init dependencies to the container', (done) => { + const mediator = new EventEmitter() + + mediator.on('di.ready', (container) => { + console.log(container) + done() + }) + + mediator.on('di.error', err => { + console.log(err) + done() + }) + + init(mediator) + + mediator.emit('init') + }) +}) diff --git a/booking/src/config/index.js b/booking/src/config/index.js new file mode 100644 index 0000000..1180b2a --- /dev/null +++ b/booking/src/config/index.js @@ -0,0 +1,9 @@ +const {dbSettings, serverSettings} = require('./config') +const database = require('./db') +const {initDI} = require('./di') +const models = require('../models') +const services = require('../services') + +const init = initDI.bind(null, {serverSettings, dbSettings, database, models, services}) + +module.exports = Object.assign({}, {init}) diff --git a/booking/src/config/ssl/index.js b/booking/src/config/ssl/index.js new file mode 100644 index 0000000..63e4cd3 --- /dev/null +++ b/booking/src/config/ssl/index.js @@ -0,0 +1,6 @@ +const fs = require('fs') + +module.exports = { + key: fs.readFileSync(`${__dirname}/server.key`), + cert: fs.readFileSync(`${__dirname}/server.crt`) +} diff --git a/booking/src/index.js b/booking/src/index.js new file mode 100644 index 0000000..cabc5c1 --- /dev/null +++ b/booking/src/index.js @@ -0,0 +1,36 @@ +'use strict' +const {EventEmitter} = require('events') +const server = require('./server/server') +const repository = require('./repository/repository') +const di = require('./config') +const mediator = new EventEmitter() + +console.log('--- Booking Service ---') +console.log('Connecting to booking repository...') + +process.on('uncaughtException', (err) => { + console.error('Unhandled Exception', err) +}) + +process.on('uncaughtRejection', (err, promise) => { + console.error('Unhandled Rejection', err) +}) + +mediator.on('di.ready', (container) => { + repository.connect(container) + .then(repo => { + console.log('Connected. Starting Server') + container.registerValue({repo}) + return server.start(container) + }) + .then(app => { + console.log(`Server started succesfully, running on port: ${container.cradle.serverSettings.port}.`) + app.on('close', () => { + container.resolve('repo').disconnect() + }) + }) +}) + +di.init(mediator) + +mediator.emit('init') diff --git a/booking/src/models/booking.model.js b/booking/src/models/booking.model.js new file mode 100644 index 0000000..f02e268 --- /dev/null +++ b/booking/src/models/booking.model.js @@ -0,0 +1,14 @@ +const bookingSchema = (joi) => ({ + city: joi.string(), + cinema: joi.string(), + schedule: joi.date().min('now'), + movie: joi.object().keys({ + title: joi.string(), + format: joi.string() + }), + cinemaRoom: joi.number(), + seats: joi.array().items(joi.string()).single(), + totalAmount: joi.number() +}) + +module.exports = bookingSchema diff --git a/booking/src/models/index.js b/booking/src/models/index.js new file mode 100644 index 0000000..2fe55d2 --- /dev/null +++ b/booking/src/models/index.js @@ -0,0 +1,26 @@ +const joi = require('joi') +const user = require('./user.model')(joi) +const booking = require('./booking.model')(joi) +const ticket = require('./ticket.model')(joi) + +const schemas = Object.create({user, booking, ticket}) + +const schemaValidator = (object, type) => { + return new Promise((resolve, reject) => { + if (!object) { + reject(new Error('object to validate not provided')) + } + if (!type) { + reject(new Error('schema type to validate not provided')) + } + + const {error, value} = joi.validate(object, schemas[type]) + + if (error) { + reject(new Error(`invalid ${type} data, err: ${error}`)) + } + resolve(value) + }) +} + +module.exports = Object.create({validate: schemaValidator, schemas}) diff --git a/booking/src/models/index.spec.js b/booking/src/models/index.spec.js new file mode 100644 index 0000000..c6b9b63 --- /dev/null +++ b/booking/src/models/index.spec.js @@ -0,0 +1,81 @@ +/* eslint-env mocha */ +const test = require('assert') +const {validate} = require('./') + +console.log(Object.getPrototypeOf(validate)) + +describe('Schemas Validation', () => { + it('can validate a booking object', (done) => { + const now = new Date() + now.setDate(now.getDate() + 1) + + const testBooking = { + city: 'Morelia', + cinema: 'Plaza Morelia', + movie: 'Assasins Creed', + schedule: now, + cinemaRoom: 7, + seats: ['45'], + totalAmount: 71 + } + + validate(testBooking, 'booking') + .then(value => { + console.log('validated') + console.log(value) + done() + }) + .catch(err => { + console.log(err) + done() + }) + }) + + it('can validate a user object', (done) => { + const testUser = { + name: 'Cristian', + lastName: 'Ramirez', + email: 'cristiano@nupp.com', + creditCard: { + number: '1111222233334444', + cvc: '123', + exp_month: '07', + exp_year: '2017' + }, + membership: '7777888899990000' + } + + validate(testUser, 'user') + .then(value => { + console.log('validated') + console.log(value) + done() + }) + .catch(err => { + console.log(err) + done() + }) + }) + + it('can validate a ticket object', (done) => { + const testTicket = { + cinema: 'Plaza Morelia', + schedule: new Date(), + movie: 'Assasins Creed', + seats: ['35'], + cinemaRoom: 1, + orderId: '34jh1231ll' + } + + validate(testTicket, 'ticket') + .then(value => { + console.log('validated') + console.log(value) + done() + }) + .catch(err => { + console.log(err) + done() + }) + }) +}) diff --git a/booking/src/models/ticket.model.js b/booking/src/models/ticket.model.js new file mode 100644 index 0000000..29af13b --- /dev/null +++ b/booking/src/models/ticket.model.js @@ -0,0 +1,11 @@ + +const ticketSchema = (joi) => ({ + cinema: joi.string(), + schedule: joi.date(), + movie: joi.string(), + seats: joi.array().items(joi.string()).single(), + cinemaRoom: joi.number(), + orderId: joi.string().alphanum() +}) + +module.exports = ticketSchema diff --git a/booking/src/models/user.model.js b/booking/src/models/user.model.js new file mode 100644 index 0000000..f86730e --- /dev/null +++ b/booking/src/models/user.model.js @@ -0,0 +1,15 @@ +const userSchema = (joi) => ({ + name: joi.string().regex(/^[a-zA-Z '-]+$/i).required(), + lastName: joi.string().regex(/^[a-zA-Z '-]+$/i).required(), + email: joi.string().email().required(), + phoneNumber: joi.string().regex(/^(\+0?1\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$/), + creditCard: joi.object().keys({ + number: joi.string().creditCard().required(), + cvc: joi.number(), + exp_month: joi.number(), + exp_year: joi.number() + }), + membership: joi.string().creditCard() +}) + +module.exports = userSchema diff --git a/booking/src/repository/repository.js b/booking/src/repository/repository.js new file mode 100644 index 0000000..bc1840f --- /dev/null +++ b/booking/src/repository/repository.js @@ -0,0 +1,79 @@ +'use strict' +const repository = (container) => { + const {database: db} = container.cradle + + const makeBooking = (user, booking) => { + return new Promise((resolve, reject) => { + const payload = { + city: booking.city, + userType: (user.membership) ? 'loyal' : 'normal', + totalAmount: booking.totalAmount, + cinema: { + name: booking.cinema, + room: booking.cinemaRoom, + seats: booking.seats.toString() + }, + movie: { + title: booking.movie.title, + format: booking.movie.format, + schedule: booking.schedule + } + } + + db.collection('booking').insertOne(payload, (err, booked) => { + if (err) { + reject(new Error('An error occuered registring a user booking, err:' + err)) + } + resolve(payload) + }) + }) + } + + const generateTicket = (paid, booking) => { + return new Promise((resolve, reject) => { + const payload = Object.assign({}, booking, {orderId: paid.charge.id, description: paid.description}) + db.collection('tickets').insertOne(payload, (err, ticket) => { + if (err) { + reject(new Error('an error occured registring a ticket, err:' + err)) + } + resolve(payload) + }) + }) + } + + const getOrderById = (orderId) => { + return new Promise((resolve, reject) => { + const ObjectID = container.resolve('ObjectID') + const query = {_id: new ObjectID(orderId)} + const response = (err, order) => { + if (err) { + reject(new Error('An error occuered retrieving a order, err: ' + err)) + } + resolve(order) + } + db.collection('booking').findOne(query, {}, response) + }) + } + + const disconnect = () => { + db.close() + } + + return Object.create({ + makeBooking, + getOrderById, + generateTicket, + disconnect + }) +} + +const connect = (container) => { + return new Promise((resolve, reject) => { + if (!container.resolve('database')) { + reject(new Error('connection db not supplied!')) + } + resolve(repository(container)) + }) +} + +module.exports = Object.assign({}, {connect}) diff --git a/booking/src/repository/repository.spec.js b/booking/src/repository/repository.spec.js new file mode 100644 index 0000000..b423fc2 --- /dev/null +++ b/booking/src/repository/repository.spec.js @@ -0,0 +1,9 @@ +/* eslint-env mocha */ +const should = require('should') +const repository = require('./repository') + +describe('Repository', () => { + it('should connect with a promise', () => { + repository.connect({}).should.be.a.Promise() + }) +}) diff --git a/booking/src/server/server.js b/booking/src/server/server.js new file mode 100644 index 0000000..33cd1c4 --- /dev/null +++ b/booking/src/server/server.js @@ -0,0 +1,43 @@ +const express = require('express') +const morgan = require('morgan') +const helmet = require('helmet') +const bodyparser = require('body-parser') +const cors = require('cors') +const _api = require('../api/booking') + +const start = (container) => { + return new Promise((resolve, reject) => { + const {port} = container.resolve('serverSettings') + const repo = container.resolve('repo') + + if (!repo) { + reject(new Error('The server must be started with a connected repository')) + } + if (!port) { + reject(new Error('The server must be started with an available port')) + } + + const app = express() + app.use(morgan('dev')) + app.use(bodyparser.json()) + app.use(cors()) + app.use(helmet()) + app.use((err, req, res, next) => { + reject(new Error('Something went wrong!, err:' + err)) + res.status(500).send('Something went wrong!') + next() + }) + app.use((req, res, next) => { + req.container = container.createScope() + next() + }) + + const api = _api.bind(null, {repo}) + api(app) + + const server = app.listen(port, () => resolve(server)) + + }) +} + +module.exports = Object.assign({}, {start}) diff --git a/booking/src/server/server.spec.js b/booking/src/server/server.spec.js new file mode 100644 index 0000000..033d152 --- /dev/null +++ b/booking/src/server/server.spec.js @@ -0,0 +1,12 @@ +/* eslint-env mocha */ +const server = require('./server') + +describe('Server', () => { + it('should require a port to start', () => { + return server.start({}).should.be.rejectedWith(/port/) + }) + + it('should require a repository to start', () => { + return server.start({}).should.be.rejectedWith(/repository/) + }) +}) diff --git a/booking/src/services/index.js b/booking/src/services/index.js new file mode 100644 index 0000000..89d69d7 --- /dev/null +++ b/booking/src/services/index.js @@ -0,0 +1,4 @@ +const paymentService = require('./payment.service') +const notificationService = require('./notification.service') + +module.exports = Object.assign({}, {paymentService, notificationService}) diff --git a/booking/src/services/notification.service.js b/booking/src/services/notification.service.js new file mode 100644 index 0000000..9fe62d7 --- /dev/null +++ b/booking/src/services/notification.service.js @@ -0,0 +1,17 @@ +const supertest = require('supertest') +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' +process.env.NODE_TLS_ACCEPT_UNTRUSTED_CERTIFICATES_THIS_IS_INSECURE = '1' + +module.exports = (payload) => { + return new Promise((resolve, reject) => { + supertest('https://192.168.99.100:8080') + .post('/notification/sendEmail') + .send({payload}) + .end((err, res) => { + if (err) { + reject(new Error('An error occured with the payment service, err: ' + err)) + } + resolve(res.body) + }) + }) +} diff --git a/booking/src/services/payment.service.js b/booking/src/services/payment.service.js new file mode 100644 index 0000000..c7d15b8 --- /dev/null +++ b/booking/src/services/payment.service.js @@ -0,0 +1,17 @@ +const supertest = require('supertest') +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' +process.env.NODE_TLS_ACCEPT_UNTRUSTED_CERTIFICATES_THIS_IS_INSECURE = '1' + +module.exports = (paymentOrder) => { + return new Promise((resolve, reject) => { + supertest('https://192.168.99.100:8080') + .post('/payment/makePurchase') + .send({paymentOrder}) + .end((err, res) => { + if (err) { + reject(new Error('An error occured with the payment service, err: ' + err)) + } + resolve(res.body.paid) + }) + }) +} diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..dc596d6 --- /dev/null +++ b/build.sh @@ -0,0 +1,24 @@ +#!/bin/bash +set -e + +export DOCKERHUB_USERNAME=${DOCKERHUB_USERNAME:-michaelact} +export VERSION=${VERSION:-latest} + +function setup-container-images { + echo "···························" + echo "·· creating microservices container images >>>> ··" + echo "···························" + + find * -type f -name "Dockerfile" -printf "%h\n" | xargs -I % sh -c "docker build -t $DOCKERHUB_USERNAME/wonderful-%:latest %/" +} + +function setup-local { + echo "···························" + echo "·· creating microservices application on host >>>> ··" + echo ".. run export NODE_ENV=production to install only production modules" + echo "···························" + + find * -maxdepth 1 -type f -name "package.json" -printf "%h\n" | xargs -I % sh -c 'cd % && npm cache clean && npm install --silent --progress=false)' +} + +$@ diff --git a/cinema-catalog/.eslintrc.json b/cinema-catalog/.eslintrc.json new file mode 100644 index 0000000..a755cdb --- /dev/null +++ b/cinema-catalog/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": ["standard"] +} diff --git a/cinema-catalog/Dockerfile b/cinema-catalog/Dockerfile new file mode 100644 index 0000000..523816b --- /dev/null +++ b/cinema-catalog/Dockerfile @@ -0,0 +1,25 @@ +FROM node:7.5.0-alpine + +RUN addgroup -S nupp && adduser -S -g nupp nupp + +ENV HOME=/home/nupp + +COPY package.json npm-shrinkwrap.json $HOME/app/ + +COPY src/ $HOME/app/src + +ADD https://github.com/Yelp/dumb-init/releases/download/v1.1.1/dumb-init_1.1.1_amd64 /usr/local/bin/dumb-init + +WORKDIR $HOME/app + +RUN chown -R nupp:nupp $HOME/* /usr/local/ && \ + chmod +x /usr/local/bin/dumb-init && \ + npm cache clean && \ + npm install --silent --progress=false --production && \ + chown -R nupp:nupp $HOME/* + +USER nupp + +EXPOSE 3000 + +CMD ["dumb-init", "npm", "start"] diff --git a/cinema-catalog/env b/cinema-catalog/env new file mode 100644 index 0000000..fa652a3 --- /dev/null +++ b/cinema-catalog/env @@ -0,0 +1,6 @@ +DB=cinemas +DB_USER=cristian +DB_PASS=cristianPassword2017 +DB_REPLS=rs1 +DB_SERVERS='192.168.99.100:27017 192.168.99.101:27017 192.168.99.102:27017' +PORT=3000 diff --git a/cinema-catalog/integration-test/cinema-catalog-service-api.jmeter.test.jmx b/cinema-catalog/integration-test/cinema-catalog-service-api.jmeter.test.jmx new file mode 100644 index 0000000..a77d528 --- /dev/null +++ b/cinema-catalog/integration-test/cinema-catalog-service-api.jmeter.test.jmx @@ -0,0 +1,182 @@ + + + + + + false + false + + + + + + + + + + + + continue + + false + 1000 + + 100 + 1000 + 1485133702000 + 1485133702000 + false + + + + + + + + + 192.168.99.100 + 3000 + + + https + + + 6 + + + + + + + false + 1 + = + true + id + + + + + + + + + + /cinemas/588ababf2d029a6d15d0b5bf/${id} + GET + true + false + true + false + false + + + + + + + + false + 3 + = + true + id + + + + + + + + + + /cinemas/588ababf2d029a6d15d0b5bf/${id} + GET + true + false + true + false + false + + + + + + + + false + 2 + = + true + id + + + + + + + + + + /cinemas/588ababf2d029a6d15d0b5bf/${id} + GET + true + false + true + false + false + + + + + + + + false + 588ababf2d029a6d15d0b5bf + = + true + cityId + + + + + + + + + + /cinemas?cityId=${cityId} + GET + true + false + true + false + false + + + + + + + + + + + + + + /cinemas/588ac3a02d029a6d15d0b5c4 + GET + true + false + true + false + false + + + + + + + diff --git a/cinema-catalog/integration-test/index.js b/cinema-catalog/integration-test/index.js new file mode 100644 index 0000000..72a8519 --- /dev/null +++ b/cinema-catalog/integration-test/index.js @@ -0,0 +1,10 @@ +/* eslint-env mocha */ +const supertest = require('supertest') + +describe('cinema-catalog-service', () => { + const api = supertest('http://192.168.99.100:3001') + it('returns schedules for a movie', (done) => { + api.get('/cinemas/588ababf2d029a6d15d0b5bf/1') + .expect(200, done) + }) +}) diff --git a/cinema-catalog/npm-shrinkwrap.json b/cinema-catalog/npm-shrinkwrap.json new file mode 100644 index 0000000..2581895 --- /dev/null +++ b/cinema-catalog/npm-shrinkwrap.json @@ -0,0 +1,520 @@ +{ + "name": "movies-service", + "version": "1.0.0", + "dependencies": { + "accepts": { + "version": "1.3.3", + "from": "accepts@>=1.3.3 <1.4.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz" + }, + "array-flatten": { + "version": "1.1.1", + "from": "array-flatten@1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" + }, + "basic-auth": { + "version": "1.0.4", + "from": "basic-auth@>=1.0.3 <1.1.0", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz" + }, + "bson": { + "version": "0.4.23", + "from": "bson@>=0.4.23 <0.5.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-0.4.23.tgz" + }, + "buffer-shims": { + "version": "1.0.0", + "from": "buffer-shims@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" + }, + "camelize": { + "version": "1.0.0", + "from": "camelize@1.0.0", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz" + }, + "connect": { + "version": "3.5.0", + "from": "connect@3.5.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.5.0.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + } + }, + "content-disposition": { + "version": "0.5.1", + "from": "content-disposition@0.5.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz" + }, + "content-security-policy-builder": { + "version": "1.1.0", + "from": "content-security-policy-builder@1.1.0", + "resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-1.1.0.tgz" + }, + "content-type": { + "version": "1.0.2", + "from": "content-type@>=1.0.2 <1.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz" + }, + "cookie": { + "version": "0.3.1", + "from": "cookie@0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz" + }, + "cookie-signature": { + "version": "1.0.6", + "from": "cookie-signature@1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + }, + "core-util-is": { + "version": "1.0.2", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "dasherize": { + "version": "2.0.0", + "from": "dasherize@2.0.0", + "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz" + }, + "dashify": { + "version": "0.2.2", + "from": "dashify@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/dashify/-/dashify-0.2.2.tgz" + }, + "debug": { + "version": "2.6.0", + "from": "debug@>=2.1.1 <3.0.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz" + }, + "depd": { + "version": "1.1.0", + "from": "depd@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz" + }, + "destroy": { + "version": "1.0.4", + "from": "destroy@>=1.0.4 <1.1.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" + }, + "dns-prefetch-control": { + "version": "0.1.0", + "from": "dns-prefetch-control@0.1.0", + "resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz" + }, + "dont-sniff-mimetype": { + "version": "1.0.0", + "from": "dont-sniff-mimetype@1.0.0", + "resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.0.0.tgz" + }, + "ee-first": { + "version": "1.1.1", + "from": "ee-first@1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + }, + "encodeurl": { + "version": "1.0.1", + "from": "encodeurl@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz" + }, + "es6-promise": { + "version": "3.0.2", + "from": "es6-promise@3.0.2", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz" + }, + "escape-html": { + "version": "1.0.3", + "from": "escape-html@>=1.0.3 <1.1.0", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + }, + "etag": { + "version": "1.7.0", + "from": "etag@>=1.7.0 <1.8.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz" + }, + "express": { + "version": "4.14.0", + "from": "express@latest", + "resolved": "https://registry.npmjs.org/express/-/express-4.14.0.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + }, + "qs": { + "version": "6.2.0", + "from": "qs@6.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz" + } + } + }, + "finalhandler": { + "version": "0.5.0", + "from": "finalhandler@0.5.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.0.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@~2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + } + }, + "forwarded": { + "version": "0.1.0", + "from": "forwarded@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz" + }, + "frameguard": { + "version": "3.0.0", + "from": "frameguard@3.0.0", + "resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.0.0.tgz" + }, + "fresh": { + "version": "0.3.0", + "from": "fresh@0.3.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz" + }, + "handle-thing": { + "version": "1.2.5", + "from": "handle-thing@>=1.2.4 <2.0.0", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz" + }, + "helmet": { + "version": "3.4.0", + "from": "helmet@>=3.4.0 <4.0.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.4.0.tgz" + }, + "helmet-csp": { + "version": "2.3.0", + "from": "helmet-csp@2.3.0", + "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.3.0.tgz" + }, + "hide-powered-by": { + "version": "1.0.0", + "from": "hide-powered-by@1.0.0", + "resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.0.0.tgz" + }, + "hpack.js": { + "version": "2.1.6", + "from": "hpack.js@>=2.1.6 <3.0.0", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz" + }, + "hpkp": { + "version": "2.0.0", + "from": "hpkp@2.0.0", + "resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz" + }, + "hsts": { + "version": "2.0.0", + "from": "hsts@2.0.0", + "resolved": "https://registry.npmjs.org/hsts/-/hsts-2.0.0.tgz" + }, + "http-deceiver": { + "version": "1.2.7", + "from": "http-deceiver@>=1.2.4 <2.0.0", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" + }, + "http-errors": { + "version": "1.5.1", + "from": "http-errors@>=1.5.0 <1.6.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz" + }, + "http-status": { + "version": "0.2.5", + "from": "http-status@latest", + "resolved": "https://registry.npmjs.org/http-status/-/http-status-0.2.5.tgz" + }, + "ienoopen": { + "version": "1.0.0", + "from": "ienoopen@1.0.0", + "resolved": "https://registry.npmjs.org/ienoopen/-/ienoopen-1.0.0.tgz" + }, + "inherits": { + "version": "2.0.3", + "from": "inherits@>=2.0.3 <3.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + }, + "ipaddr.js": { + "version": "1.2.0", + "from": "ipaddr.js@1.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.2.0.tgz" + }, + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, + "lodash.reduce": { + "version": "4.6.0", + "from": "lodash.reduce@4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz" + }, + "media-typer": { + "version": "0.3.0", + "from": "media-typer@0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + }, + "merge-descriptors": { + "version": "1.0.1", + "from": "merge-descriptors@1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" + }, + "methods": { + "version": "1.1.2", + "from": "methods@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + }, + "mime": { + "version": "1.3.4", + "from": "mime@>=1.3.4 <2.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" + }, + "mime-db": { + "version": "1.26.0", + "from": "mime-db@>=1.26.0 <1.27.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.26.0.tgz" + }, + "mime-types": { + "version": "2.1.14", + "from": "mime-types@>=2.1.10 <3.0.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.14.tgz" + }, + "minimalistic-assert": { + "version": "1.0.0", + "from": "minimalistic-assert@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" + }, + "mongodb": { + "version": "2.1.18", + "from": "mongodb@2.1.18", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.1.18.tgz", + "dependencies": { + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "readable-stream": { + "version": "1.0.31", + "from": "readable-stream@1.0.31", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.31.tgz" + } + } + }, + "mongodb-core": { + "version": "1.3.18", + "from": "mongodb-core@1.3.18", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-1.3.18.tgz" + }, + "morgan": { + "version": "1.7.0", + "from": "morgan@latest", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.7.0.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@~2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + } + }, + "ms": { + "version": "0.7.2", + "from": "ms@0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz" + }, + "negotiator": { + "version": "0.6.1", + "from": "negotiator@0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz" + }, + "nocache": { + "version": "2.0.0", + "from": "nocache@2.0.0", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.0.0.tgz" + }, + "obuf": { + "version": "1.1.1", + "from": "obuf@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz" + }, + "on-finished": { + "version": "2.3.0", + "from": "on-finished@>=2.3.0 <2.4.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" + }, + "on-headers": { + "version": "1.0.1", + "from": "on-headers@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" + }, + "parseurl": { + "version": "1.3.1", + "from": "parseurl@>=1.3.1 <1.4.0", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz" + }, + "path-to-regexp": { + "version": "0.1.7", + "from": "path-to-regexp@0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" + }, + "platform": { + "version": "1.3.3", + "from": "platform@1.3.3", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.3.tgz" + }, + "process-nextick-args": { + "version": "1.0.7", + "from": "process-nextick-args@>=1.0.6 <1.1.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" + }, + "proxy-addr": { + "version": "1.1.3", + "from": "proxy-addr@>=1.1.2 <1.2.0", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.3.tgz" + }, + "range-parser": { + "version": "1.2.0", + "from": "range-parser@>=1.2.0 <1.3.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz" + }, + "readable-stream": { + "version": "2.2.2", + "from": "readable-stream@>=2.2.2 <3.0.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.2.tgz" + }, + "referrer-policy": { + "version": "1.1.0", + "from": "referrer-policy@1.1.0", + "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.1.0.tgz" + }, + "require_optional": { + "version": "1.0.0", + "from": "require_optional@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.0.tgz", + "dependencies": { + "resolve-from": { + "version": "2.0.0", + "from": "resolve-from@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz" + } + } + }, + "select-hose": { + "version": "2.0.0", + "from": "select-hose@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" + }, + "semver": { + "version": "5.3.0", + "from": "semver@>=5.1.0 <6.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz" + }, + "send": { + "version": "0.14.1", + "from": "send@0.14.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.14.1.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@~2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + } + }, + "serve-static": { + "version": "1.11.1", + "from": "serve-static@>=1.11.1 <1.12.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.11.1.tgz" + }, + "setprototypeof": { + "version": "1.0.2", + "from": "setprototypeof@1.0.2", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz" + }, + "spdy": { + "version": "3.4.4", + "from": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz" + }, + "spdy-transport": { + "version": "2.0.18", + "from": "spdy-transport@>=2.0.15 <3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.18.tgz" + }, + "statuses": { + "version": "1.3.1", + "from": "statuses@>=1.3.0 <1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "type-is": { + "version": "1.6.14", + "from": "type-is@>=1.6.13 <1.7.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.14.tgz" + }, + "unpipe": { + "version": "1.0.0", + "from": "unpipe@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + }, + "util-deprecate": { + "version": "1.0.2", + "from": "util-deprecate@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + }, + "utils-merge": { + "version": "1.0.0", + "from": "utils-merge@1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" + }, + "vary": { + "version": "1.1.0", + "from": "vary@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.0.tgz" + }, + "wbuf": { + "version": "1.7.2", + "from": "wbuf@>=1.4.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz" + }, + "x-xss-protection": { + "version": "1.0.0", + "from": "x-xss-protection@1.0.0", + "resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.0.0.tgz" + } + } +} diff --git a/cinema-catalog/package.json b/cinema-catalog/package.json new file mode 100644 index 0000000..767d1bb --- /dev/null +++ b/cinema-catalog/package.json @@ -0,0 +1,45 @@ +{ + "name": "movies-service", + "version": "1.0.0", + "description": "A movie service, microservice example with nodejs", + "author": "Cristian Ramirez Rosas ", + "license": "ISC", + "main": "index.js", + "standard": { + "ignore": [ + "mock/**.js" + ] + }, + "scripts": { + "test": "mocha -R spec src/**/*.spec.js", + "start": "node src/index.js", + "lint": "standard --verbose | snazzy", + "node-debug": "DEBUG=express* node src/index.js", + "chrome-debug": "node --debug-brk --inspect src/index.js", + "coverage": "istanbul cover _mocha $(find ./src -name \"*.spec.js\" -not -path \"./node_modules/*\") ", + "metric": "nodejs-dashboard -- node -r nodejs-dashboard src/index.js" + }, + "keywords": [ + "express", + "mongodb", + "docker", + "microservice" + ], + "devDependencies": { + "eslint": "^3.13.1", + "mocha": "^3.2.0", + "nodejs-dashboard": "^0.3.0", + "should": "^11.1.2", + "snazzy": "^6.0.0", + "standard": "^8.6.0", + "supertest": "^2.0.1" + }, + "dependencies": { + "express": "^4.14.0", + "helmet": "^3.4.0", + "http-status": "^0.2.5", + "mongodb": "^2.1.18", + "morgan": "^1.7.0", + "spdy": "^3.4.4" + } +} diff --git a/cinema-catalog/src/api/cinema-catalog.js b/cinema-catalog/src/api/cinema-catalog.js new file mode 100644 index 0000000..aeb3a4c --- /dev/null +++ b/cinema-catalog/src/api/cinema-catalog.js @@ -0,0 +1,34 @@ +'use strict' +const status = require('http-status') + +module.exports = (app, options) => { + const {repo} = options + + app.get('/cinemas', (req, res, next) => { + repo.getCinemasByCity(req.query.cityId) + .then(cinemas => { + res.status(status.OK).json(cinemas) + }) + .catch(next) + }) + + app.get('/cinemas/:cinemaId', (req, res, next) => { + repo.getCinemaById(req.params.cinemaId) + .then(cinema => { + res.status(status.OK).json(cinema) + }) + .catch(next) + }) + + app.get('/cinemas/:cityId/:movieId', (req, res, next) => { + const params = { + cityId: req.params.cityId, + movieId: req.params.movieId + } + repo.getCinemaScheduleByMovie(params) + .then(schedules => { + res.status(status.OK).json(schedules) + }) + .catch(next) + }) +} diff --git a/cinema-catalog/src/api/cinema-catalog.spec.js b/cinema-catalog/src/api/cinema-catalog.spec.js new file mode 100644 index 0000000..3d5d4ae --- /dev/null +++ b/cinema-catalog/src/api/cinema-catalog.spec.js @@ -0,0 +1,126 @@ +/* eslint-env mocha */ +const request = require('supertest') +const server = require('../server/server') + +describe('Movies API', () => { + let app = null + const testCinemasCity = [{ + '_id': '588ac3a02d029a6d15d0b5c4', + 'name': 'Plaza Morelia' + }, { + '_id': '588ac3a02d029a6d15d0b5c5', + 'name': 'Las Americas' + }] + + const testCinemaId = { + '_id': '588ac3a02d029a6d15d0b5c4', + 'name': 'Plaza Morelia', + 'cinemaPremieres': [ + { + 'id': '1', + 'title': 'Assasins Creed', + 'runtime': 115, + 'plot': 'Lorem ipsum dolor sit amet', + 'poster': 'link to poster...' + }, + { + 'id': '2', + 'title': 'Aliados', + 'runtime': 124, + 'plot': 'Lorem ipsum dolor sit amet', + 'poster': 'link to poster...' + }, + { + 'id': '3', + 'title': 'xXx: Reactivado', + 'runtime': 107, + 'plot': 'Lorem ipsum dolor sit amet', + 'poster': 'link to poster...' + } + ] + } + + const testSchedulesMovie = [{ + '_id': 'Plaza Morelia', + 'schedules': [{ + 'room': 2.0, + 'schedules': [ '10:15' ] + }, { + 'room': 1.0, + 'schedules': [ '6:55', '4:35', '10:15' ] + }, { + 'room': 3.0, + 'schedules': [ '10:15' ] + }] + }, { + '_id': 'Las Americas', + 'schedules': [ { + 'room': 2.0, + 'schedules': [ '3:25', '10:15' ] + }, { + 'room': 1.0, + 'schedules': [ '12:15', '10:15' ] + }] + }] + + let testRepo = { + getCinemasByCity (location) { + console.log(location) + return Promise.resolve(testCinemasCity) + }, + getCinemaById (cinemaId) { + console.log(cinemaId) + return Promise.resolve(testCinemaId) + }, + getCinemaScheduleByMovie (cinemaId, movieId) { + console.log(cinemaId, movieId) + return Promise.resolve(testSchedulesMovie) + } + } + + beforeEach(() => { + return server.start({ + port: 3000, + repo: testRepo + }).then(serv => { + app = serv + }) + }) + + afterEach(() => { + app.close() + app = null + }) + + it('can return cinemas by location', (done) => { + const location = { + city: '588ababf2d029a6d15d0b5bf' + } + request(app) + .get(`/cinemas?cityId=${location.city}`) + .expect((res) => { + res.body.should.containEql(testCinemasCity[0]) + res.body.should.containEql(testCinemasCity[1]) + }) + .expect(200, done) + }) + + it('can get movie premiers by cinema', (done) => { + request(app) + .get('/cinemas/588ac3a02d029a6d15d0b5c4') + .expect((res) => { + res.body.should.containEql(testCinemaId) + }) + .expect(200, done) + }) + + it('can get schedules by cinema and movie', (done) => { + request(app) + .get('/cinemas/588ababf2d029a6d15d0b5bf/1') + .expect((res) => { + res.body.should.containEql(testSchedulesMovie[0]) + res.body.should.containEql(testSchedulesMovie[1]) + }) + .expect(200, done) + }) +}) diff --git a/cinema-catalog/src/config/config.js b/cinema-catalog/src/config/config.js new file mode 100644 index 0000000..ea6681d --- /dev/null +++ b/cinema-catalog/src/config/config.js @@ -0,0 +1,45 @@ +const dbSettings = { + db: process.env.DB || 'cinemas', + user: process.env.DB_USER || 'cristian', + pass: process.env.DB_PASS || 'cristianPassword2017', + repl: process.env.DB_REPLS || 'rs1', + servers: (process.env.DB_SERVERS) ? process.env.DB_SERVERS.substr(1, process.env.DB_SERVERS.length - 2).split(' ') : [ + '192.168.99.100:27017', + '192.168.99.101:27017', + '192.168.99.102:27017' + ], + dbParameters: () => ({ + w: 'majority', + wtimeout: 10000, + j: true, + readPreference: 'ReadPreference.SECONDARY_PREFERRED', + native_parser: false + }), + serverParameters: () => ({ + autoReconnect: true, + poolSize: 10, + socketoptions: { + keepAlive: 300, + connectTimeoutMS: 30000, + socketTimeoutMS: 30000 + } + }), + replsetParameters: (replset = 'rs1') => ({ + replicaSet: replset, + ha: true, + haInterval: 10000, + poolSize: 10, + socketoptions: { + keepAlive: 300, + connectTimeoutMS: 30000, + socketTimeoutMS: 30000 + } + }) +} + +const serverSettings = { + port: process.env.PORT || 3000, + ssl: require('./ssl') +} + +module.exports = Object.assign({}, { dbSettings, serverSettings }) diff --git a/cinema-catalog/src/config/index.js b/cinema-catalog/src/config/index.js new file mode 100644 index 0000000..12b087c --- /dev/null +++ b/cinema-catalog/src/config/index.js @@ -0,0 +1,5 @@ +const {ObjectID} = require('mongodb') +const {dbSettings, serverSettings} = require('./config') +const db = require('./mongo') + +module.exports = Object.assign({}, {dbSettings, serverSettings, db, ObjectID}) diff --git a/cinema-catalog/src/config/mongo.js b/cinema-catalog/src/config/mongo.js new file mode 100644 index 0000000..18fce0f --- /dev/null +++ b/cinema-catalog/src/config/mongo.js @@ -0,0 +1,32 @@ +const MongoClient = require('mongodb') + +const getMongoURL = (options) => { + const url = options.servers + .reduce((prev, cur) => prev + cur + ',', 'mongodb://') + + return `${url.substr(0, url.length - 1)}/${options.db}` +} + +const connect = (options, mediator) => { + mediator.once('boot.ready', () => { + MongoClient.connect( + getMongoURL(options), { + db: options.dbParameters(), + server: options.serverParameters(), + replset: options.replsetParameters(options.repl) + }, (err, db) => { + if (err) { + mediator.emit('db.error', err) + } + + db.admin().authenticate(options.user, options.pass, (err, result) => { + if (err) { + mediator.emit('db.error', err) + } + mediator.emit('db.ready', db) + }) + }) + }) +} + +module.exports = Object.assign({}, {connect}) diff --git a/cinema-catalog/src/config/mongo.spec.js b/cinema-catalog/src/config/mongo.spec.js new file mode 100644 index 0000000..6226394 --- /dev/null +++ b/cinema-catalog/src/config/mongo.spec.js @@ -0,0 +1,29 @@ +/* eslint-env mocha */ +const {EventEmitter} = require('events') +const test = require('assert') +const mongo = require('./mongo') +const {dbSettings} = require('./config') + +describe('Mongo Connection', () => { + it('should emit db Object with an EventEmitter', (done) => { + const mediator = new EventEmitter() + + mediator.on('db.ready', (db) => { + db.admin().listDatabases((err, dbs) => { + test.equal(null, err) + test.ok(dbs.databases.length > 0) + console.log(dbs.databases) + db.close() + done() + }) + }) + + mediator.on('db.error', (err) => { + console.log(err) + }) + + mongo.connect(dbSettings, mediator) + + mediator.emit('boot.ready') + }) +}) diff --git a/cinema-catalog/src/config/ssl/index.js b/cinema-catalog/src/config/ssl/index.js new file mode 100644 index 0000000..63e4cd3 --- /dev/null +++ b/cinema-catalog/src/config/ssl/index.js @@ -0,0 +1,6 @@ +const fs = require('fs') + +module.exports = { + key: fs.readFileSync(`${__dirname}/server.key`), + cert: fs.readFileSync(`${__dirname}/server.crt`) +} diff --git a/cinema-catalog/src/index.js b/cinema-catalog/src/index.js new file mode 100644 index 0000000..b19b034 --- /dev/null +++ b/cinema-catalog/src/index.js @@ -0,0 +1,45 @@ +'use strict' +const {EventEmitter} = require('events') +const server = require('./server/server') +const repository = require('./repository/repository') +const config = require('./config/') +const mediator = new EventEmitter() + +console.log('--- Cinemas Catalog Service ---') +console.log('Connecting to cinemas catalog repository...') + +process.on('uncaughtException', (err) => { + console.error('Unhandled Exception', err) +}) + +process.on('uncaughtRejection', (err, promise) => { + console.error('Unhandled Rejection', err) +}) + +mediator.on('db.ready', (db) => { + let rep + repository.connect({db, ObjectID: config.ObjectID}) + .then(repo => { + console.log('Connected. Starting Server') + rep = repo + return server.start({ + port: config.serverSettings.port, + ssl: config.serverSettings.ssl, + repo + }) + }) + .then(app => { + console.log(`Server started succesfully, running on port: ${config.serverSettings.port}.`) + app.on('close', () => { + rep.disconnect() + }) + }) +}) + +mediator.on('db.error', (err) => { + console.error(err) +}) + +config.db.connect(config.dbSettings, mediator) + +mediator.emit('boot.ready') diff --git a/cinema-catalog/src/mock/cinemas.json b/cinema-catalog/src/mock/cinemas.json new file mode 100644 index 0000000..810fd13 --- /dev/null +++ b/cinema-catalog/src/mock/cinemas.json @@ -0,0 +1,326 @@ +[{ + "_id": { + "$oid": "588ac3a02d029a6d15d0b5c4" + }, + "name": "Plaza Morelia", + "cinemaPremieres": [{ + "id": "1", + "title": "Assasins Creed", + "runtime": 115, + "plot": "Lorem ipsum dolor sit amet", + "poster": "link to poster..." + }, { + "id": "2", + "title": "Aliados", + "runtime": 124, + "plot": "Lorem ipsum dolor sit amet", + "poster": "link to poster..." + }, { + "id": "3", + "title": "xXx: Reactivado", + "runtime": 107, + "plot": "Lorem ipsum dolor sit amet", + "poster": "link to poster..." + }], + "cinemaRooms": [{ + "name": 1.0, + "capacity": 120.0, + "format": "IMAX", + "schedules": [{ + "time": "10:15", + "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], + "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0], + "movie_id": "1", + "price": 54.0 + }, { + "time": "4:35", + "seatsEmpty": [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0], + "seatsOccupied": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "movie_id": "1", + "price": 71.0 + }, { + "time": "6:55", + "seatsEmpty": [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], + "seatsOccupied": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "movie_id": "3", + "price": 79.0 + }] + }, { + "name": 2.0, + "capacity": 100.0, + "format": "Normal", + "schedules": [{ + "time": "10:15", + "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0], + "movie_id": "2", + "price": 71.0 + }] + }, { + "name": 3.0, + "capacity": 80.0, + "format": "4DX", + "schedules": [{ + "time": "10:15", + "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "seatsOccupied": [61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], + "movie_id": "3", + "price": 71.0 + }] + }], + "city_id": "588ababf2d029a6d15d0b5bf" +}, { + "_id": { + "$oid": "588ac3a02d029a6d15d0b5c5" + }, + "name": "Las Americas", + "cinemaPremieres": [{ + "id": "1", + "title": "Assasins Creed", + "runtime": 115, + "plot": "Lorem ipsum dolor sit amet", + "poster": "link to poster..." + }, { + "id": "3", + "title": "xXx: Reactivado", + "runtime": 107, + "plot": "Lorem ipsum dolor sit amet", + "poster": "link to poster..." + }], + "cinemaRooms": [{ + "name": 1.0, + "capacity": 80.0, + "format": "Normal", + "schedules": [{ + "time": "10:15", + "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0], + "seatsOccupied": [40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "movie_id": "1", + "price": 71.0 + }, { + "time": "12:15", + "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0], + "movie_id": "3", + "price": 71.0 + }] + }, { + "name": 2.0, + "capacity": 80.0, + "format": "3D", + "schedules": [{ + "time": "10:15", + "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0], + "seatsOccupied": [40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "movie_id": "1", + "price": 71.0 + }, { + "time": "3:25", + "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0], + "movie_id": "3", + "price": 71.0 + }] + }], + "city_id": "588ababf2d029a6d15d0b5bf" +}, { + "_id": { + "$oid": "588ac53c2d029a6d15d0b5c6" + }, + "name": "Estacion Central", + "cinemaRooms": [{ + "name": 1.0, + "capacity": 100.0, + "schedules": [{ + "time": "12:10", + "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], + "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0], + "movie_id": "1", + "price": 54.0 + }, { + "time": "5:35", + "seatsEmpty": [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0], + "seatsOccupied": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "movie_id": "2", + "price": 71.0 + }, { + "time": "9:55", + "seatsEmpty": [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], + "seatsOccupied": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "movie_id": "3", + "price": 79.0 + }] + }, { + "name": 2.0, + "capacity": 80.0, + "schedules": [{ + "time": "3:15", + "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0], + "movie_id": "4", + "price": 71.0 + }] + }, { + "name": 3.0, + "capacity": 80.0, + "schedules": [{ + "time": "5:25", + "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "seatsOccupied": [61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], + "movie_id": "5", + "price": 71.0 + }] + }], + "city_id": "588ababf2d029a6d15d0b5c3" +}, { + "_id": { + "$oid": "588ac53c2d029a6d15d0b5c7" + }, + "name": "San Agustin", + "cinemaRooms": [{ + "name": 1.0, + "capacity": 60.0, + "schedules": [{ + "time": "12:15", + "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0], + "seatsOccupied": [40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "movie_id": "1", + "price": 71.0 + }] + }], + "city_id": "588ababf2d029a6d15d0b5c3" +}, { + "_id": { + "$oid": "588ac65f2d029a6d15d0b5c8" + }, + "name": "Calima", + "cinemaRooms": [{ + "name": 1.0, + "capacity": 100.0, + "schedules": [{ + "time": "11:10", + "seatsEmpty": [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0], + "seatsOccupied": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "movie_id": "3", + "price": 54.0 + }, { + "time": "5:35", + "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], + "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0], + "movie_id": "1", + "price": 71.0 + }, { + "time": "7:55", + "seatsEmpty": [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], + "seatsOccupied": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "movie_id": "3", + "price": 79.0 + }] + }, { + "name": 2.0, + "capacity": 80.0, + "schedules": [{ + "time": "5:15", + "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0], + "movie_id": "1", + "price": 71.0 + }] + }, { + "name": 3.0, + "capacity": 80.0, + "schedules": [{ + "time": "12:15", + "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0], + "seatsOccupied": [40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "movie_id": "4", + "price": 71.0 + }] + }], + "city_id": "588ababf2d029a6d15d0b5c2" +}, { + "_id": { + "$oid": "588ac65f2d029a6d15d0b5c9" + }, + "name": "Hayuelos Colombia", + "cinemaRooms": [{ + "name": 1.0, + "capacity": 60.0, + "schedules": [{ + "time": "5:25", + "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "seatsOccupied": [61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], + "movie_id": "5", + "price": 71.0 + }] + }], + "city_id": "588ababf2d029a6d15d0b5c2" +}, { + "_id": { + "$oid": "588ac7332d029a6d15d0b5ca" + }, + "name": "City Plaza", + "cinemaRooms": [{ + "name": 1.0, + "capacity": 90.0, + "schedules": [{ + "time": "11:40", + "seatsEmpty": [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0], + "seatsOccupied": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "movie_id": "1", + "price": 90.0 + }, { + "time": "3:35", + "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], + "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0], + "movie_id": "1", + "price": 120.0 + }, { + "time": "6:55", + "seatsEmpty": [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], + "seatsOccupied": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "movie_id": "3", + "price": 79.0 + }] + }, { + "name": 2.0, + "capacity": 80.0, + "schedules": [{ + "time": "5:15", + "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0], + "movie_id": "2", + "price": 71.0 + }] + }], + "city_id": "588ababf2d029a6d15d0b5c1" +}, { + "_id": { + "$oid": "588ac7a12d029a6d15d0b5cb" + }, + "name": "Juriquilla Uptown", + "cinemaRooms": [{ + "name": 1.0, + "capacity": 90.0, + "schedules": [{ + "time": "11:40", + "seatsEmpty": [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0], + "seatsOccupied": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "movie_id": "1", + "price": 90.0 + }, { + "time": "3:35", + "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], + "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0], + "movie_id": "1", + "price": 120.0 + }, { + "time": "6:55", + "seatsEmpty": [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], + "seatsOccupied": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], + "movie_id": "3", + "price": 79.0 + }] + }], + "city_id": "588ababf2d029a6d15d0b5c0" +}] diff --git a/cinema-catalog/src/mock/cities.json b/cinema-catalog/src/mock/cities.json new file mode 100644 index 0000000..db1be0e --- /dev/null +++ b/cinema-catalog/src/mock/cities.json @@ -0,0 +1,36 @@ +[{ + "_id": { + "$oid": "588ababf2d029a6d15d0b5bf" + }, + "name": "Morelia", + "state_id": "588aba4d2d029a6d15d0b5ba", + "cinemas": ["588ac3a02d029a6d15d0b5c4", "588ac3a02d029a6d15d0b5c5"] +}, { + "_id": { + "$oid": "588ababf2d029a6d15d0b5c0" + }, + "name": "Queretaro", + "state_id": "588aba4d2d029a6d15d0b5bb", + "cinemas": ["588ac7a12d029a6d15d0b5cb"] +}, { + "_id": { + "$oid": "588ababf2d029a6d15d0b5c1" + }, + "name": "Medellin", + "state_id": "588aba4d2d029a6d15d0b5bd", + "cinemas": ["588ac7332d029a6d15d0b5ca"] +}, { + "_id": { + "$oid": "588ababf2d029a6d15d0b5c2" + }, + "name": "Bogota", + "state_id": "588aba4d2d029a6d15d0b5bc", + "cinemas": ["588ac65f2d029a6d15d0b5c8", "588ac65f2d029a6d15d0b5c9"] +}, { + "_id": { + "$oid": "588ababf2d029a6d15d0b5c3" + }, + "name": "Santiago de Chile", + "state_id": "588aba4d2d029a6d15d0b5be", + "cinemas": ["588ac53c2d029a6d15d0b5c6", "588ac53c2d029a6d15d0b5c7"] +}] diff --git a/cinema-catalog/src/mock/countries.json b/cinema-catalog/src/mock/countries.json new file mode 100644 index 0000000..0e2b5d1 --- /dev/null +++ b/cinema-catalog/src/mock/countries.json @@ -0,0 +1,19 @@ +[{ + "_id": { + "$oid": "588ab9d92d029a6d15d0b5b7" + }, + "name": "Mexico", + "states": ["588aba4d2d029a6d15d0b5ba", "588ab9d92d029a6d15d0b5b7"] +}, { + "_id": { + "$oid": "588ab9d92d029a6d15d0b5b8" + }, + "name": "Colombia", + "states": ["588ab9d92d029a6d15d0b5b8", "588ab9d92d029a6d15d0b5b8"] +}, { + "_id": { + "$oid": "588ab9d92d029a6d15d0b5b9" + }, + "name": "Chile", + "states": ["588ab9d92d029a6d15d0b5b9"] +}] diff --git a/cinema-catalog/src/mock/index.js b/cinema-catalog/src/mock/index.js new file mode 100644 index 0000000..e69de29 diff --git a/cinema-catalog/src/mock/states.json b/cinema-catalog/src/mock/states.json new file mode 100644 index 0000000..3a2104a --- /dev/null +++ b/cinema-catalog/src/mock/states.json @@ -0,0 +1,36 @@ +[{ + "_id": { + "$oid": "588aba4d2d029a6d15d0b5ba" + }, + "name": "Michoacán", + "country_id": "588ab9d92d029a6d15d0b5b7", + "cities": ["588ababf2d029a6d15d0b5bf"] +}, { + "_id": { + "$oid": "588aba4d2d029a6d15d0b5bb" + }, + "name": "Querétaro", + "country_id": "588ab9d92d029a6d15d0b5b7", + "cities": ["588ababf2d029a6d15d0b5c0"] +}, { + "_id": { + "$oid": "588aba4d2d029a6d15d0b5bc" + }, + "name": "Cundinamrca", + "country_id": "588ab9d92d029a6d15d0b5b8", + "cities": ["588ababf2d029a6d15d0b5c2"] +}, { + "_id": { + "$oid": "588aba4d2d029a6d15d0b5bd" + }, + "name": "Antioquia", + "country_id": "588ab9d92d029a6d15d0b5b8", + "cities": ["588ababf2d029a6d15d0b5c1"] +}, { + "_id": { + "$oid": "588aba4d2d029a6d15d0b5be" + }, + "name": "Region Metropolitana", + "country_id": "588ab9d92d029a6d15d0b5b9", + "cities": ["588ababf2d029a6d15d0b5c3"] +}] diff --git a/cinema-catalog/src/repository/repository.js b/cinema-catalog/src/repository/repository.js new file mode 100644 index 0000000..11dfd72 --- /dev/null +++ b/cinema-catalog/src/repository/repository.js @@ -0,0 +1,98 @@ +'use strict' + +const repository = (connection) => { + const {db, ObjectID} = connection + + const getCinemasByCity = (cityId) => { + return new Promise((resolve, reject) => { + const cinemas = [] + const query = {city_id: cityId} + const projection = {_id: 1, name: 1} + const cursor = db.collection('cinemas').find(query, projection) + const addCinema = (cinema) => { + cinemas.push(cinema) + } + const sendCinemas = (err) => { + if (err) { + reject(new Error('An error occured fetching cinemas, err: ' + err)) + } + resolve(cinemas) + } + cursor.forEach(addCinema, sendCinemas) + }) + } + + const getCinemaById = (cinemaId) => { + return new Promise((resolve, reject) => { + const query = {_id: new ObjectID(cinemaId)} + const projection = {_id: 1, name: 1, cinemaPremieres: 1} + const response = (err, cinema) => { + if (err) { + reject(new Error('An error occuered retrieving a cinema, err: ' + err)) + } + resolve(cinema) + } + db.collection('cinemas').findOne(query, projection, response) + }) + } + + const getCinemaScheduleByMovie = (options) => { + return new Promise((resolve, reject) => { + const match = { $match: { + 'city_id': options.cityId, + 'cinemaRooms.schedules.movie_id': options.movieId + }} + const project = { $project: { + 'name': 1, + 'cinemaRooms.schedules.time': 1, + 'cinemaRooms.name': 1, + 'cinemaRooms.format': 1 + }} + const unwind = [{ $unwind: '$cinemaRooms' }, { $unwind: '$cinemaRooms.schedules' }] + const group = [{ $group: { + _id: { + name: '$name', + room: '$cinemaRooms.name' + }, + schedules: { $addToSet: '$cinemaRooms.schedules.time' } + }}, { $group: { + _id: '$_id.name', + schedules: { + $addToSet: { + room: '$_id.room', + schedules: '$schedules' + } + } + }}] + const sendSchedules = (err, result) => { + if (err) { + reject('An error has occured fetching schedules by movie, err: ' + err) + } + resolve(result) + } + db.collection('cinemas').aggregate([match, project, ...unwind, ...group], sendSchedules) + }) + } + + const disconnect = () => { + db.close() + } + + return Object.create({ + getCinemasByCity, + getCinemaById, + getCinemaScheduleByMovie, + disconnect + }) +} + +const connect = (connection) => { + return new Promise((resolve, reject) => { + if (!connection) { + reject(new Error('connection db not supplied!')) + } + resolve(repository(connection)) + }) +} + +module.exports = Object.assign({}, {connect}) diff --git a/cinema-catalog/src/repository/repository.spec.js b/cinema-catalog/src/repository/repository.spec.js new file mode 100644 index 0000000..2ff7bb2 --- /dev/null +++ b/cinema-catalog/src/repository/repository.spec.js @@ -0,0 +1,10 @@ +/* eslint-env mocha */ +const should = require('should') +const repository = require('./repository') + +describe('Repository', () => { + it('should connect with a promise', (done) => { + repository.connect({}).should.be.a.Promise() + done() + }) +}) diff --git a/cinema-catalog/src/server/server.js b/cinema-catalog/src/server/server.js new file mode 100644 index 0000000..0fa11dc --- /dev/null +++ b/cinema-catalog/src/server/server.js @@ -0,0 +1,29 @@ +const express = require('express') +const morgan = require('morgan') +const helmet = require('helmet') +const api = require('../api/cinema-catalog') + +const start = (options) => { + return new Promise((resolve, reject) => { + if (!options.repo) { + reject(new Error('The server must be started with a connected repository')) + } + if (!options.port) { + reject(new Error('The server must be started with an available port')) + } + + const app = express() + app.use(morgan('dev')) + app.use(helmet()) + app.use((err, req, res, next) => { + reject(new Error('Something went wrong!, err:' + err)) + res.status(500).send('Something went wrong!') + }) + + api(app, options) + + const server = app.listen(options.port, () => resolve(server)) + }) +} + +module.exports = Object.assign({}, {start}) diff --git a/cinema-catalog/src/server/server.spec.js b/cinema-catalog/src/server/server.spec.js new file mode 100644 index 0000000..f552ac9 --- /dev/null +++ b/cinema-catalog/src/server/server.spec.js @@ -0,0 +1,16 @@ +/* eslint-env mocha */ +const server = require('./server') + +describe('Server', () => { + it('should require a port to start', () => { + return server.start({ + repo: {} + }).should.be.rejectedWith(/port/) + }) + + it('should require a repository to start', () => { + return server.start({ + port: {} + }).should.be.rejectedWith(/repository/) + }) +}) diff --git a/deploy.sh b/deploy.sh new file mode 100644 index 0000000..35dc38f --- /dev/null +++ b/deploy.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +export NAMESPACE=${NAMESPACE:-staging} + +# @param +function kubernetes { + cd deploy/kubernetes/ + + ./deploy.sh $1 +} + +$@ diff --git a/movies/.eslintrc.json b/movies/.eslintrc.json new file mode 100644 index 0000000..a755cdb --- /dev/null +++ b/movies/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": ["standard"] +} diff --git a/movies/Dockerfile b/movies/Dockerfile new file mode 100644 index 0000000..523816b --- /dev/null +++ b/movies/Dockerfile @@ -0,0 +1,25 @@ +FROM node:7.5.0-alpine + +RUN addgroup -S nupp && adduser -S -g nupp nupp + +ENV HOME=/home/nupp + +COPY package.json npm-shrinkwrap.json $HOME/app/ + +COPY src/ $HOME/app/src + +ADD https://github.com/Yelp/dumb-init/releases/download/v1.1.1/dumb-init_1.1.1_amd64 /usr/local/bin/dumb-init + +WORKDIR $HOME/app + +RUN chown -R nupp:nupp $HOME/* /usr/local/ && \ + chmod +x /usr/local/bin/dumb-init && \ + npm cache clean && \ + npm install --silent --progress=false --production && \ + chown -R nupp:nupp $HOME/* + +USER nupp + +EXPOSE 3000 + +CMD ["dumb-init", "npm", "start"] diff --git a/movies/integration-test/index.js b/movies/integration-test/index.js new file mode 100644 index 0000000..2818086 --- /dev/null +++ b/movies/integration-test/index.js @@ -0,0 +1,10 @@ +/* eslint-env mocha */ +const supertest = require('supertest') + +describe('movies-service', () => { + const api = supertest('http://192.168.99.100:3000') + it('returns a 200 for a known movies', (done) => { + api.get('/movies/premieres') + .expect(200, done) + }) +}) diff --git a/movies/integration-test/movie-service-api.jmeter.test.jmx b/movies/integration-test/movie-service-api.jmeter.test.jmx new file mode 100644 index 0000000..d8f1de3 --- /dev/null +++ b/movies/integration-test/movie-service-api.jmeter.test.jmx @@ -0,0 +1,118 @@ + + + + + + false + false + + + + + + + + + + + + continue + + false + 1000 + + 100 + 100 + 1485133702000 + 1485133702000 + false + + + + + + + + + localhost + 3000 + + + http + + + 6 + + + + + + + + + + + + + /movies + GET + true + false + true + false + false + + + + + + + + + + + + + + /movies/premiers + GET + true + false + true + false + false + + + + + + + + false + 1 + = + true + id + + + + + + + + + + /movies/${id} + GET + true + false + true + false + false + + + + + + + diff --git a/movies/npm-shrinkwrap.json b/movies/npm-shrinkwrap.json new file mode 100644 index 0000000..2581895 --- /dev/null +++ b/movies/npm-shrinkwrap.json @@ -0,0 +1,520 @@ +{ + "name": "movies-service", + "version": "1.0.0", + "dependencies": { + "accepts": { + "version": "1.3.3", + "from": "accepts@>=1.3.3 <1.4.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz" + }, + "array-flatten": { + "version": "1.1.1", + "from": "array-flatten@1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" + }, + "basic-auth": { + "version": "1.0.4", + "from": "basic-auth@>=1.0.3 <1.1.0", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz" + }, + "bson": { + "version": "0.4.23", + "from": "bson@>=0.4.23 <0.5.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-0.4.23.tgz" + }, + "buffer-shims": { + "version": "1.0.0", + "from": "buffer-shims@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" + }, + "camelize": { + "version": "1.0.0", + "from": "camelize@1.0.0", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz" + }, + "connect": { + "version": "3.5.0", + "from": "connect@3.5.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.5.0.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + } + }, + "content-disposition": { + "version": "0.5.1", + "from": "content-disposition@0.5.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz" + }, + "content-security-policy-builder": { + "version": "1.1.0", + "from": "content-security-policy-builder@1.1.0", + "resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-1.1.0.tgz" + }, + "content-type": { + "version": "1.0.2", + "from": "content-type@>=1.0.2 <1.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz" + }, + "cookie": { + "version": "0.3.1", + "from": "cookie@0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz" + }, + "cookie-signature": { + "version": "1.0.6", + "from": "cookie-signature@1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + }, + "core-util-is": { + "version": "1.0.2", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "dasherize": { + "version": "2.0.0", + "from": "dasherize@2.0.0", + "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz" + }, + "dashify": { + "version": "0.2.2", + "from": "dashify@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/dashify/-/dashify-0.2.2.tgz" + }, + "debug": { + "version": "2.6.0", + "from": "debug@>=2.1.1 <3.0.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz" + }, + "depd": { + "version": "1.1.0", + "from": "depd@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz" + }, + "destroy": { + "version": "1.0.4", + "from": "destroy@>=1.0.4 <1.1.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" + }, + "dns-prefetch-control": { + "version": "0.1.0", + "from": "dns-prefetch-control@0.1.0", + "resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz" + }, + "dont-sniff-mimetype": { + "version": "1.0.0", + "from": "dont-sniff-mimetype@1.0.0", + "resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.0.0.tgz" + }, + "ee-first": { + "version": "1.1.1", + "from": "ee-first@1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + }, + "encodeurl": { + "version": "1.0.1", + "from": "encodeurl@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz" + }, + "es6-promise": { + "version": "3.0.2", + "from": "es6-promise@3.0.2", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz" + }, + "escape-html": { + "version": "1.0.3", + "from": "escape-html@>=1.0.3 <1.1.0", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + }, + "etag": { + "version": "1.7.0", + "from": "etag@>=1.7.0 <1.8.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz" + }, + "express": { + "version": "4.14.0", + "from": "express@latest", + "resolved": "https://registry.npmjs.org/express/-/express-4.14.0.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + }, + "qs": { + "version": "6.2.0", + "from": "qs@6.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz" + } + } + }, + "finalhandler": { + "version": "0.5.0", + "from": "finalhandler@0.5.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.0.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@~2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + } + }, + "forwarded": { + "version": "0.1.0", + "from": "forwarded@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz" + }, + "frameguard": { + "version": "3.0.0", + "from": "frameguard@3.0.0", + "resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.0.0.tgz" + }, + "fresh": { + "version": "0.3.0", + "from": "fresh@0.3.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz" + }, + "handle-thing": { + "version": "1.2.5", + "from": "handle-thing@>=1.2.4 <2.0.0", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz" + }, + "helmet": { + "version": "3.4.0", + "from": "helmet@>=3.4.0 <4.0.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.4.0.tgz" + }, + "helmet-csp": { + "version": "2.3.0", + "from": "helmet-csp@2.3.0", + "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.3.0.tgz" + }, + "hide-powered-by": { + "version": "1.0.0", + "from": "hide-powered-by@1.0.0", + "resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.0.0.tgz" + }, + "hpack.js": { + "version": "2.1.6", + "from": "hpack.js@>=2.1.6 <3.0.0", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz" + }, + "hpkp": { + "version": "2.0.0", + "from": "hpkp@2.0.0", + "resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz" + }, + "hsts": { + "version": "2.0.0", + "from": "hsts@2.0.0", + "resolved": "https://registry.npmjs.org/hsts/-/hsts-2.0.0.tgz" + }, + "http-deceiver": { + "version": "1.2.7", + "from": "http-deceiver@>=1.2.4 <2.0.0", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" + }, + "http-errors": { + "version": "1.5.1", + "from": "http-errors@>=1.5.0 <1.6.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz" + }, + "http-status": { + "version": "0.2.5", + "from": "http-status@latest", + "resolved": "https://registry.npmjs.org/http-status/-/http-status-0.2.5.tgz" + }, + "ienoopen": { + "version": "1.0.0", + "from": "ienoopen@1.0.0", + "resolved": "https://registry.npmjs.org/ienoopen/-/ienoopen-1.0.0.tgz" + }, + "inherits": { + "version": "2.0.3", + "from": "inherits@>=2.0.3 <3.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + }, + "ipaddr.js": { + "version": "1.2.0", + "from": "ipaddr.js@1.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.2.0.tgz" + }, + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, + "lodash.reduce": { + "version": "4.6.0", + "from": "lodash.reduce@4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz" + }, + "media-typer": { + "version": "0.3.0", + "from": "media-typer@0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + }, + "merge-descriptors": { + "version": "1.0.1", + "from": "merge-descriptors@1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" + }, + "methods": { + "version": "1.1.2", + "from": "methods@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + }, + "mime": { + "version": "1.3.4", + "from": "mime@>=1.3.4 <2.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" + }, + "mime-db": { + "version": "1.26.0", + "from": "mime-db@>=1.26.0 <1.27.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.26.0.tgz" + }, + "mime-types": { + "version": "2.1.14", + "from": "mime-types@>=2.1.10 <3.0.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.14.tgz" + }, + "minimalistic-assert": { + "version": "1.0.0", + "from": "minimalistic-assert@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" + }, + "mongodb": { + "version": "2.1.18", + "from": "mongodb@2.1.18", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.1.18.tgz", + "dependencies": { + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "readable-stream": { + "version": "1.0.31", + "from": "readable-stream@1.0.31", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.31.tgz" + } + } + }, + "mongodb-core": { + "version": "1.3.18", + "from": "mongodb-core@1.3.18", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-1.3.18.tgz" + }, + "morgan": { + "version": "1.7.0", + "from": "morgan@latest", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.7.0.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@~2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + } + }, + "ms": { + "version": "0.7.2", + "from": "ms@0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz" + }, + "negotiator": { + "version": "0.6.1", + "from": "negotiator@0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz" + }, + "nocache": { + "version": "2.0.0", + "from": "nocache@2.0.0", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.0.0.tgz" + }, + "obuf": { + "version": "1.1.1", + "from": "obuf@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz" + }, + "on-finished": { + "version": "2.3.0", + "from": "on-finished@>=2.3.0 <2.4.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" + }, + "on-headers": { + "version": "1.0.1", + "from": "on-headers@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" + }, + "parseurl": { + "version": "1.3.1", + "from": "parseurl@>=1.3.1 <1.4.0", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz" + }, + "path-to-regexp": { + "version": "0.1.7", + "from": "path-to-regexp@0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" + }, + "platform": { + "version": "1.3.3", + "from": "platform@1.3.3", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.3.tgz" + }, + "process-nextick-args": { + "version": "1.0.7", + "from": "process-nextick-args@>=1.0.6 <1.1.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" + }, + "proxy-addr": { + "version": "1.1.3", + "from": "proxy-addr@>=1.1.2 <1.2.0", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.3.tgz" + }, + "range-parser": { + "version": "1.2.0", + "from": "range-parser@>=1.2.0 <1.3.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz" + }, + "readable-stream": { + "version": "2.2.2", + "from": "readable-stream@>=2.2.2 <3.0.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.2.tgz" + }, + "referrer-policy": { + "version": "1.1.0", + "from": "referrer-policy@1.1.0", + "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.1.0.tgz" + }, + "require_optional": { + "version": "1.0.0", + "from": "require_optional@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.0.tgz", + "dependencies": { + "resolve-from": { + "version": "2.0.0", + "from": "resolve-from@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz" + } + } + }, + "select-hose": { + "version": "2.0.0", + "from": "select-hose@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" + }, + "semver": { + "version": "5.3.0", + "from": "semver@>=5.1.0 <6.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz" + }, + "send": { + "version": "0.14.1", + "from": "send@0.14.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.14.1.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@~2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + } + }, + "serve-static": { + "version": "1.11.1", + "from": "serve-static@>=1.11.1 <1.12.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.11.1.tgz" + }, + "setprototypeof": { + "version": "1.0.2", + "from": "setprototypeof@1.0.2", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz" + }, + "spdy": { + "version": "3.4.4", + "from": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz" + }, + "spdy-transport": { + "version": "2.0.18", + "from": "spdy-transport@>=2.0.15 <3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.18.tgz" + }, + "statuses": { + "version": "1.3.1", + "from": "statuses@>=1.3.0 <1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "type-is": { + "version": "1.6.14", + "from": "type-is@>=1.6.13 <1.7.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.14.tgz" + }, + "unpipe": { + "version": "1.0.0", + "from": "unpipe@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + }, + "util-deprecate": { + "version": "1.0.2", + "from": "util-deprecate@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + }, + "utils-merge": { + "version": "1.0.0", + "from": "utils-merge@1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" + }, + "vary": { + "version": "1.1.0", + "from": "vary@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.0.tgz" + }, + "wbuf": { + "version": "1.7.2", + "from": "wbuf@>=1.4.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz" + }, + "x-xss-protection": { + "version": "1.0.0", + "from": "x-xss-protection@1.0.0", + "resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.0.0.tgz" + } + } +} diff --git a/movies/package.json b/movies/package.json new file mode 100644 index 0000000..02261c1 --- /dev/null +++ b/movies/package.json @@ -0,0 +1,44 @@ +{ + "name": "movies-service", + "version": "1.0.0", + "description": "A movie service, microservice example with nodejs", + "author": "Cristian Ramirez Rosas ", + "license": "ISC", + "main": "index.js", + "standard": { + "env": [ + "mocha" + ], + "ignore": [ + "mock" + ] + }, + "scripts": { + "test": "mocha -R spec src/**/*.spec.js", + "start": "node src/index.js", + "lint": "standard --verbose | snazzy", + "node-debug": "DEBUG=express* node src/index.js", + "chrome-debug": "node --debug-brk --inspect src/index.js" + }, + "keywords": [ + "express", + "mongodb", + "docker", + "microservice" + ], + "devDependencies": { + "eslint": "^3.13.1", + "mocha": "^3.2.0", + "should": "^11.1.2", + "snazzy": "^6.0.0", + "standard": "^8.6.0", + "supertest": "^2.0.1" + }, + "dependencies": { + "express": "^4.14.0", + "helmet": "^3.4.0", + "http-status": "^0.2.5", + "mongodb": "^2.1.18", + "morgan": "^1.7.0" + } +} diff --git a/movies/src/api/movies.js b/movies/src/api/movies.js new file mode 100644 index 0000000..b657e58 --- /dev/null +++ b/movies/src/api/movies.js @@ -0,0 +1,24 @@ +'use strict' +const status = require('http-status') + +module.exports = (app, options) => { + const {repo} = options + + app.get('/movies', (req, res, next) => { + repo.getAllMovies().then(movies => { + res.status(status.OK).json(movies) + }).catch(next) + }) + + app.get('/movies/premieres', (req, res, next) => { + repo.getMoviePremiers().then(movies => { + res.status(status.OK).json(movies) + }).catch(next) + }) + + app.get('/movies/:id', (req, res, next) => { + repo.getMovieById(req.params.id).then(movie => { + res.status(status.OK).json(movie) + }).catch(next) + }) +} diff --git a/movies/src/api/movies.spec.js b/movies/src/api/movies.spec.js new file mode 100644 index 0000000..d1c0c24 --- /dev/null +++ b/movies/src/api/movies.spec.js @@ -0,0 +1,103 @@ +/* eslint-env mocha */ +const request = require('supertest') +const server = require('../server/server') + +describe('Movies API', () => { + let app = null + let testMovies = [{ + 'id': '3', + 'title': 'xXx: Reactivado', + 'format': 'IMAX', + 'releaseYear': 2017, + 'releaseMonth': 1, + 'releaseDay': 20 + }, { + 'id': '4', + 'title': 'Resident Evil: Capitulo Final', + 'format': 'IMAX', + 'releaseYear': 2017, + 'releaseMonth': 1, + 'releaseDay': 27 + }, { + 'id': '1', + 'title': 'Assasins Creed', + 'format': 'IMAX', + 'releaseYear': 2017, + 'releaseMonth': 1, + 'releaseDay': 6 + }] + + let testRepo = { + getAllMovies () { + return Promise.resolve(testMovies) + }, + getMoviePremiers () { + return Promise.resolve(testMovies.filter(movie => movie.releaseYear === 2017)) + }, + getMovieById (id) { + return Promise.resolve(testMovies.find(movie => movie.id === id)) + } + } + + beforeEach(() => { + return server.start({ + port: 3000, + repo: testRepo + }).then(serv => { + app = serv + }) + }) + + afterEach(() => { + app.close() + app = null + }) + + it('can return all movies', (done) => { + request(app) + .get('/movies') + .expect((res) => { + res.body.should.containEql({ + 'id': '1', + 'title': 'Assasins Creed', + 'format': 'IMAX', + 'releaseYear': 2017, + 'releaseMonth': 1, + 'releaseDay': 6 + }) + }) + .expect(200, done) + }) + + it('can get movie premiers', (done) => { + request(app) + .get('/movies/premieres') + .expect((res) => { + res.body.should.containEql({ + 'id': '1', + 'title': 'Assasins Creed', + 'format': 'IMAX', + 'releaseYear': 2017, + 'releaseMonth': 1, + 'releaseDay': 6 + }) + }) + .expect(200, done) + }) + + it('returns 200 for an known movie', (done) => { + request(app) + .get('/movies/1') + .expect((res) => { + res.body.should.containEql({ + 'id': '1', + 'title': 'Assasins Creed', + 'format': 'IMAX', + 'releaseYear': 2017, + 'releaseMonth': 1, + 'releaseDay': 6 + }) + }) + .expect(200, done) + }) +}) diff --git a/movies/src/config/config.js b/movies/src/config/config.js new file mode 100644 index 0000000..fbface6 --- /dev/null +++ b/movies/src/config/config.js @@ -0,0 +1,45 @@ +const dbSettings = { + db: process.env.DB || 'movies', + user: process.env.DB_USER || 'cristian', + pass: process.env.DB_PASS || 'cristianPassword2017', + repl: process.env.DB_REPLS || 'rs1', + servers: (process.env.DB_SERVERS) ? process.env.DB_SERVERS.substr(1, process.env.DB_SERVERS.length - 2).split(' ') : [ + '192.168.99.100:27017', + '192.168.99.101:27017', + '192.168.99.102:27017' + ], + dbParameters: () => ({ + w: 'majority', + wtimeout: 10000, + j: true, + readPreference: 'ReadPreference.SECONDARY_PREFERRED', + native_parser: false + }), + serverParameters: () => ({ + autoReconnect: true, + poolSize: 10, + socketoptions: { + keepAlive: 300, + connectTimeoutMS: 30000, + socketTimeoutMS: 30000 + } + }), + replsetParameters: (replset = 'rs1') => ({ + replicaSet: replset, + ha: true, + haInterval: 10000, + poolSize: 10, + socketoptions: { + keepAlive: 300, + connectTimeoutMS: 30000, + socketTimeoutMS: 30000 + } + }) +} + +const serverSettings = { + port: process.env.PORT || 3000, + ssl: require('./ssl') +} + +module.exports = Object.assign({}, { dbSettings, serverSettings }) diff --git a/movies/src/config/index.js b/movies/src/config/index.js new file mode 100644 index 0000000..c7e7993 --- /dev/null +++ b/movies/src/config/index.js @@ -0,0 +1,4 @@ +const {dbSettings, serverSettings} = require('./config') +const db = require('./mongo') + +module.exports = Object.assign({}, {dbSettings, serverSettings, db}) diff --git a/movies/src/config/mongo.js b/movies/src/config/mongo.js new file mode 100644 index 0000000..18fce0f --- /dev/null +++ b/movies/src/config/mongo.js @@ -0,0 +1,32 @@ +const MongoClient = require('mongodb') + +const getMongoURL = (options) => { + const url = options.servers + .reduce((prev, cur) => prev + cur + ',', 'mongodb://') + + return `${url.substr(0, url.length - 1)}/${options.db}` +} + +const connect = (options, mediator) => { + mediator.once('boot.ready', () => { + MongoClient.connect( + getMongoURL(options), { + db: options.dbParameters(), + server: options.serverParameters(), + replset: options.replsetParameters(options.repl) + }, (err, db) => { + if (err) { + mediator.emit('db.error', err) + } + + db.admin().authenticate(options.user, options.pass, (err, result) => { + if (err) { + mediator.emit('db.error', err) + } + mediator.emit('db.ready', db) + }) + }) + }) +} + +module.exports = Object.assign({}, {connect}) diff --git a/movies/src/config/mongo.spec.js b/movies/src/config/mongo.spec.js new file mode 100644 index 0000000..6226394 --- /dev/null +++ b/movies/src/config/mongo.spec.js @@ -0,0 +1,29 @@ +/* eslint-env mocha */ +const {EventEmitter} = require('events') +const test = require('assert') +const mongo = require('./mongo') +const {dbSettings} = require('./config') + +describe('Mongo Connection', () => { + it('should emit db Object with an EventEmitter', (done) => { + const mediator = new EventEmitter() + + mediator.on('db.ready', (db) => { + db.admin().listDatabases((err, dbs) => { + test.equal(null, err) + test.ok(dbs.databases.length > 0) + console.log(dbs.databases) + db.close() + done() + }) + }) + + mediator.on('db.error', (err) => { + console.log(err) + }) + + mongo.connect(dbSettings, mediator) + + mediator.emit('boot.ready') + }) +}) diff --git a/movies/src/config/ssl/index.js b/movies/src/config/ssl/index.js new file mode 100644 index 0000000..63e4cd3 --- /dev/null +++ b/movies/src/config/ssl/index.js @@ -0,0 +1,6 @@ +const fs = require('fs') + +module.exports = { + key: fs.readFileSync(`${__dirname}/server.key`), + cert: fs.readFileSync(`${__dirname}/server.crt`) +} diff --git a/movies/src/index.js b/movies/src/index.js new file mode 100644 index 0000000..86a48c6 --- /dev/null +++ b/movies/src/index.js @@ -0,0 +1,45 @@ +'use strict' +const {EventEmitter} = require('events') +const server = require('./server/server') +const repository = require('./repository/repository') +const config = require('./config/') +const mediator = new EventEmitter() + +console.log('--- Movies Service ---') +console.log('Connecting to movies repository...') + +process.on('uncaughtException', (err) => { + console.error('Unhandled Exception', err) +}) + +process.on('uncaughtRejection', (err, promise) => { + console.error('Unhandled Rejection', err) +}) + +mediator.on('db.ready', (db) => { + let rep + repository.connect(db) + .then(repo => { + console.log('Connected. Starting Server') + rep = repo + return server.start({ + port: config.serverSettings.port, + ssl: config.serverSettings.ssl, + repo + }) + }) + .then(app => { + console.log(`Server started succesfully, running on port: ${config.serverSettings.port}.`) + app.on('close', () => { + rep.disconnect() + }) + }) +}) + +mediator.on('db.error', (err) => { + console.error(err) +}) + +config.db.connect(config.dbSettings, mediator) + +mediator.emit('boot.ready') diff --git a/movies/src/mock/movies.js b/movies/src/mock/movies.js new file mode 100644 index 0000000..b59106d --- /dev/null +++ b/movies/src/mock/movies.js @@ -0,0 +1,46 @@ +module.exports = [{ + id: '1', + title: 'Assasins Creed', + runtime: 115, + format: 'IMAX', + plot: 'Lorem ipsum dolor sit amet', + releaseYear: 2017, + releaseMonth: 1, + releaseDay: 6 +}, { + id: '2', + title: 'Aliados', + runtime: 124, + format: 'IMAX', + plot: 'Lorem ipsum dolor sit amet', + releaseYear: 2017, + releaseMonth: 1, + releaseDay: 13 +}, { + id: '3', + title: 'xXx: Reactivado', + runtime: 107, + format: 'IMAX', + plot: 'Lorem ipsum dolor sit amet', + releaseYear: 2017, + releaseMonth: 1, + releaseDay: 20 +}, { + id: '4', + title: 'Resident Evil: Capitulo Final', + runtime: 107, + format: 'IMAX', + plot: 'Lorem ipsum dolor sit amet', + releaseYear: 2017, + releaseMonth: 1, + releaseDay: 27 +}, { + id: '5', + title: 'Moana: Un Mar de Aventuras', + runtime: 114, + format: 'IMAX', + plot: 'Lorem ipsum dolor sit amet', + releaseYear: 2016, + releaseMonth: 12, + releaseDay: 2 +}] diff --git a/movies/src/repository/repository.js b/movies/src/repository/repository.js new file mode 100644 index 0000000..3c5f559 --- /dev/null +++ b/movies/src/repository/repository.js @@ -0,0 +1,88 @@ +'use strict' + +const repository = (db) => { + const collection = db.collection('movies') + + const getAllMovies = () => { + return new Promise((resolve, reject) => { + const movies = [] + const cursor = collection.find({}, {title: 1, id: 1}) + const addMovie = (movie) => { + movies.push(movie) + } + const sendMovies = (err) => { + if (err) { + reject(new Error('An error occured fetching all movies, err:' + err)) + } + resolve(movies.slice()) + } + cursor.forEach(addMovie, sendMovies) + }) + } + + const getMoviePremiers = () => { + return new Promise((resolve, reject) => { + const movies = [] + const currentDay = new Date() + const query = { + releaseYear: { + $gt: currentDay.getFullYear() - 1, + $lte: currentDay.getFullYear() + }, + releaseMonth: { + $gte: currentDay.getMonth() + 1, + $lte: currentDay.getMonth() + 2 + }, + releaseDay: { + $lte: currentDay.getDate() + } + } + const cursor = collection.find(query) + const addMovie = (movie) => { + movies.push(movie) + } + const sendMovies = (err) => { + if (err) { + reject(new Error('An error occured fetching all movies, err:' + err)) + } + resolve(movies) + } + cursor.forEach(addMovie, sendMovies) + }) + } + + const getMovieById = (id) => { + return new Promise((resolve, reject) => { + const projection = { _id: 0, id: 1, title: 1, format: 1 } + const sendMovie = (err, movie) => { + if (err) { + reject(new Error(`An error occured fetching a movie with id: ${id}, err: ${err}`)) + } + resolve(movie) + } + collection.findOne({id: id}, projection, sendMovie) + }) + } + + const disconnect = () => { + db.close() + } + + return Object.create({ + getAllMovies, + getMoviePremiers, + getMovieById, + disconnect + }) +} + +const connect = (connection) => { + return new Promise((resolve, reject) => { + if (!connection) { + reject(new Error('connection db not supplied!')) + } + resolve(repository(connection)) + }) +} + +module.exports = Object.assign({}, {connect}) diff --git a/movies/src/repository/repository.spec.js b/movies/src/repository/repository.spec.js new file mode 100644 index 0000000..2ff7bb2 --- /dev/null +++ b/movies/src/repository/repository.spec.js @@ -0,0 +1,10 @@ +/* eslint-env mocha */ +const should = require('should') +const repository = require('./repository') + +describe('Repository', () => { + it('should connect with a promise', (done) => { + repository.connect({}).should.be.a.Promise() + done() + }) +}) diff --git a/movies/src/server/server.js b/movies/src/server/server.js new file mode 100644 index 0000000..3b83e0e --- /dev/null +++ b/movies/src/server/server.js @@ -0,0 +1,29 @@ +const express = require('express') +const morgan = require('morgan') +const helmet = require('helmet') +const api = require('../api/movies') + +const start = (options) => { + return new Promise((resolve, reject) => { + if (!options.repo) { + reject(new Error('The server must be started with a connected repository')) + } + if (!options.port) { + reject(new Error('The server must be started with an available port')) + } + + const app = express() + app.use(morgan('dev')) + app.use(helmet()) + app.use((err, req, res, next) => { + reject(new Error('Something went wrong!, err:' + err)) + res.status(500).send('Something went wrong!') + }) + + api(app, options) + + const server = app.listen(options.port, () => resolve(server)) + }) +} + +module.exports = Object.assign({}, {start}) diff --git a/movies/src/server/server.spec.js b/movies/src/server/server.spec.js new file mode 100644 index 0000000..f552ac9 --- /dev/null +++ b/movies/src/server/server.spec.js @@ -0,0 +1,16 @@ +/* eslint-env mocha */ +const server = require('./server') + +describe('Server', () => { + it('should require a port to start', () => { + return server.start({ + repo: {} + }).should.be.rejectedWith(/port/) + }) + + it('should require a repository to start', () => { + return server.start({ + port: {} + }).should.be.rejectedWith(/repository/) + }) +}) diff --git a/notification/.eslintrc.json b/notification/.eslintrc.json new file mode 100644 index 0000000..a755cdb --- /dev/null +++ b/notification/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": ["standard"] +} diff --git a/notification/Dockerfile b/notification/Dockerfile new file mode 100644 index 0000000..523816b --- /dev/null +++ b/notification/Dockerfile @@ -0,0 +1,25 @@ +FROM node:7.5.0-alpine + +RUN addgroup -S nupp && adduser -S -g nupp nupp + +ENV HOME=/home/nupp + +COPY package.json npm-shrinkwrap.json $HOME/app/ + +COPY src/ $HOME/app/src + +ADD https://github.com/Yelp/dumb-init/releases/download/v1.1.1/dumb-init_1.1.1_amd64 /usr/local/bin/dumb-init + +WORKDIR $HOME/app + +RUN chown -R nupp:nupp $HOME/* /usr/local/ && \ + chmod +x /usr/local/bin/dumb-init && \ + npm cache clean && \ + npm install --silent --progress=false --production && \ + chown -R nupp:nupp $HOME/* + +USER nupp + +EXPOSE 3000 + +CMD ["dumb-init", "npm", "start"] diff --git a/notification/env b/notification/env new file mode 100644 index 0000000..ac29194 --- /dev/null +++ b/notification/env @@ -0,0 +1,6 @@ +DB=booking +DB_USER=cristian +DB_PASS=cristianPassword2017 +DB_REPLS=rs1 +DB_SERVERS='192.168.99.100:27017 192.168.99.101:27017 192.168.99.102:27017' +PORT=3000 diff --git a/notification/integration-test/index.js b/notification/integration-test/index.js new file mode 100644 index 0000000..5d6110a --- /dev/null +++ b/notification/integration-test/index.js @@ -0,0 +1,36 @@ +/* eslint-env mocha */ +const supertest = require('supertest') + +describe('Notification Service', () => { + const api = supertest('http://192.168.99.100:3004') + const payload = { + city: 'Morelia', + userType: 'loyal', + totalAmount: 71, + cinema: { + name: 'Plaza Morelia', + room: '1', + seats: '53, 54' + }, + movie: { + title: 'Assasins Creed', + format: 'IMAX', + schedule: new Date() + }, + orderId: '1aa90cx', + description: 'some description', + user: { + name: 'Cristian Ramirez', + email: 'cristiano.rosetti@gmail.com' + } + } + + it('can send a notification via email', (done) => { + api.post('/notification/sendEmail') + .send({payload}) + .expect((res) => { + console.log(res.body) + }) + .expect(200, done) + }) +}) diff --git a/notification/npm-shrinkwrap.json b/notification/npm-shrinkwrap.json new file mode 100644 index 0000000..d164fa1 --- /dev/null +++ b/notification/npm-shrinkwrap.json @@ -0,0 +1,726 @@ +{ + "name": "movies-service", + "version": "1.0.0", + "dependencies": { + "accepts": { + "version": "1.3.3", + "from": "accepts@>=1.3.3 <1.4.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz" + }, + "array-flatten": { + "version": "1.1.1", + "from": "array-flatten@1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" + }, + "awilix": { + "version": "2.2.2", + "from": "awilix@latest", + "resolved": "https://registry.npmjs.org/awilix/-/awilix-2.2.2.tgz" + }, + "balanced-match": { + "version": "0.4.2", + "from": "balanced-match@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz" + }, + "basic-auth": { + "version": "1.0.4", + "from": "basic-auth@>=1.0.3 <1.1.0", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz" + }, + "body-parser": { + "version": "1.16.0", + "from": "body-parser@latest", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.16.0.tgz", + "dependencies": { + "qs": { + "version": "6.2.1", + "from": "qs@6.2.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.1.tgz" + } + } + }, + "brace-expansion": { + "version": "1.1.6", + "from": "brace-expansion@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz" + }, + "bson": { + "version": "0.4.23", + "from": "bson@>=0.4.23 <0.5.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-0.4.23.tgz" + }, + "buffer-shims": { + "version": "1.0.0", + "from": "buffer-shims@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" + }, + "bytes": { + "version": "2.4.0", + "from": "bytes@2.4.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz" + }, + "camel-case": { + "version": "3.0.0", + "from": "camel-case@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz" + }, + "camelize": { + "version": "1.0.0", + "from": "camelize@1.0.0", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz" + }, + "concat-map": { + "version": "0.0.1", + "from": "concat-map@0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + }, + "connect": { + "version": "3.5.0", + "from": "connect@3.5.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.5.0.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + } + }, + "content-disposition": { + "version": "0.5.1", + "from": "content-disposition@0.5.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz" + }, + "content-security-policy-builder": { + "version": "1.1.0", + "from": "content-security-policy-builder@1.1.0", + "resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-1.1.0.tgz" + }, + "content-type": { + "version": "1.0.2", + "from": "content-type@>=1.0.2 <1.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz" + }, + "cookie": { + "version": "0.3.1", + "from": "cookie@0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz" + }, + "cookie-signature": { + "version": "1.0.6", + "from": "cookie-signature@1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + }, + "core-util-is": { + "version": "1.0.2", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "cors": { + "version": "2.8.1", + "from": "cors@latest", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.1.tgz" + }, + "dasherize": { + "version": "2.0.0", + "from": "dasherize@2.0.0", + "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz" + }, + "dashify": { + "version": "0.2.2", + "from": "dashify@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/dashify/-/dashify-0.2.2.tgz" + }, + "debug": { + "version": "2.6.0", + "from": "debug@>=2.1.1 <3.0.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz" + }, + "depd": { + "version": "1.1.0", + "from": "depd@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz" + }, + "destroy": { + "version": "1.0.4", + "from": "destroy@>=1.0.4 <1.1.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" + }, + "dns-prefetch-control": { + "version": "0.1.0", + "from": "dns-prefetch-control@0.1.0", + "resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz" + }, + "dont-sniff-mimetype": { + "version": "1.0.0", + "from": "dont-sniff-mimetype@1.0.0", + "resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.0.0.tgz" + }, + "ee-first": { + "version": "1.1.1", + "from": "ee-first@1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + }, + "encodeurl": { + "version": "1.0.1", + "from": "encodeurl@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz" + }, + "es6-promise": { + "version": "3.0.2", + "from": "es6-promise@3.0.2", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz" + }, + "escape-html": { + "version": "1.0.3", + "from": "escape-html@>=1.0.3 <1.1.0", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + }, + "etag": { + "version": "1.7.0", + "from": "etag@>=1.7.0 <1.8.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz" + }, + "express": { + "version": "4.14.0", + "from": "express@latest", + "resolved": "https://registry.npmjs.org/express/-/express-4.14.0.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + }, + "qs": { + "version": "6.2.0", + "from": "qs@6.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz" + } + } + }, + "finalhandler": { + "version": "0.5.0", + "from": "finalhandler@0.5.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.0.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@~2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + } + }, + "forwarded": { + "version": "0.1.0", + "from": "forwarded@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz" + }, + "frameguard": { + "version": "3.0.0", + "from": "frameguard@3.0.0", + "resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.0.0.tgz" + }, + "fresh": { + "version": "0.3.0", + "from": "fresh@0.3.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz" + }, + "fs.realpath": { + "version": "1.0.0", + "from": "fs.realpath@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + }, + "glob": { + "version": "7.1.1", + "from": "glob@>=7.0.3 <8.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz" + }, + "handle-thing": { + "version": "1.2.5", + "from": "handle-thing@>=1.2.4 <2.0.0", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz" + }, + "helmet": { + "version": "3.4.0", + "from": "helmet@>=3.4.0 <4.0.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.4.0.tgz" + }, + "helmet-csp": { + "version": "2.3.0", + "from": "helmet-csp@2.3.0", + "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.3.0.tgz" + }, + "hide-powered-by": { + "version": "1.0.0", + "from": "hide-powered-by@1.0.0", + "resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.0.0.tgz" + }, + "hpack.js": { + "version": "2.1.6", + "from": "hpack.js@>=2.1.6 <3.0.0", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz" + }, + "hpkp": { + "version": "2.0.0", + "from": "hpkp@2.0.0", + "resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz" + }, + "hsts": { + "version": "2.0.0", + "from": "hsts@2.0.0", + "resolved": "https://registry.npmjs.org/hsts/-/hsts-2.0.0.tgz" + }, + "http-deceiver": { + "version": "1.2.7", + "from": "http-deceiver@>=1.2.4 <2.0.0", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" + }, + "http-errors": { + "version": "1.5.1", + "from": "http-errors@>=1.5.0 <1.6.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz" + }, + "http-status": { + "version": "0.2.5", + "from": "http-status@latest", + "resolved": "https://registry.npmjs.org/http-status/-/http-status-0.2.5.tgz" + }, + "httpntlm": { + "version": "1.6.1", + "from": "httpntlm@1.6.1", + "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz" + }, + "httpreq": { + "version": "0.4.22", + "from": "httpreq@>=0.4.22", + "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.22.tgz" + }, + "iconv-lite": { + "version": "0.4.15", + "from": "iconv-lite@0.4.15", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz" + }, + "ienoopen": { + "version": "1.0.0", + "from": "ienoopen@1.0.0", + "resolved": "https://registry.npmjs.org/ienoopen/-/ienoopen-1.0.0.tgz" + }, + "inflight": { + "version": "1.0.6", + "from": "inflight@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + }, + "inherits": { + "version": "2.0.3", + "from": "inherits@>=2.0.3 <3.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + }, + "ipaddr.js": { + "version": "1.2.0", + "from": "ipaddr.js@1.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.2.0.tgz" + }, + "is-class": { + "version": "0.0.4", + "from": "is-class@0.0.4", + "resolved": "https://registry.npmjs.org/is-class/-/is-class-0.0.4.tgz" + }, + "is-plain-object": { + "version": "2.0.1", + "from": "is-plain-object@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.1.tgz" + }, + "is-string": { + "version": "1.0.4", + "from": "is-string@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.4.tgz" + }, + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, + "isemail": { + "version": "2.2.1", + "from": "isemail@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-2.2.1.tgz" + }, + "isobject": { + "version": "1.0.2", + "from": "isobject@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-1.0.2.tgz" + }, + "items": { + "version": "2.1.1", + "from": "items@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/items/-/items-2.1.1.tgz" + }, + "joi": { + "version": "10.2.0", + "from": "joi@latest", + "resolved": "https://registry.npmjs.org/joi/-/joi-10.2.0.tgz", + "dependencies": { + "hoek": { + "version": "4.1.0", + "from": "hoek@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.1.0.tgz" + } + } + }, + "lodash.reduce": { + "version": "4.6.0", + "from": "lodash.reduce@4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz" + }, + "lower-case": { + "version": "1.1.3", + "from": "lower-case@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.3.tgz" + }, + "media-typer": { + "version": "0.3.0", + "from": "media-typer@0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + }, + "merge-descriptors": { + "version": "1.0.1", + "from": "merge-descriptors@1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" + }, + "methods": { + "version": "1.1.2", + "from": "methods@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + }, + "mime": { + "version": "1.3.4", + "from": "mime@>=1.3.4 <2.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" + }, + "mime-db": { + "version": "1.26.0", + "from": "mime-db@>=1.26.0 <1.27.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.26.0.tgz" + }, + "mime-types": { + "version": "2.1.14", + "from": "mime-types@>=2.1.10 <3.0.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.14.tgz" + }, + "minimalistic-assert": { + "version": "1.0.0", + "from": "minimalistic-assert@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" + }, + "minimatch": { + "version": "3.0.3", + "from": "minimatch@>=3.0.2 <4.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz" + }, + "mongodb": { + "version": "2.1.18", + "from": "mongodb@2.1.18", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.1.18.tgz", + "dependencies": { + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "readable-stream": { + "version": "1.0.31", + "from": "readable-stream@1.0.31", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.31.tgz" + } + } + }, + "mongodb-core": { + "version": "1.3.18", + "from": "mongodb-core@1.3.18", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-1.3.18.tgz" + }, + "morgan": { + "version": "1.7.0", + "from": "morgan@latest", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.7.0.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@~2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + } + }, + "ms": { + "version": "0.7.2", + "from": "ms@0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz" + }, + "negotiator": { + "version": "0.6.1", + "from": "negotiator@0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz" + }, + "no-case": { + "version": "2.3.1", + "from": "no-case@>=2.2.0 <3.0.0", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.1.tgz" + }, + "nocache": { + "version": "2.0.0", + "from": "nocache@2.0.0", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.0.0.tgz" + }, + "nodemailer": { + "version": "3.0.2", + "from": "nodemailer@latest", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-3.0.2.tgz" + }, + "nodemailer-fetch": { + "version": "1.6.0", + "from": "nodemailer-fetch@1.6.0", + "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz" + }, + "nodemailer-shared": { + "version": "1.1.0", + "from": "nodemailer-shared@1.1.0", + "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz" + }, + "nodemailer-smtp-transport": { + "version": "2.7.2", + "from": "nodemailer-smtp-transport@latest", + "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz" + }, + "nodemailer-wellknown": { + "version": "0.1.10", + "from": "nodemailer-wellknown@0.1.10", + "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz" + }, + "obuf": { + "version": "1.1.1", + "from": "obuf@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz" + }, + "on-finished": { + "version": "2.3.0", + "from": "on-finished@>=2.3.0 <2.4.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" + }, + "on-headers": { + "version": "1.0.1", + "from": "on-headers@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" + }, + "once": { + "version": "1.4.0", + "from": "once@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + }, + "parseurl": { + "version": "1.3.1", + "from": "parseurl@>=1.3.1 <1.4.0", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz" + }, + "path-is-absolute": { + "version": "1.0.1", + "from": "path-is-absolute@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + }, + "path-to-regexp": { + "version": "0.1.7", + "from": "path-to-regexp@0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" + }, + "platform": { + "version": "1.3.3", + "from": "platform@1.3.3", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.3.tgz" + }, + "process-nextick-args": { + "version": "1.0.7", + "from": "process-nextick-args@>=1.0.6 <1.1.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" + }, + "proxy-addr": { + "version": "1.1.3", + "from": "proxy-addr@>=1.1.2 <1.2.0", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.3.tgz" + }, + "range-parser": { + "version": "1.2.0", + "from": "range-parser@>=1.2.0 <1.3.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz" + }, + "raw-body": { + "version": "2.2.0", + "from": "raw-body@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz" + }, + "readable-stream": { + "version": "2.2.2", + "from": "readable-stream@>=2.2.2 <3.0.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.2.tgz" + }, + "referrer-policy": { + "version": "1.1.0", + "from": "referrer-policy@1.1.0", + "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.1.0.tgz" + }, + "require_optional": { + "version": "1.0.0", + "from": "require_optional@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.0.tgz", + "dependencies": { + "resolve-from": { + "version": "2.0.0", + "from": "resolve-from@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz" + } + } + }, + "select-hose": { + "version": "2.0.0", + "from": "select-hose@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" + }, + "semver": { + "version": "5.3.0", + "from": "semver@>=5.1.0 <6.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz" + }, + "send": { + "version": "0.14.1", + "from": "send@0.14.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.14.1.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@~2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + } + }, + "serve-static": { + "version": "1.11.1", + "from": "serve-static@>=1.11.1 <1.12.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.11.1.tgz" + }, + "setprototypeof": { + "version": "1.0.2", + "from": "setprototypeof@1.0.2", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz" + }, + "smtp-connection": { + "version": "2.12.0", + "from": "smtp-connection@2.12.0", + "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz" + }, + "spdy": { + "version": "3.4.4", + "from": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz" + }, + "spdy-transport": { + "version": "2.0.18", + "from": "spdy-transport@>=2.0.15 <3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.18.tgz" + }, + "statuses": { + "version": "1.3.1", + "from": "statuses@>=1.3.0 <1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "topo": { + "version": "2.0.2", + "from": "topo@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", + "dependencies": { + "hoek": { + "version": "4.1.0", + "from": "hoek@4.x.x", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.1.0.tgz" + } + } + }, + "type-is": { + "version": "1.6.14", + "from": "type-is@>=1.6.13 <1.7.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.14.tgz" + }, + "underscore": { + "version": "1.7.0", + "from": "underscore@>=1.7.0 <1.8.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz" + }, + "unpipe": { + "version": "1.0.0", + "from": "unpipe@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + }, + "upper-case": { + "version": "1.1.3", + "from": "upper-case@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz" + }, + "util-deprecate": { + "version": "1.0.2", + "from": "util-deprecate@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + }, + "utils-merge": { + "version": "1.0.0", + "from": "utils-merge@1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" + }, + "vary": { + "version": "1.1.0", + "from": "vary@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.0.tgz" + }, + "wbuf": { + "version": "1.7.2", + "from": "wbuf@>=1.4.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz" + }, + "wrappy": { + "version": "1.0.2", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + }, + "x-xss-protection": { + "version": "1.0.0", + "from": "x-xss-protection@1.0.0", + "resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.0.0.tgz" + } + } +} diff --git a/notification/package.json b/notification/package.json new file mode 100644 index 0000000..ad6810a --- /dev/null +++ b/notification/package.json @@ -0,0 +1,51 @@ +{ + "name": "movies-service", + "version": "1.0.0", + "description": "A movie service, microservice example with nodejs", + "author": "Cristian Ramirez Rosas ", + "license": "ISC", + "main": "index.js", + "standard": { + "ignore": [ + "mock/**.js" + ] + }, + "scripts": { + "test": "mocha -R spec src/**/*.spec.js", + "start": "node src/index.js", + "lint": "standard --verbose | snazzy", + "node-debug": "DEBUG=express* node src/index.js", + "chrome-debug": "node --debug-brk --inspect src/index.js", + "coverage": "istanbul cover _mocha $(find ./src -name \"*.spec.js\" -not -path \"./node_modules/*\") ", + "metric": "nodejs-dashboard -- node -r nodejs-dashboard src/index.js" + }, + "keywords": [ + "express", + "mongodb", + "docker", + "microservice" + ], + "devDependencies": { + "eslint": "^3.13.1", + "mocha": "^3.2.0", + "nodejs-dashboard": "^0.3.0", + "should": "^11.1.2", + "snazzy": "^6.0.0", + "standard": "^8.6.0", + "supertest": "^2.0.1" + }, + "dependencies": { + "awilix": "^2.2.2", + "body-parser": "^1.16.0", + "cors": "^2.8.1", + "express": "^4.14.0", + "helmet": "^3.4.0", + "http-status": "^0.2.5", + "joi": "^10.2.0", + "mongodb": "^2.1.18", + "morgan": "^1.7.0", + "nodemailer": "^3.0.2", + "nodemailer-smtp-transport": "^2.7.2", + "spdy": "^3.4.4" + } +} diff --git a/notification/src/api/notification.js b/notification/src/api/notification.js new file mode 100644 index 0000000..e052f17 --- /dev/null +++ b/notification/src/api/notification.js @@ -0,0 +1,30 @@ +'use strict' +const status = require('http-status') + +module.exports = ({repo}, app) => { + app.post('/notification/sendEmail', (req, res, next) => { + const {validate} = req.container.cradle + + validate(req.body.payload, 'notification') + .then(payload => { + return repo.sendEmail(payload) + }) + .then(ok => { + res.status(status.OK).json({msg: 'ok'}) + }) + .catch(next) + }) + + app.post('/notification/sendSMS', (req, res, next) => { + const {validate} = req.container.cradle + + validate(req.body.payload, 'notification') + .then(payload => { + return repo.sendSMS(payload) + }) + .then(ok => { + res.status(status.OK).json({msg: 'ok'}) + }) + .catch(next) + }) +} diff --git a/notification/src/api/notification.spec.js b/notification/src/api/notification.spec.js new file mode 100644 index 0000000..01ec88e --- /dev/null +++ b/notification/src/api/notification.spec.js @@ -0,0 +1,122 @@ +/* eslint-env mocha */ +const { createContainer, asValue } = require('awilix') +const nodemailer = require('nodemailer') +const smtpTransport = require('nodemailer-smtp-transport') +const should = require('should') +const request = require('supertest') +const server = require('../server/server') +const models = require('../models') +const {smtpSettings} = require('../config/config') + +describe('Booking API', () => { + let app = null + + const serverSettings = { + port: 3000 + } + + const container = createContainer() + + container.register({ + validate: asValue(models.validate), + serverSettings: asValue(serverSettings), + smtpSettings: asValue(smtpSettings), + nodemailer: asValue(nodemailer), + smtpTransport: asValue(smtpTransport) + }) + + let _testRepo = { + sendEmail ({container}, payload) { + return new Promise((resolve, reject) => { + const {smtpSettings, smtpTransport, nodemailer} = container.cradle + + const transporter = nodemailer.createTransport( + smtpTransport({ + service: smtpSettings.service, + auth: { + user: smtpSettings.user, + pass: smtpSettings.pass + } + })) + + const mailOptions = { + from: '"Do Not Reply, Cinemas Company 👥" ', + to: `${payload.user.email}`, + subject: `Tickects for movie ${payload.movie.title}`, + html: ` +

Tickest for ${payload.movie.title}

+ +

Cinema: ${payload.cinema.name}

+

Room: ${payload.cinema.room}

+

Seat(s): ${payload.cinema.seats}

+ +

description: ${payload.description}

+ +

Total: ${payload.totalAmount}

+

number of order: ${payload.orderId}

+ +

Cinemas Microserivce 2017, Enjoy your movie 🍿🎥!

+ ` + } + + transporter.sendMail(mailOptions, (err, info) => { + if (err) { + reject(new Error('An error occured sending an email, err:' + err)) + } + transporter.close() + resolve(info) + }) + }) + } + } + + const testRepo = {} + + testRepo.sendEmail = _testRepo.sendEmail.bind(null, {container}) + + container.registerValue({repo: testRepo}) + + beforeEach(() => { + return server.start(container) + .then(serv => { + app = serv + }) + }) + + afterEach(() => { + app.close() + app = null + }) + + it('can make a booking and return the ticket(s)', (done) => { + const payload = { + city: 'Morelia', + userType: 'loyal', + totalAmount: 71, + cinema: { + name: 'Plaza Morelia', + room: '1', + seats: '53, 54' + }, + movie: { + title: 'Assasins Creed', + format: 'IMAX', + schedule: new Date() + }, + orderId: '1aa90cx', + description: 'some description', + user: { + name: 'Cristian Ramirez', + email: 'cristiano.rosetti@gmail.com' + } + } + + request(app) + .post('/notification/sendEmail') + .send({payload}) + .expect((res) => { + should.ok(res.body) + }) + .expect(200, done) + }) +}) diff --git a/notification/src/config/config.js b/notification/src/config/config.js new file mode 100644 index 0000000..0e4fbe9 --- /dev/null +++ b/notification/src/config/config.js @@ -0,0 +1,13 @@ +const serverSettings = { + port: process.env.PORT || 3000, + ssl: require('./ssl') +} + +// as a better practice we can pass this values via env variables +const smtpSettings = { + service: 'Gmail', + user: process.env.EMAIL, + pass: process.env.EMAIL_PASS +} + +module.exports = Object.assign({}, { serverSettings, smtpSettings }) diff --git a/notification/src/config/di/di.js b/notification/src/config/di/di.js new file mode 100644 index 0000000..d934d0f --- /dev/null +++ b/notification/src/config/di/di.js @@ -0,0 +1,21 @@ +const { createContainer, asValue } = require('awilix') +const nodemailer = require('nodemailer') +const smtpTransport = require('nodemailer-smtp-transport') + +function initDI ({serverSettings, models, smtpSettings}, mediator) { + mediator.once('init', () => { + const container = createContainer() + + container.register({ + validate: asValue(models.validate), + serverSettings: asValue(serverSettings), + smtpSettings: asValue(smtpSettings), + nodemailer: asValue(nodemailer), + smtpTransport: asValue(smtpTransport) + }) + + mediator.emit('di.ready', container) + }) +} + +module.exports.initDI = initDI diff --git a/notification/src/config/di/di.proto.js b/notification/src/config/di/di.proto.js new file mode 100644 index 0000000..82e6df1 --- /dev/null +++ b/notification/src/config/di/di.proto.js @@ -0,0 +1,82 @@ +/* + const container = createContainer() + + container.register({ + transient(user), + transient(ticket), + transient(booking), + singleton(objectID), + singleton(notifications), + singleton(payments) + }) + + function ({ User, Booking }) { + make some stuff with the user + Promise.all([ + user.validate(object), + booking.validate(object) + ]) + .then([user, booking] => { + + }) + } + +*/ + +const createContainer = () => { + // DI store + const registrations = {} + // returns the DI + const container = { + get registrations () { + return Object.assign({}, registrations) + } + } + + // DI cache systems + container.cache = {} + + const getDI = new Proxy({}, { + get: (taget, name) => resolve(name), + set: (target, name, value) => { + throw new Error('cannot set a value to the container') + } + }) + + container.getDI = getDI + + const register = (name, registration, opts) => { + const key = Symbol(name) + registrations[key] = Object.assign({}, {fn: registration}, {lifetime: opts}) + return container + } + + container.register = register + + const resolve = (name) => { + const di = registrations[name] + switch (di.lifetime) { + case 'TRANSIENT': + return container.registrations[name].fn + case 'SINGLETON': + if (!container.cache[name]) { + container.cache[name] = container.registrations[name] + } + return container.cache[name].fn + } + } + + const listDependencies = () => { + const list = [] + for (var key in registrations) { + if (registrations.hasOwnProperty(key)) { + list.push(key) + } + } + return list + } + + return Object.create(container) +} + +module.exports.createContainer = createContainer diff --git a/notification/src/config/di/index.js b/notification/src/config/di/index.js new file mode 100644 index 0000000..ff2d63c --- /dev/null +++ b/notification/src/config/di/index.js @@ -0,0 +1,3 @@ +const di = require('./di') + +module.exports = Object.assign({}, di) diff --git a/notification/src/config/index.di.spec.js b/notification/src/config/index.di.spec.js new file mode 100644 index 0000000..0324825 --- /dev/null +++ b/notification/src/config/index.di.spec.js @@ -0,0 +1,25 @@ +/* eslint-env mocha */ +const {EventEmitter} = require('events') +const test = require('assert') +const {init} = require('./') + +describe('DI configuration', () => { + it('can init dependencies to the container', (done) => { + const mediator = new EventEmitter() + + mediator.on('di.ready', (container) => { + console.log(database) + console.log(container) + done() + }) + + mediator.on('di.error', err => { + console.log(err) + done() + }) + + init(mediator) + + mediator.emit('init') + }) +}) diff --git a/notification/src/config/index.js b/notification/src/config/index.js new file mode 100644 index 0000000..f780c9e --- /dev/null +++ b/notification/src/config/index.js @@ -0,0 +1,7 @@ +const {smtpSettings, serverSettings} = require('./config') +const {initDI} = require('./di') +const models = require('../models') + +const init = initDI.bind(null, {serverSettings, smtpSettings, models}) + +module.exports = Object.assign({}, {init}) diff --git a/notification/src/config/ssl/index.js b/notification/src/config/ssl/index.js new file mode 100644 index 0000000..63e4cd3 --- /dev/null +++ b/notification/src/config/ssl/index.js @@ -0,0 +1,6 @@ +const fs = require('fs') + +module.exports = { + key: fs.readFileSync(`${__dirname}/server.key`), + cert: fs.readFileSync(`${__dirname}/server.crt`) +} diff --git a/notification/src/index.js b/notification/src/index.js new file mode 100644 index 0000000..19ed938 --- /dev/null +++ b/notification/src/index.js @@ -0,0 +1,36 @@ +'use strict' +const {EventEmitter} = require('events') +const server = require('./server/server') +const repository = require('./repository/repository') +const di = require('./config') +const mediator = new EventEmitter() + +console.log('--- Notification Service ---') +console.log('Connecting to notification repository...') + +process.on('uncaughtException', (err) => { + console.error('Unhandled Exception', err) +}) + +process.on('uncaughtRejection', (err, promise) => { + console.error('Unhandled Rejection', err) +}) + +mediator.on('di.ready', (container) => { + repository.connect(container) + .then(repo => { + console.log('Connected. Starting Server') + container.registerValue({repo}) + return server.start(container) + }) + .then(app => { + console.log(`Server started succesfully, running on port: ${container.cradle.serverSettings.port}.`) + app.on('close', () => { + container.resolve('repo').disconnect() + }) + }) +}) + +di.init(mediator) + +mediator.emit('init') diff --git a/notification/src/models/index.js b/notification/src/models/index.js new file mode 100644 index 0000000..cf2fadc --- /dev/null +++ b/notification/src/models/index.js @@ -0,0 +1,24 @@ +const joi = require('joi') +const notification = require('./notification.model')(joi) + +const schemas = Object.create({notification}) + +const schemaValidator = (object, type) => { + return new Promise((resolve, reject) => { + if (!object) { + reject(new Error('object to validate not provided')) + } + if (!type) { + reject(new Error('schema type to validate not provided')) + } + + const {error, value} = joi.validate(object, schemas[type]) + + if (error) { + reject(new Error(`invalid ${type} data, err: ${error}`)) + } + resolve(value) + }) +} + +module.exports = Object.create({validate: schemaValidator, schemas}) diff --git a/notification/src/models/index.spec.js b/notification/src/models/index.spec.js new file mode 100644 index 0000000..763f7a8 --- /dev/null +++ b/notification/src/models/index.spec.js @@ -0,0 +1,42 @@ +/* eslint-env mocha */ +const test = require('assert') +const {validate} = require('./') + +console.log(Object.getPrototypeOf(validate)) + +describe('Schemas Validation', () => { + it('can validate a notification object', (done) => { + const notificationSchema = { + city: 'Morelia', + userType: 'loyal', + totalAmount: 71, + cinema: { + name: 'Plaza Morelia', + room: '1', + seats: '53, 54' + }, + movie: { + title: 'Assasins Creed', + format: 'IMAX', + schedule: new Date() + }, + orderId: '1aa90cx', + description: 'some description', + user: { + name: 'Cristian Ramirez', + email: 'cristiano.rosetti@gmail.com' + } + } + + validate(notificationSchema, 'notification') + .then(value => { + test.ok(value) + console.log(value) + done() + }) + .catch(err => { + console.log(err) + done() + }) + }) +}) diff --git a/notification/src/models/notification.model.js b/notification/src/models/notification.model.js new file mode 100644 index 0000000..7d1c73d --- /dev/null +++ b/notification/src/models/notification.model.js @@ -0,0 +1,25 @@ + +const notificationSchema = (joi) => ({ + city: joi.string(), + userType: joi.string(), + totalAmount: joi.number(), + cinema: joi.object().keys({ + name: joi.string(), + room: joi.number(), + seats: joi.string() + }), + movie: joi.object().keys({ + title: joi.string(), + format: joi.string(), + schedule: joi.date() + }), + orderId: joi.string(), + _id: joi.string(), + description: joi.string(), + user: joi.object().keys({ + name: joi.string(), + email: joi.string().email() + }) +}) + +module.exports = notificationSchema diff --git a/notification/src/repository/repository.js b/notification/src/repository/repository.js new file mode 100644 index 0000000..f3a1fed --- /dev/null +++ b/notification/src/repository/repository.js @@ -0,0 +1,65 @@ +'use strict' +const repository = (container) => { + const sendEmail = (payload) => { + return new Promise((resolve, reject) => { + const {smtpSettings, smtpTransport, nodemailer} = container.cradle + + const transporter = nodemailer.createTransport( + smtpTransport({ + service: smtpSettings.service, + auth: { + user: smtpSettings.user, + pass: smtpSettings.pass + } + })) + + const mailOptions = { + from: '"Do Not Reply, Cinemas Company 👥" ', + to: `${payload.user.email}`, + subject: `Tickects for movie ${payload.movie.title}`, + html: ` +

Tickest for ${payload.movie.title}

+ +

Cinem: ${payload.cinema.name}

+

Room: ${payload.cinema.room}

+

Seats: ${payload.cinema.seats}

+ +

description: ${payload.description}

+ +

Total: ${payload.totalAmount}

+

Total: ${payload.orderId}

+ +

Cinemas Microserivce 2017, Enjoy your movie !

+ ` + } + + transporter.sendMail(mailOptions, (err, info) => { + if (err) { + reject(new Error('An error occured sending an email, err:' + err)) + } + transporter.close() + resolve(info) + }) + }) + } + + const sendSMS = (payload) => { + // TODO: code for some sms service + } + + return Object.create({ + sendSMS, + sendEmail + }) +} + +const connect = (container) => { + return new Promise((resolve, reject) => { + if (!container) { + reject(new Error('dependencies not supplied!')) + } + resolve(repository(container)) + }) +} + +module.exports = Object.assign({}, {connect}) diff --git a/notification/src/repository/repository.spec.js b/notification/src/repository/repository.spec.js new file mode 100644 index 0000000..b423fc2 --- /dev/null +++ b/notification/src/repository/repository.spec.js @@ -0,0 +1,9 @@ +/* eslint-env mocha */ +const should = require('should') +const repository = require('./repository') + +describe('Repository', () => { + it('should connect with a promise', () => { + repository.connect({}).should.be.a.Promise() + }) +}) diff --git a/notification/src/server/server.js b/notification/src/server/server.js new file mode 100644 index 0000000..b145788 --- /dev/null +++ b/notification/src/server/server.js @@ -0,0 +1,42 @@ +const express = require('express') +const morgan = require('morgan') +const helmet = require('helmet') +const bodyparser = require('body-parser') +const cors = require('cors') +const _api = require('../api/notification') + +const start = (container) => { + return new Promise((resolve, reject) => { + const {port} = container.resolve('serverSettings') + const repo = container.resolve('repo') + + if (!repo) { + reject(new Error('The server must be started with a connected repository')) + } + if (!port) { + reject(new Error('The server must be started with an available port')) + } + + const app = express() + app.use(morgan('dev')) + app.use(bodyparser.json()) + app.use(cors()) + app.use(helmet()) + app.use((err, req, res, next) => { + reject(new Error('Something went wrong!, err:' + err)) + res.status(500).send('Something went wrong!') + next() + }) + app.use((req, res, next) => { + req.container = container.createScope() + next() + }) + + const api = _api.bind(null, {repo}) + api(app) + + const server = app.listen(port, () => resolve(server)) + }) +} + +module.exports = Object.assign({}, {start}) diff --git a/notification/src/server/server.spec.js b/notification/src/server/server.spec.js new file mode 100644 index 0000000..f552ac9 --- /dev/null +++ b/notification/src/server/server.spec.js @@ -0,0 +1,16 @@ +/* eslint-env mocha */ +const server = require('./server') + +describe('Server', () => { + it('should require a port to start', () => { + return server.start({ + repo: {} + }).should.be.rejectedWith(/port/) + }) + + it('should require a repository to start', () => { + return server.start({ + port: {} + }).should.be.rejectedWith(/repository/) + }) +}) diff --git a/payment/.eslintrc.json b/payment/.eslintrc.json new file mode 100644 index 0000000..a755cdb --- /dev/null +++ b/payment/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": ["standard"] +} diff --git a/payment/Dockerfile b/payment/Dockerfile new file mode 100644 index 0000000..523816b --- /dev/null +++ b/payment/Dockerfile @@ -0,0 +1,25 @@ +FROM node:7.5.0-alpine + +RUN addgroup -S nupp && adduser -S -g nupp nupp + +ENV HOME=/home/nupp + +COPY package.json npm-shrinkwrap.json $HOME/app/ + +COPY src/ $HOME/app/src + +ADD https://github.com/Yelp/dumb-init/releases/download/v1.1.1/dumb-init_1.1.1_amd64 /usr/local/bin/dumb-init + +WORKDIR $HOME/app + +RUN chown -R nupp:nupp $HOME/* /usr/local/ && \ + chmod +x /usr/local/bin/dumb-init && \ + npm cache clean && \ + npm install --silent --progress=false --production && \ + chown -R nupp:nupp $HOME/* + +USER nupp + +EXPOSE 3000 + +CMD ["dumb-init", "npm", "start"] diff --git a/payment/env b/payment/env new file mode 100644 index 0000000..ac29194 --- /dev/null +++ b/payment/env @@ -0,0 +1,6 @@ +DB=booking +DB_USER=cristian +DB_PASS=cristianPassword2017 +DB_REPLS=rs1 +DB_SERVERS='192.168.99.100:27017 192.168.99.101:27017 192.168.99.102:27017' +PORT=3000 diff --git a/payment/integration-test/index.js b/payment/integration-test/index.js new file mode 100644 index 0000000..9568a17 --- /dev/null +++ b/payment/integration-test/index.js @@ -0,0 +1,28 @@ +/* eslint-env mocha */ +const supertest = require('supertest') + +describe('Payment Servie', () => { + const api = supertest('http://192.168.99.100:3003') + const testPayment = { + userName: 'Cristian Ramirez', + currency: 'mxn', + number: '4242424242424242', + cvc: '123', + exp_month: '12', + exp_year: '2017', + amount: 71, + description: ` + Tickect(s) for movie "Assasins Creed", + with seat(s) 47, 48 + at time 8 / feb / 17` + } + + it('can make a paymentOrder', (done) => { + api.post('/payment/makePurchase') + .send({paymentOrder: testPayment}) + .expect((res) => { + console.log(res.body) + }) + .expect(200, done) + }) +}) diff --git a/payment/npm-shrinkwrap.json b/payment/npm-shrinkwrap.json new file mode 100644 index 0000000..8954d24 --- /dev/null +++ b/payment/npm-shrinkwrap.json @@ -0,0 +1,708 @@ +{ + "name": "movies-service", + "version": "1.0.0", + "dependencies": { + "accepts": { + "version": "1.3.3", + "from": "accepts@>=1.3.3 <1.4.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz" + }, + "array-flatten": { + "version": "1.1.1", + "from": "array-flatten@1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" + }, + "awilix": { + "version": "2.2.2", + "from": "awilix@latest", + "resolved": "https://registry.npmjs.org/awilix/-/awilix-2.2.2.tgz" + }, + "balanced-match": { + "version": "0.4.2", + "from": "balanced-match@>=0.4.1 <0.5.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz" + }, + "basic-auth": { + "version": "1.0.4", + "from": "basic-auth@>=1.0.3 <1.1.0", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz" + }, + "bluebird": { + "version": "2.11.0", + "from": "bluebird@>=2.10.2 <3.0.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz" + }, + "body-parser": { + "version": "1.16.0", + "from": "body-parser@latest", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.16.0.tgz", + "dependencies": { + "qs": { + "version": "6.2.1", + "from": "qs@6.2.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.1.tgz" + } + } + }, + "brace-expansion": { + "version": "1.1.6", + "from": "brace-expansion@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz" + }, + "bson": { + "version": "0.4.23", + "from": "bson@>=0.4.23 <0.5.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-0.4.23.tgz" + }, + "buffer-shims": { + "version": "1.0.0", + "from": "buffer-shims@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" + }, + "bytes": { + "version": "2.4.0", + "from": "bytes@2.4.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz" + }, + "camel-case": { + "version": "3.0.0", + "from": "camel-case@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz" + }, + "camelize": { + "version": "1.0.0", + "from": "camelize@1.0.0", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz" + }, + "concat-map": { + "version": "0.0.1", + "from": "concat-map@0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + }, + "connect": { + "version": "3.5.0", + "from": "connect@3.5.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.5.0.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + } + }, + "content-disposition": { + "version": "0.5.1", + "from": "content-disposition@0.5.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz" + }, + "content-security-policy-builder": { + "version": "1.1.0", + "from": "content-security-policy-builder@1.1.0", + "resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-1.1.0.tgz" + }, + "content-type": { + "version": "1.0.2", + "from": "content-type@>=1.0.2 <1.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz" + }, + "cookie": { + "version": "0.3.1", + "from": "cookie@0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz" + }, + "cookie-signature": { + "version": "1.0.6", + "from": "cookie-signature@1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + }, + "core-util-is": { + "version": "1.0.2", + "from": "core-util-is@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" + }, + "cors": { + "version": "2.8.1", + "from": "cors@latest", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.1.tgz" + }, + "dasherize": { + "version": "2.0.0", + "from": "dasherize@2.0.0", + "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz" + }, + "dashify": { + "version": "0.2.2", + "from": "dashify@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/dashify/-/dashify-0.2.2.tgz" + }, + "debug": { + "version": "2.6.0", + "from": "debug@>=2.1.1 <3.0.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz" + }, + "depd": { + "version": "1.1.0", + "from": "depd@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz" + }, + "destroy": { + "version": "1.0.4", + "from": "destroy@>=1.0.4 <1.1.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" + }, + "dns-prefetch-control": { + "version": "0.1.0", + "from": "dns-prefetch-control@0.1.0", + "resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz" + }, + "dont-sniff-mimetype": { + "version": "1.0.0", + "from": "dont-sniff-mimetype@1.0.0", + "resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.0.0.tgz" + }, + "ee-first": { + "version": "1.1.1", + "from": "ee-first@1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + }, + "encodeurl": { + "version": "1.0.1", + "from": "encodeurl@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz" + }, + "es6-promise": { + "version": "3.0.2", + "from": "es6-promise@3.0.2", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz" + }, + "escape-html": { + "version": "1.0.3", + "from": "escape-html@>=1.0.3 <1.1.0", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + }, + "etag": { + "version": "1.7.0", + "from": "etag@>=1.7.0 <1.8.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz" + }, + "express": { + "version": "4.14.0", + "from": "express@latest", + "resolved": "https://registry.npmjs.org/express/-/express-4.14.0.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + }, + "qs": { + "version": "6.2.0", + "from": "qs@6.2.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz" + } + } + }, + "finalhandler": { + "version": "0.5.0", + "from": "finalhandler@0.5.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.0.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@~2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + } + }, + "forwarded": { + "version": "0.1.0", + "from": "forwarded@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz" + }, + "frameguard": { + "version": "3.0.0", + "from": "frameguard@3.0.0", + "resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.0.0.tgz" + }, + "fresh": { + "version": "0.3.0", + "from": "fresh@0.3.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz" + }, + "fs.realpath": { + "version": "1.0.0", + "from": "fs.realpath@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + }, + "glob": { + "version": "7.1.1", + "from": "glob@>=7.0.3 <8.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz" + }, + "handle-thing": { + "version": "1.2.5", + "from": "handle-thing@>=1.2.4 <2.0.0", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz" + }, + "helmet": { + "version": "3.4.0", + "from": "helmet@>=3.4.0 <4.0.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.4.0.tgz" + }, + "helmet-csp": { + "version": "2.3.0", + "from": "helmet-csp@2.3.0", + "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.3.0.tgz" + }, + "hide-powered-by": { + "version": "1.0.0", + "from": "hide-powered-by@1.0.0", + "resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.0.0.tgz" + }, + "hpack.js": { + "version": "2.1.6", + "from": "hpack.js@>=2.1.6 <3.0.0", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz" + }, + "hpkp": { + "version": "2.0.0", + "from": "hpkp@2.0.0", + "resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz" + }, + "hsts": { + "version": "2.0.0", + "from": "hsts@2.0.0", + "resolved": "https://registry.npmjs.org/hsts/-/hsts-2.0.0.tgz" + }, + "http-deceiver": { + "version": "1.2.7", + "from": "http-deceiver@>=1.2.4 <2.0.0", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" + }, + "http-errors": { + "version": "1.5.1", + "from": "http-errors@>=1.5.0 <1.6.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz" + }, + "http-status": { + "version": "0.2.5", + "from": "http-status@latest", + "resolved": "https://registry.npmjs.org/http-status/-/http-status-0.2.5.tgz" + }, + "iconv-lite": { + "version": "0.4.15", + "from": "iconv-lite@0.4.15", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz" + }, + "ienoopen": { + "version": "1.0.0", + "from": "ienoopen@1.0.0", + "resolved": "https://registry.npmjs.org/ienoopen/-/ienoopen-1.0.0.tgz" + }, + "inflight": { + "version": "1.0.6", + "from": "inflight@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + }, + "inherits": { + "version": "2.0.3", + "from": "inherits@>=2.0.3 <3.0.0", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + }, + "ipaddr.js": { + "version": "1.2.0", + "from": "ipaddr.js@1.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.2.0.tgz" + }, + "is-class": { + "version": "0.0.4", + "from": "is-class@0.0.4", + "resolved": "https://registry.npmjs.org/is-class/-/is-class-0.0.4.tgz" + }, + "is-plain-object": { + "version": "2.0.1", + "from": "is-plain-object@>=2.0.1 <3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.1.tgz" + }, + "is-string": { + "version": "1.0.4", + "from": "is-string@>=1.0.4 <2.0.0", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.4.tgz" + }, + "isarray": { + "version": "1.0.0", + "from": "isarray@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + }, + "isemail": { + "version": "2.2.1", + "from": "isemail@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-2.2.1.tgz" + }, + "isobject": { + "version": "1.0.2", + "from": "isobject@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-1.0.2.tgz" + }, + "items": { + "version": "2.1.1", + "from": "items@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/items/-/items-2.1.1.tgz" + }, + "joi": { + "version": "10.2.0", + "from": "joi@latest", + "resolved": "https://registry.npmjs.org/joi/-/joi-10.2.0.tgz", + "dependencies": { + "hoek": { + "version": "4.1.0", + "from": "hoek@>=4.0.0 <5.0.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.1.0.tgz" + } + } + }, + "lodash.isplainobject": { + "version": "4.0.6", + "from": "lodash.isplainobject@>=4.0.6 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz" + }, + "lodash.reduce": { + "version": "4.6.0", + "from": "lodash.reduce@4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz" + }, + "lower-case": { + "version": "1.1.3", + "from": "lower-case@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.3.tgz" + }, + "media-typer": { + "version": "0.3.0", + "from": "media-typer@0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + }, + "merge-descriptors": { + "version": "1.0.1", + "from": "merge-descriptors@1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" + }, + "methods": { + "version": "1.1.2", + "from": "methods@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + }, + "mime": { + "version": "1.3.4", + "from": "mime@>=1.3.4 <2.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" + }, + "mime-db": { + "version": "1.26.0", + "from": "mime-db@>=1.26.0 <1.27.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.26.0.tgz" + }, + "mime-types": { + "version": "2.1.14", + "from": "mime-types@>=2.1.10 <3.0.0", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.14.tgz" + }, + "minimalistic-assert": { + "version": "1.0.0", + "from": "minimalistic-assert@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" + }, + "minimatch": { + "version": "3.0.3", + "from": "minimatch@>=3.0.2 <4.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz" + }, + "mongodb": { + "version": "2.1.18", + "from": "mongodb@2.1.18", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.1.18.tgz", + "dependencies": { + "isarray": { + "version": "0.0.1", + "from": "isarray@0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" + }, + "readable-stream": { + "version": "1.0.31", + "from": "readable-stream@1.0.31", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.31.tgz" + } + } + }, + "mongodb-core": { + "version": "1.3.18", + "from": "mongodb-core@1.3.18", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-1.3.18.tgz" + }, + "morgan": { + "version": "1.7.0", + "from": "morgan@latest", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.7.0.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@~2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + } + }, + "ms": { + "version": "0.7.2", + "from": "ms@0.7.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz" + }, + "negotiator": { + "version": "0.6.1", + "from": "negotiator@0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz" + }, + "no-case": { + "version": "2.3.1", + "from": "no-case@>=2.2.0 <3.0.0", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.1.tgz" + }, + "nocache": { + "version": "2.0.0", + "from": "nocache@2.0.0", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.0.0.tgz" + }, + "object-assign": { + "version": "4.1.1", + "from": "object-assign@>=4.0.1 <5.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + }, + "obuf": { + "version": "1.1.1", + "from": "obuf@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz" + }, + "on-finished": { + "version": "2.3.0", + "from": "on-finished@>=2.3.0 <2.4.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" + }, + "on-headers": { + "version": "1.0.1", + "from": "on-headers@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" + }, + "once": { + "version": "1.4.0", + "from": "once@>=1.3.0 <2.0.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + }, + "parseurl": { + "version": "1.3.1", + "from": "parseurl@>=1.3.1 <1.4.0", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz" + }, + "path-is-absolute": { + "version": "1.0.1", + "from": "path-is-absolute@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + }, + "path-to-regexp": { + "version": "0.1.7", + "from": "path-to-regexp@0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" + }, + "platform": { + "version": "1.3.3", + "from": "platform@1.3.3", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.3.tgz" + }, + "process-nextick-args": { + "version": "1.0.7", + "from": "process-nextick-args@>=1.0.6 <1.1.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" + }, + "proxy-addr": { + "version": "1.1.3", + "from": "proxy-addr@>=1.1.2 <1.2.0", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.3.tgz" + }, + "range-parser": { + "version": "1.2.0", + "from": "range-parser@>=1.2.0 <1.3.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz" + }, + "raw-body": { + "version": "2.2.0", + "from": "raw-body@>=2.2.0 <2.3.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz" + }, + "readable-stream": { + "version": "2.2.2", + "from": "readable-stream@>=2.2.2 <3.0.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.2.tgz" + }, + "referrer-policy": { + "version": "1.1.0", + "from": "referrer-policy@1.1.0", + "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.1.0.tgz" + }, + "require_optional": { + "version": "1.0.0", + "from": "require_optional@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.0.tgz", + "dependencies": { + "resolve-from": { + "version": "2.0.0", + "from": "resolve-from@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz" + } + } + }, + "select-hose": { + "version": "2.0.0", + "from": "select-hose@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" + }, + "semver": { + "version": "5.3.0", + "from": "semver@>=5.1.0 <6.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz" + }, + "send": { + "version": "0.14.1", + "from": "send@0.14.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.14.1.tgz", + "dependencies": { + "debug": { + "version": "2.2.0", + "from": "debug@~2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" + }, + "ms": { + "version": "0.7.1", + "from": "ms@0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" + } + } + }, + "serve-static": { + "version": "1.11.1", + "from": "serve-static@>=1.11.1 <1.12.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.11.1.tgz" + }, + "setprototypeof": { + "version": "1.0.2", + "from": "setprototypeof@1.0.2", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz" + }, + "spdy": { + "version": "3.4.4", + "from": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz" + }, + "spdy-transport": { + "version": "2.0.18", + "from": "spdy-transport@>=2.0.15 <3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.18.tgz" + }, + "statuses": { + "version": "1.3.1", + "from": "statuses@>=1.3.0 <1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz" + }, + "string_decoder": { + "version": "0.10.31", + "from": "string_decoder@>=0.10.0 <0.11.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" + }, + "stripe": { + "version": "4.15.0", + "from": "stripe@latest", + "resolved": "https://registry.npmjs.org/stripe/-/stripe-4.15.0.tgz", + "dependencies": { + "qs": { + "version": "2.4.2", + "from": "qs@>=2.4.2 <3.0.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.4.2.tgz" + } + } + }, + "topo": { + "version": "2.0.2", + "from": "topo@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", + "dependencies": { + "hoek": { + "version": "4.1.0", + "from": "hoek@4.x.x", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.1.0.tgz" + } + } + }, + "type-is": { + "version": "1.6.14", + "from": "type-is@>=1.6.13 <1.7.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.14.tgz" + }, + "unpipe": { + "version": "1.0.0", + "from": "unpipe@>=1.0.0 <1.1.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + }, + "upper-case": { + "version": "1.1.3", + "from": "upper-case@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz" + }, + "util-deprecate": { + "version": "1.0.2", + "from": "util-deprecate@>=1.0.1 <1.1.0", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + }, + "utils-merge": { + "version": "1.0.0", + "from": "utils-merge@1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" + }, + "vary": { + "version": "1.1.0", + "from": "vary@>=1.1.0 <1.2.0", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.0.tgz" + }, + "wbuf": { + "version": "1.7.2", + "from": "wbuf@>=1.4.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz" + }, + "wrappy": { + "version": "1.0.2", + "from": "wrappy@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + }, + "x-xss-protection": { + "version": "1.0.0", + "from": "x-xss-protection@1.0.0", + "resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.0.0.tgz" + } + } +} diff --git a/payment/package.json b/payment/package.json new file mode 100644 index 0000000..81e79a8 --- /dev/null +++ b/payment/package.json @@ -0,0 +1,50 @@ +{ + "name": "movies-service", + "version": "1.0.0", + "description": "A movie service, microservice example with nodejs", + "author": "Cristian Ramirez Rosas ", + "license": "ISC", + "main": "index.js", + "standard": { + "ignore": [ + "mock/**.js" + ] + }, + "scripts": { + "test": "mocha -R spec src/**/*.spec.js", + "start": "node src/index.js", + "lint": "standard --verbose | snazzy", + "node-debug": "DEBUG=express* node src/index.js", + "chrome-debug": "node --debug-brk --inspect src/index.js", + "coverage": "istanbul cover _mocha $(find ./src -name \"*.spec.js\" -not -path \"./node_modules/*\") ", + "metric": "nodejs-dashboard -- node -r nodejs-dashboard src/index.js" + }, + "keywords": [ + "express", + "mongodb", + "docker", + "microservice" + ], + "devDependencies": { + "eslint": "^3.13.1", + "mocha": "^3.2.0", + "nodejs-dashboard": "^0.3.0", + "should": "^11.1.2", + "snazzy": "^6.0.0", + "standard": "^8.6.0", + "supertest": "^2.0.1" + }, + "dependencies": { + "awilix": "^2.2.2", + "body-parser": "^1.16.0", + "cors": "^2.8.1", + "express": "^4.14.0", + "helmet": "^3.4.0", + "http-status": "^0.2.5", + "joi": "^10.2.0", + "mongodb": "^2.1.18", + "morgan": "^1.7.0", + "spdy": "^3.4.4", + "stripe": "^4.15.0" + } +} diff --git a/payment/src/api/payment.js b/payment/src/api/payment.js new file mode 100644 index 0000000..e26993a --- /dev/null +++ b/payment/src/api/payment.js @@ -0,0 +1,25 @@ +'use strict' +const status = require('http-status') + +module.exports = ({repo}, app) => { + app.post('/payment/makePurchase', (req, res, next) => { + const {validate} = req.container.cradle + + validate(req.body.paymentOrder, 'payment') + .then(payment => { + return repo.registerPurchase(payment) + }) + .then(paid => { + res.status(status.OK).json({paid}) + }) + .catch(next) + }) + + app.get('/payment/getPurchaseById/:id', (req, res, next) => { + repo.getPurchaseById(req.params.id) + .then(payment => { + res.status(status.OK).json({payment}) + }) + .catch(next) + }) +} diff --git a/payment/src/api/payment.spec.js b/payment/src/api/payment.spec.js new file mode 100644 index 0000000..8c3d8ff --- /dev/null +++ b/payment/src/api/payment.spec.js @@ -0,0 +1,115 @@ +/* eslint-env mocha */ +const { createContainer, asValue } = require('awilix') +const {stripeSettings} = require('../config/config') +const stripe = require('stripe') +const should = require('should') +const request = require('supertest') +const models = require('../models') +const server = require('../server/server') + +describe('Payment API', () => { + let app = null + let paid = null + + const serverSettings = { + port: 3000 + } + + const container = createContainer() + + container.register({ + validate: asValue(models.validate), + serverSettings: asValue(serverSettings), + stripe: asValue(stripe(stripeSettings.secret)) + }) + + let _testRepo = { + registerPurchase ({container}, payment) { + return new Promise((resolve, reject) => { + container.cradle.stripe.charges.create({ + amount: Math.ceil(payment.amount * 100), + currency: payment.currency, + source: { + number: payment.number, + cvc: payment.cvc, + exp_month: payment.exp_month, + exp_year: payment.exp_year + }, + description: payment.description + }, (err, charge) => { + if (err && err.type === 'StripeCardError') { + reject(new Error('An error occuered procesing payment with stripe, err: ' + err)) + } else { + const paid = Object.assign({}, {user: payment.userName, amount: payment.amount, charge}) + resolve(paid) + } + }) + }) + }, + getPurchaseById ({container}, orderId) { + return new Promise((resolve, reject) => { + container.cradle.stripe.charges.retrieve(orderId, (err, charge) => { + if (err) { + reject(err) + } else { + resolve(charge) + } + }) + }) + } + } + + const testRepo = {} + + testRepo.registerPurchase = _testRepo.registerPurchase.bind(null, {container}) + testRepo.getPurchaseById = _testRepo.getPurchaseById.bind(null, {container}) + + container.registerValue({repo: testRepo}) + + beforeEach(() => { + return server.start(container) + .then(serv => { + app = serv + }) + }) + + afterEach(() => { + app.close() + app = null + }) + + it('can make a purchase', (done) => { + const testPayment = { + userName: 'Cristian Ramirez', + currency: 'mxn', + number: '4242424242424242', + cvc: '123', + exp_month: '12', + exp_year: '2017', + amount: 71, + description: ` + Tickect(s) for movie "Assasins Creed", + with seat(s) 47, 48 + at time 8 / feb / 17` + } + + request(app) + .post('/payment/makePurchase') + .send({paymentOrder: testPayment}) + .expect((res) => { + should.ok(res.body.paid) + paid = res.body.paid + }) + .expect(200, done) + }) + + it('can get purchase', (done) => { + request(app) + .get('/payment/getPurchaseById/' + paid.charge.id) + .expect((res) => { + should.ok(res.body.payment) + should.equal(res.body.payment.amount, 71 * 100) + }) + .expect(200, done) + }) +}) diff --git a/payment/src/config/config.js b/payment/src/config/config.js new file mode 100644 index 0000000..d0197a3 --- /dev/null +++ b/payment/src/config/config.js @@ -0,0 +1,50 @@ +const dbSettings = { + db: process.env.DB || 'payment', + user: process.env.DB_USER || 'cristian', + pass: process.env.DB_PASS || 'cristianPassword2017', + repl: process.env.DB_REPLS || 'rs1', + servers: (process.env.DB_SERVERS) ? process.env.DB_SERVERS.substr(1, process.env.DB_SERVERS.length - 2).split(' ') : [ + '192.168.99.100:27017', + '192.168.99.101:27017', + '192.168.99.102:27017' + ], + dbParameters: () => ({ + w: 'majority', + wtimeout: 10000, + j: true, + readPreference: 'ReadPreference.SECONDARY_PREFERRED', + native_parser: false + }), + serverParameters: () => ({ + autoReconnect: true, + poolSize: 10, + socketoptions: { + keepAlive: 300, + connectTimeoutMS: 30000, + socketTimeoutMS: 30000 + } + }), + replsetParameters: (replset = 'rs1') => ({ + replicaSet: replset, + ha: true, + haInterval: 10000, + poolSize: 10, + socketoptions: { + keepAlive: 300, + connectTimeoutMS: 30000, + socketTimeoutMS: 30000 + } + }) +} + +const serverSettings = { + port: process.env.PORT || 3000, + ssl: require('./ssl') +} + +const stripeSettings = { + secret: 'sk_test_lPPoJjmmbSjymtgo4r0O3z89', + public: 'pk_test_l10342hIODZmOJsBpY6GVPHj' +} + +module.exports = Object.assign({}, { dbSettings, serverSettings, stripeSettings }) diff --git a/payment/src/config/db/index.js b/payment/src/config/db/index.js new file mode 100644 index 0000000..8a1a1d3 --- /dev/null +++ b/payment/src/config/db/index.js @@ -0,0 +1,4 @@ +const {ObjectID} = require('mongodb') +const {connect} = require('./mongo') + +module.exports = Object.assign({}, {connect, ObjectID}) diff --git a/payment/src/config/db/mongo.js b/payment/src/config/db/mongo.js new file mode 100644 index 0000000..18fce0f --- /dev/null +++ b/payment/src/config/db/mongo.js @@ -0,0 +1,32 @@ +const MongoClient = require('mongodb') + +const getMongoURL = (options) => { + const url = options.servers + .reduce((prev, cur) => prev + cur + ',', 'mongodb://') + + return `${url.substr(0, url.length - 1)}/${options.db}` +} + +const connect = (options, mediator) => { + mediator.once('boot.ready', () => { + MongoClient.connect( + getMongoURL(options), { + db: options.dbParameters(), + server: options.serverParameters(), + replset: options.replsetParameters(options.repl) + }, (err, db) => { + if (err) { + mediator.emit('db.error', err) + } + + db.admin().authenticate(options.user, options.pass, (err, result) => { + if (err) { + mediator.emit('db.error', err) + } + mediator.emit('db.ready', db) + }) + }) + }) +} + +module.exports = Object.assign({}, {connect}) diff --git a/payment/src/config/db/mongo.spec.js b/payment/src/config/db/mongo.spec.js new file mode 100644 index 0000000..6226394 --- /dev/null +++ b/payment/src/config/db/mongo.spec.js @@ -0,0 +1,29 @@ +/* eslint-env mocha */ +const {EventEmitter} = require('events') +const test = require('assert') +const mongo = require('./mongo') +const {dbSettings} = require('./config') + +describe('Mongo Connection', () => { + it('should emit db Object with an EventEmitter', (done) => { + const mediator = new EventEmitter() + + mediator.on('db.ready', (db) => { + db.admin().listDatabases((err, dbs) => { + test.equal(null, err) + test.ok(dbs.databases.length > 0) + console.log(dbs.databases) + db.close() + done() + }) + }) + + mediator.on('db.error', (err) => { + console.log(err) + }) + + mongo.connect(dbSettings, mediator) + + mediator.emit('boot.ready') + }) +}) diff --git a/payment/src/config/di/di.js b/payment/src/config/di/di.js new file mode 100644 index 0000000..9a0f05a --- /dev/null +++ b/payment/src/config/di/di.js @@ -0,0 +1,30 @@ +const { createContainer, asValue } = require('awilix') +const stripe = require('stripe') + +function initDI ({serverSettings, dbSettings, database, models, stripeSettings}, mediator) { + mediator.once('init', () => { + mediator.on('db.ready', (db) => { + const container = createContainer() + + container.register({ + database: asValue(db), + validate: asValue(models.validate), + ObjectID: asValue(database.ObjectID), + serverSettings: asValue(serverSettings), + stripe: asValue(stripe(stripeSettings.secret)) + }) + + mediator.emit('di.ready', container) + }) + + mediator.on('db.error', (err) => { + mediator.emit('di.error', err) + }) + + database.connect(dbSettings, mediator) + + mediator.emit('boot.ready') + }) +} + +module.exports.initDI = initDI diff --git a/payment/src/config/di/di.proto.js b/payment/src/config/di/di.proto.js new file mode 100644 index 0000000..82e6df1 --- /dev/null +++ b/payment/src/config/di/di.proto.js @@ -0,0 +1,82 @@ +/* + const container = createContainer() + + container.register({ + transient(user), + transient(ticket), + transient(booking), + singleton(objectID), + singleton(notifications), + singleton(payments) + }) + + function ({ User, Booking }) { + make some stuff with the user + Promise.all([ + user.validate(object), + booking.validate(object) + ]) + .then([user, booking] => { + + }) + } + +*/ + +const createContainer = () => { + // DI store + const registrations = {} + // returns the DI + const container = { + get registrations () { + return Object.assign({}, registrations) + } + } + + // DI cache systems + container.cache = {} + + const getDI = new Proxy({}, { + get: (taget, name) => resolve(name), + set: (target, name, value) => { + throw new Error('cannot set a value to the container') + } + }) + + container.getDI = getDI + + const register = (name, registration, opts) => { + const key = Symbol(name) + registrations[key] = Object.assign({}, {fn: registration}, {lifetime: opts}) + return container + } + + container.register = register + + const resolve = (name) => { + const di = registrations[name] + switch (di.lifetime) { + case 'TRANSIENT': + return container.registrations[name].fn + case 'SINGLETON': + if (!container.cache[name]) { + container.cache[name] = container.registrations[name] + } + return container.cache[name].fn + } + } + + const listDependencies = () => { + const list = [] + for (var key in registrations) { + if (registrations.hasOwnProperty(key)) { + list.push(key) + } + } + return list + } + + return Object.create(container) +} + +module.exports.createContainer = createContainer diff --git a/payment/src/config/di/index.js b/payment/src/config/di/index.js new file mode 100644 index 0000000..ff2d63c --- /dev/null +++ b/payment/src/config/di/index.js @@ -0,0 +1,3 @@ +const di = require('./di') + +module.exports = Object.assign({}, di) diff --git a/payment/src/config/index.di.spec.js b/payment/src/config/index.di.spec.js new file mode 100644 index 0000000..e3dfa51 --- /dev/null +++ b/payment/src/config/index.di.spec.js @@ -0,0 +1,24 @@ +/* eslint-env mocha */ +const {EventEmitter} = require('events') +const test = require('assert') +const {init} = require('./') + +describe('DI configuration', () => { + it('can init dependencies to the container', (done) => { + const mediator = new EventEmitter() + + mediator.on('di.ready', (container) => { + console.log(container) + done() + }) + + mediator.on('di.error', err => { + console.log(err) + done() + }) + + init(mediator) + + mediator.emit('init') + }) +}) diff --git a/payment/src/config/index.js b/payment/src/config/index.js new file mode 100644 index 0000000..73d976a --- /dev/null +++ b/payment/src/config/index.js @@ -0,0 +1,8 @@ +const {dbSettings, serverSettings, stripeSettings} = require('./config') +const database = require('./db') +const {initDI} = require('./di') +const models = require('../models') + +const init = initDI.bind(null, {serverSettings, dbSettings, database, models, stripeSettings}) + +module.exports = Object.assign({}, {init}) diff --git a/payment/src/config/ssl/index.js b/payment/src/config/ssl/index.js new file mode 100644 index 0000000..63e4cd3 --- /dev/null +++ b/payment/src/config/ssl/index.js @@ -0,0 +1,6 @@ +const fs = require('fs') + +module.exports = { + key: fs.readFileSync(`${__dirname}/server.key`), + cert: fs.readFileSync(`${__dirname}/server.crt`) +} diff --git a/payment/src/index.js b/payment/src/index.js new file mode 100644 index 0000000..9a1c783 --- /dev/null +++ b/payment/src/index.js @@ -0,0 +1,36 @@ +'use strict' +const {EventEmitter} = require('events') +const server = require('./server/server') +const repository = require('./repository/repository') +const di = require('./config') +const mediator = new EventEmitter() + +console.log('--- Payment Service ---') +console.log('Connecting to payment repository...') + +process.on('uncaughtException', (err) => { + console.error('Unhandled Exception', err) +}) + +process.on('uncaughtRejection', (err, promise) => { + console.error('Unhandled Rejection', err) +}) + +mediator.on('di.ready', (container) => { + repository.connect(container) + .then(repo => { + console.log('Connected. Starting Server') + container.registerValue({repo}) + return server.start(container) + }) + .then(app => { + console.log(`Server started succesfully, running on port: ${container.cradle.serverSettings.port}.`) + app.on('close', () => { + container.resolve('repo').disconnect() + }) + }) +}) + +di.init(mediator) + +mediator.emit('init') diff --git a/payment/src/models/index.js b/payment/src/models/index.js new file mode 100644 index 0000000..df204a4 --- /dev/null +++ b/payment/src/models/index.js @@ -0,0 +1,24 @@ +const joi = require('joi') +const payment = require('./payment.model')(joi) + +const schemas = Object.create({payment}) + +const schemaValidator = (object, type) => { + return new Promise((resolve, reject) => { + if (!object) { + reject(new Error('object to validate not provided')) + } + if (!type) { + reject(new Error('schema type to validate not provided')) + } + + const {error, value} = joi.validate(object, schemas[type]) + + if (error) { + reject(new Error(`invalid ${type} data, err: ${error}`)) + } + resolve(value) + }) +} + +module.exports = Object.create({validate: schemaValidator, schemas}) diff --git a/payment/src/models/index.spec.js b/payment/src/models/index.spec.js new file mode 100644 index 0000000..2602ef2 --- /dev/null +++ b/payment/src/models/index.spec.js @@ -0,0 +1,34 @@ +/* eslint-env mocha */ +const test = require('assert') +const {validate} = require('./') + +console.log(Object.getPrototypeOf(validate)) + +describe('Schemas Validation', () => { + it('can validate a user object', (done) => { + const testPayment = { + userName: 'Cristian Ramirez', + currency: 'mxn', + number: '4242424242424242', + cvc: '123', + exp_month: '12', + exp_year: '2017', + amount: 71, + description: ` + Tickect(s) for movie "Assasins Creed", + with seat(s) 47, 48 + at time 8 / feb / 17` + } + + validate(testPayment, 'payment') + .then(value => { + console.log('validated') + console.log(value) + done() + }) + .catch(err => { + console.log(err) + done() + }) + }) +}) diff --git a/payment/src/models/payment.model.js b/payment/src/models/payment.model.js new file mode 100644 index 0000000..b30ff96 --- /dev/null +++ b/payment/src/models/payment.model.js @@ -0,0 +1,12 @@ +const paymentSchema = (joi) => ({ + userName: joi.string(), + currency: joi.string(), + number: joi.string().creditCard(), + cvc: joi.number(), + exp_month: joi.number(), + exp_year: joi.number(), + amount: joi.number(), + description: joi.string() +}) + +module.exports = paymentSchema diff --git a/payment/src/repository/repository.js b/payment/src/repository/repository.js new file mode 100644 index 0000000..5eb7443 --- /dev/null +++ b/payment/src/repository/repository.js @@ -0,0 +1,76 @@ +'use strict' +const repository = (container) => { + const {database: db} = container.cradle + + const makePurchase = (payment) => { + return new Promise((resolve, reject) => { + const {stripe} = container.cradle + stripe.charges.create({ + amount: Math.ceil(payment.amount * 100), + currency: payment.currency, + source: { + number: payment.number, + cvc: payment.cvc, + exp_month: payment.exp_month, + exp_year: payment.exp_year + }, + description: payment.description + }, (err, charge) => { + if (err && err.type === 'StripeCardError') { + reject(new Error('An error occuered procesing payment with stripe, err: ' + err)) + } else { + const paid = Object.assign({}, {user: payment.userName, amount: payment.amount, charge}) + resolve(paid) + } + }) + }) + } + + const registerPurchase = (payment) => { + return new Promise((resolve, reject) => { + makePurchase(payment) + .then(paid => { + db.collection('payments').insertOne(paid, (err, result) => { + if (err) { + reject(new Error('an error occuered registring payment at db, err:' + err)) + } + resolve(paid) + }) + }) + .catch(err => reject(err)) + }) + } + + const getPurchaseById = (paymentId) => { + return new Promise((resolve, reject) => { + const response = (err, payment) => { + if (err) { + reject(new Error('An error occuered retrieving a order, err: ' + err)) + } + resolve(payment) + } + db.collection('payments').findOne({'charge.id': paymentId}, {}, response) + }) + } + + const disconnect = () => { + db.close() + } + + return Object.create({ + registerPurchase, + getPurchaseById, + disconnect + }) +} + +const connect = (container) => { + return new Promise((resolve, reject) => { + if (!container.resolve('database')) { + reject(new Error('connection db not supplied!')) + } + resolve(repository(container)) + }) +} + +module.exports = Object.assign({}, {connect}) diff --git a/payment/src/repository/repository.spec.js b/payment/src/repository/repository.spec.js new file mode 100644 index 0000000..b423fc2 --- /dev/null +++ b/payment/src/repository/repository.spec.js @@ -0,0 +1,9 @@ +/* eslint-env mocha */ +const should = require('should') +const repository = require('./repository') + +describe('Repository', () => { + it('should connect with a promise', () => { + repository.connect({}).should.be.a.Promise() + }) +}) diff --git a/payment/src/server/server.js b/payment/src/server/server.js new file mode 100644 index 0000000..866aa7f --- /dev/null +++ b/payment/src/server/server.js @@ -0,0 +1,42 @@ +const express = require('express') +const morgan = require('morgan') +const helmet = require('helmet') +const bodyparser = require('body-parser') +const cors = require('cors') +const _api = require('../api/payment') + +const start = (container) => { + return new Promise((resolve, reject) => { + const {port} = container.resolve('serverSettings') + const repo = container.resolve('repo') + + if (!repo) { + reject(new Error('The server must be started with a connected repository')) + } + if (!port) { + reject(new Error('The server must be started with an available port')) + } + + const app = express() + app.use(morgan('dev')) + app.use(bodyparser.json()) + app.use(cors()) + app.use(helmet()) + app.use((err, req, res, next) => { + reject(new Error('Something went wrong!, err:' + err)) + res.status(500).send('Something went wrong!') + next() + }) + app.use((req, res, next) => { + req.container = container.createScope() + next() + }) + + const api = _api.bind(null, {repo}) + api(app) + + const server = app.listen(port, () => resolve(server)) + }) +} + +module.exports = Object.assign({}, {start}) diff --git a/payment/src/server/server.spec.js b/payment/src/server/server.spec.js new file mode 100644 index 0000000..f552ac9 --- /dev/null +++ b/payment/src/server/server.spec.js @@ -0,0 +1,16 @@ +/* eslint-env mocha */ +const server = require('./server') + +describe('Server', () => { + it('should require a port to start', () => { + return server.start({ + repo: {} + }).should.be.rejectedWith(/port/) + }) + + it('should require a repository to start', () => { + return server.start({ + port: {} + }).should.be.rejectedWith(/repository/) + }) +}) From d4ba4cc8e81b7fe28cfb6c7063f82860b521e307 Mon Sep 17 00:00:00 2001 From: michaelact <86778470+michaelact@users.noreply.github.com> Date: Sat, 14 May 2022 01:44:46 +0700 Subject: [PATCH 2/5] feat: kubernetes deployment --- _docker_setup/create-images.sh | 43 - _docker_setup/reset.sh | 16 - _docker_setup/setup-swarm.sh | 136 --- _docker_setup/start-services.sh | 25 - api-gateway/.eslintrc.json | 3 - api-gateway/Dockerfile | 17 - api-gateway/env | 9 - api-gateway/integration-test/index.js | 118 --- .../super-stress-test.jmeter.test.jmx | 198 ---- api-gateway/npm-shrinkwrap.json | 992 ------------------ api-gateway/package.json | 54 - api-gateway/readme.md | 36 - api-gateway/src/config/config.js | 33 - api-gateway/src/config/di/di.js | 16 - api-gateway/src/config/di/index.js | 3 - api-gateway/src/config/index.di.spec.js | 24 - api-gateway/src/config/index.js | 5 - api-gateway/src/config/ssl/index.js | 6 - api-gateway/src/docker/docker.js | 48 - api-gateway/src/docker/docker.spec.js | 16 - api-gateway/src/index.js | 37 - api-gateway/src/repository/repository.js | 12 - api-gateway/src/repository/repository.spec.js | 9 - api-gateway/src/server/server.js | 38 - api-gateway/src/server/server.spec.js | 16 - api-gateway/start-service.sh | 21 - automation/create-machines.sh | 3 - automation/start_all_microservices.sh | 22 - booking-service/.eslintrc.json | 3 - booking-service/Dockerfile | 25 - booking-service/create-image.sh | 11 - booking-service/env | 6 - booking-service/integration-test/index.js | 41 - booking-service/mock/index.js | 43 - booking-service/npm-shrinkwrap.json | 738 ------------- booking-service/package.json | 48 - booking-service/readme.md | 18 - booking-service/src/api/booking.js | 63 -- booking-service/src/api/booking.spec.js | 103 -- booking-service/src/config/config.js | 45 - booking-service/src/config/db/index.js | 4 - booking-service/src/config/db/mongo.js | 32 - booking-service/src/config/db/mongo.spec.js | 29 - booking-service/src/config/di/di.js | 33 - booking-service/src/config/di/di.proto.js | 82 -- booking-service/src/config/di/index.js | 3 - booking-service/src/config/index.di.spec.js | 24 - booking-service/src/config/index.js | 9 - booking-service/src/config/ssl/index.js | 6 - booking-service/src/index.js | 36 - booking-service/src/models/booking.model.js | 14 - booking-service/src/models/index.js | 26 - booking-service/src/models/index.spec.js | 81 -- booking-service/src/models/ticket.model.js | 11 - booking-service/src/models/user.model.js | 15 - booking-service/src/repository/repository.js | 79 -- .../src/repository/repository.spec.js | 9 - booking-service/src/server/server.js | 43 - booking-service/src/server/server.spec.js | 12 - booking-service/src/services/index.js | 4 - .../src/services/notification.service.js | 17 - .../src/services/payment.service.js | 17 - booking-service/start-service.sh | 3 - build.sh | 0 cinema-catalog-service/.eslintrc.json | 3 - cinema-catalog-service/Dockerfile | 25 - cinema-catalog-service/create-image.sh | 11 - cinema-catalog-service/env | 6 - ...cinema-catalog-service-api.jmeter.test.jmx | 182 ---- .../integration-test/index.js | 10 - cinema-catalog-service/npm-shrinkwrap.json | 520 --------- cinema-catalog-service/package.json | 45 - cinema-catalog-service/readme.md | 27 - .../src/api/cinema-catalog.js | 34 - .../src/api/cinema-catalog.spec.js | 126 --- cinema-catalog-service/src/config/config.js | 45 - cinema-catalog-service/src/config/index.js | 5 - cinema-catalog-service/src/config/mongo.js | 32 - .../src/config/mongo.spec.js | 29 - .../src/config/ssl/index.js | 6 - cinema-catalog-service/src/index.js | 45 - cinema-catalog-service/src/mock/cinemas.json | 326 ------ cinema-catalog-service/src/mock/cities.json | 36 - .../src/mock/countries.json | 19 - cinema-catalog-service/src/mock/index.js | 0 cinema-catalog-service/src/mock/states.json | 36 - .../src/repository/repository.js | 98 -- .../src/repository/repository.spec.js | 10 - cinema-catalog-service/src/server/server.js | 29 - .../src/server/server.spec.js | 16 - cinema-catalog-service/start-service.sh | 3 - cover.png | Bin 743388 -> 0 bytes deploy.sh | 0 .../application/booking/deployment.yaml | 47 + .../application/booking/service.yaml | 18 + .../cinema-catalog/deployment.yaml | 47 + .../application/cinema-catalog/service.yaml | 18 + .../application/mongodb/service.yaml | 18 + .../application/mongodb/statefulset.yaml | 39 + .../application/movies/deployment.yaml | 47 + .../application/movies/service.yaml | 18 + .../application/notification/deployment.yaml | 47 + .../application/notification/service.yaml | 18 + .../application/payment/deployment.yaml | 47 + .../application/payment/service.yaml | 18 + .../configmap/production/booking.yaml | 30 + .../configmap/production/cinema-catalog.yaml | 23 + .../configmap/production/database.yaml | 11 + .../configmap/production/movies.yaml | 23 + .../configmap/production/notification.yaml | 23 + .../configmap/production/payment.yaml | 23 + .../kubernetes/configmap/staging/booking.yaml | 23 + .../configmap/staging/cinema-catalog.yaml | 23 + .../configmap/staging/database.yaml | 11 + .../kubernetes/configmap/staging/movies.yaml | 23 + .../configmap/staging/notification.yaml | 24 + .../kubernetes/configmap/staging/payment.yaml | 23 + deploy/kubernetes/deploy.sh | 6 + .../ingress/production/ingress-nginx.yaml | 52 + .../ingress/staging/ingress-nginx.yaml | 52 + kraken.sh | 88 -- movies-service/.eslintrc.json | 3 - movies-service/Dockerfile | 25 - movies-service/create-image.sh | 11 - movies-service/integration-test/index.js | 10 - .../movie-service-api.jmeter.test.jmx | 118 --- movies-service/npm-shrinkwrap.json | 520 --------- movies-service/package.json | 44 - movies-service/readme.md | 14 - movies-service/src/api/movies.js | 24 - movies-service/src/api/movies.spec.js | 103 -- movies-service/src/config/config.js | 45 - movies-service/src/config/index.js | 4 - movies-service/src/config/mongo.js | 32 - movies-service/src/config/mongo.spec.js | 29 - movies-service/src/config/ssl/index.js | 6 - movies-service/src/config/ssl/server.crt | 19 - movies-service/src/config/ssl/server.csr | 17 - movies-service/src/config/ssl/server.key | 27 - movies-service/src/index.js | 45 - movies-service/src/mock/movies.js | 46 - movies-service/src/repository/repository.js | 88 -- .../src/repository/repository.spec.js | 10 - movies-service/src/server/server.js | 29 - movies-service/src/server/server.spec.js | 16 - movies-service/start-service.sh | 3 - notification-service/.eslintrc.json | 3 - notification-service/Dockerfile | 25 - notification-service/create-image.sh | 11 - notification-service/env | 6 - .../integration-test/index.js | 36 - notification-service/npm-shrinkwrap.json | 726 ------------- notification-service/package.json | 51 - notification-service/readme.md | 40 - notification-service/src/api/notification.js | 30 - .../src/api/notification.spec.js | 122 --- notification-service/src/config/config.js | 13 - notification-service/src/config/di/di.js | 21 - .../src/config/di/di.proto.js | 82 -- notification-service/src/config/di/index.js | 3 - .../src/config/index.di.spec.js | 25 - notification-service/src/config/index.js | 7 - notification-service/src/config/ssl/index.js | 6 - notification-service/src/index.js | 36 - notification-service/src/models/index.js | 24 - notification-service/src/models/index.spec.js | 42 - .../src/models/notification.model.js | 25 - .../src/repository/repository.js | 65 -- .../src/repository/repository.spec.js | 9 - notification-service/src/server/server.js | 42 - .../src/server/server.spec.js | 16 - notification-service/start-service.sh | 3 - payment-service/.eslintrc.json | 3 - payment-service/Dockerfile | 25 - payment-service/create-image.sh | 11 - payment-service/env | 6 - payment-service/integration-test/index.js | 28 - payment-service/npm-shrinkwrap.json | 708 ------------- payment-service/package.json | 50 - payment-service/readme.md | 40 - payment-service/src/api/payment.js | 25 - payment-service/src/api/payment.spec.js | 115 -- payment-service/src/config/config.js | 50 - payment-service/src/config/db/index.js | 4 - payment-service/src/config/db/mongo.js | 32 - payment-service/src/config/db/mongo.spec.js | 29 - payment-service/src/config/di/di.js | 30 - payment-service/src/config/di/di.proto.js | 82 -- payment-service/src/config/di/index.js | 3 - payment-service/src/config/index.di.spec.js | 24 - payment-service/src/config/index.js | 8 - payment-service/src/config/ssl/index.js | 6 - payment-service/src/index.js | 36 - payment-service/src/models/index.js | 24 - payment-service/src/models/index.spec.js | 34 - payment-service/src/models/payment.model.js | 12 - payment-service/src/repository/repository.js | 76 -- .../src/repository/repository.spec.js | 9 - payment-service/src/server/server.js | 42 - payment-service/src/server/server.spec.js | 16 - payment-service/start-service.sh | 3 - readme.md | 27 +- 202 files changed, 762 insertions(+), 9806 deletions(-) delete mode 100644 _docker_setup/create-images.sh delete mode 100644 _docker_setup/reset.sh delete mode 100644 _docker_setup/setup-swarm.sh delete mode 100644 _docker_setup/start-services.sh delete mode 100644 api-gateway/.eslintrc.json delete mode 100644 api-gateway/Dockerfile delete mode 100644 api-gateway/env delete mode 100644 api-gateway/integration-test/index.js delete mode 100644 api-gateway/integration-test/super-stress-test.jmeter.test.jmx delete mode 100644 api-gateway/npm-shrinkwrap.json delete mode 100644 api-gateway/package.json delete mode 100644 api-gateway/readme.md delete mode 100644 api-gateway/src/config/config.js delete mode 100644 api-gateway/src/config/di/di.js delete mode 100644 api-gateway/src/config/di/index.js delete mode 100644 api-gateway/src/config/index.di.spec.js delete mode 100644 api-gateway/src/config/index.js delete mode 100644 api-gateway/src/config/ssl/index.js delete mode 100644 api-gateway/src/docker/docker.js delete mode 100644 api-gateway/src/docker/docker.spec.js delete mode 100644 api-gateway/src/index.js delete mode 100644 api-gateway/src/repository/repository.js delete mode 100644 api-gateway/src/repository/repository.spec.js delete mode 100644 api-gateway/src/server/server.js delete mode 100644 api-gateway/src/server/server.spec.js delete mode 100644 api-gateway/start-service.sh delete mode 100644 automation/create-machines.sh delete mode 100644 automation/start_all_microservices.sh delete mode 100644 booking-service/.eslintrc.json delete mode 100644 booking-service/Dockerfile delete mode 100644 booking-service/create-image.sh delete mode 100644 booking-service/env delete mode 100644 booking-service/integration-test/index.js delete mode 100644 booking-service/mock/index.js delete mode 100644 booking-service/npm-shrinkwrap.json delete mode 100644 booking-service/package.json delete mode 100644 booking-service/readme.md delete mode 100644 booking-service/src/api/booking.js delete mode 100644 booking-service/src/api/booking.spec.js delete mode 100644 booking-service/src/config/config.js delete mode 100644 booking-service/src/config/db/index.js delete mode 100644 booking-service/src/config/db/mongo.js delete mode 100644 booking-service/src/config/db/mongo.spec.js delete mode 100644 booking-service/src/config/di/di.js delete mode 100644 booking-service/src/config/di/di.proto.js delete mode 100644 booking-service/src/config/di/index.js delete mode 100644 booking-service/src/config/index.di.spec.js delete mode 100644 booking-service/src/config/index.js delete mode 100644 booking-service/src/config/ssl/index.js delete mode 100644 booking-service/src/index.js delete mode 100644 booking-service/src/models/booking.model.js delete mode 100644 booking-service/src/models/index.js delete mode 100644 booking-service/src/models/index.spec.js delete mode 100644 booking-service/src/models/ticket.model.js delete mode 100644 booking-service/src/models/user.model.js delete mode 100644 booking-service/src/repository/repository.js delete mode 100644 booking-service/src/repository/repository.spec.js delete mode 100644 booking-service/src/server/server.js delete mode 100644 booking-service/src/server/server.spec.js delete mode 100644 booking-service/src/services/index.js delete mode 100644 booking-service/src/services/notification.service.js delete mode 100644 booking-service/src/services/payment.service.js delete mode 100644 booking-service/start-service.sh mode change 100644 => 100755 build.sh delete mode 100644 cinema-catalog-service/.eslintrc.json delete mode 100644 cinema-catalog-service/Dockerfile delete mode 100644 cinema-catalog-service/create-image.sh delete mode 100644 cinema-catalog-service/env delete mode 100644 cinema-catalog-service/integration-test/cinema-catalog-service-api.jmeter.test.jmx delete mode 100644 cinema-catalog-service/integration-test/index.js delete mode 100644 cinema-catalog-service/npm-shrinkwrap.json delete mode 100644 cinema-catalog-service/package.json delete mode 100644 cinema-catalog-service/readme.md delete mode 100644 cinema-catalog-service/src/api/cinema-catalog.js delete mode 100644 cinema-catalog-service/src/api/cinema-catalog.spec.js delete mode 100644 cinema-catalog-service/src/config/config.js delete mode 100644 cinema-catalog-service/src/config/index.js delete mode 100644 cinema-catalog-service/src/config/mongo.js delete mode 100644 cinema-catalog-service/src/config/mongo.spec.js delete mode 100644 cinema-catalog-service/src/config/ssl/index.js delete mode 100644 cinema-catalog-service/src/index.js delete mode 100755 cinema-catalog-service/src/mock/cinemas.json delete mode 100755 cinema-catalog-service/src/mock/cities.json delete mode 100755 cinema-catalog-service/src/mock/countries.json delete mode 100755 cinema-catalog-service/src/mock/index.js delete mode 100755 cinema-catalog-service/src/mock/states.json delete mode 100644 cinema-catalog-service/src/repository/repository.js delete mode 100644 cinema-catalog-service/src/repository/repository.spec.js delete mode 100644 cinema-catalog-service/src/server/server.js delete mode 100644 cinema-catalog-service/src/server/server.spec.js delete mode 100644 cinema-catalog-service/start-service.sh delete mode 100644 cover.png mode change 100644 => 100755 deploy.sh create mode 100644 deploy/kubernetes/application/booking/deployment.yaml create mode 100644 deploy/kubernetes/application/booking/service.yaml create mode 100644 deploy/kubernetes/application/cinema-catalog/deployment.yaml create mode 100644 deploy/kubernetes/application/cinema-catalog/service.yaml create mode 100644 deploy/kubernetes/application/mongodb/service.yaml create mode 100644 deploy/kubernetes/application/mongodb/statefulset.yaml create mode 100644 deploy/kubernetes/application/movies/deployment.yaml create mode 100644 deploy/kubernetes/application/movies/service.yaml create mode 100644 deploy/kubernetes/application/notification/deployment.yaml create mode 100644 deploy/kubernetes/application/notification/service.yaml create mode 100644 deploy/kubernetes/application/payment/deployment.yaml create mode 100644 deploy/kubernetes/application/payment/service.yaml create mode 100644 deploy/kubernetes/configmap/production/booking.yaml create mode 100644 deploy/kubernetes/configmap/production/cinema-catalog.yaml create mode 100644 deploy/kubernetes/configmap/production/database.yaml create mode 100644 deploy/kubernetes/configmap/production/movies.yaml create mode 100644 deploy/kubernetes/configmap/production/notification.yaml create mode 100644 deploy/kubernetes/configmap/production/payment.yaml create mode 100644 deploy/kubernetes/configmap/staging/booking.yaml create mode 100644 deploy/kubernetes/configmap/staging/cinema-catalog.yaml create mode 100644 deploy/kubernetes/configmap/staging/database.yaml create mode 100644 deploy/kubernetes/configmap/staging/movies.yaml create mode 100644 deploy/kubernetes/configmap/staging/notification.yaml create mode 100644 deploy/kubernetes/configmap/staging/payment.yaml create mode 100755 deploy/kubernetes/deploy.sh create mode 100644 deploy/kubernetes/ingress/production/ingress-nginx.yaml create mode 100644 deploy/kubernetes/ingress/staging/ingress-nginx.yaml delete mode 100644 kraken.sh delete mode 100644 movies-service/.eslintrc.json delete mode 100644 movies-service/Dockerfile delete mode 100644 movies-service/create-image.sh delete mode 100644 movies-service/integration-test/index.js delete mode 100644 movies-service/integration-test/movie-service-api.jmeter.test.jmx delete mode 100644 movies-service/npm-shrinkwrap.json delete mode 100644 movies-service/package.json delete mode 100644 movies-service/readme.md delete mode 100644 movies-service/src/api/movies.js delete mode 100644 movies-service/src/api/movies.spec.js delete mode 100644 movies-service/src/config/config.js delete mode 100644 movies-service/src/config/index.js delete mode 100644 movies-service/src/config/mongo.js delete mode 100644 movies-service/src/config/mongo.spec.js delete mode 100644 movies-service/src/config/ssl/index.js delete mode 100644 movies-service/src/config/ssl/server.crt delete mode 100644 movies-service/src/config/ssl/server.csr delete mode 100644 movies-service/src/config/ssl/server.key delete mode 100644 movies-service/src/index.js delete mode 100644 movies-service/src/mock/movies.js delete mode 100644 movies-service/src/repository/repository.js delete mode 100644 movies-service/src/repository/repository.spec.js delete mode 100644 movies-service/src/server/server.js delete mode 100644 movies-service/src/server/server.spec.js delete mode 100644 movies-service/start-service.sh delete mode 100644 notification-service/.eslintrc.json delete mode 100644 notification-service/Dockerfile delete mode 100644 notification-service/create-image.sh delete mode 100644 notification-service/env delete mode 100644 notification-service/integration-test/index.js delete mode 100644 notification-service/npm-shrinkwrap.json delete mode 100644 notification-service/package.json delete mode 100644 notification-service/readme.md delete mode 100644 notification-service/src/api/notification.js delete mode 100644 notification-service/src/api/notification.spec.js delete mode 100644 notification-service/src/config/config.js delete mode 100644 notification-service/src/config/di/di.js delete mode 100644 notification-service/src/config/di/di.proto.js delete mode 100644 notification-service/src/config/di/index.js delete mode 100644 notification-service/src/config/index.di.spec.js delete mode 100644 notification-service/src/config/index.js delete mode 100644 notification-service/src/config/ssl/index.js delete mode 100644 notification-service/src/index.js delete mode 100644 notification-service/src/models/index.js delete mode 100644 notification-service/src/models/index.spec.js delete mode 100644 notification-service/src/models/notification.model.js delete mode 100644 notification-service/src/repository/repository.js delete mode 100644 notification-service/src/repository/repository.spec.js delete mode 100644 notification-service/src/server/server.js delete mode 100644 notification-service/src/server/server.spec.js delete mode 100644 notification-service/start-service.sh delete mode 100644 payment-service/.eslintrc.json delete mode 100644 payment-service/Dockerfile delete mode 100644 payment-service/create-image.sh delete mode 100644 payment-service/env delete mode 100644 payment-service/integration-test/index.js delete mode 100644 payment-service/npm-shrinkwrap.json delete mode 100644 payment-service/package.json delete mode 100644 payment-service/readme.md delete mode 100644 payment-service/src/api/payment.js delete mode 100644 payment-service/src/api/payment.spec.js delete mode 100644 payment-service/src/config/config.js delete mode 100644 payment-service/src/config/db/index.js delete mode 100644 payment-service/src/config/db/mongo.js delete mode 100644 payment-service/src/config/db/mongo.spec.js delete mode 100644 payment-service/src/config/di/di.js delete mode 100644 payment-service/src/config/di/di.proto.js delete mode 100644 payment-service/src/config/di/index.js delete mode 100644 payment-service/src/config/index.di.spec.js delete mode 100644 payment-service/src/config/index.js delete mode 100644 payment-service/src/config/ssl/index.js delete mode 100644 payment-service/src/index.js delete mode 100644 payment-service/src/models/index.js delete mode 100644 payment-service/src/models/index.spec.js delete mode 100644 payment-service/src/models/payment.model.js delete mode 100644 payment-service/src/repository/repository.js delete mode 100644 payment-service/src/repository/repository.spec.js delete mode 100644 payment-service/src/server/server.js delete mode 100644 payment-service/src/server/server.spec.js delete mode 100644 payment-service/start-service.sh diff --git a/_docker_setup/create-images.sh b/_docker_setup/create-images.sh deleted file mode 100644 index 6edb5e5..0000000 --- a/_docker_setup/create-images.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env bash - -eval `docker-machine env manager1` - -array=('./movies-service' - './cinema-catalog-service' - './booking-service' - './payment-service' - './notification-service' -) - -# we go to the root of the project -cd .. - -for ((i = 0; i < ${#array[@]}; ++i)); do - # we go to each folder - cd ${array[$i]} - - # we get the name of our image - SERVICE=$(echo ${array[$i]} | cut -d'/' -f 2) - - # we delete the image if it exists already - docker rmi crizstian/$SERVICE - - # we create or recreate our image - sh ./create-image.sh - - # we get the image id so we can tag it - IMAGE_ID=$(docker images -q $SERVICE) - - # we tag our image so we can publish it to our docker hub account - docker tag $IMAGE_ID crizstian/$SERVICE:latest - - # we publish our image to our docker hub account - docker push crizstian/$SERVICE:latest - - # we delete our local image because we are not going to need it - # and mantain clean our environment - docker rmi $SERVICE - - # and we go back to the root again :D - cd .. -done diff --git a/_docker_setup/reset.sh b/_docker_setup/reset.sh deleted file mode 100644 index f7a984e..0000000 --- a/_docker_setup/reset.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash - -eval `docker-machine env manager1` - -docker service rm movies-service notification-service cinema-catalog-service payment-service booking-service - -for server in manager1 worker1 worker2 -do - eval `docker-machine env $server` - - for image in crizstian/movies-service crizstian/cinema-catalog-service crizstian/booking-service crizstian/payment-service crizstian/notification-service - do - IMAGE=$(docker images $image -q) - docker rmi -f $IMAGE - done -done diff --git a/_docker_setup/setup-swarm.sh b/_docker_setup/setup-swarm.sh deleted file mode 100644 index b9c45b4..0000000 --- a/_docker_setup/setup-swarm.sh +++ /dev/null @@ -1,136 +0,0 @@ -#!/bin/bash - -# default parameters -DRIVER="virtualbox" -MANAGERS=1 -WORKERS=2 -DISK_SIZE="20000" -MEMORY="2048" -DOCKER_VERSION="https://github.com/boot2docker/boot2docker/releases/download/v1.13.0/boot2docker.iso" -ADDITIONAL_PARAMS= - -function usage { - echo "Usage: bash $0 [OPTIONS] - -Run a command in a new container - -Options: - -d, --driver virtual machine provider or cloud provider (default virtualbox) - -m, --manager number of managers to create (default 1) - -w, --worker number of workers to create (default 2) - -v, --version boot2docker github url (default version 1.13.0) - -ds, --disksize hard disk size for docker-machine (default 20GB) - -r, --memory memory ram size for docker-machine (default 2GB)" - exit 1 -} - -# get parameters -while [ "$#" -gt 0 ]; do - case "$1" in - --driver|-d) - DRIVER="$2" - shift 2 - ;; - --manager|-m) - MANAGERS="$2" - shift 2 - ;; - --worker|-w) - WORKERS="$2" - shift 2 - ;; - --version|-v) - DOCKER_VERSION="$2" - shift 2 - ;; - --disksize|-ds) - DISK_SIZE="$2" - shift 2 - ;; - --memory|-r) - MEMORY="$2" - shift 2 - ;; - -h|--help) - usage - ;; - esac -done - -if [ "$DRIVER" == "virtualbox" ]; then - echo "-> about to create a swarm with $MANAGERS manager(s) and $WORKERS WORKERS on $DRIVER machines" - ADDITIONAL_PARAMS="--virtualbox-disk-size ${DISK_SIZE} --virtualbox-memory ${MEMORY} --virtualbox-boot2docker-url=${DOCKER_VERSION}" -fi - -function getIP { - echo $(docker-machine ip $1) -} - -function get_worker_token { - echo $(docker-machine ssh manager1 docker swarm join-token worker -q) -} - -function createManagerNode { - # create manager machines - for i in $(seq 1 $MANAGERS); - do - echo "== Creating manager$i machine ..."; - docker-machine create -d $DRIVER $ADDITIONAL_PARAMS manager$i - done -} - -function createWorkerNode { - # create worker machines - for i in $(seq 1 $WORKERS); - do - echo "== Creating worker$i machine ..."; - docker-machine create -d $DRIVER $ADDITIONAL_PARAMS worker$i - done -} - -function initSwarmManager { - # initialize swarm mode and create a manager - echo '============================================' - echo "======> Initializing first swarm manager ..." - docker-machine ssh manager1 docker swarm init --advertise-addr $(getIP manager1) -} - -function join_node_swarm { - # WORKERS join swarm - for node in $(seq 1 $WORKERS); - do - echo "======> worker$node joining swarm as worker ..." - docker-machine ssh worker$node docker swarm join --token $(get_worker_token) $(getIP manager1):2377 - done -} - -# Display status -function status { - echo "-> list swarm nodes" - docker-machine ssh manager1 docker node ls - echo - echo "-> list machines" - docker-machine ls -} - -# Start RancherOS -function startRancherOS { - echo "-> Starting RancherOS to monitor the cluster" - docker-machine ssh manager1 docker run --name rancher --restart=unless-stopped -p 9000:8080 -d rancher/server -} - -function main { - createManagerNode - createWorkerNode - initSwarmManager - join_node_swarm - status - startRancherOS -} - -function reset { - docker-machine rm manager1 worker1 worker2 -y -} - -reset -main diff --git a/_docker_setup/start-services.sh b/_docker_setup/start-services.sh deleted file mode 100644 index 2f7845e..0000000 --- a/_docker_setup/start-services.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash - -eval `docker-machine env manager1` - -array=('./movies-service' - './cinema-catalog-service' - './booking-service' - './payment-service' - './notification-service' - './api-gateway' -) - -# we go to the root of the project -cd .. - -for ((i = 0; i < ${#array[@]}; ++i)); do - # we go to each folder - cd ${array[$i]} - - # we create or recreate our image - sh ./start-service.sh - - # and we go back to the root again :D - cd .. -done diff --git a/api-gateway/.eslintrc.json b/api-gateway/.eslintrc.json deleted file mode 100644 index a755cdb..0000000 --- a/api-gateway/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": ["standard"] -} diff --git a/api-gateway/Dockerfile b/api-gateway/Dockerfile deleted file mode 100644 index d1877c7..0000000 --- a/api-gateway/Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -FROM node:7.5.0-alpine - -ENV HOME=/home/nupp - -COPY package.json npm-shrinkwrap.json $HOME/app/ - -COPY src/ $HOME/app/src - -ADD https://github.com/Yelp/dumb-init/releases/download/v1.1.1/dumb-init_1.1.1_amd64 /usr/local/bin/dumb-init - -WORKDIR $HOME/app - -RUN chmod +x /usr/local/bin/dumb-init && \ - npm cache clean && \ - npm install --silent --progress=false --production - -CMD ["dumb-init", "npm", "start"] diff --git a/api-gateway/env b/api-gateway/env deleted file mode 100644 index ff511d4..0000000 --- a/api-gateway/env +++ /dev/null @@ -1,9 +0,0 @@ -DB=booking -DB_USER=cristian -DB_PASS=cristianPassword2017 -DB_REPLS=rs1 -DB_SERVERS='192.168.99.100:27017 192.168.99.101:27017 192.168.99.102:27017' -PORT=8080 -DOCKER_HOST=tcp://192.168.99.100:2376 -DOCKER_TLS_VERIFY=1 -DOCKER_CERT_PATH=/certs diff --git a/api-gateway/integration-test/index.js b/api-gateway/integration-test/index.js deleted file mode 100644 index bcf84f1..0000000 --- a/api-gateway/integration-test/index.js +++ /dev/null @@ -1,118 +0,0 @@ -/* eslint-env mocha */ -const supertest = require('supertest') -process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' -process.env.NODE_TLS_ACCEPT_UNTRUSTED_CERTIFICATES_THIS_IS_INSECURE = '1' - -describe('API Gateway Service', () => { - it('returns a 200 for a known movies through api-gateway', (done) => { - const url = 'https://192.168.99.100:8080' - const api = supertest(url) - console.log(`Calling the server ${url}`) - - api.get('/movies/premieres') - .expect(200, done) - }) - - it('returns schedules for a movie through api-gateway', (done) => { - const url = 'https://192.168.99.101:8080' - const api = supertest(url) - console.log(`Calling the server ${url}`) - - api.get('/cinemas/588ababf2d029a6d15d0b5bf/1') - .expect(200, done) - }) - - it('can make a booking through api-gateway', function (done) { - this.timeout(5000) - const url = 'https://192.168.99.102:8080' - const api = supertest(url) - console.log(`Calling the server ${url}`) - - const now = new Date() - now.setDate(now.getDate() + 1) - const user = { - name: 'Cristian', - lastName: 'Ramirez', - email: 'cristiano@gmail.com', - creditCard: { - number: '4242424242424242', - cvc: '123', - exp_month: '12', - exp_year: '2017' - }, - membership: '7777888899990000' - } - - const booking = { - city: 'Morelia', - cinema: 'Plaza Morelia', - movie: { - title: 'Assasins Creed', - format: 'IMAX' - }, - schedule: now.toString(), - cinemaRoom: 7, - seats: ['45'], - totalAmount: 71 - } - - api.post('/booking') - .send({user, booking}) - .expect(200, done) - }) - - it('can make a paymentOrder through api-gateway', function (done) { - this.timeout(3000) - const url = 'https://192.168.99.100:8080' - const api = supertest(url) - console.log(`Calling the server ${url}`) - - const testPayment = { - userName: 'Cristian Ramirez', - currency: 'mxn', - number: '4242424242424242', - cvc: '123', - exp_month: '12', - exp_year: '2017', - amount: 71, - description: ` - Tickect(s) for movie "Assasins Creed", - with seat(s) 47, 48 - at time 8 / feb / 17` - } - api.post('/payment/makePurchase') - .send({paymentOrder: testPayment}) - .expect(200, done) - }) - - it('can send a notification through api-gateway', function (done) { - this.timeout(3000) - const url = 'https://192.168.99.101:8080' - const api = supertest(url) - console.log(`Calling the server ${url}`) - const payload = { - city: 'Morelia', - userType: 'loyal', - totalAmount: 71, - cinema: { - name: 'Plaza Morelia', - room: '1', - seats: '53, 54' - }, - movie: { - title: 'Assasins Creed', - format: 'IMAX', - schedule: new Date() - }, - orderId: '1aa90cx', - description: 'some description', - user: { - name: 'Cristian Ramirez', - email: 'cristiano.rosetti@gmail.com' - } - } - api.post('/notification/sendEmail') - .send({payload}) - .expect(200, done) - }) -}) diff --git a/api-gateway/integration-test/super-stress-test.jmeter.test.jmx b/api-gateway/integration-test/super-stress-test.jmeter.test.jmx deleted file mode 100644 index 682de81..0000000 --- a/api-gateway/integration-test/super-stress-test.jmeter.test.jmx +++ /dev/null @@ -1,198 +0,0 @@ - - - - - - false - false - - - - - - - - - - Content-Type - application/json - - - Accept - application/json - - - - - - continue - - false - 1 - - 1000 - 1000 - 1485133702000 - 1485133702000 - false - - - - - - - - - 192.168.99.100 - 8080 - - - https - - - 6 - - - - - - - 192.168.99.101 - 8080 - - - https - - - 6 - - - - - - - 192.168.99.102 - 8080 - - - https - - - 6 - - - - - - - false - 1 - = - true - id - - - - - - - - - - /movies - GET - true - false - true - false - false - - - - - - - - - - - - - - /cinemas/588ababf2d029a6d15d0b5bf/1 - GET - true - false - true - false - false - - - - - true - - - - false - { - "user": { - "name": "Cristian", - "lastName": "Ramirez", - "email": "cristiano@gmail.com", - "creditCard": { - "number": "4242424242424242", - "cvc": "123", - "exp_month": "12", - "exp_year": "2017" - }, - "membership": "7777888899990000" - }, - - "booking": { - "city": "Morelia", - "cinema": "Plaza Morelia", - "movie": { - "title": "Assasins Creed", - "format": "IMAX" - }, - "schedule": "2017-03-19T01:28:50.886Z", - "cinemaRoom": 7, - "seats": ["45"], - "totalAmount": 71 - } - } - = - - - - - - - - - - /booking - POST - true - false - true - false - false - - - - - - - Content-type - application/json - - - - - - - - - diff --git a/api-gateway/npm-shrinkwrap.json b/api-gateway/npm-shrinkwrap.json deleted file mode 100644 index 3e0213d..0000000 --- a/api-gateway/npm-shrinkwrap.json +++ /dev/null @@ -1,992 +0,0 @@ -{ - "name": "movies-service", - "version": "1.0.0", - "dependencies": { - "accepts": { - "version": "1.3.3", - "from": "accepts@>=1.3.3 <1.4.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz" - }, - "arr-diff": { - "version": "2.0.0", - "from": "arr-diff@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz" - }, - "arr-flatten": { - "version": "1.0.1", - "from": "arr-flatten@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.0.1.tgz" - }, - "array-flatten": { - "version": "1.1.1", - "from": "array-flatten@1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" - }, - "array-unique": { - "version": "0.2.1", - "from": "array-unique@>=0.2.1 <0.3.0", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz" - }, - "awilix": { - "version": "2.2.2", - "from": "awilix@latest", - "resolved": "https://registry.npmjs.org/awilix/-/awilix-2.2.2.tgz" - }, - "balanced-match": { - "version": "0.4.2", - "from": "balanced-match@>=0.4.1 <0.5.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz" - }, - "basic-auth": { - "version": "1.0.4", - "from": "basic-auth@>=1.0.3 <1.1.0", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz" - }, - "body-parser": { - "version": "1.16.0", - "from": "body-parser@latest", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.16.0.tgz", - "dependencies": { - "qs": { - "version": "6.2.1", - "from": "qs@6.2.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.1.tgz" - } - } - }, - "brace-expansion": { - "version": "1.1.6", - "from": "brace-expansion@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz" - }, - "braces": { - "version": "1.8.5", - "from": "braces@>=1.8.2 <2.0.0", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz" - }, - "bson": { - "version": "0.4.23", - "from": "bson@>=0.4.23 <0.5.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-0.4.23.tgz" - }, - "buffer-shims": { - "version": "1.0.0", - "from": "buffer-shims@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" - }, - "bytes": { - "version": "2.4.0", - "from": "bytes@2.4.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz" - }, - "camel-case": { - "version": "3.0.0", - "from": "camel-case@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz" - }, - "camelize": { - "version": "1.0.0", - "from": "camelize@1.0.0", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz" - }, - "collections": { - "version": "3.0.0", - "from": "collections@3.0.0", - "resolved": "https://registry.npmjs.org/collections/-/collections-3.0.0.tgz" - }, - "concat-map": { - "version": "0.0.1", - "from": "concat-map@0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" - }, - "connect": { - "version": "3.5.0", - "from": "connect@3.5.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.5.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "content-disposition": { - "version": "0.5.1", - "from": "content-disposition@0.5.1", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz" - }, - "content-security-policy-builder": { - "version": "1.1.0", - "from": "content-security-policy-builder@1.1.0", - "resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-1.1.0.tgz" - }, - "content-type": { - "version": "1.0.2", - "from": "content-type@>=1.0.2 <1.1.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz" - }, - "cookie": { - "version": "0.3.1", - "from": "cookie@0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz" - }, - "cookie-signature": { - "version": "1.0.6", - "from": "cookie-signature@1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" - }, - "core-util-is": { - "version": "1.0.2", - "from": "core-util-is@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" - }, - "cors": { - "version": "2.8.1", - "from": "cors@latest", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.1.tgz" - }, - "dasherize": { - "version": "2.0.0", - "from": "dasherize@2.0.0", - "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz" - }, - "dashify": { - "version": "0.2.2", - "from": "dashify@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/dashify/-/dashify-0.2.2.tgz" - }, - "debug": { - "version": "2.6.0", - "from": "debug@>=2.1.1 <3.0.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz" - }, - "depd": { - "version": "1.1.0", - "from": "depd@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz" - }, - "destroy": { - "version": "1.0.4", - "from": "destroy@>=1.0.4 <1.1.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" - }, - "dns-prefetch-control": { - "version": "0.1.0", - "from": "dns-prefetch-control@0.1.0", - "resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz" - }, - "docker-modem": { - "version": "0.3.4", - "from": "docker-modem@>=0.3.0 <0.4.0", - "resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-0.3.4.tgz", - "dependencies": { - "isarray": { - "version": "0.0.1", - "from": "isarray@0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" - }, - "readable-stream": { - "version": "1.0.34", - "from": "readable-stream@>=1.0.26-4 <1.1.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz" - } - } - }, - "dockerode": { - "version": "2.3.1", - "from": "dockerode@latest", - "resolved": "https://registry.npmjs.org/dockerode/-/dockerode-2.3.1.tgz" - }, - "dont-sniff-mimetype": { - "version": "1.0.0", - "from": "dont-sniff-mimetype@1.0.0", - "resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.0.0.tgz" - }, - "ee-first": { - "version": "1.1.1", - "from": "ee-first@1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" - }, - "encodeurl": { - "version": "1.0.1", - "from": "encodeurl@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz" - }, - "es6-promise": { - "version": "3.0.2", - "from": "es6-promise@3.0.2", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz" - }, - "escape-html": { - "version": "1.0.3", - "from": "escape-html@>=1.0.3 <1.1.0", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" - }, - "etag": { - "version": "1.7.0", - "from": "etag@>=1.7.0 <1.8.0", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz" - }, - "eventemitter3": { - "version": "1.2.0", - "from": "eventemitter3@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz" - }, - "expand-brackets": { - "version": "0.1.5", - "from": "expand-brackets@>=0.1.4 <0.2.0", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz" - }, - "expand-range": { - "version": "1.8.2", - "from": "expand-range@>=1.8.1 <2.0.0", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz" - }, - "express": { - "version": "4.14.0", - "from": "express@latest", - "resolved": "https://registry.npmjs.org/express/-/express-4.14.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - }, - "qs": { - "version": "6.2.0", - "from": "qs@6.2.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz" - } - } - }, - "extglob": { - "version": "0.3.2", - "from": "extglob@>=0.3.1 <0.4.0", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "from": "is-extglob@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" - } - } - }, - "filename-regex": { - "version": "2.0.0", - "from": "filename-regex@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.0.tgz" - }, - "fill-range": { - "version": "2.2.3", - "from": "fill-range@>=2.1.0 <3.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "dependencies": { - "isobject": { - "version": "2.1.0", - "from": "isobject@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz" - } - } - }, - "finalhandler": { - "version": "0.5.0", - "from": "finalhandler@0.5.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@~2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "for-in": { - "version": "0.1.6", - "from": "for-in@>=0.1.5 <0.2.0", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.6.tgz" - }, - "for-own": { - "version": "0.1.4", - "from": "for-own@>=0.1.4 <0.2.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.4.tgz" - }, - "forwarded": { - "version": "0.1.0", - "from": "forwarded@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz" - }, - "frameguard": { - "version": "3.0.0", - "from": "frameguard@3.0.0", - "resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.0.0.tgz" - }, - "fresh": { - "version": "0.3.0", - "from": "fresh@0.3.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz" - }, - "fs.realpath": { - "version": "1.0.0", - "from": "fs.realpath@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" - }, - "glob": { - "version": "7.1.1", - "from": "glob@>=7.0.3 <8.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz" - }, - "glob-base": { - "version": "0.3.0", - "from": "glob-base@>=0.3.0 <0.4.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "from": "is-extglob@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" - }, - "is-glob": { - "version": "2.0.1", - "from": "is-glob@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" - } - } - }, - "glob-parent": { - "version": "2.0.0", - "from": "glob-parent@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "from": "is-extglob@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" - }, - "is-glob": { - "version": "2.0.1", - "from": "is-glob@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" - } - } - }, - "handle-thing": { - "version": "1.2.5", - "from": "handle-thing@>=1.2.4 <2.0.0", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz" - }, - "helmet": { - "version": "3.4.0", - "from": "helmet@>=3.4.0 <4.0.0", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.4.0.tgz" - }, - "helmet-csp": { - "version": "2.3.0", - "from": "helmet-csp@2.3.0", - "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.3.0.tgz" - }, - "hide-powered-by": { - "version": "1.0.0", - "from": "hide-powered-by@1.0.0", - "resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.0.0.tgz" - }, - "hpack.js": { - "version": "2.1.6", - "from": "hpack.js@>=2.1.6 <3.0.0", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz" - }, - "hpkp": { - "version": "2.0.0", - "from": "hpkp@2.0.0", - "resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz" - }, - "hsts": { - "version": "2.0.0", - "from": "hsts@2.0.0", - "resolved": "https://registry.npmjs.org/hsts/-/hsts-2.0.0.tgz" - }, - "http-deceiver": { - "version": "1.2.7", - "from": "http-deceiver@>=1.2.4 <2.0.0", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" - }, - "http-errors": { - "version": "1.5.1", - "from": "http-errors@>=1.5.0 <1.6.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz" - }, - "http-proxy": { - "version": "1.16.2", - "from": "http-proxy@latest", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz" - }, - "http-proxy-middleware": { - "version": "0.17.3", - "from": "http-proxy-middleware@latest", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.3.tgz" - }, - "http-status": { - "version": "0.2.5", - "from": "http-status@latest", - "resolved": "https://registry.npmjs.org/http-status/-/http-status-0.2.5.tgz" - }, - "iconv-lite": { - "version": "0.4.15", - "from": "iconv-lite@0.4.15", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz" - }, - "ienoopen": { - "version": "1.0.0", - "from": "ienoopen@1.0.0", - "resolved": "https://registry.npmjs.org/ienoopen/-/ienoopen-1.0.0.tgz" - }, - "inflight": { - "version": "1.0.6", - "from": "inflight@>=1.0.4 <2.0.0", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" - }, - "inherits": { - "version": "2.0.3", - "from": "inherits@>=2.0.1 <2.1.0", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - }, - "ipaddr.js": { - "version": "1.2.0", - "from": "ipaddr.js@1.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.2.0.tgz" - }, - "is-buffer": { - "version": "1.1.4", - "from": "is-buffer@>=1.0.2 <2.0.0", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.4.tgz" - }, - "is-class": { - "version": "0.0.4", - "from": "is-class@0.0.4", - "resolved": "https://registry.npmjs.org/is-class/-/is-class-0.0.4.tgz" - }, - "is-dotfile": { - "version": "1.0.2", - "from": "is-dotfile@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.2.tgz" - }, - "is-equal-shallow": { - "version": "0.1.3", - "from": "is-equal-shallow@>=0.1.3 <0.2.0", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz" - }, - "is-extendable": { - "version": "0.1.1", - "from": "is-extendable@>=0.1.1 <0.2.0", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" - }, - "is-extglob": { - "version": "2.1.1", - "from": "is-extglob@>=2.1.0 <3.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" - }, - "is-glob": { - "version": "3.1.0", - "from": "is-glob@>=3.1.0 <4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz" - }, - "is-number": { - "version": "2.1.0", - "from": "is-number@>=2.1.0 <3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz" - }, - "is-plain-object": { - "version": "2.0.1", - "from": "is-plain-object@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.1.tgz" - }, - "is-posix-bracket": { - "version": "0.1.1", - "from": "is-posix-bracket@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz" - }, - "is-primitive": { - "version": "2.0.0", - "from": "is-primitive@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz" - }, - "is-string": { - "version": "1.0.4", - "from": "is-string@>=1.0.4 <2.0.0", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.4.tgz" - }, - "isarray": { - "version": "1.0.0", - "from": "isarray@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - }, - "isemail": { - "version": "2.2.1", - "from": "isemail@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/isemail/-/isemail-2.2.1.tgz" - }, - "isobject": { - "version": "1.0.2", - "from": "isobject@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-1.0.2.tgz" - }, - "items": { - "version": "2.1.1", - "from": "items@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/items/-/items-2.1.1.tgz" - }, - "joi": { - "version": "10.2.0", - "from": "joi@latest", - "resolved": "https://registry.npmjs.org/joi/-/joi-10.2.0.tgz", - "dependencies": { - "hoek": { - "version": "4.1.0", - "from": "hoek@>=4.0.0 <5.0.0", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.1.0.tgz" - } - } - }, - "jsonparse": { - "version": "0.0.5", - "from": "jsonparse@0.0.5", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz" - }, - "JSONStream": { - "version": "0.10.0", - "from": "JSONStream@0.10.0", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.10.0.tgz" - }, - "kind-of": { - "version": "3.1.0", - "from": "kind-of@>=3.0.2 <4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.1.0.tgz" - }, - "lodash": { - "version": "4.17.4", - "from": "lodash@>=4.0.0 <5.0.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz" - }, - "lodash.reduce": { - "version": "4.6.0", - "from": "lodash.reduce@4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz" - }, - "lower-case": { - "version": "1.1.3", - "from": "lower-case@>=1.1.1 <2.0.0", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.3.tgz" - }, - "media-typer": { - "version": "0.3.0", - "from": "media-typer@0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" - }, - "merge-descriptors": { - "version": "1.0.1", - "from": "merge-descriptors@1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" - }, - "methods": { - "version": "1.1.2", - "from": "methods@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" - }, - "micromatch": { - "version": "2.3.11", - "from": "micromatch@>=2.3.11 <3.0.0", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "from": "is-extglob@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" - }, - "is-glob": { - "version": "2.0.1", - "from": "is-glob@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" - } - } - }, - "mime": { - "version": "1.3.4", - "from": "mime@>=1.3.4 <2.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" - }, - "mime-db": { - "version": "1.26.0", - "from": "mime-db@>=1.26.0 <1.27.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.26.0.tgz" - }, - "mime-types": { - "version": "2.1.14", - "from": "mime-types@>=2.1.10 <3.0.0", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.14.tgz" - }, - "minimalistic-assert": { - "version": "1.0.0", - "from": "minimalistic-assert@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" - }, - "minimatch": { - "version": "3.0.3", - "from": "minimatch@>=3.0.2 <4.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz" - }, - "mongodb": { - "version": "2.1.18", - "from": "mongodb@2.1.18", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.1.18.tgz", - "dependencies": { - "isarray": { - "version": "0.0.1", - "from": "isarray@0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" - }, - "readable-stream": { - "version": "1.0.31", - "from": "readable-stream@1.0.31", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.31.tgz" - } - } - }, - "mongodb-core": { - "version": "1.3.18", - "from": "mongodb-core@1.3.18", - "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-1.3.18.tgz" - }, - "morgan": { - "version": "1.7.0", - "from": "morgan@latest", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.7.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@~2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "ms": { - "version": "0.7.2", - "from": "ms@0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz" - }, - "negotiator": { - "version": "0.6.1", - "from": "negotiator@0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz" - }, - "no-case": { - "version": "2.3.1", - "from": "no-case@>=2.2.0 <3.0.0", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.1.tgz" - }, - "nocache": { - "version": "2.0.0", - "from": "nocache@2.0.0", - "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.0.0.tgz" - }, - "node-docker-monitor": { - "version": "1.0.10", - "from": "node-docker-monitor@latest", - "resolved": "https://registry.npmjs.org/node-docker-monitor/-/node-docker-monitor-1.0.10.tgz", - "dependencies": { - "dockerode": { - "version": "2.2.10", - "from": "dockerode@2.2.10", - "resolved": "https://registry.npmjs.org/dockerode/-/dockerode-2.2.10.tgz" - } - } - }, - "normalize-path": { - "version": "2.0.1", - "from": "normalize-path@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.0.1.tgz" - }, - "object.omit": { - "version": "2.0.1", - "from": "object.omit@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz" - }, - "obuf": { - "version": "1.1.1", - "from": "obuf@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz" - }, - "on-finished": { - "version": "2.3.0", - "from": "on-finished@>=2.3.0 <2.4.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" - }, - "on-headers": { - "version": "1.0.1", - "from": "on-headers@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" - }, - "once": { - "version": "1.4.0", - "from": "once@>=1.3.0 <2.0.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - }, - "parse-glob": { - "version": "3.0.4", - "from": "parse-glob@>=3.0.4 <4.0.0", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "from": "is-extglob@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" - }, - "is-glob": { - "version": "2.0.1", - "from": "is-glob@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" - } - } - }, - "parseurl": { - "version": "1.3.1", - "from": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz" - }, - "path-is-absolute": { - "version": "1.0.1", - "from": "path-is-absolute@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - }, - "path-to-regexp": { - "version": "0.1.7", - "from": "path-to-regexp@0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" - }, - "platform": { - "version": "1.3.3", - "from": "platform@1.3.3", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.3.tgz" - }, - "preserve": { - "version": "0.2.0", - "from": "preserve@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz" - }, - "process-nextick-args": { - "version": "1.0.7", - "from": "process-nextick-args@>=1.0.6 <1.1.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" - }, - "proxy-addr": { - "version": "1.1.3", - "from": "proxy-addr@>=1.1.2 <1.2.0", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.3.tgz" - }, - "randomatic": { - "version": "1.1.6", - "from": "randomatic@>=1.1.3 <2.0.0", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.6.tgz" - }, - "range-parser": { - "version": "1.2.0", - "from": "range-parser@>=1.2.0 <1.3.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz" - }, - "raw-body": { - "version": "2.2.0", - "from": "raw-body@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz" - }, - "readable-stream": { - "version": "2.2.2", - "from": "readable-stream@>=2.2.2 <3.0.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.2.tgz" - }, - "referrer-policy": { - "version": "1.1.0", - "from": "referrer-policy@1.1.0", - "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.1.0.tgz" - }, - "regex-cache": { - "version": "0.4.3", - "from": "regex-cache@>=0.4.2 <0.5.0", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz" - }, - "repeat-element": { - "version": "1.1.2", - "from": "repeat-element@>=1.1.2 <2.0.0", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz" - }, - "repeat-string": { - "version": "1.6.1", - "from": "repeat-string@>=1.5.2 <2.0.0", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" - }, - "require_optional": { - "version": "1.0.0", - "from": "require_optional@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.0.tgz", - "dependencies": { - "resolve-from": { - "version": "2.0.0", - "from": "resolve-from@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz" - } - } - }, - "requires-port": { - "version": "1.0.0", - "from": "requires-port@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" - }, - "select-hose": { - "version": "2.0.0", - "from": "select-hose@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" - }, - "semver": { - "version": "5.3.0", - "from": "semver@>=5.1.0 <6.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz" - }, - "send": { - "version": "0.14.1", - "from": "send@0.14.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.14.1.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@~2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "serve-static": { - "version": "1.11.1", - "from": "serve-static@>=1.11.1 <1.12.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.11.1.tgz" - }, - "setprototypeof": { - "version": "1.0.2", - "from": "setprototypeof@1.0.2", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz" - }, - "spdy": { - "version": "3.4.4", - "from": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz" - }, - "spdy-transport": { - "version": "2.0.18", - "from": "spdy-transport@>=2.0.15 <3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.18.tgz" - }, - "split-ca": { - "version": "1.0.1", - "from": "split-ca@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/split-ca/-/split-ca-1.0.1.tgz" - }, - "statuses": { - "version": "1.3.1", - "from": "statuses@>=1.3.0 <1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz" - }, - "string_decoder": { - "version": "0.10.31", - "from": "string_decoder@>=0.10.0 <0.11.0", - "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - }, - "through": { - "version": "2.3.8", - "from": "through@>=2.2.7 <3.0.0", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz" - }, - "topo": { - "version": "2.0.2", - "from": "topo@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", - "dependencies": { - "hoek": { - "version": "4.1.0", - "from": "hoek@4.x.x", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.1.0.tgz" - } - } - }, - "type-is": { - "version": "1.6.14", - "from": "type-is@>=1.6.13 <1.7.0", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.14.tgz" - }, - "unpipe": { - "version": "1.0.0", - "from": "unpipe@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" - }, - "upper-case": { - "version": "1.1.3", - "from": "upper-case@>=1.1.1 <2.0.0", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz" - }, - "util-deprecate": { - "version": "1.0.2", - "from": "util-deprecate@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - }, - "utils-merge": { - "version": "1.0.0", - "from": "utils-merge@1.0.0", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" - }, - "vary": { - "version": "1.1.0", - "from": "vary@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.0.tgz" - }, - "wbuf": { - "version": "1.7.2", - "from": "wbuf@>=1.4.0 <2.0.0", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz" - }, - "weak-map": { - "version": "1.0.5", - "from": "weak-map@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.5.tgz" - }, - "wrappy": { - "version": "1.0.2", - "from": "wrappy@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - }, - "x-xss-protection": { - "version": "1.0.0", - "from": "x-xss-protection@1.0.0", - "resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.0.0.tgz" - } - } -} diff --git a/api-gateway/package.json b/api-gateway/package.json deleted file mode 100644 index ddf940a..0000000 --- a/api-gateway/package.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "name": "movies-service", - "version": "1.0.0", - "description": "A movie service, microservice example with nodejs", - "author": "Cristian Ramirez Rosas ", - "license": "ISC", - "main": "index.js", - "standard": { - "ignore": [ - "mock/**.js" - ] - }, - "scripts": { - "test": "mocha -R spec src/**/*.spec.js", - "start": "node src/index.js", - "lint": "standard --verbose | snazzy", - "node-debug": "DEBUG=express* node src/index.js", - "chrome-debug": "node --debug-brk --inspect src/index.js", - "int-test": "node_modules/.bin/mocha integration-test/index.js" - }, - "keywords": [ - "express", - "mongodb", - "docker", - "microservice" - ], - "devDependencies": { - "eslint": "^3.13.1", - "mocha": "^3.2.0", - "nodejs-dashboard": "^0.3.0", - "nsp": "^2.6.2", - "should": "^11.1.2", - "snazzy": "^6.0.0", - "standard": "^8.6.0", - "supertest": "^2.0.1" - }, - "dependencies": { - "awilix": "^2.2.2", - "body-parser": "^1.16.0", - "cors": "^2.8.1", - "dockerode": "^2.3.1", - "express": "^4.14.0", - "helmet": "^3.4.0", - "http-proxy": "^1.16.2", - "http-proxy-middleware": "^0.17.3", - "http-status": "^0.2.5", - "joi": "^10.2.0", - "mongodb": "^2.1.18", - "morgan": "^1.7.0", - "node-docker-monitor": "^1.0.10", - "parseurl": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", - "spdy": "^3.4.4" - } -} diff --git a/api-gateway/readme.md b/api-gateway/readme.md deleted file mode 100644 index 2a1527b..0000000 --- a/api-gateway/readme.md +++ /dev/null @@ -1,36 +0,0 @@ -## Build a NodeJS microservice and deploy it to Docker - -[![Standard - JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/) - -Example of the **api-gateway service** microservice and API. - -![](https://cdn-images-1.medium.com/max/1600/1*jxFIFA8WI8TkMmdbOorOsA.png) - -### Stack -- NodeJS 7.5.0 -- MongoDB 3.4.1 -- Docker for Mac 1.13 - -### how to run it - -**This to run our microservice in a docker container** - -**To run in locally** -we need nodejs installed - -- install the dependencies -``` -$ npm i --silent -``` - -- run the tests -``` -$ npm test -``` - -- start the service -``` -$ npm start -``` - -[![Standard - JavaScript Style Guide](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard) diff --git a/api-gateway/src/config/config.js b/api-gateway/src/config/config.js deleted file mode 100644 index cdffbcc..0000000 --- a/api-gateway/src/config/config.js +++ /dev/null @@ -1,33 +0,0 @@ -const fs = require('fs') - -const serverSettings = { - port: process.env.PORT || 8080, - ssl: require('./ssl') -} - -const machine = process.env.DOCKER_HOST -const tls = process.env.DOCKER_TLS_VERIFY -const certDir = process.env.DOCKER_CERT_PATH - -if (!machine) { - throw new Error('You must set the DOCKER_HOST environment variable') -} -if (tls === 1) { - throw new Error('When using DOCKER_TLS_VERIFY=1 you must specify the property DOCKER_CERT_PATH for certificates') -} -if (!certDir) { - throw new Error('You must set the DOCKER_CERT_PATH environment variable') -} - -const dockerSettings = { - protocol: 'https', - host: machine.substr(machine.indexOf(':', 0) + 3, machine.indexOf(':', 6) - 6), - port: parseInt(machine.substr(-4), 10), - checkServerIdentity: false, - ca: fs.readFileSync(certDir + '/ca.pem'), - cert: fs.readFileSync(certDir + '/cert.pem'), - key: fs.readFileSync(certDir + '/key.pem'), - version: 'v1.25' -} - -module.exports = Object.assign({}, { serverSettings, dockerSettings }) diff --git a/api-gateway/src/config/di/di.js b/api-gateway/src/config/di/di.js deleted file mode 100644 index c211cc0..0000000 --- a/api-gateway/src/config/di/di.js +++ /dev/null @@ -1,16 +0,0 @@ -const { createContainer, asValue } = require('awilix') - -function initDI ({serverSettings, dockerSettings}, mediator) { - mediator.once('init', () => { - const container = createContainer() - - container.register({ - dockerSettings: asValue(dockerSettings), - serverSettings: asValue(serverSettings) - }) - - mediator.emit('di.ready', container) - }) -} - -module.exports.initDI = initDI diff --git a/api-gateway/src/config/di/index.js b/api-gateway/src/config/di/index.js deleted file mode 100644 index ff2d63c..0000000 --- a/api-gateway/src/config/di/index.js +++ /dev/null @@ -1,3 +0,0 @@ -const di = require('./di') - -module.exports = Object.assign({}, di) diff --git a/api-gateway/src/config/index.di.spec.js b/api-gateway/src/config/index.di.spec.js deleted file mode 100644 index e3dfa51..0000000 --- a/api-gateway/src/config/index.di.spec.js +++ /dev/null @@ -1,24 +0,0 @@ -/* eslint-env mocha */ -const {EventEmitter} = require('events') -const test = require('assert') -const {init} = require('./') - -describe('DI configuration', () => { - it('can init dependencies to the container', (done) => { - const mediator = new EventEmitter() - - mediator.on('di.ready', (container) => { - console.log(container) - done() - }) - - mediator.on('di.error', err => { - console.log(err) - done() - }) - - init(mediator) - - mediator.emit('init') - }) -}) diff --git a/api-gateway/src/config/index.js b/api-gateway/src/config/index.js deleted file mode 100644 index b5db798..0000000 --- a/api-gateway/src/config/index.js +++ /dev/null @@ -1,5 +0,0 @@ -const {dockerSettings, serverSettings} = require('./config') -const {initDI} = require('./di') -const init = initDI.bind(null, {serverSettings, dockerSettings}) - -module.exports = Object.assign({}, {init}) diff --git a/api-gateway/src/config/ssl/index.js b/api-gateway/src/config/ssl/index.js deleted file mode 100644 index 63e4cd3..0000000 --- a/api-gateway/src/config/ssl/index.js +++ /dev/null @@ -1,6 +0,0 @@ -const fs = require('fs') - -module.exports = { - key: fs.readFileSync(`${__dirname}/server.key`), - cert: fs.readFileSync(`${__dirname}/server.crt`) -} diff --git a/api-gateway/src/docker/docker.js b/api-gateway/src/docker/docker.js deleted file mode 100644 index 97a67fa..0000000 --- a/api-gateway/src/docker/docker.js +++ /dev/null @@ -1,48 +0,0 @@ -'use strict' -const Docker = require('dockerode') - -const discoverRoutes = (container) => { - return new Promise((resolve, reject) => { - const dockerSettings = container.resolve('dockerSettings') - - const docker = new Docker(dockerSettings) - - const getUpstreamUrl = (serviceDetails) => { - const {PublishedPort} = serviceDetails.Endpoint.Spec.Ports[0] - return `http://${dockerSettings.host}:${PublishedPort}` - } - - const addRoute = (routes, details) => { - routes[details.Spec.Name] = { - id: details.ID, - route: details.Spec.Labels.apiRoute, - target: getUpstreamUrl(details) - } - } - - docker.listServices((err, services) => { - if (err) { - reject(new Error('an error occured listing containers, err: ' + err)) - } - - const routes = new Proxy({}, { - get (target, key) { - console.log(`Get properties from -> "${key}" container`) - return Reflect.get(target, key) - }, - set (target, key, value) { - console.log('Setting properties', key, value) - return Reflect.set(target, key, value) - } - }) - - services.forEach((service) => { - addRoute(routes, service) - }) - - resolve(routes) - }) - }) -} - -module.exports = Object.assign({}, {discoverRoutes}) diff --git a/api-gateway/src/docker/docker.spec.js b/api-gateway/src/docker/docker.spec.js deleted file mode 100644 index 4252fba..0000000 --- a/api-gateway/src/docker/docker.spec.js +++ /dev/null @@ -1,16 +0,0 @@ -/* eslint-env mocha */ -const Docker = require('dockerode') -const fs = require('fs') -const {dockerSettings} = require('../config/config') - -describe('Docker Connection', () => { - it('should connect with docker', (done) => { - const docker = new Docker(dockerSettings) - - docker.info(function (err, info) { - console.log(info) - - done() - }) - }) -}) diff --git a/api-gateway/src/index.js b/api-gateway/src/index.js deleted file mode 100644 index 5e32834..0000000 --- a/api-gateway/src/index.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict' -const {EventEmitter} = require('events') -const server = require('./server/server') -const docker = require('./docker/docker') -const di = require('./config') -const mediator = new EventEmitter() - -console.log('--- API Gateway Service ---') -console.log('Connecting to API repository...') - -process.on('uncaughtException', (err) => { - console.error('Unhandled Exception', err) -}) - -process.on('uncaughtRejection', (err, promise) => { - console.error('Unhandled Rejection', err) -}) - -mediator.on('di.ready', (container) => { - docker.discoverRoutes(container) - .then(routes => { - console.log('Connected. Starting Server') - container.registerValue({routes}) - return server.start(container) - }) - .then(app => { - console.log(`Connected to Docker: ${container.cradle.dockerSettings.host}`) - console.log(`Server started succesfully, API Gateway running on port: ${container.cradle.serverSettings.port}.`) - app.on('close', () => { - console.log('Server finished') - }) - }) -}) - -di.init(mediator) - -mediator.emit('init') diff --git a/api-gateway/src/repository/repository.js b/api-gateway/src/repository/repository.js deleted file mode 100644 index d633787..0000000 --- a/api-gateway/src/repository/repository.js +++ /dev/null @@ -1,12 +0,0 @@ -'use strict' -const repository = (container) => { - return Object.create({}) -} - -const connect = (container) => { - return new Promise((resolve, reject) => { - resolve(repository(container)) - }) -} - -module.exports = Object.assign({}, {connect}) diff --git a/api-gateway/src/repository/repository.spec.js b/api-gateway/src/repository/repository.spec.js deleted file mode 100644 index b423fc2..0000000 --- a/api-gateway/src/repository/repository.spec.js +++ /dev/null @@ -1,9 +0,0 @@ -/* eslint-env mocha */ -const should = require('should') -const repository = require('./repository') - -describe('Repository', () => { - it('should connect with a promise', () => { - repository.connect({}).should.be.a.Promise() - }) -}) diff --git a/api-gateway/src/server/server.js b/api-gateway/src/server/server.js deleted file mode 100644 index e490f69..0000000 --- a/api-gateway/src/server/server.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict' -const express = require('express') -const proxy = require('http-proxy-middleware') -const spdy = require('spdy') - -const start = (container) => { - return new Promise((resolve, reject) => { - const {port, ssl} = container.resolve('serverSettings') - const routes = container.resolve('routes') - - if (!routes) { - reject(new Error('The server must be started with routes discovered')) - } - if (!port) { - reject(new Error('The server must be started with an available port')) - } - - const app = express() - - for (let id of Reflect.ownKeys(routes)) { - const {route, target} = routes[id] - app.use(route, proxy({ - target, - changeOrigin: true, - logLevel: 'debug' - })) - } - - if (process.env.NODE === 'test') { - const server = app.listen(port, () => resolve(server)) - } else { - const server = spdy.createServer(ssl, app) - .listen(port, () => resolve(server)) - } - }) -} - -module.exports = Object.assign({}, {start}) diff --git a/api-gateway/src/server/server.spec.js b/api-gateway/src/server/server.spec.js deleted file mode 100644 index 0b26f2f..0000000 --- a/api-gateway/src/server/server.spec.js +++ /dev/null @@ -1,16 +0,0 @@ -/* eslint-env mocha */ -const server = require('./server') - -describe('Server', () => { - it('should require a port to start', () => { - return server.start({ - repo: {} - }).should.be.rejectedWith(/port/) - }) - - it('should require a repository to start', () => { - return server.start({ - port: {} - }).should.be.rejectedWith(/routes/) - }) -}) diff --git a/api-gateway/start-service.sh b/api-gateway/start-service.sh deleted file mode 100644 index cd79159..0000000 --- a/api-gateway/start-service.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash - -for server in manager1 worker1 worker2 -do - eval `docker-machine env $server` - - echo $(env | grep DOCKER) - - docker rm -f api-gateway-service - - docker rmi api-gateway-service - - docker image prune - - docker volume prune - - docker build -t api-gateway-service . - - docker run --name api-gateway-service -v /Users/Cramirez/.docker/machine/machines/$server:/certs --net='host' --env-file env -d api-gateway-service - -done diff --git a/automation/create-machines.sh b/automation/create-machines.sh deleted file mode 100644 index bef7e59..0000000 --- a/automation/create-machines.sh +++ /dev/null @@ -1,3 +0,0 @@ -docker-machine create -d virtualbox --virtualbox-disk-size "20000" --virtualbox-memory "2048" --virtualbox-boot2docker-url=https://github.com/boot2docker/boot2docker/releases/download/v1.13.0/boot2docker.iso manager1 -docker-machine create -d virtualbox --virtualbox-disk-size "20000" --virtualbox-memory "2048" --virtualbox-boot2docker-url=https://github.com/boot2docker/boot2docker/releases/download/v1.13.0/boot2docker.iso worker1 -docker-machine create -d virtualbox --virtualbox-disk-size "20000" --virtualbox-memory "2048" --virtualbox-boot2docker-url=https://github.com/boot2docker/boot2docker/releases/download/v1.13.0/boot2docker.iso worker2 diff --git a/automation/start_all_microservices.sh b/automation/start_all_microservices.sh deleted file mode 100644 index e4d65f4..0000000 --- a/automation/start_all_microservices.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -eval `docker-machine env manager1` - -array=('./movies-service' - './cinema-catalog-service' - './booking-service' - './payment-service' - './notification-service' - './api-gateway' -) - -# we go to the root of the project -cd .. - -for ((i = 0; i < ${#array[@]}; ++i)); do - # we go to each folder - cd ${array[$i]} - sh ./start-service.sh - # and we go back to the root again :D - cd .. -done diff --git a/booking-service/.eslintrc.json b/booking-service/.eslintrc.json deleted file mode 100644 index a755cdb..0000000 --- a/booking-service/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": ["standard"] -} diff --git a/booking-service/Dockerfile b/booking-service/Dockerfile deleted file mode 100644 index 523816b..0000000 --- a/booking-service/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM node:7.5.0-alpine - -RUN addgroup -S nupp && adduser -S -g nupp nupp - -ENV HOME=/home/nupp - -COPY package.json npm-shrinkwrap.json $HOME/app/ - -COPY src/ $HOME/app/src - -ADD https://github.com/Yelp/dumb-init/releases/download/v1.1.1/dumb-init_1.1.1_amd64 /usr/local/bin/dumb-init - -WORKDIR $HOME/app - -RUN chown -R nupp:nupp $HOME/* /usr/local/ && \ - chmod +x /usr/local/bin/dumb-init && \ - npm cache clean && \ - npm install --silent --progress=false --production && \ - chown -R nupp:nupp $HOME/* - -USER nupp - -EXPOSE 3000 - -CMD ["dumb-init", "npm", "start"] diff --git a/booking-service/create-image.sh b/booking-service/create-image.sh deleted file mode 100644 index 91e7cdc..0000000 --- a/booking-service/create-image.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -docker rm -f booking-service - -docker rmi booking-service - -docker image prune - -docker volume prune - -docker build -t booking-service . diff --git a/booking-service/env b/booking-service/env deleted file mode 100644 index ac29194..0000000 --- a/booking-service/env +++ /dev/null @@ -1,6 +0,0 @@ -DB=booking -DB_USER=cristian -DB_PASS=cristianPassword2017 -DB_REPLS=rs1 -DB_SERVERS='192.168.99.100:27017 192.168.99.101:27017 192.168.99.102:27017' -PORT=3000 diff --git a/booking-service/integration-test/index.js b/booking-service/integration-test/index.js deleted file mode 100644 index 4aaebb3..0000000 --- a/booking-service/integration-test/index.js +++ /dev/null @@ -1,41 +0,0 @@ -/* eslint-env mocha */ -const supertest = require('supertest') - -describe('Booking Service', () => { - const api = supertest('http://192.168.99.100:3002') - const now = new Date() - now.setDate(now.getDate() + 1) - const user = { - name: 'Cristian', - lastName: 'Ramirez', - email: 'cristiano@gmail.com', - creditCard: { - number: '4242424242424242', - cvc: '123', - exp_month: '12', - exp_year: '2017', - }, - membership: '7777888899990000' - } - - const booking = { - city: 'Morelia', - cinema: 'Plaza Morelia', - movie: { - title: 'Assasins Creed', - format: 'IMAX' - }, - schedule: now.toString(), - cinemaRoom: 7, - seats: ['45'], - totalAmount: 71 - } - it('can make a booking', (done) => { - api.post('/booking') - .send({user, booking}) - .expect((res) => { - console.log(res.body) - }) - .expect(200, done) - }) -}) diff --git a/booking-service/mock/index.js b/booking-service/mock/index.js deleted file mode 100644 index b46daad..0000000 --- a/booking-service/mock/index.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - -------------------------------------- - | | - | v - | Jane ------(went to)----- - | | | - | | (loyal vistor) | - | v v - Joe --(common user)--> Movie Name <--(displayed)-- Plaza Morelia - | | - | (format) | (city) - v v - 4DX Morelia - - city - | - cinema - | - movie - | - --- | --------- - | | -visitor format - | | ---- | ---- --- | --- -| | | | | -normal loyal 4Dx 3D normal - -const nodes = { -movie: '', -visitor: '', -cinema: '', -city: '', -format: '' -} - -const edges = { -wentTo: '', -displayed: '', -available: '' -} - -*/ diff --git a/booking-service/npm-shrinkwrap.json b/booking-service/npm-shrinkwrap.json deleted file mode 100644 index 82bde98..0000000 --- a/booking-service/npm-shrinkwrap.json +++ /dev/null @@ -1,738 +0,0 @@ -{ - "name": "booking-service", - "version": "1.0.0", - "dependencies": { - "accepts": { - "version": "1.3.3", - "from": "accepts@>=1.3.3 <1.4.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz" - }, - "array-flatten": { - "version": "1.1.1", - "from": "array-flatten@1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" - }, - "asynckit": { - "version": "0.4.0", - "from": "asynckit@>=0.4.0 <0.5.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" - }, - "awilix": { - "version": "2.2.2", - "from": "awilix@latest", - "resolved": "https://registry.npmjs.org/awilix/-/awilix-2.2.2.tgz" - }, - "balanced-match": { - "version": "0.4.2", - "from": "balanced-match@>=0.4.1 <0.5.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz" - }, - "basic-auth": { - "version": "1.0.4", - "from": "basic-auth@>=1.0.3 <1.1.0", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz" - }, - "body-parser": { - "version": "1.16.0", - "from": "body-parser@latest", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.16.0.tgz", - "dependencies": { - "qs": { - "version": "6.2.1", - "from": "qs@6.2.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.1.tgz" - } - } - }, - "brace-expansion": { - "version": "1.1.6", - "from": "brace-expansion@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz" - }, - "bson": { - "version": "0.4.23", - "from": "bson@>=0.4.23 <0.5.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-0.4.23.tgz" - }, - "buffer-shims": { - "version": "1.0.0", - "from": "buffer-shims@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" - }, - "bytes": { - "version": "2.4.0", - "from": "bytes@2.4.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz" - }, - "camel-case": { - "version": "3.0.0", - "from": "camel-case@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz" - }, - "camelize": { - "version": "1.0.0", - "from": "camelize@1.0.0", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz" - }, - "combined-stream": { - "version": "1.0.5", - "from": "combined-stream@>=1.0.5 <1.1.0", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz" - }, - "concat-map": { - "version": "0.0.1", - "from": "concat-map@0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" - }, - "connect": { - "version": "3.5.0", - "from": "connect@3.5.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.5.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "content-disposition": { - "version": "0.5.1", - "from": "content-disposition@0.5.1", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz" - }, - "content-security-policy-builder": { - "version": "1.1.0", - "from": "content-security-policy-builder@1.1.0", - "resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-1.1.0.tgz" - }, - "content-type": { - "version": "1.0.2", - "from": "content-type@>=1.0.2 <1.1.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz" - }, - "cookie": { - "version": "0.3.1", - "from": "cookie@0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz" - }, - "cookie-signature": { - "version": "1.0.6", - "from": "cookie-signature@1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" - }, - "cookiejar": { - "version": "2.1.0", - "from": "cookiejar@>=2.0.6 <3.0.0", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.0.tgz" - }, - "core-util-is": { - "version": "1.0.2", - "from": "core-util-is@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" - }, - "cors": { - "version": "2.8.1", - "from": "cors@latest", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.1.tgz" - }, - "dasherize": { - "version": "2.0.0", - "from": "dasherize@2.0.0", - "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz" - }, - "dashify": { - "version": "0.2.2", - "from": "dashify@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/dashify/-/dashify-0.2.2.tgz" - }, - "debug": { - "version": "2.6.0", - "from": "debug@>=2.1.1 <3.0.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz" - }, - "delayed-stream": { - "version": "1.0.0", - "from": "delayed-stream@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" - }, - "depd": { - "version": "1.1.0", - "from": "depd@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz" - }, - "destroy": { - "version": "1.0.4", - "from": "destroy@>=1.0.4 <1.1.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" - }, - "dns-prefetch-control": { - "version": "0.1.0", - "from": "dns-prefetch-control@0.1.0", - "resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz" - }, - "dont-sniff-mimetype": { - "version": "1.0.0", - "from": "dont-sniff-mimetype@1.0.0", - "resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.0.0.tgz" - }, - "ee-first": { - "version": "1.1.1", - "from": "ee-first@1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" - }, - "encodeurl": { - "version": "1.0.1", - "from": "encodeurl@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz" - }, - "es6-promise": { - "version": "3.0.2", - "from": "es6-promise@3.0.2", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz" - }, - "escape-html": { - "version": "1.0.3", - "from": "escape-html@>=1.0.3 <1.1.0", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" - }, - "etag": { - "version": "1.7.0", - "from": "etag@>=1.7.0 <1.8.0", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz" - }, - "express": { - "version": "4.14.0", - "from": "express@latest", - "resolved": "https://registry.npmjs.org/express/-/express-4.14.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - }, - "qs": { - "version": "6.2.0", - "from": "qs@6.2.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz" - } - } - }, - "extend": { - "version": "3.0.0", - "from": "extend@>=3.0.0 <3.1.0", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz" - }, - "finalhandler": { - "version": "0.5.0", - "from": "finalhandler@0.5.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@~2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "form-data": { - "version": "2.1.2", - "from": "form-data@>=2.1.1 <2.2.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.2.tgz" - }, - "formidable": { - "version": "1.1.1", - "from": "formidable@>=1.0.17 <2.0.0", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.1.1.tgz" - }, - "forwarded": { - "version": "0.1.0", - "from": "forwarded@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz" - }, - "frameguard": { - "version": "3.0.0", - "from": "frameguard@3.0.0", - "resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.0.0.tgz" - }, - "fresh": { - "version": "0.3.0", - "from": "fresh@0.3.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz" - }, - "fs.realpath": { - "version": "1.0.0", - "from": "fs.realpath@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" - }, - "glob": { - "version": "7.1.1", - "from": "glob@>=7.0.3 <8.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz" - }, - "handle-thing": { - "version": "1.2.5", - "from": "handle-thing@>=1.2.4 <2.0.0", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz" - }, - "helmet": { - "version": "3.4.0", - "from": "helmet@>=3.4.0 <4.0.0", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.4.0.tgz" - }, - "helmet-csp": { - "version": "2.3.0", - "from": "helmet-csp@2.3.0", - "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.3.0.tgz" - }, - "hide-powered-by": { - "version": "1.0.0", - "from": "hide-powered-by@1.0.0", - "resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.0.0.tgz" - }, - "hpack.js": { - "version": "2.1.6", - "from": "hpack.js@>=2.1.6 <3.0.0", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz" - }, - "hpkp": { - "version": "2.0.0", - "from": "hpkp@2.0.0", - "resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz" - }, - "hsts": { - "version": "2.0.0", - "from": "hsts@2.0.0", - "resolved": "https://registry.npmjs.org/hsts/-/hsts-2.0.0.tgz" - }, - "http-deceiver": { - "version": "1.2.7", - "from": "http-deceiver@>=1.2.4 <2.0.0", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" - }, - "http-errors": { - "version": "1.5.1", - "from": "http-errors@>=1.5.0 <1.6.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz" - }, - "http-status": { - "version": "0.2.5", - "from": "http-status@latest", - "resolved": "https://registry.npmjs.org/http-status/-/http-status-0.2.5.tgz" - }, - "iconv-lite": { - "version": "0.4.15", - "from": "iconv-lite@0.4.15", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz" - }, - "ienoopen": { - "version": "1.0.0", - "from": "ienoopen@1.0.0", - "resolved": "https://registry.npmjs.org/ienoopen/-/ienoopen-1.0.0.tgz" - }, - "inflight": { - "version": "1.0.6", - "from": "inflight@>=1.0.4 <2.0.0", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" - }, - "inherits": { - "version": "2.0.3", - "from": "inherits@>=2.0.3 <3.0.0", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - }, - "ipaddr.js": { - "version": "1.2.0", - "from": "ipaddr.js@1.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.2.0.tgz" - }, - "is-class": { - "version": "0.0.4", - "from": "is-class@0.0.4", - "resolved": "https://registry.npmjs.org/is-class/-/is-class-0.0.4.tgz" - }, - "is-plain-object": { - "version": "2.0.1", - "from": "is-plain-object@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.1.tgz" - }, - "is-string": { - "version": "1.0.4", - "from": "is-string@>=1.0.4 <2.0.0", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.4.tgz" - }, - "isarray": { - "version": "1.0.0", - "from": "isarray@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - }, - "isemail": { - "version": "2.2.1", - "from": "isemail@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/isemail/-/isemail-2.2.1.tgz" - }, - "isobject": { - "version": "1.0.2", - "from": "isobject@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-1.0.2.tgz" - }, - "items": { - "version": "2.1.1", - "from": "items@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/items/-/items-2.1.1.tgz" - }, - "joi": { - "version": "10.2.0", - "from": "joi@latest", - "resolved": "https://registry.npmjs.org/joi/-/joi-10.2.0.tgz", - "dependencies": { - "hoek": { - "version": "4.1.0", - "from": "hoek@>=4.0.0 <5.0.0", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.1.0.tgz" - } - } - }, - "lodash.reduce": { - "version": "4.6.0", - "from": "lodash.reduce@4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz" - }, - "lower-case": { - "version": "1.1.3", - "from": "lower-case@>=1.1.1 <2.0.0", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.3.tgz" - }, - "media-typer": { - "version": "0.3.0", - "from": "media-typer@0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" - }, - "merge-descriptors": { - "version": "1.0.1", - "from": "merge-descriptors@1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" - }, - "methods": { - "version": "1.1.2", - "from": "methods@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" - }, - "mime": { - "version": "1.3.4", - "from": "mime@>=1.3.4 <2.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" - }, - "mime-db": { - "version": "1.26.0", - "from": "mime-db@>=1.26.0 <1.27.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.26.0.tgz" - }, - "mime-types": { - "version": "2.1.14", - "from": "mime-types@>=2.1.10 <3.0.0", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.14.tgz" - }, - "minimalistic-assert": { - "version": "1.0.0", - "from": "minimalistic-assert@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" - }, - "minimatch": { - "version": "3.0.3", - "from": "minimatch@>=3.0.2 <4.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz" - }, - "mongodb": { - "version": "2.1.18", - "from": "mongodb@2.1.18", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.1.18.tgz", - "dependencies": { - "isarray": { - "version": "0.0.1", - "from": "isarray@0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" - }, - "readable-stream": { - "version": "1.0.31", - "from": "readable-stream@1.0.31", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.31.tgz" - } - } - }, - "mongodb-core": { - "version": "1.3.18", - "from": "mongodb-core@1.3.18", - "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-1.3.18.tgz" - }, - "morgan": { - "version": "1.7.0", - "from": "morgan@latest", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.7.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@~2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "ms": { - "version": "0.7.2", - "from": "ms@0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz" - }, - "negotiator": { - "version": "0.6.1", - "from": "negotiator@0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz" - }, - "no-case": { - "version": "2.3.1", - "from": "no-case@>=2.2.0 <3.0.0", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.1.tgz" - }, - "nocache": { - "version": "2.0.0", - "from": "nocache@2.0.0", - "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.0.0.tgz" - }, - "obuf": { - "version": "1.1.1", - "from": "obuf@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz" - }, - "on-finished": { - "version": "2.3.0", - "from": "on-finished@>=2.3.0 <2.4.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" - }, - "on-headers": { - "version": "1.0.1", - "from": "on-headers@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" - }, - "once": { - "version": "1.4.0", - "from": "once@>=1.3.0 <2.0.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - }, - "parseurl": { - "version": "1.3.1", - "from": "parseurl@>=1.3.1 <1.4.0", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz" - }, - "path-is-absolute": { - "version": "1.0.1", - "from": "path-is-absolute@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - }, - "path-to-regexp": { - "version": "0.1.7", - "from": "path-to-regexp@0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" - }, - "platform": { - "version": "1.3.3", - "from": "platform@1.3.3", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.3.tgz" - }, - "process-nextick-args": { - "version": "1.0.7", - "from": "process-nextick-args@>=1.0.6 <1.1.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" - }, - "proxy-addr": { - "version": "1.1.3", - "from": "proxy-addr@>=1.1.2 <1.2.0", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.3.tgz" - }, - "qs": { - "version": "6.3.0", - "from": "qs@>=6.3.0 <6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.0.tgz" - }, - "range-parser": { - "version": "1.2.0", - "from": "range-parser@>=1.2.0 <1.3.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz" - }, - "raw-body": { - "version": "2.2.0", - "from": "raw-body@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz" - }, - "readable-stream": { - "version": "2.2.2", - "from": "readable-stream@>=2.2.2 <3.0.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.2.tgz" - }, - "referrer-policy": { - "version": "1.1.0", - "from": "referrer-policy@1.1.0", - "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.1.0.tgz" - }, - "require_optional": { - "version": "1.0.0", - "from": "require_optional@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.0.tgz", - "dependencies": { - "resolve-from": { - "version": "2.0.0", - "from": "resolve-from@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz" - } - } - }, - "select-hose": { - "version": "2.0.0", - "from": "select-hose@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" - }, - "semver": { - "version": "5.3.0", - "from": "semver@>=5.1.0 <6.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz" - }, - "send": { - "version": "0.14.1", - "from": "send@0.14.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.14.1.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@~2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "serve-static": { - "version": "1.11.1", - "from": "serve-static@>=1.11.1 <1.12.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.11.1.tgz" - }, - "setprototypeof": { - "version": "1.0.2", - "from": "setprototypeof@1.0.2", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz" - }, - "spdy": { - "version": "3.4.4", - "from": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz" - }, - "spdy-transport": { - "version": "2.0.18", - "from": "spdy-transport@>=2.0.15 <3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.18.tgz" - }, - "statuses": { - "version": "1.3.1", - "from": "statuses@>=1.3.0 <1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz" - }, - "string_decoder": { - "version": "0.10.31", - "from": "string_decoder@>=0.10.0 <0.11.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - }, - "superagent": { - "version": "3.4.1", - "from": "superagent@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.4.1.tgz", - "dependencies": { - "component-emitter": { - "version": "1.2.1", - "from": "component-emitter@>=1.2.0 <2.0.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz" - } - } - }, - "supertest": { - "version": "3.0.0", - "from": "supertest@latest", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.0.0.tgz" - }, - "topo": { - "version": "2.0.2", - "from": "topo@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", - "dependencies": { - "hoek": { - "version": "4.1.0", - "from": "hoek@4.x.x", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.1.0.tgz" - } - } - }, - "type-is": { - "version": "1.6.14", - "from": "type-is@>=1.6.13 <1.7.0", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.14.tgz" - }, - "unpipe": { - "version": "1.0.0", - "from": "unpipe@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" - }, - "upper-case": { - "version": "1.1.3", - "from": "upper-case@>=1.1.1 <2.0.0", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz" - }, - "util-deprecate": { - "version": "1.0.2", - "from": "util-deprecate@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - }, - "utils-merge": { - "version": "1.0.0", - "from": "utils-merge@1.0.0", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" - }, - "vary": { - "version": "1.1.0", - "from": "vary@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.0.tgz" - }, - "wbuf": { - "version": "1.7.2", - "from": "wbuf@>=1.4.0 <2.0.0", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz" - }, - "wrappy": { - "version": "1.0.2", - "from": "wrappy@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - }, - "x-xss-protection": { - "version": "1.0.0", - "from": "x-xss-protection@1.0.0", - "resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.0.0.tgz" - } - } -} diff --git a/booking-service/package.json b/booking-service/package.json deleted file mode 100644 index 50216ed..0000000 --- a/booking-service/package.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "name": "booking-service", - "version": "1.0.0", - "description": "A Booking service, microservice example with nodejs", - "author": "Cristian Ramirez Rosas ", - "license": "ISC", - "main": "index.js", - "standard": { - "ignore": [ - "mock/**.js" - ] - }, - "scripts": { - "test": "mocha -R spec src/**/*.spec.js", - "start": "node src/index.js", - "lint": "standard --verbose | snazzy", - "node-debug": "DEBUG=express* node src/index.js", - "chrome-debug": "node --debug-brk --inspect src/index.js", - "coverage": "istanbul cover _mocha $(find ./src -name \"*.spec.js\" -not -path \"./node_modules/*\") ", - "metric": "nodejs-dashboard -- node -r nodejs-dashboard src/index.js" - }, - "keywords": [ - "express", - "mongodb", - "docker", - "microservice" - ], - "devDependencies": { - "eslint": "^3.13.1", - "mocha": "^3.2.0", - "nodejs-dashboard": "^0.3.0", - "should": "^11.1.2", - "snazzy": "^6.0.0" - }, - "dependencies": { - "awilix": "^2.2.2", - "body-parser": "^1.16.0", - "cors": "^2.8.1", - "express": "^4.14.0", - "helmet": "^3.4.0", - "http-status": "^0.2.5", - "joi": "^10.2.0", - "mongodb": "^2.1.18", - "morgan": "^1.7.0", - "spdy": "^3.4.4", - "supertest": "^3.0.0" - } -} diff --git a/booking-service/readme.md b/booking-service/readme.md deleted file mode 100644 index 1d6cf29..0000000 --- a/booking-service/readme.md +++ /dev/null @@ -1,18 +0,0 @@ -## Build a NodeJS microservice and deploy it to Docker - -[![Standard - JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/) - -Example of the **cinema catalog service** microservice and API. - -![](https://cdn-images-1.medium.com/max/1600/1*IIubhnmWMrxiE5fzF7Kmvw.png) - -### Architecture at the moment for the step-3 -![](https://cdn-images-1.medium.com/max/1600/1*n9fXFHppV5FXRnIyQvlpeQ.png) - - -### Stack -- NodeJS 7.5.0 -- MongoDB 3.4.1 -- Docker for Mac 1.13 - -[![Standard - JavaScript Style Guide](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard) diff --git a/booking-service/src/api/booking.js b/booking-service/src/api/booking.js deleted file mode 100644 index e916439..0000000 --- a/booking-service/src/api/booking.js +++ /dev/null @@ -1,63 +0,0 @@ -'use strict' -const status = require('http-status') - -module.exports = ({repo}, app) => { - app.post('/booking', (req, res, next) => { - const validate = req.container.cradle.validate - const paymentService = req.container.resolve('paymentService') - const notificationService = req.container.resolve('notificationService') - - Promise.all([ - validate(req.body.user, 'user'), - validate(req.body.booking, 'booking') - ]) - .then(([user, booking]) => { - const payment = { - userName: user.name + ' ' + user.lastName, - currency: 'mxn', - number: user.creditCard.number, - cvc: user.creditCard.cvc, - exp_month: user.creditCard.exp_month, - exp_year: user.creditCard.exp_year, - amount: booking.totalAmount, - description: ` - Tickect(s) for movie ${booking.movie}, - with seat(s) ${booking.seats.toString()} - at time ${booking.schedule}` - } - - return Promise.all([ - paymentService(payment), - Promise.resolve(user), - Promise.resolve(booking) - ]) - }) - .then(([paid, user, booking]) => { - return Promise.all([ - repo.makeBooking(user, booking), - Promise.resolve(paid), - Promise.resolve(user) - ]) - }) - .then(([booking, paid, user]) => { - return Promise.all([ - repo.generateTicket(paid, booking), - Promise.resolve(user) - ]) - }) - .then(([ticket, user]) => { - const payload = Object.assign({}, ticket, {user: {name: user.name + user.lastName, email: user.email}}) - notificationService(payload) - res.status(status.OK).json(ticket) - }) - .catch(next) - }) - - app.get('/booking/verify/:orderId', (req, res, next) => { - repo.getOrderById(req.params.orderId) - .then(order => { - res.status(status.OK).json(order) - }) - .catch(next) - }) -} diff --git a/booking-service/src/api/booking.spec.js b/booking-service/src/api/booking.spec.js deleted file mode 100644 index 33b767f..0000000 --- a/booking-service/src/api/booking.spec.js +++ /dev/null @@ -1,103 +0,0 @@ -/* eslint-env mocha */ -const { createContainer, asValue } = require('awilix') -const should = require('should') -const request = require('supertest') -const server = require('../server/server') -const models = require('../models') -const services = require('../services') - -describe('Booking API', () => { - let app = null - - const serverSettings = { - port: 3000 - } - - let testRepo = { - makeBooking (user, booking) { - return Promise.resolve('booking made successfully') - }, - generateTicket (paid, booking) { - const testTicket = { - cinema: booking.cinema, - schedule: booking.schedule.toString(), - movie: booking.movie, - seats: booking.seats, - cinemaRoom: booking.cinemaRoom, - orderId: 123 - } - return Promise.resolve(testTicket) - }, - getOrderById (orderId) { - return Promise.resolve('orderId: ' + orderId) - } - } - - beforeEach(() => { - const container = createContainer() - - container.register({ - validate: asValue(models.validate), - booking: asValue(models.booking), - user: asValue(models.booking), - ticket: asValue(models.booking), - serverSettings: asValue(serverSettings), - paymentService: asValue(services.paymentService), - notificationService: asValue(services.notificationService), - repo: asValue(testRepo) - }) - - return server.start(container) - .then(serv => { - app = serv - }) - }) - - afterEach(() => { - app.close() - app = null - }) - - it('can make a booking and return the ticket(s)', (done) => { - const now = new Date() - now.setDate(now.getDate() + 1) - - const user = { - name: 'Cristian', - lastName: 'Ramirez', - email: 'cristiano@nupp.com', - creditCard: { - number: '1111222233334444', - cvc: '123', - exp_month: '07', - exp_year: '2017' - }, - membership: '7777888899990000' - } - - const booking = { - city: 'Morelia', - cinema: 'Plaza Morelia', - movie: 'Assasins Creed', - schedule: now.toString(), - cinemaRoom: 7, - seats: ['45'], - totalAmount: 71 - } - - request(app) - .post('/booking') - .send({user, booking}) - .expect((res) => { - res.body.should.containEql({ - cinema: booking.cinema, - schedule: now.toString(), - movie: booking.movie, - seats: booking.seats, - cinemaRoom: booking.cinemaRoom, - orderId: 123 - }) - }) - .expect(200, done) - }) -}) diff --git a/booking-service/src/config/config.js b/booking-service/src/config/config.js deleted file mode 100644 index 64540e2..0000000 --- a/booking-service/src/config/config.js +++ /dev/null @@ -1,45 +0,0 @@ -const dbSettings = { - db: process.env.DB || 'booking', - user: process.env.DB_USER || 'cristian', - pass: process.env.DB_PASS || 'cristianPassword2017', - repl: process.env.DB_REPLS || 'rs1', - servers: (process.env.DB_SERVERS) ? process.env.DB_SERVERS.substr(1, process.env.DB_SERVERS.length - 2).split(' ') : [ - '192.168.99.100:27017', - '192.168.99.101:27017', - '192.168.99.102:27017' - ], - dbParameters: () => ({ - w: 'majority', - wtimeout: 10000, - j: true, - readPreference: 'ReadPreference.SECONDARY_PREFERRED', - native_parser: false - }), - serverParameters: () => ({ - autoReconnect: true, - poolSize: 10, - socketoptions: { - keepAlive: 300, - connectTimeoutMS: 30000, - socketTimeoutMS: 30000 - } - }), - replsetParameters: (replset = 'rs1') => ({ - replicaSet: replset, - ha: true, - haInterval: 10000, - poolSize: 10, - socketoptions: { - keepAlive: 300, - connectTimeoutMS: 30000, - socketTimeoutMS: 30000 - } - }) -} - -const serverSettings = { - port: process.env.PORT || 3000, - ssl: require('./ssl') -} - -module.exports = Object.assign({}, { dbSettings, serverSettings }) diff --git a/booking-service/src/config/db/index.js b/booking-service/src/config/db/index.js deleted file mode 100644 index 8a1a1d3..0000000 --- a/booking-service/src/config/db/index.js +++ /dev/null @@ -1,4 +0,0 @@ -const {ObjectID} = require('mongodb') -const {connect} = require('./mongo') - -module.exports = Object.assign({}, {connect, ObjectID}) diff --git a/booking-service/src/config/db/mongo.js b/booking-service/src/config/db/mongo.js deleted file mode 100644 index 18fce0f..0000000 --- a/booking-service/src/config/db/mongo.js +++ /dev/null @@ -1,32 +0,0 @@ -const MongoClient = require('mongodb') - -const getMongoURL = (options) => { - const url = options.servers - .reduce((prev, cur) => prev + cur + ',', 'mongodb://') - - return `${url.substr(0, url.length - 1)}/${options.db}` -} - -const connect = (options, mediator) => { - mediator.once('boot.ready', () => { - MongoClient.connect( - getMongoURL(options), { - db: options.dbParameters(), - server: options.serverParameters(), - replset: options.replsetParameters(options.repl) - }, (err, db) => { - if (err) { - mediator.emit('db.error', err) - } - - db.admin().authenticate(options.user, options.pass, (err, result) => { - if (err) { - mediator.emit('db.error', err) - } - mediator.emit('db.ready', db) - }) - }) - }) -} - -module.exports = Object.assign({}, {connect}) diff --git a/booking-service/src/config/db/mongo.spec.js b/booking-service/src/config/db/mongo.spec.js deleted file mode 100644 index 6226394..0000000 --- a/booking-service/src/config/db/mongo.spec.js +++ /dev/null @@ -1,29 +0,0 @@ -/* eslint-env mocha */ -const {EventEmitter} = require('events') -const test = require('assert') -const mongo = require('./mongo') -const {dbSettings} = require('./config') - -describe('Mongo Connection', () => { - it('should emit db Object with an EventEmitter', (done) => { - const mediator = new EventEmitter() - - mediator.on('db.ready', (db) => { - db.admin().listDatabases((err, dbs) => { - test.equal(null, err) - test.ok(dbs.databases.length > 0) - console.log(dbs.databases) - db.close() - done() - }) - }) - - mediator.on('db.error', (err) => { - console.log(err) - }) - - mongo.connect(dbSettings, mediator) - - mediator.emit('boot.ready') - }) -}) diff --git a/booking-service/src/config/di/di.js b/booking-service/src/config/di/di.js deleted file mode 100644 index 339306d..0000000 --- a/booking-service/src/config/di/di.js +++ /dev/null @@ -1,33 +0,0 @@ -const { createContainer, asValue } = require('awilix') - -function initDI ({serverSettings, dbSettings, database, models, services}, mediator) { - mediator.once('init', () => { - mediator.on('db.ready', (db) => { - const container = createContainer() - - container.register({ - database: asValue(db), - validate: asValue(models.validate), - booking: asValue(models.booking), - user: asValue(models.user), - ticket: asValue(models.ticket), - ObjectID: asValue(database.ObjectID), - serverSettings: asValue(serverSettings), - paymentService: asValue(services.paymentService), - notificationService: asValue(services.notificationService) - }) - - mediator.emit('di.ready', container) - }) - - mediator.on('db.error', (err) => { - mediator.emit('di.error', err) - }) - - database.connect(dbSettings, mediator) - - mediator.emit('boot.ready') - }) -} - -module.exports.initDI = initDI diff --git a/booking-service/src/config/di/di.proto.js b/booking-service/src/config/di/di.proto.js deleted file mode 100644 index 82e6df1..0000000 --- a/booking-service/src/config/di/di.proto.js +++ /dev/null @@ -1,82 +0,0 @@ -/* - const container = createContainer() - - container.register({ - transient(user), - transient(ticket), - transient(booking), - singleton(objectID), - singleton(notifications), - singleton(payments) - }) - - function ({ User, Booking }) { - make some stuff with the user - Promise.all([ - user.validate(object), - booking.validate(object) - ]) - .then([user, booking] => { - - }) - } - -*/ - -const createContainer = () => { - // DI store - const registrations = {} - // returns the DI - const container = { - get registrations () { - return Object.assign({}, registrations) - } - } - - // DI cache systems - container.cache = {} - - const getDI = new Proxy({}, { - get: (taget, name) => resolve(name), - set: (target, name, value) => { - throw new Error('cannot set a value to the container') - } - }) - - container.getDI = getDI - - const register = (name, registration, opts) => { - const key = Symbol(name) - registrations[key] = Object.assign({}, {fn: registration}, {lifetime: opts}) - return container - } - - container.register = register - - const resolve = (name) => { - const di = registrations[name] - switch (di.lifetime) { - case 'TRANSIENT': - return container.registrations[name].fn - case 'SINGLETON': - if (!container.cache[name]) { - container.cache[name] = container.registrations[name] - } - return container.cache[name].fn - } - } - - const listDependencies = () => { - const list = [] - for (var key in registrations) { - if (registrations.hasOwnProperty(key)) { - list.push(key) - } - } - return list - } - - return Object.create(container) -} - -module.exports.createContainer = createContainer diff --git a/booking-service/src/config/di/index.js b/booking-service/src/config/di/index.js deleted file mode 100644 index ff2d63c..0000000 --- a/booking-service/src/config/di/index.js +++ /dev/null @@ -1,3 +0,0 @@ -const di = require('./di') - -module.exports = Object.assign({}, di) diff --git a/booking-service/src/config/index.di.spec.js b/booking-service/src/config/index.di.spec.js deleted file mode 100644 index e3dfa51..0000000 --- a/booking-service/src/config/index.di.spec.js +++ /dev/null @@ -1,24 +0,0 @@ -/* eslint-env mocha */ -const {EventEmitter} = require('events') -const test = require('assert') -const {init} = require('./') - -describe('DI configuration', () => { - it('can init dependencies to the container', (done) => { - const mediator = new EventEmitter() - - mediator.on('di.ready', (container) => { - console.log(container) - done() - }) - - mediator.on('di.error', err => { - console.log(err) - done() - }) - - init(mediator) - - mediator.emit('init') - }) -}) diff --git a/booking-service/src/config/index.js b/booking-service/src/config/index.js deleted file mode 100644 index 1180b2a..0000000 --- a/booking-service/src/config/index.js +++ /dev/null @@ -1,9 +0,0 @@ -const {dbSettings, serverSettings} = require('./config') -const database = require('./db') -const {initDI} = require('./di') -const models = require('../models') -const services = require('../services') - -const init = initDI.bind(null, {serverSettings, dbSettings, database, models, services}) - -module.exports = Object.assign({}, {init}) diff --git a/booking-service/src/config/ssl/index.js b/booking-service/src/config/ssl/index.js deleted file mode 100644 index 63e4cd3..0000000 --- a/booking-service/src/config/ssl/index.js +++ /dev/null @@ -1,6 +0,0 @@ -const fs = require('fs') - -module.exports = { - key: fs.readFileSync(`${__dirname}/server.key`), - cert: fs.readFileSync(`${__dirname}/server.crt`) -} diff --git a/booking-service/src/index.js b/booking-service/src/index.js deleted file mode 100644 index cabc5c1..0000000 --- a/booking-service/src/index.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict' -const {EventEmitter} = require('events') -const server = require('./server/server') -const repository = require('./repository/repository') -const di = require('./config') -const mediator = new EventEmitter() - -console.log('--- Booking Service ---') -console.log('Connecting to booking repository...') - -process.on('uncaughtException', (err) => { - console.error('Unhandled Exception', err) -}) - -process.on('uncaughtRejection', (err, promise) => { - console.error('Unhandled Rejection', err) -}) - -mediator.on('di.ready', (container) => { - repository.connect(container) - .then(repo => { - console.log('Connected. Starting Server') - container.registerValue({repo}) - return server.start(container) - }) - .then(app => { - console.log(`Server started succesfully, running on port: ${container.cradle.serverSettings.port}.`) - app.on('close', () => { - container.resolve('repo').disconnect() - }) - }) -}) - -di.init(mediator) - -mediator.emit('init') diff --git a/booking-service/src/models/booking.model.js b/booking-service/src/models/booking.model.js deleted file mode 100644 index f02e268..0000000 --- a/booking-service/src/models/booking.model.js +++ /dev/null @@ -1,14 +0,0 @@ -const bookingSchema = (joi) => ({ - city: joi.string(), - cinema: joi.string(), - schedule: joi.date().min('now'), - movie: joi.object().keys({ - title: joi.string(), - format: joi.string() - }), - cinemaRoom: joi.number(), - seats: joi.array().items(joi.string()).single(), - totalAmount: joi.number() -}) - -module.exports = bookingSchema diff --git a/booking-service/src/models/index.js b/booking-service/src/models/index.js deleted file mode 100644 index 2fe55d2..0000000 --- a/booking-service/src/models/index.js +++ /dev/null @@ -1,26 +0,0 @@ -const joi = require('joi') -const user = require('./user.model')(joi) -const booking = require('./booking.model')(joi) -const ticket = require('./ticket.model')(joi) - -const schemas = Object.create({user, booking, ticket}) - -const schemaValidator = (object, type) => { - return new Promise((resolve, reject) => { - if (!object) { - reject(new Error('object to validate not provided')) - } - if (!type) { - reject(new Error('schema type to validate not provided')) - } - - const {error, value} = joi.validate(object, schemas[type]) - - if (error) { - reject(new Error(`invalid ${type} data, err: ${error}`)) - } - resolve(value) - }) -} - -module.exports = Object.create({validate: schemaValidator, schemas}) diff --git a/booking-service/src/models/index.spec.js b/booking-service/src/models/index.spec.js deleted file mode 100644 index c6b9b63..0000000 --- a/booking-service/src/models/index.spec.js +++ /dev/null @@ -1,81 +0,0 @@ -/* eslint-env mocha */ -const test = require('assert') -const {validate} = require('./') - -console.log(Object.getPrototypeOf(validate)) - -describe('Schemas Validation', () => { - it('can validate a booking object', (done) => { - const now = new Date() - now.setDate(now.getDate() + 1) - - const testBooking = { - city: 'Morelia', - cinema: 'Plaza Morelia', - movie: 'Assasins Creed', - schedule: now, - cinemaRoom: 7, - seats: ['45'], - totalAmount: 71 - } - - validate(testBooking, 'booking') - .then(value => { - console.log('validated') - console.log(value) - done() - }) - .catch(err => { - console.log(err) - done() - }) - }) - - it('can validate a user object', (done) => { - const testUser = { - name: 'Cristian', - lastName: 'Ramirez', - email: 'cristiano@nupp.com', - creditCard: { - number: '1111222233334444', - cvc: '123', - exp_month: '07', - exp_year: '2017' - }, - membership: '7777888899990000' - } - - validate(testUser, 'user') - .then(value => { - console.log('validated') - console.log(value) - done() - }) - .catch(err => { - console.log(err) - done() - }) - }) - - it('can validate a ticket object', (done) => { - const testTicket = { - cinema: 'Plaza Morelia', - schedule: new Date(), - movie: 'Assasins Creed', - seats: ['35'], - cinemaRoom: 1, - orderId: '34jh1231ll' - } - - validate(testTicket, 'ticket') - .then(value => { - console.log('validated') - console.log(value) - done() - }) - .catch(err => { - console.log(err) - done() - }) - }) -}) diff --git a/booking-service/src/models/ticket.model.js b/booking-service/src/models/ticket.model.js deleted file mode 100644 index 29af13b..0000000 --- a/booking-service/src/models/ticket.model.js +++ /dev/null @@ -1,11 +0,0 @@ - -const ticketSchema = (joi) => ({ - cinema: joi.string(), - schedule: joi.date(), - movie: joi.string(), - seats: joi.array().items(joi.string()).single(), - cinemaRoom: joi.number(), - orderId: joi.string().alphanum() -}) - -module.exports = ticketSchema diff --git a/booking-service/src/models/user.model.js b/booking-service/src/models/user.model.js deleted file mode 100644 index f86730e..0000000 --- a/booking-service/src/models/user.model.js +++ /dev/null @@ -1,15 +0,0 @@ -const userSchema = (joi) => ({ - name: joi.string().regex(/^[a-zA-Z '-]+$/i).required(), - lastName: joi.string().regex(/^[a-zA-Z '-]+$/i).required(), - email: joi.string().email().required(), - phoneNumber: joi.string().regex(/^(\+0?1\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$/), - creditCard: joi.object().keys({ - number: joi.string().creditCard().required(), - cvc: joi.number(), - exp_month: joi.number(), - exp_year: joi.number() - }), - membership: joi.string().creditCard() -}) - -module.exports = userSchema diff --git a/booking-service/src/repository/repository.js b/booking-service/src/repository/repository.js deleted file mode 100644 index bc1840f..0000000 --- a/booking-service/src/repository/repository.js +++ /dev/null @@ -1,79 +0,0 @@ -'use strict' -const repository = (container) => { - const {database: db} = container.cradle - - const makeBooking = (user, booking) => { - return new Promise((resolve, reject) => { - const payload = { - city: booking.city, - userType: (user.membership) ? 'loyal' : 'normal', - totalAmount: booking.totalAmount, - cinema: { - name: booking.cinema, - room: booking.cinemaRoom, - seats: booking.seats.toString() - }, - movie: { - title: booking.movie.title, - format: booking.movie.format, - schedule: booking.schedule - } - } - - db.collection('booking').insertOne(payload, (err, booked) => { - if (err) { - reject(new Error('An error occuered registring a user booking, err:' + err)) - } - resolve(payload) - }) - }) - } - - const generateTicket = (paid, booking) => { - return new Promise((resolve, reject) => { - const payload = Object.assign({}, booking, {orderId: paid.charge.id, description: paid.description}) - db.collection('tickets').insertOne(payload, (err, ticket) => { - if (err) { - reject(new Error('an error occured registring a ticket, err:' + err)) - } - resolve(payload) - }) - }) - } - - const getOrderById = (orderId) => { - return new Promise((resolve, reject) => { - const ObjectID = container.resolve('ObjectID') - const query = {_id: new ObjectID(orderId)} - const response = (err, order) => { - if (err) { - reject(new Error('An error occuered retrieving a order, err: ' + err)) - } - resolve(order) - } - db.collection('booking').findOne(query, {}, response) - }) - } - - const disconnect = () => { - db.close() - } - - return Object.create({ - makeBooking, - getOrderById, - generateTicket, - disconnect - }) -} - -const connect = (container) => { - return new Promise((resolve, reject) => { - if (!container.resolve('database')) { - reject(new Error('connection db not supplied!')) - } - resolve(repository(container)) - }) -} - -module.exports = Object.assign({}, {connect}) diff --git a/booking-service/src/repository/repository.spec.js b/booking-service/src/repository/repository.spec.js deleted file mode 100644 index b423fc2..0000000 --- a/booking-service/src/repository/repository.spec.js +++ /dev/null @@ -1,9 +0,0 @@ -/* eslint-env mocha */ -const should = require('should') -const repository = require('./repository') - -describe('Repository', () => { - it('should connect with a promise', () => { - repository.connect({}).should.be.a.Promise() - }) -}) diff --git a/booking-service/src/server/server.js b/booking-service/src/server/server.js deleted file mode 100644 index 33cd1c4..0000000 --- a/booking-service/src/server/server.js +++ /dev/null @@ -1,43 +0,0 @@ -const express = require('express') -const morgan = require('morgan') -const helmet = require('helmet') -const bodyparser = require('body-parser') -const cors = require('cors') -const _api = require('../api/booking') - -const start = (container) => { - return new Promise((resolve, reject) => { - const {port} = container.resolve('serverSettings') - const repo = container.resolve('repo') - - if (!repo) { - reject(new Error('The server must be started with a connected repository')) - } - if (!port) { - reject(new Error('The server must be started with an available port')) - } - - const app = express() - app.use(morgan('dev')) - app.use(bodyparser.json()) - app.use(cors()) - app.use(helmet()) - app.use((err, req, res, next) => { - reject(new Error('Something went wrong!, err:' + err)) - res.status(500).send('Something went wrong!') - next() - }) - app.use((req, res, next) => { - req.container = container.createScope() - next() - }) - - const api = _api.bind(null, {repo}) - api(app) - - const server = app.listen(port, () => resolve(server)) - - }) -} - -module.exports = Object.assign({}, {start}) diff --git a/booking-service/src/server/server.spec.js b/booking-service/src/server/server.spec.js deleted file mode 100644 index 033d152..0000000 --- a/booking-service/src/server/server.spec.js +++ /dev/null @@ -1,12 +0,0 @@ -/* eslint-env mocha */ -const server = require('./server') - -describe('Server', () => { - it('should require a port to start', () => { - return server.start({}).should.be.rejectedWith(/port/) - }) - - it('should require a repository to start', () => { - return server.start({}).should.be.rejectedWith(/repository/) - }) -}) diff --git a/booking-service/src/services/index.js b/booking-service/src/services/index.js deleted file mode 100644 index 89d69d7..0000000 --- a/booking-service/src/services/index.js +++ /dev/null @@ -1,4 +0,0 @@ -const paymentService = require('./payment.service') -const notificationService = require('./notification.service') - -module.exports = Object.assign({}, {paymentService, notificationService}) diff --git a/booking-service/src/services/notification.service.js b/booking-service/src/services/notification.service.js deleted file mode 100644 index 9fe62d7..0000000 --- a/booking-service/src/services/notification.service.js +++ /dev/null @@ -1,17 +0,0 @@ -const supertest = require('supertest') -process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' -process.env.NODE_TLS_ACCEPT_UNTRUSTED_CERTIFICATES_THIS_IS_INSECURE = '1' - -module.exports = (payload) => { - return new Promise((resolve, reject) => { - supertest('https://192.168.99.100:8080') - .post('/notification/sendEmail') - .send({payload}) - .end((err, res) => { - if (err) { - reject(new Error('An error occured with the payment service, err: ' + err)) - } - resolve(res.body) - }) - }) -} diff --git a/booking-service/src/services/payment.service.js b/booking-service/src/services/payment.service.js deleted file mode 100644 index c7d15b8..0000000 --- a/booking-service/src/services/payment.service.js +++ /dev/null @@ -1,17 +0,0 @@ -const supertest = require('supertest') -process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' -process.env.NODE_TLS_ACCEPT_UNTRUSTED_CERTIFICATES_THIS_IS_INSECURE = '1' - -module.exports = (paymentOrder) => { - return new Promise((resolve, reject) => { - supertest('https://192.168.99.100:8080') - .post('/payment/makePurchase') - .send({paymentOrder}) - .end((err, res) => { - if (err) { - reject(new Error('An error occured with the payment service, err: ' + err)) - } - resolve(res.body.paid) - }) - }) -} diff --git a/booking-service/start-service.sh b/booking-service/start-service.sh deleted file mode 100644 index fc51749..0000000 --- a/booking-service/start-service.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -docker service create --replicas 1 --name booking-service -l=apiRoute='/booking' -p 3002:3000 --env-file env crizstian/booking-service diff --git a/build.sh b/build.sh old mode 100644 new mode 100755 diff --git a/cinema-catalog-service/.eslintrc.json b/cinema-catalog-service/.eslintrc.json deleted file mode 100644 index a755cdb..0000000 --- a/cinema-catalog-service/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": ["standard"] -} diff --git a/cinema-catalog-service/Dockerfile b/cinema-catalog-service/Dockerfile deleted file mode 100644 index 523816b..0000000 --- a/cinema-catalog-service/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM node:7.5.0-alpine - -RUN addgroup -S nupp && adduser -S -g nupp nupp - -ENV HOME=/home/nupp - -COPY package.json npm-shrinkwrap.json $HOME/app/ - -COPY src/ $HOME/app/src - -ADD https://github.com/Yelp/dumb-init/releases/download/v1.1.1/dumb-init_1.1.1_amd64 /usr/local/bin/dumb-init - -WORKDIR $HOME/app - -RUN chown -R nupp:nupp $HOME/* /usr/local/ && \ - chmod +x /usr/local/bin/dumb-init && \ - npm cache clean && \ - npm install --silent --progress=false --production && \ - chown -R nupp:nupp $HOME/* - -USER nupp - -EXPOSE 3000 - -CMD ["dumb-init", "npm", "start"] diff --git a/cinema-catalog-service/create-image.sh b/cinema-catalog-service/create-image.sh deleted file mode 100644 index dcdbb68..0000000 --- a/cinema-catalog-service/create-image.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -docker rm -f cinema-catalog-service - -docker rmi cinema-catalog-service - -docker image prune - -docker volume prune - -docker build -t cinema-catalog-service . diff --git a/cinema-catalog-service/env b/cinema-catalog-service/env deleted file mode 100644 index fa652a3..0000000 --- a/cinema-catalog-service/env +++ /dev/null @@ -1,6 +0,0 @@ -DB=cinemas -DB_USER=cristian -DB_PASS=cristianPassword2017 -DB_REPLS=rs1 -DB_SERVERS='192.168.99.100:27017 192.168.99.101:27017 192.168.99.102:27017' -PORT=3000 diff --git a/cinema-catalog-service/integration-test/cinema-catalog-service-api.jmeter.test.jmx b/cinema-catalog-service/integration-test/cinema-catalog-service-api.jmeter.test.jmx deleted file mode 100644 index a77d528..0000000 --- a/cinema-catalog-service/integration-test/cinema-catalog-service-api.jmeter.test.jmx +++ /dev/null @@ -1,182 +0,0 @@ - - - - - - false - false - - - - - - - - - - - - continue - - false - 1000 - - 100 - 1000 - 1485133702000 - 1485133702000 - false - - - - - - - - - 192.168.99.100 - 3000 - - - https - - - 6 - - - - - - - false - 1 - = - true - id - - - - - - - - - - /cinemas/588ababf2d029a6d15d0b5bf/${id} - GET - true - false - true - false - false - - - - - - - - false - 3 - = - true - id - - - - - - - - - - /cinemas/588ababf2d029a6d15d0b5bf/${id} - GET - true - false - true - false - false - - - - - - - - false - 2 - = - true - id - - - - - - - - - - /cinemas/588ababf2d029a6d15d0b5bf/${id} - GET - true - false - true - false - false - - - - - - - - false - 588ababf2d029a6d15d0b5bf - = - true - cityId - - - - - - - - - - /cinemas?cityId=${cityId} - GET - true - false - true - false - false - - - - - - - - - - - - - - /cinemas/588ac3a02d029a6d15d0b5c4 - GET - true - false - true - false - false - - - - - - - diff --git a/cinema-catalog-service/integration-test/index.js b/cinema-catalog-service/integration-test/index.js deleted file mode 100644 index 72a8519..0000000 --- a/cinema-catalog-service/integration-test/index.js +++ /dev/null @@ -1,10 +0,0 @@ -/* eslint-env mocha */ -const supertest = require('supertest') - -describe('cinema-catalog-service', () => { - const api = supertest('http://192.168.99.100:3001') - it('returns schedules for a movie', (done) => { - api.get('/cinemas/588ababf2d029a6d15d0b5bf/1') - .expect(200, done) - }) -}) diff --git a/cinema-catalog-service/npm-shrinkwrap.json b/cinema-catalog-service/npm-shrinkwrap.json deleted file mode 100644 index 2581895..0000000 --- a/cinema-catalog-service/npm-shrinkwrap.json +++ /dev/null @@ -1,520 +0,0 @@ -{ - "name": "movies-service", - "version": "1.0.0", - "dependencies": { - "accepts": { - "version": "1.3.3", - "from": "accepts@>=1.3.3 <1.4.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz" - }, - "array-flatten": { - "version": "1.1.1", - "from": "array-flatten@1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" - }, - "basic-auth": { - "version": "1.0.4", - "from": "basic-auth@>=1.0.3 <1.1.0", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz" - }, - "bson": { - "version": "0.4.23", - "from": "bson@>=0.4.23 <0.5.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-0.4.23.tgz" - }, - "buffer-shims": { - "version": "1.0.0", - "from": "buffer-shims@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" - }, - "camelize": { - "version": "1.0.0", - "from": "camelize@1.0.0", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz" - }, - "connect": { - "version": "3.5.0", - "from": "connect@3.5.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.5.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "content-disposition": { - "version": "0.5.1", - "from": "content-disposition@0.5.1", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz" - }, - "content-security-policy-builder": { - "version": "1.1.0", - "from": "content-security-policy-builder@1.1.0", - "resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-1.1.0.tgz" - }, - "content-type": { - "version": "1.0.2", - "from": "content-type@>=1.0.2 <1.1.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz" - }, - "cookie": { - "version": "0.3.1", - "from": "cookie@0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz" - }, - "cookie-signature": { - "version": "1.0.6", - "from": "cookie-signature@1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" - }, - "core-util-is": { - "version": "1.0.2", - "from": "core-util-is@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" - }, - "dasherize": { - "version": "2.0.0", - "from": "dasherize@2.0.0", - "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz" - }, - "dashify": { - "version": "0.2.2", - "from": "dashify@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/dashify/-/dashify-0.2.2.tgz" - }, - "debug": { - "version": "2.6.0", - "from": "debug@>=2.1.1 <3.0.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz" - }, - "depd": { - "version": "1.1.0", - "from": "depd@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz" - }, - "destroy": { - "version": "1.0.4", - "from": "destroy@>=1.0.4 <1.1.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" - }, - "dns-prefetch-control": { - "version": "0.1.0", - "from": "dns-prefetch-control@0.1.0", - "resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz" - }, - "dont-sniff-mimetype": { - "version": "1.0.0", - "from": "dont-sniff-mimetype@1.0.0", - "resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.0.0.tgz" - }, - "ee-first": { - "version": "1.1.1", - "from": "ee-first@1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" - }, - "encodeurl": { - "version": "1.0.1", - "from": "encodeurl@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz" - }, - "es6-promise": { - "version": "3.0.2", - "from": "es6-promise@3.0.2", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz" - }, - "escape-html": { - "version": "1.0.3", - "from": "escape-html@>=1.0.3 <1.1.0", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" - }, - "etag": { - "version": "1.7.0", - "from": "etag@>=1.7.0 <1.8.0", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz" - }, - "express": { - "version": "4.14.0", - "from": "express@latest", - "resolved": "https://registry.npmjs.org/express/-/express-4.14.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - }, - "qs": { - "version": "6.2.0", - "from": "qs@6.2.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz" - } - } - }, - "finalhandler": { - "version": "0.5.0", - "from": "finalhandler@0.5.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@~2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "forwarded": { - "version": "0.1.0", - "from": "forwarded@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz" - }, - "frameguard": { - "version": "3.0.0", - "from": "frameguard@3.0.0", - "resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.0.0.tgz" - }, - "fresh": { - "version": "0.3.0", - "from": "fresh@0.3.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz" - }, - "handle-thing": { - "version": "1.2.5", - "from": "handle-thing@>=1.2.4 <2.0.0", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz" - }, - "helmet": { - "version": "3.4.0", - "from": "helmet@>=3.4.0 <4.0.0", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.4.0.tgz" - }, - "helmet-csp": { - "version": "2.3.0", - "from": "helmet-csp@2.3.0", - "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.3.0.tgz" - }, - "hide-powered-by": { - "version": "1.0.0", - "from": "hide-powered-by@1.0.0", - "resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.0.0.tgz" - }, - "hpack.js": { - "version": "2.1.6", - "from": "hpack.js@>=2.1.6 <3.0.0", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz" - }, - "hpkp": { - "version": "2.0.0", - "from": "hpkp@2.0.0", - "resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz" - }, - "hsts": { - "version": "2.0.0", - "from": "hsts@2.0.0", - "resolved": "https://registry.npmjs.org/hsts/-/hsts-2.0.0.tgz" - }, - "http-deceiver": { - "version": "1.2.7", - "from": "http-deceiver@>=1.2.4 <2.0.0", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" - }, - "http-errors": { - "version": "1.5.1", - "from": "http-errors@>=1.5.0 <1.6.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz" - }, - "http-status": { - "version": "0.2.5", - "from": "http-status@latest", - "resolved": "https://registry.npmjs.org/http-status/-/http-status-0.2.5.tgz" - }, - "ienoopen": { - "version": "1.0.0", - "from": "ienoopen@1.0.0", - "resolved": "https://registry.npmjs.org/ienoopen/-/ienoopen-1.0.0.tgz" - }, - "inherits": { - "version": "2.0.3", - "from": "inherits@>=2.0.3 <3.0.0", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - }, - "ipaddr.js": { - "version": "1.2.0", - "from": "ipaddr.js@1.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.2.0.tgz" - }, - "isarray": { - "version": "1.0.0", - "from": "isarray@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - }, - "lodash.reduce": { - "version": "4.6.0", - "from": "lodash.reduce@4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz" - }, - "media-typer": { - "version": "0.3.0", - "from": "media-typer@0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" - }, - "merge-descriptors": { - "version": "1.0.1", - "from": "merge-descriptors@1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" - }, - "methods": { - "version": "1.1.2", - "from": "methods@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" - }, - "mime": { - "version": "1.3.4", - "from": "mime@>=1.3.4 <2.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" - }, - "mime-db": { - "version": "1.26.0", - "from": "mime-db@>=1.26.0 <1.27.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.26.0.tgz" - }, - "mime-types": { - "version": "2.1.14", - "from": "mime-types@>=2.1.10 <3.0.0", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.14.tgz" - }, - "minimalistic-assert": { - "version": "1.0.0", - "from": "minimalistic-assert@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" - }, - "mongodb": { - "version": "2.1.18", - "from": "mongodb@2.1.18", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.1.18.tgz", - "dependencies": { - "isarray": { - "version": "0.0.1", - "from": "isarray@0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" - }, - "readable-stream": { - "version": "1.0.31", - "from": "readable-stream@1.0.31", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.31.tgz" - } - } - }, - "mongodb-core": { - "version": "1.3.18", - "from": "mongodb-core@1.3.18", - "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-1.3.18.tgz" - }, - "morgan": { - "version": "1.7.0", - "from": "morgan@latest", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.7.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@~2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "ms": { - "version": "0.7.2", - "from": "ms@0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz" - }, - "negotiator": { - "version": "0.6.1", - "from": "negotiator@0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz" - }, - "nocache": { - "version": "2.0.0", - "from": "nocache@2.0.0", - "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.0.0.tgz" - }, - "obuf": { - "version": "1.1.1", - "from": "obuf@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz" - }, - "on-finished": { - "version": "2.3.0", - "from": "on-finished@>=2.3.0 <2.4.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" - }, - "on-headers": { - "version": "1.0.1", - "from": "on-headers@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" - }, - "parseurl": { - "version": "1.3.1", - "from": "parseurl@>=1.3.1 <1.4.0", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz" - }, - "path-to-regexp": { - "version": "0.1.7", - "from": "path-to-regexp@0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" - }, - "platform": { - "version": "1.3.3", - "from": "platform@1.3.3", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.3.tgz" - }, - "process-nextick-args": { - "version": "1.0.7", - "from": "process-nextick-args@>=1.0.6 <1.1.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" - }, - "proxy-addr": { - "version": "1.1.3", - "from": "proxy-addr@>=1.1.2 <1.2.0", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.3.tgz" - }, - "range-parser": { - "version": "1.2.0", - "from": "range-parser@>=1.2.0 <1.3.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz" - }, - "readable-stream": { - "version": "2.2.2", - "from": "readable-stream@>=2.2.2 <3.0.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.2.tgz" - }, - "referrer-policy": { - "version": "1.1.0", - "from": "referrer-policy@1.1.0", - "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.1.0.tgz" - }, - "require_optional": { - "version": "1.0.0", - "from": "require_optional@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.0.tgz", - "dependencies": { - "resolve-from": { - "version": "2.0.0", - "from": "resolve-from@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz" - } - } - }, - "select-hose": { - "version": "2.0.0", - "from": "select-hose@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" - }, - "semver": { - "version": "5.3.0", - "from": "semver@>=5.1.0 <6.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz" - }, - "send": { - "version": "0.14.1", - "from": "send@0.14.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.14.1.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@~2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "serve-static": { - "version": "1.11.1", - "from": "serve-static@>=1.11.1 <1.12.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.11.1.tgz" - }, - "setprototypeof": { - "version": "1.0.2", - "from": "setprototypeof@1.0.2", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz" - }, - "spdy": { - "version": "3.4.4", - "from": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz" - }, - "spdy-transport": { - "version": "2.0.18", - "from": "spdy-transport@>=2.0.15 <3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.18.tgz" - }, - "statuses": { - "version": "1.3.1", - "from": "statuses@>=1.3.0 <1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz" - }, - "string_decoder": { - "version": "0.10.31", - "from": "string_decoder@>=0.10.0 <0.11.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - }, - "type-is": { - "version": "1.6.14", - "from": "type-is@>=1.6.13 <1.7.0", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.14.tgz" - }, - "unpipe": { - "version": "1.0.0", - "from": "unpipe@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" - }, - "util-deprecate": { - "version": "1.0.2", - "from": "util-deprecate@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - }, - "utils-merge": { - "version": "1.0.0", - "from": "utils-merge@1.0.0", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" - }, - "vary": { - "version": "1.1.0", - "from": "vary@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.0.tgz" - }, - "wbuf": { - "version": "1.7.2", - "from": "wbuf@>=1.4.0 <2.0.0", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz" - }, - "x-xss-protection": { - "version": "1.0.0", - "from": "x-xss-protection@1.0.0", - "resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.0.0.tgz" - } - } -} diff --git a/cinema-catalog-service/package.json b/cinema-catalog-service/package.json deleted file mode 100644 index 767d1bb..0000000 --- a/cinema-catalog-service/package.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "movies-service", - "version": "1.0.0", - "description": "A movie service, microservice example with nodejs", - "author": "Cristian Ramirez Rosas ", - "license": "ISC", - "main": "index.js", - "standard": { - "ignore": [ - "mock/**.js" - ] - }, - "scripts": { - "test": "mocha -R spec src/**/*.spec.js", - "start": "node src/index.js", - "lint": "standard --verbose | snazzy", - "node-debug": "DEBUG=express* node src/index.js", - "chrome-debug": "node --debug-brk --inspect src/index.js", - "coverage": "istanbul cover _mocha $(find ./src -name \"*.spec.js\" -not -path \"./node_modules/*\") ", - "metric": "nodejs-dashboard -- node -r nodejs-dashboard src/index.js" - }, - "keywords": [ - "express", - "mongodb", - "docker", - "microservice" - ], - "devDependencies": { - "eslint": "^3.13.1", - "mocha": "^3.2.0", - "nodejs-dashboard": "^0.3.0", - "should": "^11.1.2", - "snazzy": "^6.0.0", - "standard": "^8.6.0", - "supertest": "^2.0.1" - }, - "dependencies": { - "express": "^4.14.0", - "helmet": "^3.4.0", - "http-status": "^0.2.5", - "mongodb": "^2.1.18", - "morgan": "^1.7.0", - "spdy": "^3.4.4" - } -} diff --git a/cinema-catalog-service/readme.md b/cinema-catalog-service/readme.md deleted file mode 100644 index 344338b..0000000 --- a/cinema-catalog-service/readme.md +++ /dev/null @@ -1,27 +0,0 @@ -## Build a NodeJS microservice and deploy it to Docker - -[![Standard - JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/) - -Example of the **cinema catalog service** microservice and API. - -![](https://cdn-images-1.medium.com/max/1600/1*oj7mSGXTnnMBDVYeqE3SRw.png) - -To import the database used for this repo and article run the following command on your MongoDB env: -First we need to do a `$ docker cp file mongoNodeContainer:/tmp` - -``` -$ docker exec mongoNode{number} bash -c 'mongoimport --db cinemas --collection countries --file /tmp/countries.json --jsonArray -u $MONGO_USER_ADMIN -p $MONGO_PASS_ADMIN --authenticationDatabase "admin"' - -$ docker exec mongoNode{number} bash -c 'mongoimport --db cinemas --collection states --file /tmp/states.json --jsonArray -u $MONGO_USER_ADMIN -p $MONGO_PASS_ADMIN --authenticationDatabase "admin"' - -$ docker exec mongoNode{number} bash -c 'mongoimport --db cinemas --collection cities --file /tmp/cities.json --jsonArray -u $MONGO_USER_ADMIN -p $MONGO_PASS_ADMIN --authenticationDatabase "admin"' - -$ docker exec mongoNode{number} bash -c 'mongoimport --db cinemas --collection cinemas --file /tmp/cinemas.json --jsonArray -u $MONGO_USER_ADMIN -p $MONGO_PASS_ADMIN --authenticationDatabase "admin"' -``` - -### Stack -- NodeJS V7 -- MongoDB 3.4.1 -- Docker for Mac 1.12.6 - -[![Standard - JavaScript Style Guide](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard) diff --git a/cinema-catalog-service/src/api/cinema-catalog.js b/cinema-catalog-service/src/api/cinema-catalog.js deleted file mode 100644 index aeb3a4c..0000000 --- a/cinema-catalog-service/src/api/cinema-catalog.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict' -const status = require('http-status') - -module.exports = (app, options) => { - const {repo} = options - - app.get('/cinemas', (req, res, next) => { - repo.getCinemasByCity(req.query.cityId) - .then(cinemas => { - res.status(status.OK).json(cinemas) - }) - .catch(next) - }) - - app.get('/cinemas/:cinemaId', (req, res, next) => { - repo.getCinemaById(req.params.cinemaId) - .then(cinema => { - res.status(status.OK).json(cinema) - }) - .catch(next) - }) - - app.get('/cinemas/:cityId/:movieId', (req, res, next) => { - const params = { - cityId: req.params.cityId, - movieId: req.params.movieId - } - repo.getCinemaScheduleByMovie(params) - .then(schedules => { - res.status(status.OK).json(schedules) - }) - .catch(next) - }) -} diff --git a/cinema-catalog-service/src/api/cinema-catalog.spec.js b/cinema-catalog-service/src/api/cinema-catalog.spec.js deleted file mode 100644 index 3d5d4ae..0000000 --- a/cinema-catalog-service/src/api/cinema-catalog.spec.js +++ /dev/null @@ -1,126 +0,0 @@ -/* eslint-env mocha */ -const request = require('supertest') -const server = require('../server/server') - -describe('Movies API', () => { - let app = null - const testCinemasCity = [{ - '_id': '588ac3a02d029a6d15d0b5c4', - 'name': 'Plaza Morelia' - }, { - '_id': '588ac3a02d029a6d15d0b5c5', - 'name': 'Las Americas' - }] - - const testCinemaId = { - '_id': '588ac3a02d029a6d15d0b5c4', - 'name': 'Plaza Morelia', - 'cinemaPremieres': [ - { - 'id': '1', - 'title': 'Assasins Creed', - 'runtime': 115, - 'plot': 'Lorem ipsum dolor sit amet', - 'poster': 'link to poster...' - }, - { - 'id': '2', - 'title': 'Aliados', - 'runtime': 124, - 'plot': 'Lorem ipsum dolor sit amet', - 'poster': 'link to poster...' - }, - { - 'id': '3', - 'title': 'xXx: Reactivado', - 'runtime': 107, - 'plot': 'Lorem ipsum dolor sit amet', - 'poster': 'link to poster...' - } - ] - } - - const testSchedulesMovie = [{ - '_id': 'Plaza Morelia', - 'schedules': [{ - 'room': 2.0, - 'schedules': [ '10:15' ] - }, { - 'room': 1.0, - 'schedules': [ '6:55', '4:35', '10:15' ] - }, { - 'room': 3.0, - 'schedules': [ '10:15' ] - }] - }, { - '_id': 'Las Americas', - 'schedules': [ { - 'room': 2.0, - 'schedules': [ '3:25', '10:15' ] - }, { - 'room': 1.0, - 'schedules': [ '12:15', '10:15' ] - }] - }] - - let testRepo = { - getCinemasByCity (location) { - console.log(location) - return Promise.resolve(testCinemasCity) - }, - getCinemaById (cinemaId) { - console.log(cinemaId) - return Promise.resolve(testCinemaId) - }, - getCinemaScheduleByMovie (cinemaId, movieId) { - console.log(cinemaId, movieId) - return Promise.resolve(testSchedulesMovie) - } - } - - beforeEach(() => { - return server.start({ - port: 3000, - repo: testRepo - }).then(serv => { - app = serv - }) - }) - - afterEach(() => { - app.close() - app = null - }) - - it('can return cinemas by location', (done) => { - const location = { - city: '588ababf2d029a6d15d0b5bf' - } - request(app) - .get(`/cinemas?cityId=${location.city}`) - .expect((res) => { - res.body.should.containEql(testCinemasCity[0]) - res.body.should.containEql(testCinemasCity[1]) - }) - .expect(200, done) - }) - - it('can get movie premiers by cinema', (done) => { - request(app) - .get('/cinemas/588ac3a02d029a6d15d0b5c4') - .expect((res) => { - res.body.should.containEql(testCinemaId) - }) - .expect(200, done) - }) - - it('can get schedules by cinema and movie', (done) => { - request(app) - .get('/cinemas/588ababf2d029a6d15d0b5bf/1') - .expect((res) => { - res.body.should.containEql(testSchedulesMovie[0]) - res.body.should.containEql(testSchedulesMovie[1]) - }) - .expect(200, done) - }) -}) diff --git a/cinema-catalog-service/src/config/config.js b/cinema-catalog-service/src/config/config.js deleted file mode 100644 index ea6681d..0000000 --- a/cinema-catalog-service/src/config/config.js +++ /dev/null @@ -1,45 +0,0 @@ -const dbSettings = { - db: process.env.DB || 'cinemas', - user: process.env.DB_USER || 'cristian', - pass: process.env.DB_PASS || 'cristianPassword2017', - repl: process.env.DB_REPLS || 'rs1', - servers: (process.env.DB_SERVERS) ? process.env.DB_SERVERS.substr(1, process.env.DB_SERVERS.length - 2).split(' ') : [ - '192.168.99.100:27017', - '192.168.99.101:27017', - '192.168.99.102:27017' - ], - dbParameters: () => ({ - w: 'majority', - wtimeout: 10000, - j: true, - readPreference: 'ReadPreference.SECONDARY_PREFERRED', - native_parser: false - }), - serverParameters: () => ({ - autoReconnect: true, - poolSize: 10, - socketoptions: { - keepAlive: 300, - connectTimeoutMS: 30000, - socketTimeoutMS: 30000 - } - }), - replsetParameters: (replset = 'rs1') => ({ - replicaSet: replset, - ha: true, - haInterval: 10000, - poolSize: 10, - socketoptions: { - keepAlive: 300, - connectTimeoutMS: 30000, - socketTimeoutMS: 30000 - } - }) -} - -const serverSettings = { - port: process.env.PORT || 3000, - ssl: require('./ssl') -} - -module.exports = Object.assign({}, { dbSettings, serverSettings }) diff --git a/cinema-catalog-service/src/config/index.js b/cinema-catalog-service/src/config/index.js deleted file mode 100644 index 12b087c..0000000 --- a/cinema-catalog-service/src/config/index.js +++ /dev/null @@ -1,5 +0,0 @@ -const {ObjectID} = require('mongodb') -const {dbSettings, serverSettings} = require('./config') -const db = require('./mongo') - -module.exports = Object.assign({}, {dbSettings, serverSettings, db, ObjectID}) diff --git a/cinema-catalog-service/src/config/mongo.js b/cinema-catalog-service/src/config/mongo.js deleted file mode 100644 index 18fce0f..0000000 --- a/cinema-catalog-service/src/config/mongo.js +++ /dev/null @@ -1,32 +0,0 @@ -const MongoClient = require('mongodb') - -const getMongoURL = (options) => { - const url = options.servers - .reduce((prev, cur) => prev + cur + ',', 'mongodb://') - - return `${url.substr(0, url.length - 1)}/${options.db}` -} - -const connect = (options, mediator) => { - mediator.once('boot.ready', () => { - MongoClient.connect( - getMongoURL(options), { - db: options.dbParameters(), - server: options.serverParameters(), - replset: options.replsetParameters(options.repl) - }, (err, db) => { - if (err) { - mediator.emit('db.error', err) - } - - db.admin().authenticate(options.user, options.pass, (err, result) => { - if (err) { - mediator.emit('db.error', err) - } - mediator.emit('db.ready', db) - }) - }) - }) -} - -module.exports = Object.assign({}, {connect}) diff --git a/cinema-catalog-service/src/config/mongo.spec.js b/cinema-catalog-service/src/config/mongo.spec.js deleted file mode 100644 index 6226394..0000000 --- a/cinema-catalog-service/src/config/mongo.spec.js +++ /dev/null @@ -1,29 +0,0 @@ -/* eslint-env mocha */ -const {EventEmitter} = require('events') -const test = require('assert') -const mongo = require('./mongo') -const {dbSettings} = require('./config') - -describe('Mongo Connection', () => { - it('should emit db Object with an EventEmitter', (done) => { - const mediator = new EventEmitter() - - mediator.on('db.ready', (db) => { - db.admin().listDatabases((err, dbs) => { - test.equal(null, err) - test.ok(dbs.databases.length > 0) - console.log(dbs.databases) - db.close() - done() - }) - }) - - mediator.on('db.error', (err) => { - console.log(err) - }) - - mongo.connect(dbSettings, mediator) - - mediator.emit('boot.ready') - }) -}) diff --git a/cinema-catalog-service/src/config/ssl/index.js b/cinema-catalog-service/src/config/ssl/index.js deleted file mode 100644 index 63e4cd3..0000000 --- a/cinema-catalog-service/src/config/ssl/index.js +++ /dev/null @@ -1,6 +0,0 @@ -const fs = require('fs') - -module.exports = { - key: fs.readFileSync(`${__dirname}/server.key`), - cert: fs.readFileSync(`${__dirname}/server.crt`) -} diff --git a/cinema-catalog-service/src/index.js b/cinema-catalog-service/src/index.js deleted file mode 100644 index b19b034..0000000 --- a/cinema-catalog-service/src/index.js +++ /dev/null @@ -1,45 +0,0 @@ -'use strict' -const {EventEmitter} = require('events') -const server = require('./server/server') -const repository = require('./repository/repository') -const config = require('./config/') -const mediator = new EventEmitter() - -console.log('--- Cinemas Catalog Service ---') -console.log('Connecting to cinemas catalog repository...') - -process.on('uncaughtException', (err) => { - console.error('Unhandled Exception', err) -}) - -process.on('uncaughtRejection', (err, promise) => { - console.error('Unhandled Rejection', err) -}) - -mediator.on('db.ready', (db) => { - let rep - repository.connect({db, ObjectID: config.ObjectID}) - .then(repo => { - console.log('Connected. Starting Server') - rep = repo - return server.start({ - port: config.serverSettings.port, - ssl: config.serverSettings.ssl, - repo - }) - }) - .then(app => { - console.log(`Server started succesfully, running on port: ${config.serverSettings.port}.`) - app.on('close', () => { - rep.disconnect() - }) - }) -}) - -mediator.on('db.error', (err) => { - console.error(err) -}) - -config.db.connect(config.dbSettings, mediator) - -mediator.emit('boot.ready') diff --git a/cinema-catalog-service/src/mock/cinemas.json b/cinema-catalog-service/src/mock/cinemas.json deleted file mode 100755 index 810fd13..0000000 --- a/cinema-catalog-service/src/mock/cinemas.json +++ /dev/null @@ -1,326 +0,0 @@ -[{ - "_id": { - "$oid": "588ac3a02d029a6d15d0b5c4" - }, - "name": "Plaza Morelia", - "cinemaPremieres": [{ - "id": "1", - "title": "Assasins Creed", - "runtime": 115, - "plot": "Lorem ipsum dolor sit amet", - "poster": "link to poster..." - }, { - "id": "2", - "title": "Aliados", - "runtime": 124, - "plot": "Lorem ipsum dolor sit amet", - "poster": "link to poster..." - }, { - "id": "3", - "title": "xXx: Reactivado", - "runtime": 107, - "plot": "Lorem ipsum dolor sit amet", - "poster": "link to poster..." - }], - "cinemaRooms": [{ - "name": 1.0, - "capacity": 120.0, - "format": "IMAX", - "schedules": [{ - "time": "10:15", - "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], - "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0], - "movie_id": "1", - "price": 54.0 - }, { - "time": "4:35", - "seatsEmpty": [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0], - "seatsOccupied": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "movie_id": "1", - "price": 71.0 - }, { - "time": "6:55", - "seatsEmpty": [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], - "seatsOccupied": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "movie_id": "3", - "price": 79.0 - }] - }, { - "name": 2.0, - "capacity": 100.0, - "format": "Normal", - "schedules": [{ - "time": "10:15", - "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0], - "movie_id": "2", - "price": 71.0 - }] - }, { - "name": 3.0, - "capacity": 80.0, - "format": "4DX", - "schedules": [{ - "time": "10:15", - "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "seatsOccupied": [61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], - "movie_id": "3", - "price": 71.0 - }] - }], - "city_id": "588ababf2d029a6d15d0b5bf" -}, { - "_id": { - "$oid": "588ac3a02d029a6d15d0b5c5" - }, - "name": "Las Americas", - "cinemaPremieres": [{ - "id": "1", - "title": "Assasins Creed", - "runtime": 115, - "plot": "Lorem ipsum dolor sit amet", - "poster": "link to poster..." - }, { - "id": "3", - "title": "xXx: Reactivado", - "runtime": 107, - "plot": "Lorem ipsum dolor sit amet", - "poster": "link to poster..." - }], - "cinemaRooms": [{ - "name": 1.0, - "capacity": 80.0, - "format": "Normal", - "schedules": [{ - "time": "10:15", - "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0], - "seatsOccupied": [40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "movie_id": "1", - "price": 71.0 - }, { - "time": "12:15", - "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0], - "movie_id": "3", - "price": 71.0 - }] - }, { - "name": 2.0, - "capacity": 80.0, - "format": "3D", - "schedules": [{ - "time": "10:15", - "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0], - "seatsOccupied": [40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "movie_id": "1", - "price": 71.0 - }, { - "time": "3:25", - "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0], - "movie_id": "3", - "price": 71.0 - }] - }], - "city_id": "588ababf2d029a6d15d0b5bf" -}, { - "_id": { - "$oid": "588ac53c2d029a6d15d0b5c6" - }, - "name": "Estacion Central", - "cinemaRooms": [{ - "name": 1.0, - "capacity": 100.0, - "schedules": [{ - "time": "12:10", - "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], - "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0], - "movie_id": "1", - "price": 54.0 - }, { - "time": "5:35", - "seatsEmpty": [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0], - "seatsOccupied": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "movie_id": "2", - "price": 71.0 - }, { - "time": "9:55", - "seatsEmpty": [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], - "seatsOccupied": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "movie_id": "3", - "price": 79.0 - }] - }, { - "name": 2.0, - "capacity": 80.0, - "schedules": [{ - "time": "3:15", - "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0], - "movie_id": "4", - "price": 71.0 - }] - }, { - "name": 3.0, - "capacity": 80.0, - "schedules": [{ - "time": "5:25", - "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "seatsOccupied": [61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], - "movie_id": "5", - "price": 71.0 - }] - }], - "city_id": "588ababf2d029a6d15d0b5c3" -}, { - "_id": { - "$oid": "588ac53c2d029a6d15d0b5c7" - }, - "name": "San Agustin", - "cinemaRooms": [{ - "name": 1.0, - "capacity": 60.0, - "schedules": [{ - "time": "12:15", - "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0], - "seatsOccupied": [40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "movie_id": "1", - "price": 71.0 - }] - }], - "city_id": "588ababf2d029a6d15d0b5c3" -}, { - "_id": { - "$oid": "588ac65f2d029a6d15d0b5c8" - }, - "name": "Calima", - "cinemaRooms": [{ - "name": 1.0, - "capacity": 100.0, - "schedules": [{ - "time": "11:10", - "seatsEmpty": [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0], - "seatsOccupied": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "movie_id": "3", - "price": 54.0 - }, { - "time": "5:35", - "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], - "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0], - "movie_id": "1", - "price": 71.0 - }, { - "time": "7:55", - "seatsEmpty": [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], - "seatsOccupied": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "movie_id": "3", - "price": 79.0 - }] - }, { - "name": 2.0, - "capacity": 80.0, - "schedules": [{ - "time": "5:15", - "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0], - "movie_id": "1", - "price": 71.0 - }] - }, { - "name": 3.0, - "capacity": 80.0, - "schedules": [{ - "time": "12:15", - "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0], - "seatsOccupied": [40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "movie_id": "4", - "price": 71.0 - }] - }], - "city_id": "588ababf2d029a6d15d0b5c2" -}, { - "_id": { - "$oid": "588ac65f2d029a6d15d0b5c9" - }, - "name": "Hayuelos Colombia", - "cinemaRooms": [{ - "name": 1.0, - "capacity": 60.0, - "schedules": [{ - "time": "5:25", - "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "seatsOccupied": [61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], - "movie_id": "5", - "price": 71.0 - }] - }], - "city_id": "588ababf2d029a6d15d0b5c2" -}, { - "_id": { - "$oid": "588ac7332d029a6d15d0b5ca" - }, - "name": "City Plaza", - "cinemaRooms": [{ - "name": 1.0, - "capacity": 90.0, - "schedules": [{ - "time": "11:40", - "seatsEmpty": [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0], - "seatsOccupied": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "movie_id": "1", - "price": 90.0 - }, { - "time": "3:35", - "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], - "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0], - "movie_id": "1", - "price": 120.0 - }, { - "time": "6:55", - "seatsEmpty": [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], - "seatsOccupied": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "movie_id": "3", - "price": 79.0 - }] - }, { - "name": 2.0, - "capacity": 80.0, - "schedules": [{ - "time": "5:15", - "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0], - "movie_id": "2", - "price": 71.0 - }] - }], - "city_id": "588ababf2d029a6d15d0b5c1" -}, { - "_id": { - "$oid": "588ac7a12d029a6d15d0b5cb" - }, - "name": "Juriquilla Uptown", - "cinemaRooms": [{ - "name": 1.0, - "capacity": 90.0, - "schedules": [{ - "time": "11:40", - "seatsEmpty": [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0], - "seatsOccupied": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "movie_id": "1", - "price": 90.0 - }, { - "time": "3:35", - "seatsEmpty": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], - "seatsOccupied": [20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0], - "movie_id": "1", - "price": 120.0 - }, { - "time": "6:55", - "seatsEmpty": [11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 61.0, 62.0, 63.0, 64.0, 65.0, 66.0, 67.0, 68.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 76.0, 77.0, 78.0, 79.0, 80.0], - "seatsOccupied": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 52.0, 53.0, 54.0, 55.0, 56.0, 57.0, 58.0, 59.0, 60.0], - "movie_id": "3", - "price": 79.0 - }] - }], - "city_id": "588ababf2d029a6d15d0b5c0" -}] diff --git a/cinema-catalog-service/src/mock/cities.json b/cinema-catalog-service/src/mock/cities.json deleted file mode 100755 index db1be0e..0000000 --- a/cinema-catalog-service/src/mock/cities.json +++ /dev/null @@ -1,36 +0,0 @@ -[{ - "_id": { - "$oid": "588ababf2d029a6d15d0b5bf" - }, - "name": "Morelia", - "state_id": "588aba4d2d029a6d15d0b5ba", - "cinemas": ["588ac3a02d029a6d15d0b5c4", "588ac3a02d029a6d15d0b5c5"] -}, { - "_id": { - "$oid": "588ababf2d029a6d15d0b5c0" - }, - "name": "Queretaro", - "state_id": "588aba4d2d029a6d15d0b5bb", - "cinemas": ["588ac7a12d029a6d15d0b5cb"] -}, { - "_id": { - "$oid": "588ababf2d029a6d15d0b5c1" - }, - "name": "Medellin", - "state_id": "588aba4d2d029a6d15d0b5bd", - "cinemas": ["588ac7332d029a6d15d0b5ca"] -}, { - "_id": { - "$oid": "588ababf2d029a6d15d0b5c2" - }, - "name": "Bogota", - "state_id": "588aba4d2d029a6d15d0b5bc", - "cinemas": ["588ac65f2d029a6d15d0b5c8", "588ac65f2d029a6d15d0b5c9"] -}, { - "_id": { - "$oid": "588ababf2d029a6d15d0b5c3" - }, - "name": "Santiago de Chile", - "state_id": "588aba4d2d029a6d15d0b5be", - "cinemas": ["588ac53c2d029a6d15d0b5c6", "588ac53c2d029a6d15d0b5c7"] -}] diff --git a/cinema-catalog-service/src/mock/countries.json b/cinema-catalog-service/src/mock/countries.json deleted file mode 100755 index 0e2b5d1..0000000 --- a/cinema-catalog-service/src/mock/countries.json +++ /dev/null @@ -1,19 +0,0 @@ -[{ - "_id": { - "$oid": "588ab9d92d029a6d15d0b5b7" - }, - "name": "Mexico", - "states": ["588aba4d2d029a6d15d0b5ba", "588ab9d92d029a6d15d0b5b7"] -}, { - "_id": { - "$oid": "588ab9d92d029a6d15d0b5b8" - }, - "name": "Colombia", - "states": ["588ab9d92d029a6d15d0b5b8", "588ab9d92d029a6d15d0b5b8"] -}, { - "_id": { - "$oid": "588ab9d92d029a6d15d0b5b9" - }, - "name": "Chile", - "states": ["588ab9d92d029a6d15d0b5b9"] -}] diff --git a/cinema-catalog-service/src/mock/index.js b/cinema-catalog-service/src/mock/index.js deleted file mode 100755 index e69de29..0000000 diff --git a/cinema-catalog-service/src/mock/states.json b/cinema-catalog-service/src/mock/states.json deleted file mode 100755 index 3a2104a..0000000 --- a/cinema-catalog-service/src/mock/states.json +++ /dev/null @@ -1,36 +0,0 @@ -[{ - "_id": { - "$oid": "588aba4d2d029a6d15d0b5ba" - }, - "name": "Michoacán", - "country_id": "588ab9d92d029a6d15d0b5b7", - "cities": ["588ababf2d029a6d15d0b5bf"] -}, { - "_id": { - "$oid": "588aba4d2d029a6d15d0b5bb" - }, - "name": "Querétaro", - "country_id": "588ab9d92d029a6d15d0b5b7", - "cities": ["588ababf2d029a6d15d0b5c0"] -}, { - "_id": { - "$oid": "588aba4d2d029a6d15d0b5bc" - }, - "name": "Cundinamrca", - "country_id": "588ab9d92d029a6d15d0b5b8", - "cities": ["588ababf2d029a6d15d0b5c2"] -}, { - "_id": { - "$oid": "588aba4d2d029a6d15d0b5bd" - }, - "name": "Antioquia", - "country_id": "588ab9d92d029a6d15d0b5b8", - "cities": ["588ababf2d029a6d15d0b5c1"] -}, { - "_id": { - "$oid": "588aba4d2d029a6d15d0b5be" - }, - "name": "Region Metropolitana", - "country_id": "588ab9d92d029a6d15d0b5b9", - "cities": ["588ababf2d029a6d15d0b5c3"] -}] diff --git a/cinema-catalog-service/src/repository/repository.js b/cinema-catalog-service/src/repository/repository.js deleted file mode 100644 index 11dfd72..0000000 --- a/cinema-catalog-service/src/repository/repository.js +++ /dev/null @@ -1,98 +0,0 @@ -'use strict' - -const repository = (connection) => { - const {db, ObjectID} = connection - - const getCinemasByCity = (cityId) => { - return new Promise((resolve, reject) => { - const cinemas = [] - const query = {city_id: cityId} - const projection = {_id: 1, name: 1} - const cursor = db.collection('cinemas').find(query, projection) - const addCinema = (cinema) => { - cinemas.push(cinema) - } - const sendCinemas = (err) => { - if (err) { - reject(new Error('An error occured fetching cinemas, err: ' + err)) - } - resolve(cinemas) - } - cursor.forEach(addCinema, sendCinemas) - }) - } - - const getCinemaById = (cinemaId) => { - return new Promise((resolve, reject) => { - const query = {_id: new ObjectID(cinemaId)} - const projection = {_id: 1, name: 1, cinemaPremieres: 1} - const response = (err, cinema) => { - if (err) { - reject(new Error('An error occuered retrieving a cinema, err: ' + err)) - } - resolve(cinema) - } - db.collection('cinemas').findOne(query, projection, response) - }) - } - - const getCinemaScheduleByMovie = (options) => { - return new Promise((resolve, reject) => { - const match = { $match: { - 'city_id': options.cityId, - 'cinemaRooms.schedules.movie_id': options.movieId - }} - const project = { $project: { - 'name': 1, - 'cinemaRooms.schedules.time': 1, - 'cinemaRooms.name': 1, - 'cinemaRooms.format': 1 - }} - const unwind = [{ $unwind: '$cinemaRooms' }, { $unwind: '$cinemaRooms.schedules' }] - const group = [{ $group: { - _id: { - name: '$name', - room: '$cinemaRooms.name' - }, - schedules: { $addToSet: '$cinemaRooms.schedules.time' } - }}, { $group: { - _id: '$_id.name', - schedules: { - $addToSet: { - room: '$_id.room', - schedules: '$schedules' - } - } - }}] - const sendSchedules = (err, result) => { - if (err) { - reject('An error has occured fetching schedules by movie, err: ' + err) - } - resolve(result) - } - db.collection('cinemas').aggregate([match, project, ...unwind, ...group], sendSchedules) - }) - } - - const disconnect = () => { - db.close() - } - - return Object.create({ - getCinemasByCity, - getCinemaById, - getCinemaScheduleByMovie, - disconnect - }) -} - -const connect = (connection) => { - return new Promise((resolve, reject) => { - if (!connection) { - reject(new Error('connection db not supplied!')) - } - resolve(repository(connection)) - }) -} - -module.exports = Object.assign({}, {connect}) diff --git a/cinema-catalog-service/src/repository/repository.spec.js b/cinema-catalog-service/src/repository/repository.spec.js deleted file mode 100644 index 2ff7bb2..0000000 --- a/cinema-catalog-service/src/repository/repository.spec.js +++ /dev/null @@ -1,10 +0,0 @@ -/* eslint-env mocha */ -const should = require('should') -const repository = require('./repository') - -describe('Repository', () => { - it('should connect with a promise', (done) => { - repository.connect({}).should.be.a.Promise() - done() - }) -}) diff --git a/cinema-catalog-service/src/server/server.js b/cinema-catalog-service/src/server/server.js deleted file mode 100644 index 0fa11dc..0000000 --- a/cinema-catalog-service/src/server/server.js +++ /dev/null @@ -1,29 +0,0 @@ -const express = require('express') -const morgan = require('morgan') -const helmet = require('helmet') -const api = require('../api/cinema-catalog') - -const start = (options) => { - return new Promise((resolve, reject) => { - if (!options.repo) { - reject(new Error('The server must be started with a connected repository')) - } - if (!options.port) { - reject(new Error('The server must be started with an available port')) - } - - const app = express() - app.use(morgan('dev')) - app.use(helmet()) - app.use((err, req, res, next) => { - reject(new Error('Something went wrong!, err:' + err)) - res.status(500).send('Something went wrong!') - }) - - api(app, options) - - const server = app.listen(options.port, () => resolve(server)) - }) -} - -module.exports = Object.assign({}, {start}) diff --git a/cinema-catalog-service/src/server/server.spec.js b/cinema-catalog-service/src/server/server.spec.js deleted file mode 100644 index f552ac9..0000000 --- a/cinema-catalog-service/src/server/server.spec.js +++ /dev/null @@ -1,16 +0,0 @@ -/* eslint-env mocha */ -const server = require('./server') - -describe('Server', () => { - it('should require a port to start', () => { - return server.start({ - repo: {} - }).should.be.rejectedWith(/port/) - }) - - it('should require a repository to start', () => { - return server.start({ - port: {} - }).should.be.rejectedWith(/repository/) - }) -}) diff --git a/cinema-catalog-service/start-service.sh b/cinema-catalog-service/start-service.sh deleted file mode 100644 index 81cf997..0000000 --- a/cinema-catalog-service/start-service.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -docker service create --replicas 1 --name cinema-catalog-service -l=apiRoute='/cinemas' -p 3001:3000 --env-file env crizstian/cinema-catalog-service diff --git a/cover.png b/cover.png deleted file mode 100644 index c538ea61ed1ec6c976241ed943b9defff4328913..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 743388 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

j*YO0H^s4<<%JXtqr8Z}f2*fxjihP$w(R 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%0A~oJ)BG+S02`R@3)@9!S(o! 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%0Dogu(Utev!{2iPM>8FIV6@-z6V9Gp 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�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

x&C9Yvw9$psk*2D|_)Jt)O?Aj&X~$dHWX z%?Y*h>Bnf7y|*fhT3djA`o8EWh0|ZDWc$Ti*Iw)5z3BGW!ylm(wAb=a0D~ ze-3WZmY5%B{-BJy)Y~MJ_(=W^6cBOJJaf&U3$okZ@5=+9+5W;*>F7y z_Kr-K34U2Ws|_J;;R8ngI`?gx9bK1<>jSK5Ap=lzoea~hKWk&pnF#n0!zv27~8Caf>n^bHa6cEJ!#&<{%P_!iS zj5j%6rB#t_y9Js*T?$XimcuzteXkZ}X(R-2&1l<-Rq2+=rI&jvK0Lb#uWOnR#VICc zOb-;PkQXM_or@de3e|{vuG>-JpI4}4Q^#YYHt}SiS$6GyVKBE)uvpUgbUnd+Ga?qv zFHmTwVV^io*rE&mvebhEIm3F`$Yt_W@3`okG`q+Iv6bRi1l$)oM8FmeCKa2rp@*7J z$1x+5j~h{mNMzvn>}#1(JmrKv28gD{=^ZlJ#XmG1*Zxs_Mw2Zdz(tv2UOW5>$mMO}a+y$At ztg*SvJnL@k+M;hyq~6FUq7S6i{V-p)oqBsp{^eTQ&Eg_%Y8s7Z@S3jyC!=SUvA81^ zPbA!sQ8b+GE8`3%yq`KVn2f+q7*ubzTAeBTHm2BzQ*|V#lO~|+aN{Py2vQ=tS+`p^ zRmb*QB%#pV8~HTM4g%!eXk*$=r@qKz?pWM(->J#LWWwj3QG-I{OXU)&Dr!TbTT@q; z&uHI?w*ieRLNV&yEffPLyXk_84&uvYcqd8`sD^;S=m(KJp;xhao^`x%$j~0K^{9z< zSvjpBW8|$JkeiFaD+`8S%^g(4@4}NJ9|f(I_hMsc(t~W|^PeQ2lp-bLyZJM|4+|O! zGGfo9*hP{lb`sG!#WNTy4rm^jA-|h(QXVbrWidyZ%~v}SK0k1xaRp!fgMHl9B)QCyn-I1tI9 z{{KtdAxK2G3+gSHJJ})m^kWu4QBv1pQH9~kR*9CoX;|4}8I&R#T_K6x_HI>S*#YqFt}xPtkrSM%X03yf?^@XZP}oy zh#)NHUM_ENAAlX0aF}0BN;rHO5nSgwa?JnpiGeF4SWO)nu z{a?r{A`k1Nw~lj6NDBSLwo-)l>Z*Ublzd8dxt50hZJNNWI`=-YT3w}=iDF4W9*zbU z-sQBbtSA(t*aMoG9WcFpCf-5>K8HU=roxT2psdk+OXc#zi!6ShNC`~l zP-r%s2b zEY%GVF3rzRyE3JMks9JYCKC0}uFI_lZ?ZnmV)hA*UN|6nVS(z_82S&TXd=hsg_6uq z<|%x2x3;#LZWECYum$sVFP)t=BOo%H6Ky~k8oopjLnO||YN#dqip1~dyi=#S> z$!HiQ86%h^8Em&bQiKvN3oIugEa*yD?@0FO_OC}FzDhVJUHkU(~c*U{4K75 z#ad^x_O5Sfd2;3e*EW?);PY$*-VUtm-)6c3Q69M9<0{)VWe(v4DlyMPWndvQG6;eV zbFQMweg`!OQKqIg5>kx&dOvLU&z1TYedOYTIM_zD2ahQLlGwj+qz9P`9TMNCQI0KAOV`j%;wCW$H>L zQ5Mmnh|~`^s!$;U_6-U03s8scBw1vVIBs2Lk{g!O^Qcgq~pJW zl@|=~N$^c|9)%YoK3TaPnO;>Ko{x8UjtenEzFl9!Qg#9xXrXzIA0YqQojzMZYUG zh%%^&a9FPy^9G9%vc8du*U9;-gUa%+Umz~%6@5o#KAORpLDM&&kAGZGqc~{^*j>Bs zUC*v#CMxnDs4yUc4bl59*Mki!gg7uFz^C@ognP95Ni68rXND0v?qJrwCbiFwvpGwk zi6z@+$^XpR&F1fyTOG@WO$Lc=lL~lij^OrLEK^ECqovo_}qCE9KM`^U72F$pSk!;ATXx)tPesCq` zL^%Khk@NFsy>jU$!1<51jdIq+S*qnFi1#CDVc02Bcyz^=aG_vdJ}epJK!WV?X*R@i ze*N4nnE=!n8`+M>GD4>0CsEj z(fEw;ZK!&NJ9P2MQ#;@xA^X1RXHp`rZdRo3k<%fLD2MRNX_OmWvzxkc*{_w62vL$* z@L6ANIkg4R2(nM4mnV~8_w~FRKer0pL5B$@0lpNv9#lVgf1s#3<}1ZBJ6}dnTfD^y zn5Fq${Kq3kwM#ut>qT?n*)Diqjr(?c+nSdfH$FO)n2P$e>q5XzRfIK$;=Gc>eEN(C z*ZWWSNQ_R-<)2SSUm?~%(uiSZWqZr=^ZTM!1FLi z)g@W7t>{m>J=xC}F(rP7-E|yiUke1Xb)$Tr*OmPM5SK0A_c;2`^X^)i>K2SeFH@X& za#ahsUqp9-ib%)~q}xEwmBG(~a( zaq(jj!a-lge+q3f1XUi!V4^8pf-(?sud2KU%eU~2Lhf=r}5y6e%mtP<><1|;CIZKaWrj5yRbMt|N8kDEM<;zl11?}qGS;9 zsxWWRTSpg)B%)(led#F2<@kShL2OSOqiVMa&g(|aD^@?pl6TP(dCikd-f`Q?oWj%= zKk3P7m8<^cPP%e|u@lR<@{<=`sSj*TQS4Rh_qnD^UEix$Q0e3r=0vRKq?mNLr<552 z_7YA;(Dp@XzFJ|o2Xpvy=u7JsRnc7^3Hj&->@%Q3IkTJR$h53E8 z)%a+c)7V4reMv?_Nt35$(Ckc{OoA;>55i}^vS5D~^foj^z4_rr;}=KSl&mu$Z?U<; zi+`b35wTU$y;;YUzv8I~rp_ZGk}sa#)aDvoiP!(2 zgK3W}gaUj+$NRIFyA#bUX&$U={g*S#%g63x zV-CYQxQA^^J)KC+Iv>9?fBRC_hlUu#(0pvcd-NZx4#8%XnSKcKIR5z9y$SI+KQv6h zl(Z-DgJTS~?Wa6~nbc8k$L(x@Pzm)|;@M!pH`c#y*e#b#eJ`l2?c;zaX`b7-MC~fTE7=m00UDXPV#15x3%}Qg zY=)2V`9Ew#9Vm2hWNkp@QMb>hrS1bYf$93TR6w`!$vJa7&5vI*T@PHr4HJ%|0=}Zu z5$NXCa|5?RdN9W3Q+rA4%znN}96AUZ1`I4K?`l_X0!92lsHNDjZ8QGHYr=Um3_tIG z{M&Z0g^U~oV4`-Fk}~NFM;7z8C*9@9Dnq7;1Y9ph@#*+@z5)x-K-w>Nrj8E*Ov~Nq z=Gt&AF^$P@QGjQe#x>ykp6*O1tqm+iyQcQgn;CzG_~6TR!9}TTdeEIZdk`T#qoi=I zlYTQ6SV;Y|h&|Lzzpvev25cIdOvZW7nchYWsH=-J($IWVQfb4+!MYMqR$=$H2UnWz z2-_gl0LG$>-E~0~ObzuPr8VnZN1f;==VnVjqi_BW57aeh;QJ?S^$=^;@OG*9- zuFF+`4u;Lu*p)?B%t$$1Q5p74ZzE?#iF`@fDeKP*)|T!rPQg<9$~KROg#@xM?f7I_ zz1S^9Hsoz*QNgmzMQ@@WL{IL1wCYqBQK(Q}i_`_+$UAhxYXNiP z9G@)Df2*!%0*_ST(`V%MJuI|&?;knWH0it@EXOq*?U+Dl1S}-g2umb8!2-8pW;;t> z%vX=u{cXJ~Hb7Z0LZf1l3|!kb6gKULHQvQ*X8mi|gmeF}p87YNnR$u$4A75q0(Oz2 z9~^`pQ;Vyanqxco$_PYP+^*$NPL&V37EBczyD<*Qz`Kk>;p4F4n_q5~wZ>AI^_ za4l8_RsLIZy3VK1Y#GDi&!127WY}vsWrdHIMlOOHwai*af{G1Dkvm@56qp?WbS$h^ zbkOx22|o0i0ty8knDal3BSu|nC`eb9ZmA<>gcqSZ#wkzb^w-pqZtYhbt97N?qlP*opqNl zsV>2j|1x!Z#LrQnN759oc<^L$&*efB&pI}Ld}_8`drSwwBC9}m0rdC3{Frn5?t>RY ziw~;vC@}fFg*+4L8i^L=!i}a(>nRY(SHk$mI*CG)pDHsZX(M2jU$YnvrufNRc`D=A z-h1W`5Be2DE)@?N8ud*gnNvbDX#v`7Ft;Szq7!YA0{}C zQ-;08F0dc<4rOFMP0dFov0IJP1uJaP22=FZA1ZdA9{P6;&7thwj6aQIs*52%Gyl78 z_>r*IKM%rE3By#GSH6({thy?m-}7!*NxNI-e)MRXNc(^`m`8&WJ1%rUtszBe88Z}VP=E`#eDnc3Ur(4m~Z zE|w3N$CLNS{gu62ei(I7XE5BtK3;>yCH|)ksfDjilS=np;KiCN+wVBU+i>erf-&^V zgUZM|?s7_C7J9Kjn9$8N556yUO<&QDi(b$C+Hh&0l9E>6+qChHq`=(DMq+sS<6WkS zXW#1W4MOv!6Tfr)cVd7XfiWvGQ;^)-8;tsA z_yh6hiph^*Khkq?ZNYLaoq7RFR*#~fKXEtd9sQ1i=+3eQ^6mT4;FP^e0vP$lsg6TgW%q z#9_Y75d0cXDV2n;=`I4FL z2M-Z`)Y>Ig#i)fkrb3NUn99q)a#Gv|s)*3-Y~(`Q*>sDSO}lp|U3AFn1v(u&QE1_wEaS&ix*oI7@$^!)GH?rf`*aA`)@To~U5F?umn^H>w30yu=>YsOdy>oW&)CN9%Fs56tlusH|brB^ee1e<%i0%x_4H7R30Al3L`s`9>e_slxGC4UU zUZ!gIT}#lgMCMLK76BAbkqjb4_~;2EQw+^w6nRI!-VZlus_Q;N zYpK!*`*g!=v-|)PJq0z6T(*=&CZMIIYtNPJcsB<@E~(V(#Q)hX=(nC)(-aXFSOdqW zlCmHf84+=dnwCWjuBWT(l1~(tLlE(~Vr-Ghrsr|El zq9PW+d)_`YFc_k8++R#Voq$e&n~vRdG=^aJSjDCHEu@nU8#y?AFJ*lacYM?qV7VI? z76gNh%D4Q11Q`G~5*=R;3DF(C9H)SmCRglWo20BFXU{59-!kz4_BF$>w#ZZ2gTWa5O z`iOcURoY-?9vF-sGnt#>j+IMyK^Pk!{Vw1Ov?q#S43-Z|u4NN{JmkP{j6WlCm~CG^ zQy{6;&r(AJ@rZ~gG=wmlwLN`LKo<-&1P7<8@K{uP2cl(@!I^bHLvR>+qRP7dLoxt< z5dgim^-YEzyGFEQ&cDY`I~1891NXILf^rITx@X%tg|B6-=tkcLf9t_V*GJIwe)~ zl)P|JVZ91PUl*-8#nuVQ<(77L!F=7g)3($2WiId5kiG-~P0;O~7m<}y;_0#b{b?K3 zSANFDsYWJ*A#1@%`;~KX3jl_0ptqUtLxG?K(urhcBQT9Xwj}awS5;mkS+TFA%h-S| zV{?*u(3}i;MUojff`p9;2-gxj1%navw`c=Ad`*|D6W9&mX1!7Sqh717UR#R)yud(A zsU;j-B_$<$6T&JC+e;`z)9L!6oxFKec=$nG6QOqIWxjf6a@ghtSC`UE8xoNXX+des z)fJO2C*ceTwM|8`qM_lH;iUUZ<5Sa8ziCLv6QYY5K_HJAS5kT(EE9hln{`f*^f1yN z>6j9dj4IXRe(g2m0*GFIZ($cTCj8XQ3)*DFP(Y)uyM2Cdy_-@{<*N;eyyXDLIP(p= z#h()qqLLG{}i-C7QQ zL+1LF>S6^e?P@%ff2FRL%y>F=CAC#vQrhx|)SN*@?cgkrYWSu%>?fF(-_Y+L~o*`ADEbWTkGtyWTG~WjmEZ<#*J;;c4IWo#5Nn-wr#$% z_rC7yJ)VDIj#=k#tuH=jTr+cBO*qZu_kZnim_V@j#$gXSO;+zO7vgrW+rt@j@w<0AR#>fJBqZ9&mP%sf-SoB(Z z@=ybaNv+Fft5#pm)Qbu*X8@T-i!j;49?b79P&D-qy_&xMo}zcuLq#}He$s5e>guCp zTsFjTYF00wYTags1Sr-NY9+2bys=>dB}h;`MBfUzLR)5^$ zSXtiZwEl^@Bh~b(4&{Ln$L=o4nFCLS=RmrkT|=-#>3wfFo%8zJ!;0r3 z|Li-q00|xxP?Q`N0b?Qpr!;mLj8qh9V!;C3 z?k~t!6nev6p(GFH>lKZUE~na&>oE9J&<=Ju7Z)5Hj3FlJ1!m;KIv?wQkT6`W;b)&m zD=F`$GTB;NTT9ZTE6wc$YGqCJAkttL0!dJ%G6}b?3bgDZaDoLgu zpKqhra@A5Qyn#qf&CQ%cyVv|x5)LwLehQhA)-)?qpH&r=I$TRniSxd)Vgpu^sJ1ah zvV^~~Y30a|JX9J)4R^{~GcstxRX_`^X9{fuevx>NX@i765o_o9x?0+b2k18xiTpGI z`5PWIdn_>+{sW)cDFI~-mAl|fn^wA_S0WKc=Jg!){jpdhq1|BPJn!b99f-eNByB`| zs=B(@%zapwf;&Q4@l!)Ns@kfz>eVF`aafZ&W!l$ei*ujB$n_K%9~F!e2!ejT-lWG; z^(1wDydm4^6cVc~C5f!4+w#SB+m%i1x!!M7#~z_@%u+de%6f8}W02TAwG+YofnqR* z<9;MN#Q%3*Whewqz5X9H@CMGWXCkF{I*bm=))Dc^V!1Y7EI0 zvB%_<&E}Q5%SQu=iN93_vrETr5`y>^A{?rHmc#{p@fnTDk`?{%r7?UqqJk25;f^TP z2&3v=P7qu)4HGxc5lVKC_o3dQ{6`Z4cyIp{Ja2lI_eYD>TOl)W;b0fgwFM~sIiNrA z(svm+Re*M#MQ9&uJ{LcH)o8Oim>1J%5Q(k0`Agu0aXfu{Je2B=mqp4xHr>dI22MC0 zu!DxT0jZ?cNfW)!X$aHCOCfJFLtasP490_s9ASu&avNRJVYK^I`Py`8m4n|l=e9>o z>W3cqXxEn3!Q`-*1bP7x*1AJ9!hgLVH*&D`&=zXyf@rRGBLqwC`pk}|ZOw&gDc(mA zaH$blJkilfZqK#$O>PL%u5Ejvrvq{Ei?~Mu!heS!t~1=+hTgr`_O1y|S;QTm@x=QF zfeOE5xRUyMa(37HX$SH4@?anFmAhCFd0zE?@b{;S?faKCK_(^P5Yl`^%btwuRcHP3 z*L&1}?btyyaOJPIaa2^%a9Y=>W(hi|6OhZZb-(86@gF5Tz{!wK69+5>O;LA*2+16v zD-h+t==Q9PeLQC%{h;Wj7N9w0VsKc4Mlcq@bx~vl!t6jq=s=KTX(kmhVp>joeBov| z^=%T9X}AmbPrN{8b_%P}g|p*jxvoHMo1q`@n>KpUCuEI@Fo4_dgy&?;Mw-L6x}@B* z+ALf7ya`?5fOH&JF|wM|M9SdXcUcOA&3anS<03m#LwwGjZ#!8EM^Jb?2VP*?N=?RL z9T9GSF7B=jq`qTZGV`Ro*n612>)Y>wiQ-VmIq2V(Z5Z_!T%EfY-MTC{0!bnoh}wBx zs!TIXo8SY``~@&BIJ0rMxeM)RRW=XqJ$PAB~4)$Zp%StP}5V?1K%@@Y#d8O(%Q6Za?Vs!7Ii4v>T|vC%^EkB}Kg1hR}{ ziFiIJ|NVyVgoDXm5C^S(f#oSZbKtCXn@_ykLcW=e|7~M#h$i|qZ@XJ%9uMnoRanZXxsYE392dE{S+Aa|oL`Mj67Q8XcV(CI5Bu0J+WI>ij@Dq#>I8N+r!UBEMva3ZLCrokWboJ@zRS@7=j1#Leb3ohTHW~Mod+R7uYr8 znmnjn+9UM43iVX@%X3Rg;ajQ_6G$2%%Y(5>8-gR6zd~seUWV6-;9r{>3gZVov5R1= z#F7MQ0>YsQP&A13VMfO?BihI_*>=AkND{zi;dOu9urREslKn2gfB;>Tx8M+=!M}!t zl*-OACN^*o8HF}=jo@$krZy0Rs^9NPl8jAU`A1<;@+%21KZdr$80GsPUAH$vD5PZr zb4&(A{-+fSmXXFCRzE2k70y+AB-?7@m-fq%SzgUaQx+|ET*?L!pxWx#z7wyrczB!; zQwOKQI0JTaqG4;P1Xkrq5WV5~ejDUmt9|536F^uo&ZEbBGZ1&Gg^E*>$J{O?kGWseJ(bSI-n*Eo`0e4tVn1mUNymA*~S_>inE=6jx$ zm2V0X`St;$?qy|r)NMQN7alZranBrqReZ<}4U|g*0krxdwi77Nd>c;W!pf_XLvCO0 zzYBH_T(nPf0FEeZEBGr7j#b+zctNH960d|IkH&Yx)S+n zVECD%5#>1ean|a5N)1+*nXkwgHt#`zo@_?U^v}SEVuC_{U}bML*lGEnZTz1%HjpeX zHfnO4-!=XE^6ag|y~G62uv0ls%Ii8pT=j zoj;hS?;kGQ3|K|MhE5Os2c5|y${uk=7er2a@MQ4$)gZun={}T~5D1j3ki1+FHfepa_Wq4WX>)+A(hEq}GgM)q2QZ^nQbV5DP ztz_T?$-bL)5L(eu?MG1_SFerCh`rZ%f(F+=sT=B(KE9}JU50bi#KJKY8_wn7`h0=fG^BC8 zkKfm0#=*w+P+flHk;LvqwI!q#wnO}c)Smvt{nMv&>M?FpjU#=SvH{lmqNGtxLSl

K8yHB~8uyB0mj4sH}Fa{08O|=}<~15h6fszd@7YS~(4yvz%)%5`f2$6wxG`72;B6 z^o!2PW@>~p5jh@*PM*_^(Aogbwvzm))Pco)nah&?U=3#>hVmqhxglj|{>r(Z5c)%r z);lgNWv7SoO~>9Ng=)6DHbd2!#MijB0UszVtohVwc`qd&eLv==Z%?cfiBu0&Y9k;4 zjFzXZ9;9m*AMWGzqHsqSY``TiBPQ}>#{`{2&yDQ3`Y1vbdf*X->e{a&dk!h%(^894 zcBBmWM1=@f^o^JJ300}>M@<+M9LaqSo(QO`o;`+n@}uNKJ>^Ee$7l;FEoy(&)B_uTR}X#>dDSRWM?8N z?-dOg{(;0RQn-+O^kjLsDjtt{GVb`Pw~gjiqGUuz_^EFWeb?9}sMK?fwW~4_#v>&D zZjz@CD>y_z%+d%ja!zagJ@vk{^@D5|Z&B1MZ7IzFWi>H>mYSz#!#t#;P-E5zRWlLp zBj?vv49(_|=v#=c_J7p*pVlxWo;&de;UulMd<&Ocj_aUQ>k|5CIFY(ch|YKDkhW|*$7^0+xO4W7D@QO&Evd3sB);= zU}48!0oZ*n8qlxe1S^r-_e)hl&;hnVTiYe9z|((+EJ0pUP>fhQ0q{XESQBr^5nId9 zcR3W}daW?-UMI~MW?Uhc5uAZnmG9Z<##qdiWUTTSk{^8e z7!pUyY?!OOydLK+lE>y+QPfLM*9AENE;`Ayw4b739%}8~g53p@-NUyioXg=un-C-? z9A~>X6~pKAe-YcL{LT|s)jpvKT^f`<4AM!~BC}nW;d|VE_}G69aGT!TElKVP3jkHa zY)Ed0;EWrhtdBw=74e_55G()u@yMya_L|{x0Ggo8P|a*F?Qo4xgad>XpEr51=l|*6cy7FYd9I4hr0KSP z-5Kj=rspO}@INW-v)E>~_o?P#OS+J=?rnjGoZBF$bI1Fz^B(bBKeN}DHIR9xBL>xK zn>)B>jJfMKA^^H|*T;o6@{Mxu&0i{}B>ma@|NnImJD`&V%KjVA(Lhn{#6!pnAo>y@ zes9u(e0NQV+?iA_altTi(X8qSFGqC{ey34hcl*Qk+jP8civEF9?GHWGBfUH#xGzq9 zktPVZnr7;}j~eckmt6Xc-Tvft@u8V&Al1ebE*rvr8I*ybCukB%5XO)N>~Mb zj;5`dXEOsLzc!O6_=CRNrAQ5-IHh>*vu0-4(rhA(Ddy^ZC-`YrL|i(CeKNx5U&lPH^by;XgpCERnQe}c~7lQ4i98NOi@TG^gRTh)Dm%~zW zS<*eD}vWDRwgeEg)*#Y-m@x{6?^{4ORrfF)*B#mlq;+Z0=neE7W0ZmG4rW@B5X51gDX(`;Xp-7hl;21G#(96VqiEE^ zw?D3-xp-Dy>x%@uLgd6|0XIL6ZP;wQTtk~@*ncbxR}AjzFAB_go6E@LMWQp7GHS-F zggy-ZKWgKC5QP5VKf3!{cIqy^tP<&hTSNE}>XERKDkAbaZ=%*(9bXyRE+&{pGZ}{% zDW+trLX!{j&X#!_c8eW}qjRmQbslJ^k*{~4iGO;EBF{|>{8(_ts>7(IBZlT=;fm1s zTfLsv$`elK;5zqNf4zLR)h?}X=$xP#c`^Yab`CR|b@PBcUiyUkqL20RHS@-y3kT>iZk<@aR;Pd*eaRb- z$RV8)A$jI6=}|JJern}g8Am~7hN>fr)jkM`aF1Kk2rzGH{rq(S7kwoyEEjce=;P1s zKFhuRB80|EF+OGHV!`fq2q+QGg3Zl2AJ!FWjmB~ zuU2$jg`aA3HA3Lv|4Lz(NP)3}F776p6L4?6f60xovAnufXlD}gRv6jNfL;p}5<@T4 zm_(s_(B$(#-DNrLG{L{E4Q3K3LN1%(t6R61z~dHDenO-(8}bD$vT@Sb;~v^u;#F>! zb1eaXE3G=SaYG-J3y_BX#c};Ug(GIaf4%$bI`_m6^pXEHBmc~1)o18r62kvVV=#~u z!krWmp6}@pz`23tf)*&!p8yLeJE#O~jJk+@!y{sTi*PZ+=I>;2G6%(hN4v{>!h9}C z$L1W0zv9qPK2Bk?_DPGuAcWEoug%aeMKgsTN(E7!PfIXL=@gp@d)!VrB`nG0f~$@d z%eqj0`dP5lL%a0fR4Cczg1jVUqQJaYI*A)w=IKm1Rw1@|szzEd<~+||ibLba9bhdv z9W4>>-^1WQLLJW82Ey!a!7?U0m9-VC?_Qpi0XPlcY?gVwt}VoJtD?S@!aroA|eK`4OKbd!SU7()di`Q1zA1FJEgUSwGBGT|ItD`L6IwyzM6^ zOhe{*snj9BK1R|x^E4!qtWVA%C4VIl9+b^6p4qzyV`B2SBsWy+ z2%8*yJjXahzCTMuBV|)FEp}(w{F`E5{hy?!M|PI#-_mgYU@dPyVOqy6c1KA|-B}#s z-X`T!JjR(8ENgQnp_cgsDS6hm{~4|j<1bY7hZLd%1!LE;o8tct>8uMmYR`wsK`lS$ zT3cnSi~)OgVeV9cO;?BP$xd#M2mSh+gFvVWAEG3tTbox1jT<5+z1pHX@{#`zE#&{_TA$J+9$0;%K*h&0WK?KN?A(c^UW@c{l zSKyinQ!vrc%h+QmR$Ic(rq*CFGSo- ztSF(jy@O$9_w>9u`zSDu0yPfJrfU_6ZPj#uV(h*0p>~344$Utg-)_qBSVQ$98}!d# zu)G_1+V$4D3ACNs$H3WQKd>e&Iipk*;LjFQ-=5HfD?dw%z}6q`MBMeU<_hd){M$Rz z;e)AelzDlm61+A;4?FaNzQlXse$E6<8^a#?H%3D7FS;ITF>(HFR=q`ngXMqv>}<35 zUzGvvo6c3doUr$uT*c8*w91&Y=a(Kwmk}*)5tDR^gQu*>aQj+eJO5|Pv_>;Lhouox z6ZEvxKWUQ(4F8MmWad}jFWWcC_Z7YsrxkUS_Ce(Wr}QfE(Y!(+_@t5m6#SSFkrxaa za_>@T+j_}i)@$0Oja*}#XM`it=)@xP1Xw7&UR1}+Q1DU<^8g#`6b5J5_+ zoT7q(8-}NMEQ;^?>o88L_vE0w2}>Txp(GW|`HX9_Eb-(i;HW?O&G)!aEhJWq)FXpx zPVxNFr+(&N{<>(R;r|YhWTRvfd#kS$@CT20+!xrkTEWw+T}Gh~v|V>&^ZosW1jHnL z3-6z%CvZCp^nCBz%9MbE1%1I*J}&U?s=fRH5ji@g>ATlKqEMMJE0>I(+amfo)u?W9_sGktlCt9W!FAGSY3u+x6Be!^T?f z=DQ!CxE^|(mehRS3A6XUZBunjV__4Rhe(y)VoAPEYu&U>5!ENK8{Kj&@8XoV=9$SV zueO=M^0+VKGx*TdH(AE{;^bN}r2yCKwfDo|p>eD5yfjQYhWyZ8qzif%wjNgH?}FA` z4^K6pVTi7(Gr0?EAt~*#z)rt!_;cS(Zji}t*Qq13?{D?wKiJL*-e$d>_jviVYB6OE z%Mj~T=UuEM>Kmyui=nV(y{m)XF2T#S!-`%{HZ@Yhd&XuC}GAS z!>yZ7TK}4`+9!m>T$ZvR({#mdtsU5X2yE|3YD#+;c?5mz6HyNriZDdyi7DGvbah#n zQEXhqF|lhK>p1;x4K%7Lv2y*vfMU}3%7wmYX`9yH!(b8cId1dYwIN>eJdC`SLu_|O zVT1eN+?ibuv@BP!huU{jzW%9E{+SvPvR^jdI4O=QJNM{va*h987o!hq*XiaR+Wzi zz^4j{SOwpxVx;bNPx@uqA8BtKp?0phzSC<$0%qS97_HP* zBGjon=fHOuq%A>l&;IO8= zLOHKM}9_ceL@~!W3CI;4VLJ=i2fg^9Wh@^3yoQwS8Z{0@Z1KU11j#?C-+; zUoznY-<;AmPC?Ly(hIm-|2+Ew64no_f<}1x4r{>t8!OuyFPzGcrH|L59;*}Fif zH6@b{4%f2M$9IGKTa{Rm6FBvmPEtwjl@m7Dt`2XEcQqP&R0qd(?fJR8bWjm!@1Jo; ze!ytU`BCIVZ08jDMm#jmu1c(=FDi*+sj74>p12DX?YE=X!$+@e7_N{t#V9Rwaxtya zEw1u%;)MZwWv1Bz;pF|m=$2T)$n>Vv(FxTcYDnU&a3#H2I!Z#PDC>3s>tnyCpNU%`VwXw$OUReLm zj*=59;`??a^)fACaMPJh{dNSMRFS!rZM^=g#q3{-(gh6_s(v+u-;iTu&^~JOs;_@N zt&hvCyIji;ltY!1jKosp&^5esl3=f}zL}y1M5V-;t7$5WvnPS)bbh4`8c-2D26u z=|B{Z9*>}3>Bi>zY%c?%%@p%^d@aSK4b6TeyXqopu$qiy!z`60@Cgoe_F{WbyMNv$ z_hHiNf9D1N6i~UbFkT4!k5+S776~IRMAtTu+?UQn;zW1z3CCd3o`z&2Kt`bD0cES| z4P)WFA~8ccEgc=t>d}}O`t`X!!;PX;Vu^lGW7Fl-e2H(|l=F+|9w`AVeQLe*^h{jm z;#03S7E^=7XM?%#^xryiLY5yZ{pt;Sd(bvY8#;F(dD(@`MQauBZ6K)m$y{ z4EOx!Of@H3ONvj@5yYKV{q*$d>#R3fcC*_v5&*i8CEL={b2`YvkfM9}sB%V|!?| z6sltU=GCSqSGBynmOtvdrwIUw$8_2!90Gz0n~^>zq+p<0$Yq>kfSr8Z=Qdyegt^yL z)4Izh&N`)&W#!48%>L+G1g4MkXv`2NsW>U7m18O?;dwef_jW>e8YGBOfbiwdRj*9B zD%Dicl0R*{ew|V?Q)l8vTTF7CbE~gRwyg9rQ~bW` z>1CcQ~W!q+CwVDTIg<4S2!C)}@i0M;TwmX~jnWgcRMeX4N7 z8=z|PAnlK)EZ`EZT}d4*@>UP8A{C(u&``Bd# zkqIoHyu7uvFy6?|LW?Kmm840{lW{9QbN`-ilTT&}AF_g?dKX&c4V|^GVl?8FIOnN_ zKSzU}5y^6N??!!gQkCRhEdf@@E^wyR<9)IYs?61Bf)NU&&LgFceZzUOB#3Erp z**;SA(j?Te=39)Ko~}6|hH-wPoISt#S_OO;$M^X02}t|Wll+f)0n24HExu44ZP$IK zWCmFgAM?>uH^^-GB?|16WBZeA{uSvS%5_w=X3+I}WsH@r$D)*^J}UX@IyE)6VYGZR zG810At}nH2mi$;bUT0^rJ)`|iQZg>u|3NcGZ~vM|ne!m|=#O&h1*3>YJWe5!VF2&H zOFVI5{kU-aWWwe80tO{HyEsUH_iDW$+Xts5o@QTr~euFa_*c<#Ho*0TP>R+Svd z{o#L|bn6I{4W26PS}%M)l*6T4u30=)qB*_fUo9*mupO5WUle+M_N^RwdKY=V=ktb; zn7$f2fylHll7KgZ1+||7x_5Jh;r!+ayyzp^$E}cOUW2q{svDp8W0GV)cZw;|l;oSd z+10A|=BZc4+4^qzsy<~}cUY-|=%>Q3!Li=xM>MW&tP0IDZQLO1rFQ=>pUwroi6jO7>+SflW!^lHTOtU+y_)~A zs3BP1^!_VJjv=1w-TB2%wE?XGM)JyX-ZTddMt{P1y&_xXzAe?3djVLwSqFHJa8_IXHxvCi zZ=pwq^WK^9f1q=g8AY~s8|8%LMD;EG9G0q2>{caHNnIJ>#R{C=m?}TpA(S|qmJYZn zvJJjZ^26mfL$-IHa4xwEF+niY9@2DH|Im4zh^z-6F1V**M2-{QJ{6&iCn1RFYfjr+kWvz`zmT; z*miYQOJ&pWx;u5spIyt?-z3^6SGnSB3Dr|t%;B*sD(H0bRo961;)rfsC%M2)uavyj zm;XrJmv~@?s~iR#iLuMCj$+Ad&BsHmdNz8h(_pEj5p%i}f1k@Eb$@#$FiY0`pZkx2 z31&?|d2s;QX^@IK{n_L${Pi<{mTd~U=;!Th($!%=!?ScT-f^5?-AkH~+ZS4a#J@gA zFc@@QC{6!nl|N4CeF^CZCzADoH3%060o+l@TI8y^AewRMNk|K7hDT;f( zrRfuPugDe5-ldqs9NA$;p>kQlm=GdDPIrktya-%mR=2CNdzExg{D;nToE;sBWXq?3 zA}myn)k;jBHoFMneGxr<-r#qc6u64lT3ueg9$SH=HFMHp%{K%Gw%V=6YIJcd!nmZ@ zNx?ZJNsra$5w<&956MEL^EN9<%amkY2yC;=Y`7L2g)EWZ#VXd)yZZ#;6#Yp0TPKPnqdHkDIo^v)ArC`EFkr$#+<|%SZjzv_AiL9)yny zK5_Tl$jbvgbldUad<&*3`%=`+b{}Z|Xu))2S0JFvh zFF)Zn!}+@NdxwJ=`4lk*CdIHM2o~|*pq9!swrx5zt*TH$SO>q2KV1&D{Vp^JZf#CP zv>wo%?m0VE-`~S(f@mqFo0Ay$j>43+VCS5tUE>wntfWbZkTE1vZI zF}pbJB0;P$N-9Qx9xwG6-CaD_?ItJDc~N?;K3NZ&8npt7GJYMh|s}xjT7>l6Rl8PIdau zJ|nEp7VYmAF>)HLDP*_5K+#qXz030>drk}DlyqgcYzNvpC#r#Y5KW-oL zehj?$_r#sDgG=qFp!R8#)wJo(`=CwrYq1+bw`4YK|$ ziiXvsF59g#o|!{Pt1@m)X+OMz$u#)nQC+Q`mJ;i98$$o(ewuUKqapwH^VR|76syLP zZ;4gk+UigI&J}tVSB|yL`(iGjCXvB7_bZdVBJkFi0Rp>QTRXx?$RKOApDMe=Ye`dw zIImqPIqFp}8!w#)MV-TW&Po~?1(jCZ_c(4QZ6H3@yXHfj*?(Q*f2@vLrQj7o%m*Z> z|EvZwG*2=p{&j#JW*ydc?H!cOxiVQ>6+R^uFkmtR5TDzaX$s8e>0!v3 z;y&oOTLcA%5iQ@DD1VL!S7eG;A3hi;EYb;_rCn(67YjVmkc|3blJ*Y01OsjNjZkwz<(pT7 zFUnR+23}{<424?rap<7}uE&XqcYSa=I0S51bS>jiaUtuKo@=u2Br6uCw^RC$zx{BpX zPqXa)Nu?Mx`TeY4+{8Iz@$L*kAZyWTUPdmjwnc}r^8|gsv5i$jR_*!i%PgrbNlU9S z#2aQ#k5~r-m|>rH14WRxR5XB<7MEt-k~Tgwe*Tk%k_F{#9pn78X+q~5-|sDIaKNx` zrGU1Kiw%lq#@qp`=PxPdV~F`b=cfMt;`-ITs>f~~weYu{RD>-z z-Gzv|23k*JM^8}Oxpu?MZVNSnS!}F$oI~mEdb%BX`kJRIvg+Tf{Jxw~H%4Kc#vhcB zfL}5_mtYF}Dp-L#!|m|2gkT43CFA|L6f3by+m7vRn%4(nqRpb&D0qX7lkbzXwDfnM zg}su?4U)n&KVmgzqE|yxOMA#mtIP~h?ab%wG^(k695ksj@R%9VUS^@(DJsCaxup)w zz=Inx`9@pdS1QgX*@86=jqOfwHXDyi<&BQE#Xz2vbGJ+8mM%pyyUqtGpDdYhSzW!~ zZuZf}6!wk=qVuzyu8Q<<5FS>FF+}XE%(&SptqLX1fYGlSDC)C{Ds0)h!nIHQ#h^l@ zH4%wqh;j5u@4KCN)x{>>pw(2g)+(9UK7bW%$-N2HKqwsKknAI>-GvOM-<{>P-|Wmi zd_Txz*PQXWA;CHf@j~xV+#GLaR>69>JGR8Hvsx^{d*~YYVphC<>lNhE0lM!hCo<#v z-rV6j#DAA-elXtiz7um}r6p#({LS{w&uQ&-|E-~n?^iPPsK8aT0Fv(cFie+k3AbT` zk9#t7Gbxv-?!1V*E>2yEbpP1}@Q@4){qC$_#FV80kb>`2fFXH|fmo&<=q;|hKcNYq z_e-1+zwEy|HyI$kvC1h^mV1uz_bQ`6BkAl1IJ7JW8nG80d z4%+;|)Fyx0gqs0y4mZ4AK&%96EcHT!5OkgRH*FP*S7a?41^szryT)Yz#=9h-%JqcY%ZCIq7XwAp#ao9g z*oF~Abdf|1;_pw0%J6i{42e21S(6WpXsx;iylQ zWVKACse(d^C=I~TO#}*xp?a5c(ZSncRDGB~|4Y~&kT!0?-dNKIenM}P*`!1p@rFrU z5iMTcpA@s7!O7+e`lGc96bo$VLK27S{GQO@n0$_V(<@c)SM2L15Qz+@42i7W5;c&O zl*>2Qw?xx6swhm9*ln5c4DnxWBg`)F@c_2;!9u>p#$OW<%X3*{WT~*tMdRFF5%wQ_5T} zK`BTK=hg^Lr#e^f%6HZFbMUfu^Sv1^n!3l&6)pA??FCZaPv7$wG5|kJsjqzNyazQ| zFyE26TFZ2mxb@zD+iL(=g@D)w0g}bQ>}umo;aV?sZl5e!bV(9ya%-*j+VkD8$iARD zzMs&Y{^j~S&9^!*f04-M&?7d+J^BsWtgJ9zxTu;dcP_sR!;-bM^dSj1%@^SCg^@*Q z*Wuxn!?9R3{O8ay92rw>lW9}XKU~+y4~j`xJghK#I6)zbivcUknZ7`g;U{M0v|bNY z^?-!&Q3ZT3;D&T$XayC(*N+$v7QqGw~ou*&L_{n}Y1UxZVqGH(#^oO-D z>hz-!fDPlje7NiicC%W0LiNZ#Gm7m9!ZBU1G5b>iq^&kk*rV*HLtZ7?3{sDfvskJLkF zdw6%1gBg*x+a?UbLM`}9_9lb`g2^`wJa(0nXdLg;O=aU0hZKwel@r#jhdr82?G7HA zbT-Hl@5xer(TfiOaS3dE&)Ub4XY!x`Ingof%|c>g^utd-E_9SU(E*L-qwyXHN5Wc# z1db0#Oyn}W`1W)MZ+1yD3O3VGN~RATOaSZ1uSxht_}AWT$0ZpuzJ?|Mg_A|IWy@+e zBZ7_~f*Z?(wxEHl>sxp3IF^mEeenduv>=4k_!SD`2A6{4>xD(EDteH<7piOsf{2Th z*R0qQomiYJk8kl}5!kzeUD49+up-dFxy`k(FLp+W6;)ut?a@Q`~! zhJZ=@>C5A1!wpTP{S}WbcciISy~&kjmn7k^dN9N4{Hk5`Cw;32zi?j=rPXD z;J0hKqqSqSy>>X2qv)dAD4DYn6NBR~rb#P5Z=kueBze7C9T&rq%l(I5{=AsRMYW^( zjoAB$2y-KaE$*!tppM-M1d}EbAZ^WRu*OpdvxG6Rd zDPov8rrUra7m)`CZtMd-`Q`2Ay%iIB*5Orush4RWDiN*Yi%AJ78{cc+k#L$RX%2Bq zyk2_vMUj5BlZC6Lht=4^f=Xk(^T5cxxG^r4IgewHArji{8}8y@TnF_WhTBrNf=0R< z5@bL;E6WWZ`$%ZJsYx>2n@I|6Df5)H5?Ib(1WYYzX9*n;IeU#J6cl8<5}b7s^|K?j zX0tO$^PcUd;og0b(uEG{7i&4KiU0mA*M)vqYr|?KYgvGX`Gb|_0M?I5AVN6ISP<%z z4mW$6^*p0-!qXQP2aNy`YS|k`?_C3HhqcA((LqxibrRvkbstY-PRCu!=y2+Sg2N*c zrcxQKnY@PPqV=LA!g0u5#<3pL^4L`Qi23PD$$IrI%!`K9?RAbmL?zp*bE*y+Q`F_* zx|X2g8ISMX^MBpc+{uyAQf8!Kqr)@WbQEn25IzVj)YSQySll-W_^B?9Uoz5pV5t z*I5Skgo(!%^ZBluLjx(#`GLopz;^e*uG!ZaUi|bvn32OnPOuV=k0JC@h;>GKno;tR zBctArHytO~KI7QL`|>zbFDv3#n+20uahoR(FCfpw)ykK%g6f`LOM{RNHzqt>emiLuqB%0>xF-Q(qpWSblPn`r(6SEb$OipI4?u z#JNwL?|peZ?Z^wUkUV8y>(xwG$CtmF>$TZ?upMu(`2eEMFF2%QOdG)=lE0qTU*%ux zlx|goIu^F6L1~EDJnptqNKyaAm)gf?+7p(xm~%nbb^aK8IWXwGyW$av_;|5IYcHIk zwf>w*-I-|T9p7iocaVqyiH@j4%COmwZO2J>m1e%q4B!SN1o>%n+rL+wKd^^ZDczRt zi}?eqp*q^${l(yw60nTZyz5uaU!z@@WLPF2Suxg+IioG|!-!Abr8P3F%>vdpKlZbq z@jKRk=(nJW+!NWUY;;_il+uG-I`Y?9(QFDizs%;fZuST~Zq~}O$f^>5zh%O zUStanvXMs7m3$5xZ4t#m-B=!xkn3MRfCP)2xk)*S;C?YktXn>m=$S|N{id|4qq@@2 zn0XlfI^8V?MsRwPMhJk~C70@1IW=6e-LxjF5TBLmS9cO5@F->*jXQ{pK1H!K?<_3-8l1rVOC{z7;-Ez>N6{K9n(wXd#vmQeVH6AY$QEh;aA$yD z3lhoXK5pnFXrwH*_j?vVK)`L^q1z7|?g4SJ##2r-W*0h=;2X-jFg-2V2O_P>zcRcU z3oNn1BZdd6CP$+zu0ySh&8+kDRmsA(dR9TPy+Wn4Te#)M#a9O;2-%0kt%9u6x?{tx zoTQ!Iq$zJ|x-Doe8?r5Epwedj z2j7s)t%xNMvHaF#0H)jx;Hv~l2hDgN`YU=wm`2+wrry(cb|pudsva$M)k@LZh<%f- zGTze+XZ3{Mf;m-eSt`drXV;NPWt_gBNaa`N7>%(mA$&DKGr3e zUL4~Xvft^VxO+p%VP5~_44=5A?@Z?D+xhQ9&0-u?V`xcBlQz409y8Wo_<~#;4nVrh z#W9U6VrvynH{J1~2MHvKGZ64WmXEL2Ql8?@m6BR2nQo7dH8fT4uIja@E0O#M7cjR6F1eP}DT<|xDMRyVbjQGrAY}oDr^YvO(=Lrs^}xWhi7oB+>z-+^L*3-x zO5)!%A{fV?_#UP0*il}8-ZU~p^PEusc}+hf)v-C~MZW7;AxT-A>hDr1JQ>sx(=$96ujEI_Ls}@WuiJqgw7j3(->(TpFGP632;Rx`? z1+#eHqml>^Hgxs)-dIgt3yZ$&`EKZDBI?bNWj8fa=K|#>4p)Ij&vamv4@dG3|MC+L zjVKhn=+YLGcbe%>%0G8s-(21K>SI1@8oSzMx>ywDH;S+@hFIjwjw!6D8E(7=R5}!J zWf?qk^!jf80DOvstmRz9gR^%v*R>&@-e;~qQQ}QQuR-))Qrozd?0x)!V6xi!18f=I zeX^>J!%xER%ewO`7ZrG}{B59Hj|mJx$}gP}g`oxAy?B=*S`O$?Xj+1PV_HvH6m~@N z+EiQ_fm7R_V`q9T0BAq$EMPCVhBEGPvds_hA)ZI8#L*>hSM4GId#ZzPG7t z&k#^syQt^NL8U?InGlkqJ*?@DqOYA77ltbRch&<_e$c_CLR(Jw;UN#*1s1hY zo~bL-NWLp;aL{bX8rLN5B-cNN$6x%K9z0%lXR-S!-WO88?B*Mai0pB#XT%A_SHrxY z#_cC{Vs8kUb$hGS4T>9;0Np9xVUM{7K6>=to>v!T%unjx?QdnoK`xfPY4#vq6~5Sh z|2x(GUYOUnt1%1>9sV&&CqM`!e;ap;_hAIQ6O5vWhe0Ea zscKulvwCQ5+hU#jF}-$2BsFK*tU$Ber_qQg#?HXn$@-U^(tH}wZchDBP9Pdh&t>LH5S@*(Hzr`R{{ zN5Ly?F<0rV#PmGIpz?Iw{Y?TN#81}GEEk9M9qwxzf_zoIhn+`@&M~;80!g1TzNjC> z(le|6^!b1$PRrio>W@t~c93Pk-H%KneRZHxuaOKUHsEyFc!IHC30ZV4!L^`YY5;Y6 zCDt4e0)9OXZuhQpl9f<3%A{F6EDEjSR*MUWZ6_Q%4j9*dlF^y-pulKLcuhH>*?)~X zXg2y4vg#-K!AaZH$tiJq8~DMv7@wtbFWy}s<6}Ab!YFdh8{=Y;;oadHQQx-_KFF;N z7$y>Q+fx~eZEc;8l#I&Vd+RP0>#S*Z{Z|tE*K%3A9|`YGAdg7>DgX}wX7mM)zHiu{ z38qZJCMq!etz!RTs(l>s!#L+m5DXcCq^!3HygSPF-x%>|WV}fGx&rmQTfYvvEGktG zAm6jBf5H=#l+xIj(02W$Rf+YIa3SKF6%;V=W>*H)*qzPwh8-Op{ciqCg5)>*k)fN` z!e{?Gm1>y6@pwluJ*U6r|3^V2KSPCOqrvF+Kf1{q+Gz!-5&|0)q6YaG&`TN-|R zET~4S$n$ZmQK1w|)hpT!1f2Fs?01cFZXS4tcrgbs;admxA99VGR=O;v}!0cRVzCh3&5B;*&zJSgEiWej0R zNVm4p1F-JWxWj~YTExCpNrSQhgwJ#NGUr)27C2+EQMAz*U(~xkghd`( z^HaADRfoR+uK(c~Jf1JhcqV6C(HL)^N-z4o) zl_fbz++Xj=GqpaW0_d8QJrr;V#-_iL8dtb6X+JA1r)%?nYLu2v-+%!7kxJc?8wnsO z8;xR7Ak*mtnhVH{I(}yc5E7Q z8_p58Y`a91^5kSUrMvkL^jTSYqtf_^jkJb&Hc>{OZ z1E=Oajuj#a1IF!gp66f5{YAE@5A+yOiriuBUa>eiIuJ;zfb@I7sllW_k{8K=hqfe? zLAbHI#qWI`qdp%2YP}6T-0f)`H=BvwIepgqOM)-n_5>?C?sY7u!B}9ZG*K%_g|dy= zUDv2n2!1%QO}|piToUE0MuyC_I5*eO6%}l!^?HKj>9X_}M+OG6K|u}oec8f&ieJ4$*XQ*iJH!KT){rd@MCN%( zH~}WD-w2UZd~vZ^ozTVzVD;T~Z|WfPL#I3zJeU}aMQ&C%hFn)8LTq*A>SApna9@xG zZq|X~4bQU1lDlGZ>A;fj^&9KnZ?)F9gwFf`s9Q$S$ywUk&}$26`A%O@L4nc0++jVq z_knG{AN#W85`+9t zfX2He&ne!=zw>w4_lKaXE#3vvi!gR~>9SqZUq?6h^NvRishpqN*3aKL_I{h^xJU$U zeGjDj_U1Q0OruCa_fPkfT79#-}a_Jt^4x0zy0!JEAO54 z{p5_m(ZR*A*A&QfIOx0)q8+t`3u8tbOE|Ci#c?SM@ZOxJ_uFOMhy7J9``@dBnCj1R#jtoMH^((9Adap$QO^ZpI%lrR)$ zhwNYpJU>(s96zpDR3{Hr-q;oSXeufWW6N~@^YL;X`S|ezyoBlEKIHHT$i;Mw>*vC- zWwU0v=y}kt;zG{yn)S#PjVe!Ygyjo79|lQ3pmf->x%^|1zy7*102(EZ7ETH$IWgMU z2{F;n@uI;;G3(H4srB_E5^q_OcIPok8yA-zysmJ?l;*JjxP5D>t{|bC&&I{FMA)|f zq^0(shG3N-myTI;GqF29GVQMG9w`YATP3`o%I7^~up+~~sMQai(dElJxz`;Ak< zgnCWRel4tv6!pc49wnL;FPuS9TJvTW6`NRbBCJ=>jOra_zwep8SF2Q2-;T#GdUllO zm?Q_1!Ic@_1da%WCwTaVcr$vcbEIyxWB7bKn5O?sEE>7bSyONBtsB2B@Pg#(i!KHP z9R@Rep&D62SJ^DFnj6qQ|9YyEXBPdUV$zCc(UE@jrX#hlE|pgh!sRng`8nV`GiO=T zW-&h_CeIwx#4L4ZYwsK{FIvBT8Ecq{M)j`aGgX(N0v1+Ent$8d=se?_*3ZgQ;if6{ z9$Jh0%P7ch>S#6giVkzc{_T1PWO04s@Qd{{7jKUu(f+)Ips=fugRm&JBq6UYY2>9f z>hF*alEnoXlb9P5FMHMuKthh0WF-%_rp1;xKoDe zWiODNAk_eS7Lh^d%^IO(12-z?7F5ND-J+ESyo6VeyiKs8j z&^PlE;*VVb_Z8-?JsQ3>W!x^^w=b71X0S%M>4>h#z&lweeIXov4mi9zmuQ)d7A7PZ z>kwinVx8YoXJbPpPr%Zt9qt4==1E(&;&R!V+r&2{6a)%cLQW;z*N2NdtbL!@P8Hqe zgJ|g|=9y0Bb!KE;vmW!rhB(Aarcpv7K$-Kj8^Ai(_vZBRA7US2`w_;`(cYz|%-_VN ztXWXe!>KBt;>R@U9WPePFv5D_F8Zw*3y`PBF-+x!sG3A51)C_%kP2GC7-z9y{|R%}{UWqM)~_OBvPXmj=Uh zx9i~<%a^SM4*uNl4_xZ>q<`pZU<#dVBkgi_QkF#M*q>@=6{m0SX8P>Y7>?ApAwi&( z0r1pvsGrS;ZSh$o_-#h6M~D`;W~^5b3T&MSTa7JQhs}kAt)B z^V=lA$)!#X&X@WHwp|Q|r?J=H_~;b_)ZX)w`6)8$ww{9%MC)5`dEAE#5kfS8MLgcN zwo{xXAF<+m$^)(YI|xLMcH*z>36MI}8(W9z(l+MnmrH9B_WDBk`-vI&ue}g_*XR2J z*IuoO>v)*#1DNYSkgZBHB^eyij9;@oH#V$cR++MCbOju`8#9Vv5jZ!W>I1PjICH(I zhO0kZZ-9?5)L<$816h+`MJVkfeKyi5_Zv%?2>MRr58$Y^*vXx}~ zh)`Y1Cpa_fS&E~3$>@=QwUj>lc+B;HFO?o!am3+Dlb($i!C+WNl{O!}Ay&pt{&A!u zjZXXd389;rjyMoV*$!VkUyo2oPWwr2Kl}!9`B`6N&fZOQiHEcU;FNda8UmF5wE6Uo z!kEjW2ch=@Ou@af%kZ;vG0$ z{zg=Qog4bXaQ0Y_30R?^LTn1yH57uy~Jfk zjfuw%zcG9NaiepL{rmam^KR1n2=TG@LuI_>N1^MjPw)n3>C5J=e+h}AC!meNA-&^f zAKO;1w?w%eO4i*P*HhYW)`q1!SDqLPw)z~e%SdMPE{i&fs@`g{N8KOmJ%97|ytP40 zAiBi3E;gMgclxJKnX2Wj1pzsAePuGV(Z-$CnuER~B6Pe1pw zjCr3E=UeJ>K<~k5GWneEzfx9X(Hw<>V0JVJ_hDErGRg!xK^cC2bv~P27WV5J$8>>%zd<^Cp zW8(PqyaaF)JCNKToozca6x?~9kOQoWu7vXyC#P8x}v-7!K#5I%}cxnC-e>sJ^U^4DTZxWUb-P)QKBL2D?OBf9f>mY>vB_ffs= z*&MxVa)hU4*WND3E7p}_#<*_8gF-JH+^^@WPbxR0BA9#v|pEG<=rCIIYi=|z50&C^~ zb~vN=BT0TCG4OMFZXjZ!#<%Xv`hufnbRsH|h_oe9jDxMtTfa-MU=U)Tu2%Pp7p-t+ zcq_&{kr=l2KjII}D*Ji&LUo~Zp0xj`@)AA_DCF!S5h5ROll4yCJky)5e)D>K*0VEl ztN9u8zd5-x8<@QvxvG7>c;3-YaC6eW4C(zrv-SY8abp+au>hwBZ~DLMrxTBT!~N0b z+4=|pz=`>LPWwjrp37^A;<4VihxxpxMl4%rUzS8DL*)jYzCIsCcW&W# ziu`;vk>^xI)y3Rcv&4!m_BKV7f@hcY!5>Sk6X0>qPkL$6KPI^B} zpu-WL-KBg)S4lTDBtYxu6RQB0c*IdDbwWATlo|o&A9Bs`p|nA1mYk?85L~x`i`MG{ zAd9}CBrWV9ntJ_8H&6N)+y#`C7V_dLG4#;TORYTi*1fZ4_j@;ggqVOZ<5ltW@#)-I z^8mRxI$<^;Ewpm9BM@5!-D;y_=W6vlCMl+3CI>1sCe_@#J9`-|+Tfisd!%k+`_*=# zYp0)`G58McTS3;lpI=&k2Y7B#H0SmWxP@YZ)9s+3jUA1zUu$*;T3f;fEuzoO*|z5x zP0U+{tljKuP~QGi-bQD2x`)408BjH@|Lu-C5*~05&0`Y(Afj_L1)f*pft(vj65au& z&ngB!oI7oTmTRlt{Nm^NiV;x+R7MIw?C(ak$E1XPl*qqT{2w9S16M=tGb37x3haX- z{h^|Q)6;imBiV(jDFyjsPt{cnAQ{DC@Z<5(8~;TxVA!11g!Tx%9cOuvt>2p=1o&3F zn!M@Qy*AjDfLx=Qj=C>PO6|(CCWq)0-+0z$o8#D=C04Q-aq{8OvbCUavzMl+J7@GK zHTc(IWz@AmnHQz*8IBy33eJ(VbHBsR`pm4z6VAFYvZGJOuqR34AP z{TY?i^<1``WI!bM2Ug>-LyZWc$v+>fYI9)Z>k$n9l=pCM*# zA(vMcdvWzGBSj}Cd8e1No5M3jUnlK=lrwnR2SUVF;uv$REvRsA6iHL3?-+Tw*%CeZO zh)BH)M6>ai;oFH~jop4u@j68yC0IIo2^Bd~zompah=_yZ~el&4J>!+6+{ix1D&)W|f(L;P2bKgb9bX)C=ijv#f?3MbuPQv-VQRCrQ}ljBi*%dLH!>_* z8`E_=AnK{+zXrg4+X%4()W1H1>&9lGpkZT#tgHR!Mr(tF9|P8TYa$1-d8X$MSyTY= zH9K_8`=cKI*!K5Ci9298miMq_bV#;XMmpy5W`luCwQlE&aa+MdfDNEY8Yvy=DB|0Q zLbUJ(;3C29AaY;Xo@7*GW-!mF+VJD5IFgEZmI(w0c{g>+9l$6dUF6~MzyUTvX*B|q zLkk~vI)iKmN)8&S1w@|$!1=KL6bqtjY! z^(^6efng~(a=BD0V-iF4_CD-jhD#OOMjb5h9^mtuWTXIv9+6LpX!-;MlR{{Nho+~u zC*6d8jDOFuc@Yo)*_$0Wp~&XTf^_pgbFsjeC}q6r97}TGHTRrOO!P$(v#y>7wxoW` z#p{i}P!wufGU`xwJA(j7gE^meG6ez=aS zR*X>zP`WjPM7d#f1Vo;8N=cEZ;1U^Pc+m-;Q^6r~)?U|i^VUTANkjdjdxCH+Dr3l& zdW^SDw-T4ZM4{^gLR#H9Nen;yTRFq5_yjLl^hjuwx8<7*Yoy^JMRmGN9 z1a12oS*SLe6>#<#k%U0mh1Y5v?sT;eZN}3wT-NLfHRLPxB@TF6xi{`sL0>%-ksP*g zdY4K;VPLW3zO^Wg&IP|DH>jDCzHvn1(0P))Vw~kTC0_?I9>fsc22mo#LUHHKec3vu zCcfkQFzi{h8m4zJgrFj_ctT=^*R>)pPL8-={Wu9B%{7?kO62lf^pfaJ-GCg7ztd4> z*m--?%SXIvK35A32HCFjeZ7yd4tw4TFUEPBwPDsU|90|Dq(nfMy(u!<>vmZwQqoWU zP|soT%2IIHJd5@yMe|+h*oheQ3}Ok#U(mcJ2(dgEF!H+I*?(GwU~ne=X}JEv7=PO4 zKwPZ%w2MaN+UX2VAJLppyZV*yZosq$WmFypl%QKH7S%;bKA{s=!lDJkBB6|k2*t9< zl(NyHy0k5$!fDd4F!^vyGZiL6IT(%H$X8W$CE1NHw_LuZi|=lY64uth8wPD|)dCXs z_<+G?70xGld4HJkb~kAVM#fqUH_ozx3A^zIj7eXn;LuQ|;oo*p- z=Vs7#+yFX}U#bI7K2bdC2ovTite`SIAEiAco)p{~&JvXHy#;!{?wGq< zoL|xP8&-+U4hisUj}4$dwqHJ1aXCNjGq+jgNIX#Wb8rw10bQPEUf8)KBAHans=z%r z@EhC7yf+-_=}RtR-IrCWQPpr9R`$)n&@2ogiMZD$SSDa)c(66bf z4jmfgsw0Z!!bn~3FD_(9&Sb$IRFv;OXjZyE4*Tgx50lwT!UDdthZryUVcr`SW%ZWau3n zdap7JzWuT1X?tYZ9D+LiHt3@I9U&arnSOh>?7ncFiwM1Uhh(Pb$VyKBi=y(EOffx| zX1HWJwcwa6^;y9+g7tzxQLvyr8d}=22?nd`MF;KOvoyres0038H=#{Bcv7e&Ge=cBJOw8C0KXQ$h9D{$ar$n zI}X5z8-`$56U{VD9Mu60rqSKzWr$q$(?9FG2821l7NlG!-v@R~`~G1vi`F3rBt2H9 z9=$%D?GaeVuVg7K+@C)0U_d`6VXJI?^vJ5l3y$fnUHn$>$LV?F-n0WR?e&aW%9+rD z`IKEf5g=S_bvzv9 zvB@Pe6_E(Ae!J5@;rm}8zU3j%>EuIQO2!F0uxhc;DSIvL2*)u~inwyiOhBgc4CiWGm zSr(svRLqcfzzS5Z65Wdft30CndSo#D{W7Zw55;YvJ&;;5f~FUbWN6)(3_oW*$fU&ptW2V$Pnfco0%zsAvr<<64q%Y zpLJVpNX3b}ym=Boo?;A+E$+nj{81`{oDpy9i+c2PDa}`4c#|Deda_cg?bA(Aw3m02 z1leQNtsrMv*!lS+D(RF(62)6yoRFU>z@NY z|BzYr%v}%V1CPAf`O{FHC7k7h@P*mwA=8}9w$+Z-yvX8_4ni|Yv^&B>p`ivojm;iM zDf?K!oE82vG%5G%OZ}!vob)qM{{;1$JDM5%nSpYV8LAPz>aYJO1Akwa=V6OioJF)C z8tm?}eL?puQm}h%afOz!3&~O~Fl=fEMZBkdcAf=sDu|7uKhbW+ z{{{Bj1>_Jm#ddeEnU@8XC`S$1=b@Z0VP0{tRbSJ{*!&l*z{lthA9eFgaF~#%32L%O zp*Sv$M42nJug+9!ws7>LDk>K~DGJyDlq+S*r8cf6$8zu-^nBD~JCynO2u)<+?}o!F zX=%8?OiZ}|Hx2|E@Cpr)n;*^*O+W#9`B`Nc5IEPa@NDLXc@_`@6;w?|KkoYMO=RD0 zJzH*%_t=|XTDe)^^6N!}lzIrhTM-?eocvE}VkMYJ_8-#TPW1w5^(#4bZVvg}rX&!f8CJvweVAa$E5 z;(Sv+dz+bzV2(DalqmT&J@7sf!GL4zE6%WyqaXbYLi+akIkjdH>l;r?{d;_^u} zJxAgm>%CxlTFHot8n`}sWo5K_F0=ka)k&dTSt5Qne>6q29AKF&3auooRf8~lOHLfO zDgI}3&k3{ojDwZXhgPD(9Y<)Hns3+XX`bbt)=!64HS{QUjkkXwe8^iCX?kx!E%v$J zOryhfOE{ZXc1TGO4=pOo6IJQi$K40R>yt;T11y9uRpgm~+Yu)Xs}pHwR3Bo}9fp0k z8Kvetrb5>{6%df47AOZ7Bn>sk)_Szn_uP-312!I?|FV{ zP-VMic+$zIH<+pc8j1o-+7Cz52%X6fRad~sKpu-P>{Pe&C_O0ZD z&4dKLZpKN2{Sv@Uln#XThQq1$!FS!G8dr}ae5cQzly1d7L)wNJDxiSFGra-tllRgx z6bc)#3`V_KQrS#%aP!h%VCtlPG(8b6-FhC< zgn^+X@ruOJ_i`l^@q7oy+PuFQv!!Y%ry_$_0St0pJNev1$MWovR)cH&*F1-+hM5uQ z^JUD2>)mV4O9)Erm}PEOmY6TjUbDUxq8^;8#m6tp$jIEwu5o>h36ZEb7H|F$Jg#qv zd+hZl?+-DZrVcDpycs5<36#>kJPFAE!~5p$V!5sF z>2-Fu?>d2rH!)zcw3APF!RQccm7lm=qlSbGPjTf(`Eb9e{XqdlPN zI?r+z>K5Ws802_u}X5#XmuBcl(EHjpHD`aEzzz>niqV_ zZ1mA9t-{UTk`Z)sARLhhU9BqUSDGaqs+r7i5Er@?5WH_9lq4Z0pO07^xs^Yp@ zF{naEHMq9Ik;(OI)0Z3?qf-K_9vpN^e-TG5OK)^ld7Y7&ns)_1Z~nCID&q0J$L3@t z?l#&Jx`{b>{eWt4`}mbgY@niPbN?gP41+<7qS3HFV~2FbfHs!Ps7^QHH7|RO^rH0C z@19kza92eAZqX7Pd$2j{D48Tp2z96BcHQ4H{lUD?y6;+^Y&>uLFASa2ceGE1t!EQ{ zZ;tiKms{`e;#zy$=7pLf?j6JvTTt1rprP93^nxx--7ufc{`hXi6wy&tptnDAsi|R* zSoPvNXglI~Kes8%kw5?8-*D!S3l1KX)OBEloAP1-H$@e zNbScaV;c5aixEc!dIYu(k}%wSpAl%2VaHJm6}`>tvsa#R&Un+X67FuB z`}$nGVDWey88V^g5TxneeJ=E)vPX}WqZL;q+A**;H6o`dsxmMg8^SZ|?H4S^doz2t zpSJ4RUSQzuRr!8-xXdF)*LvT)CME`n@%TX@M6mC5bM#$%FYNr!lCu6ZnlLh{@rQEB z89n2=c1a{}f?~|t%f@#m=N)$(BXF)35FhPc|M40{pqV%rF&#OMk6+x>;a4?wFVmyY zW9drL>Iy+Wnms1X*oB>wsMvA~Cnz}osThGmkpWvrb+}r5&K$8hmX5W9I~8l2SB~~P z-X2hH1^fe{u=4|clOpSK=@bM}+-Hk{H5T4vqOb0TCJ(jKelzbqqn%G)42< z_m!F&=MaJ?aO-c?UtO$>?lKGOdr~be-9B1KJ~X(YJ`dYL>#teCvgc}Ug~pg|iS<5T z4qB@+tLN$zS{kxjY$Wwi|7R(0V{76Z1&t8f#C9twxUToZ``Q%Hq+cRO?h%XlDxE?c|2?42ZqK z&C>2*e9%K55^B&PF;@V)c;yQ;N5vi4KTNwZ5wa?)8@ZX+Nq%^y z2}LyEef>)?ES3H$E%2+?lm#j+KP-mLwQ8I>mZ9*CNc^P?eaF1g&0Bi_pROH7XehV; zRSHO4#Q=YE_7HD6)u!qPNz@+#t&f4CFQq(+IN&TePPjA3P^U#p$VxRf^{PSFb$|QI zd+@OKY8U23!>_i!gf*)K{+Bwzy|hAwCROE*T`=yMjDXDGSL9`*RD}O*l@a!XBalnt zmML<~x|!>!gnd5EhV0L{@*h6~i=qOa!?dR_&ScMOCv6%KjF*C~ickLJC@pm|Mb2as zl*p?}LV_lVIxB`Vq030bbJN=<`E5rzlqM?JSj{C|tS?wuckFU7*l&&Ph%-}m68l>Z zC4Z>ZN4d!CAp;OytIV7PDb*9UpXjW{vLa(vLc%4C=^dF* zSw8bKYk}ny^M(xnc}`JUa0^vObKaLk+mSLj1`%FxLh{u$}0+U%qUn=V3>TD&KR-Pek`N`WMgI{A%JgZ^m-;J@3izmo$T=!l*=t`Nr+xAT>iFxuMA z=D@%hQhy6)w94py72BnBQAvYhxd%|%);qi5p{>Z%HbV{)2gKO652b4uFEgMW;Y+XI*MlzvCo>> z1B$p6>!n}relJ$`8-$X{1qAgPl%sO1nx5|CyET&bmdP{|xuZr`;iGP)@7ps1Yx;tu zvp{U&R-TbNu0Sy*au%NPD{Vuc-u?Nj$dkHzuvJluFJr?7`}8{W{%4#p;=D{V%Xj9f zY$P7BZAgGT?WzJ$PJ!8W4-N?oeg6H3RgGw!Qw4p1vCTNlSeb|!yK={F{R@xv`;Go0;r_l=4i6wD;QDg+ zjh##}0OivAuz^KLNN8)Q_i(O$(vMEyFw|#0F(#Yivy zhNL)BUZL3uL}#stl$krDTC1AQW^^4#q3#tllvsAPk2{GA2~B3DrMxd-9u|Golp32& z1&)a>b#nBEXIf6CJt)w5;!2YmA-wVRap7FZj=S@a(w_!xCL2@#gRMWqdxZseF~P8N z8vZK21WULwR~oSbe*XA4v8BrmqNiXxXS{fNaDSf!blmgRBNlFDVr5LymK{J7Y#(-1 zLa*Nc&lsrxLYIEAI|P2IQ;p+#*fs$=3^7hY`Nou%`m1A5;+nmp&2^2s;&gyF#6Vd=!a5L{+2&x90m(mSUh4?4=mS z>R3r#HJBaJfrn`1d!hCd?@!E<%^g+qew2O0KB4jzf1)n}xqvZOui(O?>vwtSt)$M5 z)7uA`Q6(wK3_zS!5t&!&sS%Ka=*R;O;S_IYYQ8sib2YmeUos`#I7IyR!=;+-LdNlB z3lZk&*b{syLhJafqmwsrGZEye_g5#8CYDom4WmP_Ko$25;M&;jSuwY(t9rik;O5MboH|LPD-nqtRIPm*`;J-#m79+BZ=3b+FWO%-8C#$# z*SJo5w(WbIz_{*ROx&#Bal4E?b8~0*x3sAh!qK}Dj%?<3*!(1Xe(ePp(&|rw`-10Z z-i2&5?A}yr&2WMU+l0CZg9yVRP23b>>XQxJy>{LCSboTYHFS&dq@9+ZJVU~qBrVc- z47fIN1XbzZ#wn9_2@fShj(o|NmZP*r0B0TS;=xey&u?;utN`_PDkzBuULFee@6fX# z;7snGOmGTh9~*1cs@!)BXKgm?OM4bi@t1waJWY%eqa&45{LP#Zh2CA(Y9Q?d?}a!qD})*y+N56jx7KDG6?AO zYh+eEKDP1t`=d0xY$;4`=3^Et%-+-;UDxwL5m%>W&Z?7*t%Sa#svQL9kxGH!fJ<;! zvn&R^{j#LpIi-sg6=WFOi5uSW|xhG`Y9HO@i z?&uV>f|hEJ^+mW6zRyz8F7relf5&t{ORlm6?|=ur&NmIxClaBN%{~V1;hGBO|FPQB z49J{Q`7jz(mT1TBcQx|`_;H8CYi8wq%yv_QsTJd!-A8Mi+bg%5`!f;MhDE&yjJLXb zqw-LW2xNetNS#h0jNwWf0y8UbDbFqU-!2fTbsg0HZ^7_C0=a*7U9W_oKDRw@W5t1_ z4;8GX>htjQJ$WG`SfE%*sTAuWi(NTqBT9$0(#C4jMdf8$vxh&y0FY>6EC6;Fl;~ub zKHQbA4-_6+jTP-ydd})s*cfYx>c%jW*CaQQJa)z)(MskGIcPC`2=t2!OZG4YdN~rr zrjb`1x%Ph1A>h%A)_qhFb^Ya%58o8@<1(dp)~)C1{_7yY*ApKTy<_ITxy_lgJi^qP zI`G>h%Hp}1#|(s?ihbw%^fj}6=S#BT@7M$=fhIg}ZmNjGEK<0DHvgbY+)ff{?da8v z3;D8m=WN8(t74C_Q%Z2-yFpoc=5f5th(|{iUGOnt5Pq+>yFEczsQiuTce_ye&n&s@ zpWz=E2QmzsHS=`_5p2u>ae~;5Ssau?hd-WH&x{50$_h>B_(Y56RDnJJlz4SWD`Aaq zXQI1)wh1n_30a~k5Ea^p&J?y(1xN+;$eNMk9`w`2hDXIn*$AuhZT?`4T-Y-4HjeAU z?*M%GXSw-*?aA~*5Z#vk#BJ4T{@3F&)*JmU3pVHpuCDptQ|Bs$Ba}^wHiosSVyQw8 zTNy!Gc&DEo@q!j2E!nB9LrQ$aB300!6(lhl`@={pb(%iH>aoHOAa4fr$AUV6)FF>k z>uJ0XS`STL9EjNv1I;e%^1~~*SZ9PoV3|Q4y=>yGAX1<|7YXF7#hfAhn4F~{i1eqJ zp)njS)mvdZcE-!6Zhm2YGT%JNr^pnFb?O04nF;{i{sS$%RR?{ z*?RovF85{!FZW03!=rh#l0lhknN<^of2E@JA0p$-?1-dHtCBQG5qPugTh4?Tk8`Vp zS~A)(;VGS=cZjjDQHGq(;>nvZ@0mlMPX$?Brp_(wFUh+dTBL+F$BU}G9C+dyM z1=O_}r4F$WsOF6B3?FywidEwdTQ_ys?=GIdSzZ6ni_+I9Bsi?iM`*0Ue438suW^P% z-|bvyAj80i}6 zzduP~gi;0e9JqaNNzFn0adT!9 zkGkkx1Q+K~um8vxBS?R)2jFa4{jL5Hd=1ybeG#Cyl-W7dPb4$DD1SVGcr%GC+ZmiC zX`MFY#Va5ZJ8(0i_-Q8WGSkckx7S$+E-~PoxaL}$y(3%R7JT#o5N0Ak9_PBh2`v6! zxlt!l;-Ak^wU5~JTMW21C>w;Ip2?K)d`dB=dE*QXwmZ<;U3*=$l9TdO(1cQVRIKH( z7h!~lcne|_ph)yp=3tem+k3*#dJ;4V-CYDfRA+H>9NR@WC=tRRn z7e2F(HzFfKwPt2;M&V(_beUPRYl!1|7*t0bP{2pg1{2U{Zo@Nz|Du-2*a5qG^hJVfD=X#V8qIMKLfSMIDap#cb@+doG=|Lpr|oL_?m zCxotkG9GfhRK>9JS&m_5_Ihh*l22UYO$jp=782MJoU^x@zDw{;TH0|Fk=l;>`p!48 zn+Yh$Z{O$~@*MSM#L9az25%Ob!O+=9W{=jc z+#+SS9OZatOfGmBW4@&4R((lIY2a%u-ZVc#RT;; zdYVt~R2`uy`Uf|O3eCWkM=X59M!F)yCdK|-&5T=C1Su zj~48i8|+gl=}X7%RW4`ceH*CbH}|vNRV<31;KN`>hPeLz#v<@e7F9bQG76eAtbNQ~ z=8*Gy(sK%n%8xs8ypjj$cbLuFFS#CG$b^z9_DTR)ZP-R%a3(sC1=yLKmB7So#~Vqx^19$!>~g%9w+v051^Kh#z5i-tmMUpFxzK^5 zgUk*~(9C&f@g?7p_wHt-VV--mZh6${A*Yd_g!uhng2~$4229%sp3s+%%S9r(%_k`? zJTpdS+*JC*T?BA(CiHA>;AD@InsC*dNB0_kv;CE*INJUlS*5o5y$0;gqze>C)K$Lv`Si1ja;nN)8CH3h{cs^5 z?;4RVxf$J7@n$3Ee*W|cSZguj&; zHHbeXG%{?wRPrvJ#=X6BIfry*vr1mD8{rg!mxv`#8jNt+iw3?d+MW}eNyv-vX)iVy zse|x;Jv)$AArSanTkoX)<+PAi@Dk~AvnSoi?T`H-Zoq@isZGoJo8G+@s{3VsR>X7# zmDtcOFI(GOH-6zn?aRs$$t=Tn?&B=LeGWhU=$amj z#Ur=F9g!j+|7OSkr(i(3zDdi<`I2j&YZ#6PiMJD=wX0P&3JrI$nb>8Mwj7~Vm$^J z)vX&Cz{CtEi>@}fb)`yxY+hbvT4>!x9Mz&4QQ!w?h`u32ggm}Neo8JTFQWAIw>N(K4*=kg zT`MJu`AV@Re+j)0H_kRaDY84AJJL(KL4^YA(xW>+B@9S}l_}k&Shj{ZNe4M#3kp0*@M}sn*?sYt zcwQR4Us|+3?h4uw31wz=OmJ=dr{&NNX zb2|eGzM}-7;Y&rL#7R7oAh~lX9GA)*%6!-{DkV%=d+vU|70bM)#bWEGcXE)g^|R?f z_3j-z*ByJsb{rsPVBZP&xNx&`O~3(rp@baL((Vc;QMEO`v@|7>RCCSamGR(Q-8#ZY zDMk$~Vs;?YTeRi~H8&h4K~K`oyy7<0d4-3@r3MRt0)xoRIm6Cga$vRX@4n?}_YBeY z+GLbA==O_d^x~q+s>f#A+?|^L{-%lcNuI;I!VgIC{0A{YviGx&VdrN;vaM}2bJLt` zpV#!K-oCSU9;%Zs;V&C~KJuX5FH2$x3cfE&xXAEnUUVQRb+lW!oT9zyfP|$bu>Y|k zh$Xu`B5l{;@x}v?^&uPG)AZ( za47FIS3!ojuONKFsx^N3qP=TnJR6<_>*2cf($U`z>#?97D`JcZ^|<_0Wlu!*l3;DN zG^6&HZC&_+q~~^5!IZoc{W4|yXRLTb*oO}-u!RJ*kiu-BxcL3)MW-uRf<~~+0DC^2 z%BN$$?^1G&fXw*fG{5VDF3b-rkGNe`q7{zi6Xz0;F1UXCaUXqFqq3~e-Qs)Zr$3Cw zzct_gpv>)I2FTt)_oIhScT!m*_@XCqqL8SPE6Fk z)8jbkmv;!pyVhuHA>l^s#YN?hDr(c`GM*s5@T}!=&EwtD>*|ILCg=W0ETl4A9)|7% z#2a$)J8Lg3X{+^lHzHjaa;bctT1Pg7csEfoxAc%tqx|e+9A;=i@hS5R$a@o6Xtp&= zGNR_1)|<4uczmy#d%^hFl8H<`w~h&^b&6Y8jK-#s9oD?;HU zPEZN%*Rnv$=?i$CKxV#M?wHFZNRY>KTyZLmktp@;d9K6aObUEy&41i?WtMhb>Jr{o zkbL3{z&?LqkOz_?}L~Y_djg^FXKmxjvi1*?Wcnd@a8}bSSHM=5dM+8%W$9aGdf#ah`kast^TvZF@`ZM zE;H(rf&TE1!OiN?AXkd#n9g`PG-wdMtn6+XAFCYLX)@7MLM9zyM{wt zVc3K>&CN|0*Cx&GyuB7h#7cq3-O*$cz3h){050N%eE4g9d=kzXuOd@55{NYh?M0)2 zw`Og5!{LlkWn?AnT_0Me;$z~Txz&Rs0zGJO6tQ?XD;reBq;mb_k4=qe-JCq3zg-uE zr4&ip3I{3OD@RVO=(0L`ix?i3zas!x>NAVOpd&z&@_p7D#zP=$cRdm1?Dgr17)I&d z(KhS89Zd*=xz<&>9|84inpkOaaXpzEJ>S&wa65S3>bWNGe!XyIXMgZq$58jt_S|T$ z1|0Q3lbm$stk!Ak%s!+Qv7nHy9BEOifjZm~@9+L+c{rHxrsGRV?5-7VJA3;u#97D3 zo9C9m!&DX=y34@xy)aDp%I=2pWXGMM1U3F8s^!$0_uOEiVO4l3@d8P-5QB)m zC+|DT(9^PQ(xug;QdeijOb22GD0EdeyvHN?b`m29iXCc1gvQ0%s^xcjSt_bauPzx2 zrb|~ZIpjmi+{uOoUgQyB#M_b9|aP=QZH88szr9A@}cwaZ}94O(hT+67J zjNE-+fX8Y`(CYMfT%PXKyqYOy@rp!+@OvbKw327=#(>Lf+WiAd|8s?VdA&4l%9zk5 zqx+M4kMEN4}2m+Z8 z^dvlhNKWH!>_(`2cz?0+=rZ@?>8)uloX*VJtwS$`ylf#|QzFFWpzgA8*-7cEVb|qJ z|7xAHG(phpa>((r#&1TrB+lJ&yf9K=93$|HPS%brr~UKgH@K$8b0zTvJ?*EDo)y#x zG)8>y5MUaz!N=xzRm!rR^zw9ie|n;TIEudg()4u_693=c?obdtK<@t8c`|Q~N5CtH zns`t4$EO2GkXe1C2pr`&V{tdnYZK`sv@z*Iqm>+m>#vzrCJ<)XWx`@6P8tKkfz>l&l`l6~d-_3W@d^M|UL4ML|3B+I~X?Iv~W zV8xRzp2jraUX5LZ4QdBRqTKj?l@eNwd+K%?(^=Rswv07hx`5?q*htRVe5wyz^^Qx{ zE^B7vf_bmhBxgT8ZBaj7bmpfvzc!@UaioA;oXWK?t5fgOt758O9jd`gr6E zx)`-HXa(Js?32z;7x07ymY*&bS(@$G(w55iEud4-q#Bu@Y9Pi!(KPqKVaeLsg zO`&_p+wVPtG`2f7w`iXXm{dN&^7CVxIJy1hq1RsL_^@GRk#lWV(_`d=1*BGm0Wh%> zt!a@RVP>wn*T5(>k^$!<%#84d)+3KKCqfk8JwSFmFIFtSuV4Z4v-b?=m=qT_cE444 zBjKLt*0Y^4jI=9T|Bbg@3iEep>XD8j-f=nm5TFx~3l#QyjX~%2>^vM#J#mYiTRc#3 z0@JVUjBvW=H0|cnJfnB~nkTCAjbX9{B8@@)=0iuvx+Q=)cct9xXx97q>h85*YILW> zg(0pl%?rJ^hBz#$rC|;psw4Xueku7S^%Q9!Ui$MadHc#68^k^vd;mK$nCgl4mgg<$^CwbDR(K; znTUb?)`L0w7zdNp2U6a%lrDc zLs&y!P2_KF_q)c)+j^L@^>ViD)6rn3*fF$!ctDb|i(TCKCJnFbXTT9T65E+4D@y7x zz~wQ4GFWEU6mz`!aHZpA^T3+P6$}P(+Bx1UoAkd4yBDR3iH&rhq=7^ZSF6#mbt>nvaYhmv^&p=lDq2KuFlGvsz~t(j3*p%f$z7*5foOQA?Kx>A|I+GGI9=`YiiZakh8l0p}Ax&2#O_Li5wL-yr8dNzeSL z@PQt0kknTgDbU(IRPptc*NPAELKWgZYo3XHeFh*Ee!8`?7F7T9#Gz>M?a!)W_Ma^* zjb;X>OkBmF#+OGII|6uEGR|^uiG7F^qeJM$1c;fym3h#$V z8UYt@i!F023-RS|+0VR|h%}_ovqFO3WC1$nIJ*nE zE{VT%jgq5FMrB|x&d%bB>CLaK4uC@*1Rerixr!8lhkb2jMopJ4^~b&Wh_PfWiF0Dw z*QEI!FmaH9GS}Kh~veYsaR!%|yV^_8k&2{033!YW%7|WjIZDY+t zHHwg?^kfR4B+Pr%9aDJG{7$@87AO!fop}4gE_oO97~;n7Ob66^tkUvHfj8uBzzQ%Z zS>fU>V7TZ?&eKzh;zz5gr%!ewXBk!rH_}EFVH67#%OczRJ~|3`W2|1iEK`Ajl;DfSRwv3Mo(c`? z^v}tw)}R`Ex;JBi@WS>71Ma1U=y!~aFC%#W%QF}!fB02^HN&)mr2pab{K~|!21FlX#L15$Pgj(`O2rWnzM4V zNjo(Rf4}m-2ZX<&VzUSO61F=KDzVTaur_yib>nz3TpCKe_Bv}}K+!5g6PF=Z%;m?@ z)7_&kKaQi9AR-&S1 zGab8Njqn+~H;Mb=#zWS7P3h-_pe+2DJ+cR!qd?CbuS4&KjmFOjA`0S)Ty4U|J-MGp z-5U0Cl2Ysau`x{Rwn`K2%i*x zIFGb9)92XM0$Xd-CjyiSjWwTUtG(heb#v|;=W&UxU$DLhy`^$w?ZI*;sa$^e74DJb z5jl0;e{;j-QRSq>Ld2=rawPO-mheW8#5MF!X}G~-L;9u)@jM4rIwDZTUBf;G?^8A#W`8NwUN(zJ>Tqw)W^Fap zK9xIL_qeZZDKB4;^gQ2xXJOx>W1wey-|KiMw6cT=z`Mw36MFBxc*#+yEegOc+Q4+} z?)04K6mCxt77z)=c5J;rd7RG8^i26#%!R+AQ%>A@zv4Z#2GRUx3$* zjAez#=Z0Xe{7?iopB`JFx8|*Zo zQCsR)Cow1Kh8ovv!NRqobXld__4oeYmS?YrDA76vH2C^fB#AW!ESxB zF4I=ng_h70PjeXh7O=YfG;dxZW5cs-+#z#X!hWan$0;!qbZW}tw_WuMB|&URF)7;Cw1d_;DsKzgBY*vISrJE1%5hs)6ZEwz~3T*VoZ{Zg=Qii-To+=ftR z5t$)&S=+hI%xvQ;0(^qbj*ilt%c1?=m^~9=a&tsBnc8sWMCAn|zxL2p8h`ea{?{Uy z1}{#o)Tj>L3~yyaANg4aLE}zoWN53K7}nsJ&_ivDvi_f_p_lKkhH@K z+QFh|*;25L<%8&R!4n5|y^Ov6>>}9;oh{8JN-|x!g?=#Z5%5KPA4SKAt>-JZ-9|!V zhWl`&t?r-LABL=uIdM@xAm~C=p2Wp(KR|<%4S}MF%$4@>d1+OFz><_j9)mUnPK#2O{s^3QsZ0X_KQW=Is+e9&J3I813UmrkR#`+=L#to|7-1 zCfSQ#a*TLamQw~omCD6ng3jS1%`?2FM6*QRn5$ZZ0-r5&g;$r48aq1D7{q)0)#-JPur&+RLrkSjYJS6s(#e6{#wH}`sjwHlui*5c;M_ukN-r`lamwxJmidk6=z zCQs#$>a*hZ*q12yuIEpcrqDaet{hcz31bl)Z*;nR%d?df$4V0KouU>dKe%0{QSDSLE|`5}%#fzh*NDD*WA1pIq3+rxB`+b8ao&lPyjy`_tRHq1BD=jgM( zmHy1AHZNi9YNNA5@;*PF5d4%ppbA_^wmf2P;}T=cm5AqXlGuo@d(4=Kqen$Gy}9w- zOLD*s@94;JH`!yx*8HsOwzuu)a8{F$_)UaDW!DFpcRTS5JL6lOw*1t79jQ0MH4$!bZ;8!EDv|wB= zDKd9Q2h8Rs=%HP3NeR^oeEG`#c9l;mUf~iMdR9Dom~q9}1$USbK8A$MEHFxYxbhD7{g1H+o7ainzC- z3I*Or77=}g$LeXv1!E+9agQgfU&(4NG8DUkX<;|Ea~EkDK=j+ohO1Z zV=BNRVEc)&)^|g`u0){{b}X6~lC*KpICU_&V3~W4!Ba5P5PbdQ1D$ytcN140KJmX7^j zdBTX%`V4!eTA@mBwAxOu$I*$xW>p{)c!`+UllqX}yVDI-R&K)>9t?0fthC}Y^y=zO z%QQ?A(b0wOZ39-vP=@;Y##5H9kM7fXbEQ<+P&eod>K3}b9~yi##Il-bR^EP96tK8^ zo%{%n?X|^~FD2~75EaS{b5FMS2kRo5U73mT!&dqexmJdzO|`s9#b)PPQK%F2;-NZK znJM>}Nn2q|%h@hh*WplwGQQF_Y}V&m6-AOgq+(4BT^5kfJf(wN9B--HL)@1!>HL!8 za0R<~I!qrtv_wU6aegPv0pMMUwb;h`#hLMPfS;sO<6pD#Z>wm&VoQC_j7Q;60&)Om_AXB+6*a%ysj* z8Y;xNXAW43BkL{+uq!N|R~>nIC;N}1Y%CR@c%2&_MxdncV zw>KejouF-b7Tu>-5!DWS+FhM?e@ z>T{an1`%l;b#lCyc@?I}q}0GeyEFG!TPs{KQvlZjPT&AbaHB_i%aUQ3+zn*?NM02Qw0M* z@WK5!X?lCNd{!In(@>PwaOb;Rq{6{}PR)O3hza3ENq@*Kq`&PvzpZKavfu8t+my9-#3eM#(?P^|CPcY`5?7 zqO58n%8mN!14>XS3tHR?nIn2bmCqxRcB41;c#_;lt}>l9UKj#~-uB+2PAM^|eo3khstswyAB>InK<2 zs{+G%MBC3z?Gu&U{cM7nr;r=d-l$NrufW994m?}1V>>tn)X+%6T=7Al=_sk<%yJk! zeiu}(iuQQ`NO&yW_)j(^5ZH_j#vs=tFq=iz#u%%+KE`^0AKc+D@4>;Gk(3#SRa@2f z`}asx$^+u|{iOZ<)3h)i-Wx|clNUxfUG^XH!rX&h$O)jC`X1;=y&2~ON>eYJn5~Np z5)qqWSdV=;>rGWfHu3LyI0%j!Z==vfK3O{G{e0a7?r}KEtuP?N zz}zYb9az|U9@|`g0NY2C4%}GaX#|*2neTn9?%JBZCqgy*G%I#n(eAsS3&;M_JW;Y) z8>xK1NJ28^Nb2@KgajmK9v$^}5cIDpd0*Es-*=KTOA95(XQsN=cNr>?H9b(V{JQS^@pozo;Z|fEy7H& z5m;J!MEMalunIYh=56F>j^TdB8m9Wg=0iWTH1?18MOa?(VGbUF3uL0NwuG{}@r?Cc zZ#1|G;YZvA2vdT1^f+JZgP`Hh_k#5Xdm$^GsCf?XOG~a$Z9<)y&V0)UlS~B{56Ly> zjc?Y?1nM+C@?|Y={Gii({^2r~Cl%oOk&-2>RrQJ?s! zGpDcoH;$`(;@?U55*zJ@b@*AVSqo+;?R##}z!&R6>A`FZ8SfqF|E%{M;0+(@S3So% zvdn%`?ssuv+n>ilQj4Ifn>$F*_dcpFU^Y(`X8<}kTa zyH(q@vGEnrl*HZt1+EhIcTGqVXN)#-wAmLEY_paLEf*GAYI{5^b9hn)zN=HHqC3hA>0LlgFC^$}^CA z$X~WZ{C_^}OZ8Xwi40_FnPZY2C^om^Jh}rzfIahNzV!u{VHN~KfUCk52i|v zay{XT3b?wS81V6wOz`s8Gai`pnKAq1GU-&7odj+e=VKd@@MdsEH9y9` ztm1$fB6fM0a%)z=xwrWQ-P{h3^%2gj3lDY}4(8 zM!6(R)XGQ93YS$Dkd+jt&r$;R-lRv~V_I5zkV^8{Dgc5#z7~j;)|0yMsVJH6O}~CJ zc;8`vJJk$ns7v4F!>6@#X1`!)SFX8!aXl;Z=emW9E8EU`=GJn$%Ix9;>6vZM``Q1} z2)8R}VA0nD_MLlwGoW&oVz35RB`&3B)TncK0N0|_Xb)@7uM1cSYG0o(zrBA7g?aNA z^+-;a&>v_v#_hK(8qJmeXy-jRMuFE0^{)u)%Qt3qPIny4 z=FSi5fa+o`5I!;sG_5OcB9k9Xh%s7)VcN# z_b2Xf_*lCAqY#?us?bP>G%S_l}KcRu%~f%%~d6RlSBf3+9tqvi~M?V^0v~>BBbd9#LdM?!R_K30A#Wi zw67QE6aM$2A?{qa{|PSJtQ3f=H?QW3y-Q$F^e2ZFbPKcq`$?akX1v>dv~l0B3TrvJ z=yt&w$7HwLvbgl)7ND0cY9vlSp7WFhY%)*_Ti6MC^UB;)A;8C3QdJkXm8%k0P6tK$ z9~@r2jCs}=F=2c{2v_X*`10tq>5W~YO;QX`L3cK*X#zShSR`~4 z<6+4PJtEHd@*uEY6?ktQHMKaql+d~2W`c#Co*hNYn5gh0`_`Zf6 z>(x4898;~Uxa;Tq3!a58AC2@S|0kx0jMW94Kk9H0#5%t*8$gn@F<#Z|wMU0XhO?ek9s9bb98b3@SI#*d542yjE zq&BYS(8o=pC{pg`XRXx8+0(Mx=T(LW9*J9G@~K+~VUowGbnh`3&nBSn_2~6&m{d}> zxW992&HGY)DVUhJ3raPn2nIv)teM(MU;S()SzO`v^Q(TurWyLyX1?j`jfPkjPDVF! zqKAHCtwxYJ3?mn4Rd z@=?GUugE-*9h&(-uhRHFrJ0{3_;{f$-L1(r)z6v{aXK&Xg@#7&)3IFwVUF`2fPHaM zrC!SFWFSlb59eA-A1MMf?&H_=BXYXmkLdK*RVGH{?fKwqFAFK=H33;E+Lug)JiOxQ z#zJS30*zl=ABG=W@6;;Ofm_>{eB{p9`7aC2Bz^q3*BFW3YPAh6{SUfW&lYR|siziT zf|29b23G5B`Pd)*>$s0V>GgiRn#XVQI_uu#M`?fdnp&R(n{KU&@E_~ek!3_qW11Eo zDT9_x0z4$xdwpLsC9tc9l~&a)pYzKggVyE76AsvH>dJYT-#(N`)@$cM0jl7!^J=PM zQy&S3JjHr8QS3p|E1a3H!eMVWU9WV~bV_@`U&6Gen1_=ukPzN$bvu(bidh=x&|@pw zPqi4OY*v>|i?<`9*jv2(_8BF&Pqd5;Tt^^$-nw?&P$V_|=A?fFzQt0v#oN2)l@fb7 zT+6w$HZbw)C*`C8BL5P}+CC0#2^ZL4ID{4ZSlmr}-Jr^Z0<+s1z8+mC5fk&zCiPB! zpo=#apZE}90x=+ox@p`upuXyTOC7_F1PxEP&y+fdiWo$5xvBEvIfgi9Zy#DLShAPBKdo z+VPr-f|IE_$0jw@uGYP`W~&s2s8X$YW}XFA_v z{a(%b^bOJKxgiICRgGxz#IqTY6?LgV)wI!CB3kuO6lSCN_o(P$lxX@QW(p%djfZu8 zgA-2K!*%=IsYiStT9W@`<#`^aFcKX zu&Rg%o{<3a?aS^A5myvxWj4h&FWjR1f_{{mngMR!_u?^!e39NueF#4cHK8*^}0F!UG_a-UO8)oAvsY(Cwv>m}6M1wY3jXxF7A$Ii(}GYr4dv^%GU-csy(L_%i&9jl)1fy+G=rXNs;lF#o~4 zTT+t^bnf}4E*sk7U~NOS$|6zQtsL@96|X0=D9Fg=d0JAfuL_fs?|29*`m-WJ%fDny zJaJrbGQ4`K;>L#j^s^ML=|>zWP`MP))xV;MFL39as$z>(iw+}xPxs>YlK6=4{CLYo z);zK0P17hDW@|I*TUO945U&G>;X0h@Mmx-mL*c?WQCog@_LS0uUu^L%-M*_xSyy%b z$`~D9l|`dkriv(dp@KOXBAalXol$~23O;-62en=oa{g#^Kn?s(ubNb@4W7hGxDwvZQNRTCYKB)OWDe4UO@c=A`{Tk~1_hQJ#VhO#Sqz3>}dty&z za_EC!?h+XO=x8SRqEU~hNYunu>2vbB##^Qu95=uPYpI*;kRlpUK z18t6SiI#t?c_$?5EFr>vvfrN}=1?(;EL68`e1EOauogkd2qGg8CRglOj0gX2t3*1?%;!iURcP)P+-!1_($ zgz}cc(mPvjjCHD&dhXMg z%|2nk2cgX1cZYj#L+}m$l6owMX)T)YMqbm3nPMdIH1ubuV2*_E2txoLz@@aU-0i-c&Ziuw z%X|iKr&hGfr#>r|-b`*8$Kmgjlfs~St2!oHzctXG@{!!;Ydg4hM06BxtLINtzoE;! zuV$Nauc|7m^vupD&5p_|%Ly}%LKc5oh`8@Min#2$Q4#c->Kl@%Tu$aTE(QfS9n{uI ziI<=>?E#LA$c@SRkwb#Y?D0yDlAIs)nc+rYL|-jy@FQr}hUgx?xLM4wqmDdmo`_Sd zHEUC0cvmw*%u(D@O4&32o>7UFU;*&kO6MIIC-p77)J1`U>Jy}1kp0ryl*&lZV$snzX^%J2)2Dg`uC@hpCu44`$D^o$Ki?pE_HGEQR=}zvjFbanf5SfAg<25 z8W+wgDT;|bgH#YVmr01K_Y@@(6*8pq0R2JX9qhd`xS6OlsR*gOJi5M4Eq&}2klcgW zKvS(9_~toSY(GRalPe5I=lOl4<|oJt=iAX|W_t>l$WNOVte-(J2n~S=IGrlfHhM%0 zBkTu%b4q<1onQ0TjtPI!PoeirBuYoBzEMqETD~5AllCEph&Z|1#^m9pDY^c z96m4aRHpqG3>C-##cDSLYyN?p#Sy1aiO@wKLz@05d1&7IeoMr^Y?5ORxVW-j#~Cf+ zrb>@9$VuMA1+9^#x03|Bl@56I8NIj}bTWOIpt>k`rw)QhAm1t1O67pC=SX|Kc9T0+ zm`L4u%rp6p8R?yNzb?NFW1De}*wDF7H@g~d(QRHB!|L!bwW?@5ydG*abvDyDYXT27 zth=<1xEn;>v3u!N&?Q$he}8Aaxs)2G4FmKs)UQyeO4g6)ZVJ)74HBQlJg=$L9$Yogjb2?;uF3>A2f*LPZa&qB>N#m_Y;{z(o^>v9 z^!F4#3!%Ka2*C?Ha6KMbwnmpVayoN*f45chdc#0WB3mG_;sw5+yo4zJcA^~Jv5Dq- zEtiENI$P1)9nv!+WX0zf3eyb36?;-Ucc4sTlDx*Nd6k*D;O*C1#6Xi4%-;6rz>t29 zi-bI*8S`T`^m1-)fzU{}k|+bjMZ)hwgC@M-zi(Th%*~K_)ln6f9gWDxNAOSXi z=(wpo45z(LmaS-*$_>K%hAGdyVp;P|#6H48eNW!;m7#{fo0dRaEziW6)^7T)K49pM z*cU-{>Au;lcBV6Yyu3#=-4?WCkbOOCTWiF0?^er@kAup+d3Euz^%GGG`nrV}lcbx} z2(bvvr{^sVJ2YSDn0OFMmy>_P?fic+g#W=yOX5A8cb%?qeA=CFLR2`~MzEy1_R%$< zFuPpPYQcytlj;6hr)}N z;b=(bjw7a%MtQ&nHx(WXy?=PgoyLm2GR|76wJEE}XOEa7PjQW!)>O>?5{M{2>eT0X zxq;;`?G-7)Q_;NtslKn?Z+FKmIA}r+>`2NdV6sgrJ@GgiX%eW1ow1ulaz6r}iDti_ z3&H3WnaJ*ZQcByGzSFsyP)C*d+HRA1@V$0$q+{N)KYV_rhLBO}OMh6FW zTrX(9lPAx#I~K10X4ciui>u1uJM7cj)7+gYytTIIXh63*z=SVvix?T~pHSP;&5{^e^!o8GW{;BwDODtjBbpu$Z% zw4urG0Oe(SBCn9O>^k+u?@2{nn8XwM7e3SSoB3r{kxUEBt9J2(3Xo_V*v=9C*v_H` z`-WC(x(dBJ!H#d|gTm)$YCi6of?)0BG(ef`R;iQ8_MA>mFV>mvAQ^ND{`g>sj8{V zRwDb0*Aum<%1* z4?}Ea9DJDH@Js&Dh&Wz0U1c?cG!00i?awYt{G1OzMdP!AJ-?@t)YHqqg6T|4@+sXNd{KXazd# z5~n}-Ch=->gA9?xJiYi^qzMFqs z*qlf}g+q-)#?Y@mFn0E#RjFui0)!s-z$VGj{%*F!97Ic3&qMBBtb08%WS$vQI zE`zeIS5tyOZ7yWM^+AcVo0gtGp~nQqwJ)9zrPjYTaBekQi#1uC?CI$6y$K+b?Uo$R z2&@=QBAsRyX*tAD_P4Ywkl11!xAQ>v44UVr9#<3#SDH?hbUe5FoKR7fJ(d;Afc327 zc2Qk|8d~>YT2gbGh-jdC>E>p}m856wotemT`}H_HeaNW%Vf|~hgmEZtTZ6OloNn5c zs>x}rwhk2uN%05WoviJIEtedI*;=pJd>`nN68>y1DDZlwv2$>T2)*;6DLbvuo+u!S z9d^nR6E+H5d+#jL9_Zis3fA$=&CqMv9|(dVAZRT0Z}) zss1-y71Vf#@&vbD-jEl;_mu96EG{lfm$G~gord==q2GHHJ=XM{2a2rj3zZilFmIBG zu`!3v;`OHT2a~o$&L3+Vj$RItGh-O`3Ip}z$p{lD7RI=8*a7y!R=JPJ+pVVZ^_MXC zqk!-&RDS9}t&Pi98ZnwXmB(F-N2B+%1Qjl_m&xKI1QVa#qMvjN9shinmu@jgl(ig= zH-J;VMrhjEd`X!u_Z%Pz3&PhZ;;ByY&5v?%jn~d6o{Dwfl40$A=IxlQcd<=qO6n(> zpf%u&Wz^#5N)>oGmhrJD`Hsi(=cm?V^o=;i1v&pg&j-0Z^rx6Edi?77?%1+!`Mr zaShJJgV>@tvLd6_8BGwx7aB8OVEjV%d!%D+6J&e|eVHo#9T=XPMRA4e(5ZkTjF69ER3*Y_~@!6N@Q~0iL z=A|}Me#&v`%a=t7;kM^ZlO!8(sr8#jfk&uiNqYHS$q0PDU*CTj>Y(CpBp*yLpz7+(nKD=0LjH-lCFrhpdOTxJnMVQZA(jSsH+DNf?5Mg|CE&IF0*2lW*1A;T2V1RqXNXM{(GJf*Is^J}r~`|nOux+#mJe)y0ObF&3FMx3 z8y|6ObISy**ZFAZ5(9=NdNd8@XFJE{%s8NTlKMCKmxO~w5sjqe9QcE5Hl`)5aePBU z@;7TW-(T6RO$M)B+tXE!Zga0pRXuy9?JzL2k9|~3zzE$s<(m_pbkh~`7*a9paip7S zzflbEGGyQDvFngXZNa}w(@W2H(Gq{O@YpWeG-B8%=o{7aY4)LX8u>*;;^kUeOr?@m z@?JvnWlqGm2nEyKFiEfIuozaVj4VT9oEtyu5`pH z+OOSqCF@72f|7yuc3?G42^vm!8LcGITi)xTUs=OW&r6?|EOD~2ybL(hRIT+n^*PvOG96=n23V&xZU zc&04h7=IPcT5h(`E`(fEQ=XUfoIf91^CBy1X1nFHxrkD;EfO^fcUhZwG+Y>x*;5br zwPmQl_nSyGz{{vz{0~KsMmQOEMs#F7wgox`>y#aItOZ40*l_^-%)sB<&qFq1lH*0r z5`Gk=hni$}=ZM>3Lrm{P=97D2@9WAXJ0B|T-KBV-?^XG25Yktj4yJeDz9HL^1_p1Z zCg8dbbun;O8oB0XrGL&^7EOtvD`8m8y`=mejqigP!9kI8J@R4BdJxeLc1K97B=uZ2 zW?dQ(Cz3#LVWH8vsofPM-&?;h@9-}@`{X*N5uj^gZB1l8@E2|NUHlQi_})wPz&jmx zzt>M3qdz6YAF0nTC1(csQBuq}-wXGH_g_;Z1rC0}pW9i%zn4 z2jrKeW4nK6D}-(;NKH(J53V&9q3Z2LT^RxIwd8Y##PKfG#A&)aG#NOhu;vm9E($$5 zC)lMnUP%r4H>GO+;wH!xbVv#5?^}DKMy{$(&lHIjla=F#N&#MR=XeT2_pBvr3kUS& z>D}$p1)0=+Ibg&^@oZ8$OP#LD@; zhM$tEl38UJ^gdn~AR2jgKpRn6s?>}Bp}W@0hi4r{YW5>fu+9rducI-bNfjr*A4qPK zwm7waaLELOZj|i*`ev*!XhdjHm^vWq!=}$rb=Gwz&*32~yKoTlhCj-MQxSZcRL^5r zjAbs?gX^aA$ifvjiqgyWh&v>&${Tyj6|oG&`#B&0KP3ga(a+Tci+H&X1*beGUwJ28 z*;rO($OvBc4j#ao5bA-8#Ps-zE+_1v375r8I7hl%Qf#^jKnHb+!dIGE`zIlfDvlxV zS`d@2cG6${_%yTm8>@giMP&u;Px?Ci_X8d+-p@CX)z7_ne?9>m+r{=<%XrFXc|94sfZLhSmGWDy&VI8 z)Ka`D;NKTRz_bLs{u&1%+M{#2A?75q= ze!J-iw;`Wk2=&`KvWT15?%J#JvpSWVmO{bys}p{6FTfuz{>x_9sQ&l=4bu77@BQaa z?Ei0woijcHP&9JMmW?m&T6Hzx)i@K>wR&nswrNl10mxjf-wNP~l(r2*u+2vXH*EYy^^%iH2sibrnK1p}72emUl z<7vM$3&|@+FQc|!`AOBCH9Q?O?X88g9_@{edmF9gg>1&^rBR=}rVg5C_MUk5^Q9$r zB0j933a=19aOcA6q2XNmo7pjAc_uRnYW+VH1JNdenk*F)B>}G8rJI}eq2tHzAU;># zc5h7|gdiFk&OBv&psw>KvB~F+yqr@T;eKMmUaUirB|=qdM~&c{Y3wss7bWyh%?vZ{ zDhzsF2B*_C$GrSoxk99a-R1A_SwQ>VP`=ZhZk9xnPxMLTX_9Dv|9!x(zslSBj5eT` znit>&~hH@RWGsHfGihSK`8)|F0I`_M#}Q;T%buO-q_W0HR97r$zx=>l!| zxX6BonlK4otDfdWHMoMqfqHqi=LDG@V+3QN#TPCzd2X5+mw9HW!+j}JqU&xN@E6-r z=9`M9YK9g-v_P9Gg@@ zv3|p<%;L!LH`CLNx4w75iZ^dzPRY|~X4r>hg^N4IcB#>{ML3nPItyF+t-i{H-aD8c z{nYVl6uVb_cp_f*T1jgX<`lv8A8W2sSg}eIV^o96hY{!~$s}CLJHLu#l0L@ltDj^N zTA4%9vp`bDL0-%Y6jW?&rw$c8yNP za%xa&lbPcUKj-u_tmD#ZHsxnn4&$-32LGDW3{UX_3OubHc>(F!iC8i?A~-s2OqSz- zcQ;}D%XW;r|Hun)l(avI*+=YCT0?dmwULU^nQ=E-)Q}g`?c0#)38UE2B*;<(J}>Z8 z4R(KDA%!wfGDQo!ZHE%+W6+HtOu+FIkizD>;m7Rp_wSIWFfe91EPJ^r`Y@nI!rpJn zQXlZ0GTx)wa>l#$66gVMEt<_P5a6Bv$etYa$y(M|)6Kxjgj$b?_m{SJyL$QkzdxS-DtPab zIb+)6n;i}Ftajnr>fPc$6F=8HhfeB9e0uk--5wk#torFGhZELF!10VeA`);XSn^<$ z2z0Oy*wT;I393=;Q02F7@yYmj>{<0lCGe~35FT_rb(4)&vOAabtLaB9&FAlp+=Ym4 z<0)9^w{UxTs&?d@UuFGn4(i6MBC;A*FidYhL_8$w^ww$4`n4l+@8i)>SPh6hsosmx zooa4?%bTs2_U$ewhbiR~3Q=krghI7jlp^^_ZwfGcDg#_cB$(WA!FY5wV@HMRScm~V zCooSIKHq^;J=c^uEh4?LhLZqB$d+M7zV>ee&^k<144~sDAw0+b%&LjA`jEfl<8 zKe6gcIXnenvcue zSs*#^=R!*m)Jk=HQkfM z|7D{U&-f1UNeeiV>9-BszJ*ce2)`4Hd13BZiYXj(yu+#q>T=C4Eu8FuP~UDm3MeDk zdIJ9?K1Y#rKVY{c`%KK`>Wjlv>KUYD2{)MC+*rqn=7Yl}3-1d{J~jt7-p3G87qf2K z(Wv*kH6(S`k?m+Nd)vyY{^Ad8+vqsrmZg|n*D)QMh2NN{)w`GxInglMkubp%W;OGL z?H=EsnmG%ZfoSu;1Q~ygm;dJ&^Q^`ubZguz)OXs#KM+8NcxRZ<1EV(wl-xB|M2*W; z*G%Yi74}IW2*|c7qw5}I{xjg9sf`7+eTCiAwMY>2tI2iL$b0=Yl8vE}YLq*6%&$si zS|2bM>!0_)@qsko^7*m*U<3f}d15F4ObiUesnEMijb%TIoqqqD4lm${YW z)i*i#@V4e2-EM&N+J&T*cM(POUF460yL`!|3vyHo;3bZS2(sj48KF7% zesQ<>vY6sF1UB8Re|>*qBh*-~oKP4mzzVdVL!24seve(%kSgvvRu4mL^#%?teg?jv zt-nl`A2vJoq2n{G=0+RhS*)^dF`#Rw9e!~1X!486Y9P2w;PDB5 zVG+0e6rR4i_>01T-9a*B<|W}r_H2h;lNdgRZXa!V-=AFkn?43-52(?@{px+Ktg^KX zz50}IseqXQn>(Nd;J+Vp_m2rE`RqO*e?IXp!S|0;H+Ecu@QbR)*4s|WI-HCOq=H$? zmZS|h#SdC>;E}@4=KF7+LN`{O3$vExUMTd6$}Ch@?s8=*y;!)Bt%~iP8pvFR@7v9; zs4{ptf^aP;eRw6bEfym&sPKOMf#a7P_{d*f9GsQ264glTPQ1a|LRDU{%bk1JV8+Wd zI%}z3WOW_SlrHoM^aNFBsvKqke5`D;sze{(fZk@6^3I@)srr@*&M#u^;jT=&jA?8_NA}9TI)(xONz;=(C$p?&O4$l@p&7wPMoBu_ z;V>d}LH(|8fh)nWL>FIxqopOz*U!XnidOzVrpfl^XMltU#kYm!Gv`8+f9k?l7gwVb zZTthPnc&jhiywUP0b((t)&Yx;sIL#gE?W&4fc-yMNk+v3nwF#&17GR2OF>s-=nqX-s$FGTqnq zJ(pRDSc_G?t<09(fb+pbKdQZ&h^BR%<#FNk5vf=g^8k4NxO&vBlE6Lt{}GTMor4Wv z^K>X4&Je|!fA~!pQ$}oIz%&Z#=~a<23&=YzC1C*po|uCfNN|k?nqi)j*uU!vE?pSh z&P_jr4tFw0EBBbyD z%c!O=p(M!XCT4&cero5>0Y!dc{&Dl+UNGe#Ju+wUv49ZX7PC7EQ9jQu!3QEkd_m_1 zy!3`O=>Rw{DV4vLD~}8hDZ||{z=WKwZ(;orF)iKCu87ixOE+Dpc1`RDp5S(Dp%B@9 z?_n^IIBGE}*}bCtmGot?EPAXnZ`A>OvKC#p5dKxN-LC*`LymQc;>o59Z^?6(K09ug z4L(g*V#`c9a%5z{35~`FTw2tyDdals9MDm|FkwklEY$C#Kt0ViGB6hLxwH8&>{E2D zIR6>&Z#?cXyLpC8{;S^HB^-ao?lFoJe}?1HrUh_<2722UVV^%>A-R6Q@#`D+q_sbG z1c}!#)2z%#=;Kd|iPh8{MBo$HD|wSKFKvA7q6cWeVBp5_6v;;*EimAh{vh5LI#|SU zDKYSPFr2Tqh-7hCxa=M?O6)iN<_J4n!zYiLC zea7|_z%{#BJi4JbSM^#~Y2&l^6w~3(6YKaa@+W6h+RD(v<6|EU)FAW6>t5hD+3IG} z(z|SNjCG?v9RNm}TNt>?Nvk#`MX_!`2i!KGE}A$kc##S?R9@^6__1)R*U9r}z}2VP zU83&R|7@{fI_|l|uo2hOGf9k!X<4bWV=v-2qPIqb)UksXYmWCx5I+4o^IjYv_|Y}x zC4(2l>nGWkHBd0_HCCuO(26F9_0yYKCyk-U&81~!HK=*aOvA@Vev6=|>RE&RyKFN$ z3yI;LI(G-(D0CX`89_7dc_TZGvf%;CE$a1}zeOA5UM_)eJf4N&x;(X`j2pp^&1$s) z?N=?#sT_Rpe9G!uDEiA!we;GW06jSbE3JeYxPo*ZJQZE_bX4$(mkbWB#Jvb6SYkqW ziih>?5FGQCg5G_JSxVGwgIzud_KW1ySEb-C$@Uk|{47!Y7|wn?MGIVdaF+I^>72!S z{q~JZ>~6XW_B=@Q)z4QgdcJ33z^2NyCW?*&@Hb#HOoRPf1^s;)x$Tn?SGR?J^G zs7I4T-5!?Ditei19>_vEPSYt^7(mLFT3g!I(3L_VZL3Zqv}s;Wr6tNX8wPoCBQ*T`z>*NOT3bz?^H zrwysMAK}@=4eluhwS8R2gbI4HwkLPQH?w$!IPKo9d=U#>`{agka?Y+N?V`+YXD;O; zydzv^^pZ3fG~3J-Ns|ZFDY3;}V`>(;9?@|c_r#6sIOt07av&&jSiD{nCs|7I=~jU? zCRqcG*9PdHUWc;4O?hKpRkc_ZjPG>;3Vvuor(nCUgKgHoguD3^?^f&6$M0QH*B?Cn z6^{!lOcVBgqiRvk;uU_7n3cIXL7O|;lYwcg`y{EH0BZIr;Zh*D%>Q#D{(|Z%mmaNU zuzOVhOwVTse#Ya>S68n4&9`boQ<$6=>wj?tR#633HQ_RRe`0*o`f645aV_o%Z)&5P znO!SLgtD(TUQLfn)DwTYnJgrbMVLwPz93#Wd6+DFH1DF0C6Tg{bI4bF)^dNZRVG?K zf?jBc>dRH>+(6w)hm=aKtyB_AaHOD?(c(Fez05|TbEIypO4h59jw`olsT)k~X$VM+(5 zt42RmY9zXN$-qh$$q|e6+4)ZRAh<8N3|z)ynA;vhIowETa6?gY`(wOV;WR%TO3bx6 zekAf?5ER&|fIL!Pe4Tp#MK%Bevle|NZ z`MZVapC#|Vz21xt+c_9_NicyE_9V4QHrT1w%B6FouSQqOU|NiO2d1hz{Bbd^e(m;M z=GvZXc6*Dx%=f6J@O+N%ad z^BL21Kdp7hSoc^zrWb8n65pIAGh3WsMHAc(?7WK=1=0=Ht3&^Eax{7i1LZ|;e(?S zdtW9zl@{Y#rprVsS#ruk1SRIBqP$(wm^0HQ`Sdj3i*~TIs39|J2R}wxEa^1rcd!&^-E|Q*#S8>BI>6~7)JgqJJ zE6)gG`FSpbjK_*Ilz~UG5-b&zXWEJ@!$zk3`kK>eEO07q%Y00H*5@c^ceN0tKOmg}?a zV-DM<8KXO*I~nXROKZjxv@V`({O|5N8}bojfc5pHbKA|)P0PYUCQKlENOC6WeWPhr zc3pvZY@RWbx1Rp2@)iA)r$Sr&)oYJ5zgcY`?)Wf$;NonlYK%f~H?;g5BjL;pj2EdC zeWo;f*$LdVXie)p+1$NgY-LuSo~A5mZDeHfO}=Q0z4WzmnAmA$!ZJM(XyuiD?Hi6d ziS|#}ohu{V88`kZ@>A%kmyhzch^3A~bTD^dwnYm5PHPr3s%mWif}JUaTzvR4T^m$2 zL%9dOFf2D>+5pbkW;~o_-5=L8p()u7_YvqBnu#vCqTRV>tOqVWc=66KeJ)8b< zDa)qTdmq}qpyc_bLFO*Mv+FglYR1?adi1;|aC)}Lj3&fqGiF56?@*s#ZA#Q;DAr=w z*Y&Jd1^2{uwF8W>8##(IUb2tMm|asSVeA(W?EV;^wi#_(C`z`qHuGsNg2GFrYk)A> z_TA^O2yOqNMx#h85SZa0T=)2?-1W^n#71h}+>3e>O!9*FNt^%8XkWD7ny?@9A7q#m z?c+$YTmJveN{>Z;ZvD`UIc^yP^>p64xmI9JJa{j+>%Hr&6r^A!Uo8J(i}AMW6TP?6 z=)orkx`!f48z0w{gN`;NnH5!>87S=NLLT2}R=IY-TFEA5zb7R~(!?((@(;r&(_VT? z#s=`LNbX867P7GZD5ACy-FhlyviG!TFYn>+af>9ehqK`^40VSi^O7RJh!Tzd!d9&SLBvhNz-_JPRXRR+rOtgu!c;HC z%eus(=)<9o`jqchQQt2CoAYTsc}i@HdvWXASYtm9y=fhhfWMx4Dc8EZ`la^oo=c!- zeZxC~3vdlwIwX1m44BhYpEYud``$HyzGje8Bf1qGN+X0$YrJ;L`DuKqLb+ z$4G7U=o^f$lZcnfVP7A?%?;rU)@7<|eUR2BCI9K>0Y%D4H>w52U2Ajf>yx2pTWkh) zpE?R-dJx~yu0_wK-B!FZyE#tuyBhE9!@clZg5Mq|Ge;xOpKNc^Lb_D}bd()Zw1anN zWCFRj(=Ivhmu8;V-d_z395#c|+=stwiK(T_FSJ`%^b))NV*_DR;u_Q&tjE#l$ zCFyl^0a7T{HWw;P<6L7COD>de|BuJTeS#mG6#Hxx*E8H>cvtkqqUkvFoAXTJLg}_f z6>rv+1o29%;It4fwQxUfI%!6Xgd-wC+_4+ea6@%togV=&eb>L&Ix%kf&Z z@GrsUbpf$Vh}oHi!1=g`rAl;If|MrV88~WdbwXshF|5@te|}}wLi0d=Msl`!1^$G!QPfTC|)yLPxbsY&BK;D1RU zMI~zn=l5PW+c;^Xua0B}f{LnnGxZ4-n`Q+|*%n~1Iibe*OnMh7fDEdXkr$C~a*EY* z5U>H!?>;4RZ4}8c>R~j4LSYTVaemwTGV>1*?3pWu3L0SfJE1wOOoh*Hs-Plf`2)-U zjs_Qe3Z{np@wMshVbC2_F*T)Q92Oc#Nf8vOD1>YsyhUYhO{$KnPY1{BKBrGiWGQ?H z1i5eG4z;FsJ-Lky*TL0qv&vYS`(c{H-*C7EV&lP{S#mKgK>EoJ3;4*eJr|}zf$_U> zzn_eSQ$b%1(wHE_CNy>^^F61JM6;-fctXOL*oPwJs(@`fK!f8dn;yCVNw%F!d(Wk4 zhN_c#+IVk5^=5{VO zfM{_)C49uABTt*23?3OVIyT*4C0i7Y+H^4vwa3mwC7TWIsD*!TfnkPZq9N-sMG2<%St61cRCrCZIOVSx}n$GhmvcKC1Pm0Rng3>_xo}K%;Ycy+Mpy z1X_DJVQN~482hM<;L&JRzm$gLiu*cw`O5I-UkBui8#h%<70!rs#gwrO1Dv3)BI18T z2&J2|PllGNjvtyi9y$7MR^>B|S41N&(^ih?wllzQZQ8}v%?dv+8*lAITHY9zS<(RW zH@dmO46}ggekb9WF7GU7d3mQuH2a>vKbJXbK%Sj**l!C_tJpDXd$B-0K;WA{vdxe= zX1!`$yG{r6%IYpmkn-hyha7*VSyiK+NYmwT>Nw=2xEA_v!rCe42k7(HB8Qg$H&n*r+px3bi9Jk9Ga4gfBVS?iSOO zMKk1XIBA0@3osh0;m-H2BNDAF;A^BX`RAEs(tl3f&2i2=-T2xyweDPk*t{Q#i?$;* zpkve68brAB)jBt@MP$1bvZA*{Ps=$OgHFHR(^{EW;1!gjlF8e-Q&f$6&KvgnOvq6W z(Q22yXDyS63kQjed&{dsa&o0U_R|5>hkuQ~a~|f?c#_lcToeB)=75Rm&)OTwO7cUm z4mDNv4;*-mTTGV9%)Pw6ENy4YvH8%pKS@s4Df-V7iho>Lv1FALZ+tZ`(+*~jyIOkl z*RY4MrcO_6aUIaswGosk-emME6S8xIgdIw?7xAgGjpwn?U29hV68Wt35w?MyfmjkR z3vN?C0b_QLm?3<8;#nDc1JFPz&eZ|GT_`MiTcX)&KxH7R6@To0zV^wikPTd6qh65H z^Cqv3zX+B!V-C)>c1;C4E{Go_@-g66#CIifne8mYGCceFj?krSC3-|5a;YD4%vLTz&l9Pm( zEYt&YS~L{IZCz3&G%{~l4mtgoB}K^%-^JVRq9s!^w*1i~DuP9rZ$~ttkgO8b2*;ov z%-^&MOvHkvcy0CWi$zM?VI_AjhLHUvUgQlf1phlXXj z0Dp7r)G_HVYXQn&OWAe1QpMmH;S$lXc8#s_)Lf-y4ekX)bqf3{o*q9PpXIacUB4Do z_0!$da5&lcGDQ3&hc8J57%P?AEPh``5CRx^FjxzDM3DXOgnV#Hq(=v1PXxX;9+9&Z zQy_z#s$S+JvzaAa2jgKV=G0wqmnJ@F^a>2vPvXMQ`Q(18(Eoz+N-F2{m8ey`ijiiL zee83-7h3^XYe#*q6uF{Z3h&(*iK}arIFFpQmTR{UNA#Y!W-cmFTe{uH<8$Q~12i-# z(X3cwQ-Y`idSu~_T=TdG3H?|*Fsb=84e7i_W#{++S>5v5duPnj2*BY5S!pV4F`kns z0{X!VU!5^}Z(JZvTFVnqRK9=#`M0t-s{N6m=Hg5!KD61+uFPuH`dB~18NbRRG@S3> zJ?hYuFm2uwd^}0idVin&6f-oTU6XL zDX-<+;v0H=u^rTav+L{Q?>MXAi`gpm+zgDq7}7nkD=C4L%|VeQtusPE>8{(bDyj2! zu0~KIY%5jQuag?BoTM;m6gxCr;0J>br32PaeGc$*|E;&C{#d&t@`(KlP%Aicn}2O5 z&DDQiUaukWZYvvnKX zq&@Zc!)6$uw^ooD@8RCRua8`w@C1Ge_7KGS6RIOu2)8ZlBS9kEt1U-z7CY$|_EU6E z#0zT*!}L!GF#Oa{6hZ>tt;h!KUL!4NerhtMP2VkYlQR!Sz0ZM0t;M&+ens+_ni~WL z<+^rE5FGs-SLbI=Tcfh6|{ID`zGLokBC*T}GPaJv~IztUTGl}yJH?5=zw znrlZ;;HFlqVYwxl!Et{@oT*=iGN57}nSwHF%qXKk=~s!nta%M(E2;RY3HVooDW}R%I7^Kmg~N%Kn5UbDLVB&0i|ZeUFlzphGFjsJ^Z zApNLUM<IU6grJ^7{Vn+=6Ggm=acbpjbr z2^dekPnh!a{eayuUQvZpqh@aPpbXb|%2*QqVHY!MB?T{yt0IPqU&2Cp+4^t&m1jl* zq6)343&{S{{gFw3J|=MzjXOwBVmliB5(6c^D>`+|<#bztie3(RuG4hOt`C3Q#Mn%F>&%!6!zzhD9Xen!`_B3P<}1=l?YkD!RZ=D=q3 zU*gvakF>H&nU)0yLY=}O>ayz9vP=;3Gl+QxeEUW{db`rZuGL%vi!Xq77g-RmR*i z6yvzZyzvb%`6Qv}49CueN22`5uq`4CmpxQHd;+Ji@)(L`RrGDZ=W&ii0f8l@W&(76 zwwk53kf(Y}Z5zKocCgl6QBw4OX93(Dvl=@=n_=-DPG&90|*H6;K%wB>P(Np>z($nd;{?dcL(4w92XJk z>(@Wu+z&I($_P$Ra}v!H+HSB$=8w<<$oL+yBuM-pBxu}K9lQA?M&^9*K?;PDCp1mC zV_>FMcTrh@7(bMBax$0RIVAX5{ue^@Vq0E5$RF(us+U=6?2kE;PjSyPq-{$T=H(g7 zl4P|Zs3Nzih6+p~hG_t{T*#68sn;tB&7z%_S&9(sWRxH>q|*`s)kz{+Q7^Cxne4(3`!LmI}CUN+1B@Eq;} z(-opu(%F!OW@uuc&?f??j;cKd;fx~k-rNetV-gsR5%stDJ7-YB-mulEE#O~qL_&F{ z%9l?drr^>7ppj%@1RENNjvF`VQ!Six^#a{SLdJB>4ZgpdxuieVv?~Ty>e16EBBq ze_a-}{nzV|`EC&f`K6?<_~RCQffT4$&Xk>Doh}Sa9MC+0hW)X<6exjPhAsX3eKoq_ zDm)X@>Kj~;Z6lTq<~r>*4_hC*FF=E|g=1pFCxDJtkp@u67rny%RNqYfYFAbvMlvLB?Oqt%hR^!d2tLC!|rSPl-@t z<>-Ih{KyUOD(wMDYXXXy$ho0oBA@fqh!6Z=%`QP73S(AmissL=G|oG2tWBe$R>RWm zeEG%;t&Uywvn$*<4__Wd&NnzxN6hvC)B7hsU8+Sb90?%2w;Ah~D%3H?wAI2wosvc1 zc764L(c+j2tz?5=c-&CKMRz^zUDMIV&G&JCB+3~#x?xLx#>&7Ck0ODU3p~iEU7`HM zy%8z*8bV%jaE%BC01-A75g+Fj_5^if(j!l%h6%QN(+!D+3XKTzh@02Chs(Tb%(o(*I)4yNBaUSgNQ2g%v5Hnk< z-cL9P8lOvD@!5Zm??j?|XE9D<9bQ`D`rng3BEc{D32?guK{%D2-K-)hMz*@scFkb` zJWG(H2Jk1Iof($6v!KjIf+P~K9HL!~XghHR#kX{-F968hc&={<{tj1D0%F=Q6z;*P z(J1d~&}zXIu{qj@3d2wXV=IpOaC#=n$5n#6DXjvZ%|?2p;tLRt#`$Flip^6>z0vU%s4?IO37- zO@3H#yr?O}*qPAxHz4}c)qla1D@ol#P!$c8)&p3m)G;&!)VzEw{G)WV9hi$+GTHKy zVxn0-6vMsVAViP-8luUa`Pybz&yLkCwco`Nb~fbIe8?a2lh8y>*;--usl$40Mq>XX zK@8PZ>`DgzXHpvk+paq8_YZHMg_zhvgfXE<)n1V|o50xI|8O-pWe z4z%E>QQp}tsXQZg+O={(G;TbM?-xyR-Xcv^0cD~VI4Drfj?7>cRy%+?_40=_=5x7OuAGL^K{y~W>zY6Oj*dt2ZuuN{JxP!_Nu5czx_6Lo=q|*1X zx#Bbj^Um4m`HuNfqpJVmIjP@eTv{5F6IY@XMIC}F8cdE|DF61DCop>92R{b{JM=$9B8s=6Sldo!mUNtFctcm2sI5RJA!k^)6!OfTB*+;b@0Wd`a z_7Wty8-)_4s(b~1viPRq_rW&ikmxnGNYy|(`6F7KHxCR39y}PWTbe!uPYi}{n>DM!y1-y-hTQ2E6w~rl$|CG4!259vl>QG&!%YhwS$k#C*$Y#bU@5; zzHF&HAZ+tI1mPXo+Mws5|GV@XwvGQ&5;PW+u?>qT{o#qbSYnTN?uWDZe#KYSw`3>Y zWJh5>8OZS#1`$9nLdi;VZqOdEv%cAWTA9=0)==Ve#1ZVAv=) zc|bp|uh^O#*IXQCuCZ2}2y-XGR?@Py*Lq~QXQNi?AI2|U-f_BWcuU>bIW}k#ND)tu z?3i>1TPc;=#KACEMNxlTgiv^l4fAd0UPO&tM3K`0$Z@}+;WZc)mqP410wfn_+R)ye z<>`+-`~Iv8RQCXM!XC^`4b|e>0WB`bYT$4K{^vf2L{U4|u}de$gVSBo7)Z@Kv$_pO zzP4|Ms)A2%jaDMhKW_r#PUwp5 zq1N^N`SdN%h5*o(!Ys7Sk{hqu*Uashb((6Gc|>ptsE-p=V1-4({=r7Mx%UhdL9Cas z*G}&}x1GtnrUzl!zSt6Z#1KtIvS+jvr&^xFfBdDgoRq2Z18r`bvgIk?){|aM;-PBNLCNH`uzLe zB|VpWT&K?&63^MBH*il(9ZrQ&qP>~V@RH4n-zFs_(1a^{mj%(?d%{k+1v1 z`9$7%pJxY=?SFjygI`pprEW+x<9$AIsU>jY1<9fwBH+ctRymE6K~k4T-}d08dT zjpPXOIfLq?0=7wckNUeG<7LT!th%CN!nevuILaDN%i?iAEX6zqh)ddS`_^qT@tbF( zf(z+3CJv}qQFUDGL^f7e-Fnk@{e*3iQfL4Y+_{Oof|ykhFKi;;p1c(7_o60Jm>Ku2 zmtt+k5rFwxfFejafxu;z6FEZP(UyU%qx3 zQUsqpSv7jqFjUGpvr5Uf+%IYl7%lEeWE5yAFs^RmFUDL1YaQeUm!U!R#V1RBxaO2Q z7suBg6)|G99fw%X0hgn<1Hzukm7zxogF{WDk^cIELC(nNMZ<(iP2F%S$PJ(ea_Cyl zZXmG7q=;|G=r{jGhuD-@FEac0lxfl}=sXBjjcHY2t-XEt{jBO0v#MqlD@DM(wE^)? zi-nQ!8GCsF#R&))CPT=Io>iq8{#)2y{C5PBJuPw6M9K8CO`)_n%gVBQ?Bw=PPtVJ9 z9S6Oim;GIV-Bu_Z{mh(DqW}b+ah8L>&%X!Me7)#t%1sA|kT{1(2!7|T6QU#7EEHPYI zc#hWNwRTm~PUxGiOuv0O^}Q0GvCFhQ`i>@(?R6$xoB|&rX3iE-U)yuNR#D^L-#gfM z+~Yl%ZqI`5z|Cb}3S=dh+E3=@8s&+s{KKL2nvFoXhwnMrVSSem)0a?~J3vJHZ8-|gb%kYJH;TUpfy(u?H;iDv?H+b?+^5yba`J({=W zxzY6^h&gyD1s)^X>H}K6yTDjk^Q}NARJkHCgb|A)zYlXD&luadhJPgmMucl_DSvEF)9x8h}#BuioH+A5F@6sa$ zP_tJwj-#(TRG9}J8cAp~xZ6Ta3H3_s=&ozyC4B!_OXm$W3qhUVu?ohnB$cxRYDT}E z9uBl!Olwq5N@L+N1sFcqgK5jB1D##RbO5_I49>}$e9Sc4HF{>u5cwSsZ^+1fUEE@_BV< zyb3mzeT6u@1E3X~zkj)PCDf=oG_w z>+9ADH8_zqT<|jD>EQDHCiPoSGhVoOBd_yqDk>WlfZv=8AgO+cd=K~d-m-WgwZk|W9|C6@@5Gg_&>?8fp zgsrB*N6Dq2i5#KAy638S@^3Fi?07RjpHZtsI{^l>m!Q$hfNB1su@jUl_2ThhJYsVt zEUs4_FtYsf3Hc>n=RQTO>T<2!2CJFdc|{%6Y!7@adZWEmX?4Ih6ZkK`Qj1!eiI)9@ zjKq$^C#K>0H91Z%M}JU>zXx3bHP?j-~1Mx}}Y zh=1Zulccn|oRLW784clkT-2e3!aAl>Emh9dYzH$Al{8EF&h|J>a8u3e07&1K`AHuz=_}ci}b0>^Gg4IvtR43HPja;(UV3W-F>0;lr zVyF&^LPM%<*H8b|aL4V~bK7L95@4~P_GCpi-W>^Vv=@J8z|ufr7fZxGzjO?8Sy}jE z1?r^$zb2UCX|)nyi2-|HWWrSJAI@n5ql z)r89L)CUV&9N~Q%kqd7=g7pEE1ZZVpM49M6#x(oD8+t;|paeOg{r!iV*t#x@$hByC zSXKg#e`QRm{=AnlxkK=y`}u`9`MFUpCe#w_WEVQ9ih_U6mwUab5LT!>y*B-jZy?Dy z)^;2k2$l$c_T0T;IV17I@$-R+Y~w@+-dCH}sPh>kiv0ukUT~D_SOXR0t8%Z6OLk`k z$EAHZg&2(=!(_StcT+{hH_{+Jv2>|C$92v%w|7W@h(!#e;1fCR3;!%T)>r%8a?lhm zei1w91#E|@T3|~ZcGS99Qjm~8-wL5^8x%GINg3e`w&Cm06|K_#1hA!T+h}y!Aj-9}mS7Sbcq3=$;d;Sro;UwCuzg!_Ie}@At zwCpSgg_B6uTnnqSpG4L#<)H2_kKCXX^u}B}%QIigxr-z|t}Fz-THY2z+&j7Nf!CD1~ z_EV>UEmqrMgusOZ79GF8iowk1(|SYJv#Kru0rlmQa!ErUcb&rMLsu*AwX5Z;A z|8g4hFUJ{|I8$C0>w%H23l}@)vp#TQDv`eMn^JnvDl0ZfkC2aIo%h-T z{B|vh?!XM2M-Q^TeglyByTeYdVpxDH0DB@NA-_i-_Uu9^2{p(pymQmC}`E6;-(&fD8xJ}Y?Fl2jzu~r#SGJROF{~w>fD~PEv zX&uM8uLGLTX!NE4IAUuvVxeKHJrQl5$>-!oQs*{|0VpK4vGlKdUn6C1foM$qff3Pg z26XF;>ZceC%5}eU^l)57iFU4AZ!kE@GB$zFF`pSXPW-y*y!?c6BdO)FhUdUeG1M|A zGxA7No?N)ML|eWc;&+m_$c4JMI=_-Z?0ltX!qi0Z@%dAt>1F4|>Re!#rRV$6mC&q3 zP#B}*AZmWRhs`pZBRVqSDMT5-Xgp(9;wVY+{Sd3SO>jwD!|8{y0y>qFYwQ_R&E61c zSA+lOq>V5CG#M~&uD$V|{4Tn^uq`_KUI`#SH5+ovbek#f3Gup-#adeg?&!@3{5Rfp zB%18fl6tFwLEG2_$dp}zs&A>U?<#(Yz@1+cD0srRylvs*_2)Oa$)~oF0RQkaAQiIj zbpe<+aoAI)3q&1+QO%0O%m(Y152~(hXB{|J?2nB<-4S`psDBjDq{}C0dxqU>T_Vd! zWZGxu3VEo3|k#o=v z+6wTUTlDB@9AA%GYT{NoNDm$Bk0e@W8+DIZ|5E5y$?4VPh#ou%u@z((YkQ)kYBM)i zC+?C9KG{i^?cF3GcgFgV z(+0WU#WyyED-}sOlR7VEb;;f@f{+g5Wlp(W3m=LHE<<6Y<|m*PN2 zU+3;_W_OyO?>sGJ)OUIE==i}H{ec*zzxLjt@%08*gEC-usL|IQ<xMHLOY0CoZO(=|Mz4G{xweq#XhCz*Y@$RwyB1_A^*!!iRZEc|-XV_hwaZ`hX zSv&Q9BCwL=cw-=1LEyW;wci^qVnlSb^Usvmg9xP^K z>Lz!)CmZapUm!g-f4N+=RHP2BHPb7kRHm=h{>r|RH72L5LWFZlZKDQre8Wcm@|H8N zSYaG?7Bt@5M%0#dtPf}vW$M!C&FWDTc10Jg3Ipi4-XYM(Ar)MqJ|{TpFT|n7(H~C9 zKy<@F_?NZc{JyW3UZ+}Qg{1XexEoY&vb{bezOG?-mk>1P>DMt|R6eF|`j2^+O-SYI ztuK`|iCH(^aPuo;3)iu} z(=Hu#zZ zIAeX9IByy>6aZ0a-GtR@26eE01q^L};#C#lM*j9e+Q-wO!bR!CN&%vbBDfqX4EpXT zg+Ww}=j^*Ale?UZbE=fbVh&R0T==G~LmF*gip)1OcMy4Z{@x8gZ2b>sGWBMB=LvpG zf_N}aL04Zfd;C0qOLN!k;3{@17rZ>lH`Nk1KePPhSzm9`AGxx6Bvkje{!J-vw2
!OjM6Dbvv*V_w4s5_)OQ|)uSjBUSZd3sloUz}#(&b@;h7Z7x z0S!0r$hy^L!^e+usCBLg@kh@IOLHS17ZpWA0gHZYnnX73*d;me2fugE95X?%4b5Mm zc}DqyPPo-ECC>fKGClAS+jxDv>lYP?VHxg5sp-s15oM#bbPZ*fX!hmx^Hz0x8rUU? zR42~OhML$$8{l`0ZG=St9Wn^mLHYEs!Cgw(GvKz!o~TAp%gw+x*vBlxG?w!&;BAa}1`i4)J0`J_=4)i>NcEHJmqmi2Fh{KDqo?XwK(0w%tg|C}gy49U&1 z%K2R^`97xm&IcIGhQc?!5Va*7*;=~g)w#2xLwm+s2E8toKD+Vz)6M9`t-q6(v#1>3 z)nSwm78IdPZ(@kN3Q~k6}5fdJ7#_>hP}iKSQYAouSvut z@Q4&nm4DV5O;*R6QrYL~8z_o^58@b2U1jiD%8bjW_YQm9!KFRqk(~Z2~ z@8u=9#1wo$(8~eK>syn*&)G5;6Rwu>8`ca-%#SwgtPYe7={nShqiJt~Wqj-&OMExF zM4?^3)u3YXrF-a)zo~hGN9oR52vps-Zij^QE7BNzDq0rQ()FJdrtcl#v{ADm7L)~%vFIEKe8_z11?WBJ=!)|H*5&!D+{w#0qU!%3;_RG=acQ{Vd z%Z6nX%SiO{lh?}H(9MPO+;sOo=If&bo@ai+yFz%CD3(Efq4+qIUL?Rh?1gchAP#GW zIfyj2Ij^x&=J#A9y4hbP5C>DV9s;l!SV0Vd6hxyy@ij)>wmOq znFBQZ7LAd1w(oAwGH$`n9(u~lUCs$p?#3mzG{nIx$Mv(fFN^!B{8CjN!qI(uXLHgIgzuD2HJME7^(^ffi zj1C43>y1L5y93dwx)zZBEb%AlnDdLMz2v7(_YDO=d;Kwb_~5qd{S)n?_$BmcaDUa% z>7Cz&OB0{+V+*X^jabqNOAfbO&JfR_U60Y^kkC)NgyrQid)N9k_1vv? z;0?12-XDukyuy~lLwL{c&?S|voTR%M=6?RzZzo`rhMYsUKvaP``c<@7o-v@t!Yz6W zyDHcpKZo?CoBMdD{+f0sZ-eGGo@$k=mj`3qk-%1iay74WCE|r?oZG8m?XVfkptP*r zD>SYZ=YWI_<;UQxd^F{T&tIGn{q`QP+~|hXKSK6Ax-s%u(?wnX+*)z3p@o&=JG0+R zNZI)8-@NbzRrs@^;q4Y9ZoYfSnZLeWtagq4m{u6l_n#*@UNxb>kacAIHZw0smo% zVoxMOy-W+&_{&OBEpzBpruVfRw-WK~4tlDWz9rHlK>nSBmjEO2Ma88526al4 zZ(&R!zr#{YJnIpEljbKT)7u@`=`Dic>!Eyij14geFkIm>q!Bd&%u8@V!on&1Q_5NM zrT40ZiShNAi)=s7X*DCb5XU7l8^5VsN)@}^ggVDfJ-ZMt4k{&|O(A`d1!$)?E3@hW7?qdXI&-OdYV~f z=i^Kk%2CnNUoyk4+%KmFccIuCQ4eCFR2t{+RG4M)weXKg1T%7){7@$fp||Ew{0Qt4 z0#@P?CVl>d%ZO=9FmNNDZ&G{;$HR{Xj7U5)*Fhr2&L{-Fgh{zk2F+ijnh`mZa{Rbg zI~LyPvL|+3k?4Utnk`*R`p4a#-67{}KdYVR&9CKGNBS$gcv2-e7~rky{K?rphqfM!XZ${CNRvsko$4VYgunRD?Ze*o6eOXH$WX(8Z$p%jSWEkvA=*08V(0HOlNLM zFCj+lTNF71NEhxz-~}qzGIkL>_FruDfcOWFU-ZFO76Y2?If58-uF~QMLkq-*bZ5ir z(QIGUn{*-Yy+0M3{j1;h>OZXd{u~LrS$#0({Q-5zcmO#0fB#&zLpu3_zePZsrn#Se zV7+Ir$_@32A_FGjp?Fd?*8-qGBJJQby$%}urU~FM;`c_Kf?LsR5I8m7vB@Sb&oonwT?wda3%q9Lx*VfiR?R;U zUniJ-j+t3i(e|Qe$t`{cFMb~RBg8&l2v56jPvI&cu%CPY>{b3n$KCU&TLJ8ysLlSIY z|Je866!gVA#x};LWU9m@#(y-gpRc&QradaM);lb)x~cne{H!Q^9#o5iIC{?oI?rFE zggwNZ#(M$3QZUjRLV72I3uY=*wRfAZ^d>ZBj-7F!`*f_FZ$BSRUAamhP&8gnDl}M> ztKTV1xPkYo_R85I#SNRfG=v{~vAHPvU;$P;&$3bo#suN-r5GsVRwE$7IkB5>Aa8E< ze81Ro*&Hu#{$bd7&l|b7+%w*^Zv`35w13g^7ksTQ3lUN+cVdpl`{uj+vh~+2mtb|_ zWy+DZIwP=jt5?5v+UI>Jf*Mq%OH<5~oRxA%nn^S$Y?V+$hlSmu{Olj8xq zLXAppps-~*z(`l8vy0R9Vc;htchTHs*2d|PAaHIryOpeA5H|G=KcaF&>n+=; zkBrMqVu_Ti^tXbxxOSdkKun(0%hQBMrH#qky#LYjK}-voGf3CArb6)OIni-N+WCqEq~4Dd7i7Ln`VhBtv@I%R_;Pz4`8w#_g{?`_+&xe z@Bgl^SZ*}U`EgT{beSYE%MT=~J?HIMOnz6&GnRUE+ZSQ-oBuL;gIYqIU;TH+u1Y#Co>aBrK&1h* zBM}gd80P`1Yl>-m*cOCqu7p>jjPlzq2rR zf9+1x{Ut7sCNVwDcfqSV?OTR}co+*KvQ3D{1u@BVNzy{rAA7I82vpgqy)5UAV6Js? z)f&_O_~Opn^J!bFZp8j(E%@Y4W}?68VY{F~{G1bk-1}S9xd27CeO^wAlM@a%xri@4 z*ek7^Eclb{3SZ0~|2uTQ=g}Q;w77OL{8ecw7(rlYbM;fe7!M zvSsXi(k;x@@e0%YGQc>m=#|Q>9P~l>Il8sWOF6#EYT=>6cJi#c3v(|dzG}F&7R64#1ULw zku{oa04KEil5n73?Y{f`&uppqIhzCVf6i@*bBq)doQWQkGAl*QM3W^XqgcgcOI|xWKhK_V8 z2{n|2Bm##H(utH1klvC|1BAev@4fGx`Tcp1_n*&9W>RK$)?Vvb&-3iH%fJ&&V++a5 zAuG#)Xjky&om`uO{bgBW^5*^ndBH4?fJg1r=&r?0?>d{n?sE<_-FX6$>um0^xRc}! zZt#9pCxfux<0^c0WP8WvfIiXTY~(%IPTwW1GO*N{sNJ= z607Xxj3;%V9cIQbULp|os zddh0fXn*tpqiXlp|EWvUpDNRtLL#PW0||{})#j%Xzp#N5^tb1xr_bFQ?Hc%EGpHBQ zDUO1gaG^7{tjRt@a$y=$A2bhNM#UE*0T%dbVhvJ%Z zqARW#Fjr6{HM)gL5D7?cJF~(oztS*3E%YXQJxhl^kvUuK?+{X=Ta`6H)^RVh5Sy18 z&Jg6~YRnKk<6D%Ce;5bmrlG;tEz8uu@GYrau?SHLyT(0f|N58)}gLPk8ME_W>_AD>)zVxwyCly|rgB zp|>9i3JPx4thiq9QpxkGY$$x{tJ9k;HE76UP$LyA1dBSGO!IkVq2^6WBKcTCUpsY> zC273X8Feg$FTdPk{(S8yf{*qx&{gc1=_yqEgx7E?E0Zzt(U+_@Uf|RIY{9NLvroD) zFfPR3kF!Zof9KRu0nI_;idsx zQJQC#vhWa-mM)(4dQjdx|9S>^iMc%*+3@i3z@w%8?Kg|tIUkDTBBZ=*5?J0?dzE)=g{&7Bw@-`YmqgPS5t*0p`#vf)!k#*pj)u?_CNAN z9vrQbVCmLo8B`{E2er%)CuN-CJ}Y##Pn6@ymGHkB&MtIc``~%@%EQnPhS8sz(?dl+ z$@ND2W^P`AM+-;%^<^mJuJ1{H+0A25=46GV#2iHvI8Gw8wNqKM+?K7(ETF@aj6J6L zFa_m>Ns{2;YPZ)I9)qo+iC_k(Cz#AU&c<=}@iErp;W2jV-q{AZR9VfcL5T$Yr{M3| z_JaA|Z0~%6;$(Q$_1YD`xC5D>P}=2cfUYl4od`%=dv}MkpsT_`A$mnv#b%-i88HS* z#!Xsszt>Cgd-+*x;0E_ENH{Csuc6ufGoBHlNmvIXE6GL(4fo6Y?=W(bL@7cvz$7i~ zw@|)uKt>ozyjptmeTxSuYf_h(U-f0gqL|&r-+RgHMzxBY)spH=uZ5CG*|QO|Gqo1r zYWwriT>&TS3hA7fosZ)SETfI9=LJ7vrr^sV=4I7?FB_C`ul^o&3Q;}W_Opb`t;kg#5; z)&qm5acE886YJhCXv@5L(aEg)Iz`&T5{a$EwkdtpPjIrdUdiXClj`g$5fi&9bRrwb?Q zNhJ>dOfkr+7xe6+*J+HWEf! z3*T;gGm*oFJK_fv;F7!9CR(7Xk88uK6Cbb@ev*!Le6E%VnX3#l{a9911h_v$oX@`; z;9~-69$S)5B3i1YNS|39Q*@nF-Xn9AU;Fp*{NcyAxLbMHR7Rm|$wttC6C%c|@Lss1 zPP8Fw?g@IhbLw)#Nb&4OSzaCpk}s2(NFIB8|8HrLG!ZZO=ndo#ik`f;L3$Sg0=4#w z4qePQZyHIh9GSv)&+82D+%3KL8kBTfU$GnXmo}VUUNQU>8Y@v;>>0Aw&N)4&gu9PQ z2D{Ao`M7o|h~(aml`_aLoSC^7@p*LabgQz-@|_HsKy3ZnjCB>sT?ksGhK0_Ityx+Bd$7;bsNB^&wP=Bo!hYg+g7$$+J9u%kWjla}v%=nRnu8z@M$FgquP~mX5Bggt#DEN`U)p?AS|+y zjB|Z`C6CM~zt`*EywW!an>4Wy+ynZ79{9Q7EQ)^n+YJ#xH-<^f91aq?6Km?C5PBSi zzU)R_lO6NtcdHFtGPY`uj*Xa-Uj^UCm$a5i@M{t!4}abVN1MAK;%*L4Y`auW=B&Oi z(X-H7LpV~dFV)v{Zsrv1@2i{1-tI!D1<0)1H5oeHy6}k!3LNb@p5hc7zoj9R`f;d~ z&-wi6sAWupMUd5pD-c5$Va zU(w;3`gnf1pW=Jr$QE%GWQem$VYV}py-XyR4Z1Y=t@dVuBdJVB3Lh2$rPiCc_1Yvp--EruFfuj(6OQ05NA6qOs>PiHPgq>XX&LlSMMLCS?bA< zP)QCEUU83tpH9)&A>B=kmrzr|Kse^=R3+~!8Vx`Er01M zpNM>yOXPZT9dz3HQZ{@RSA5wa|6@JZj7rfN8HO?3T7B02d%zp|ueAtQ+ACksjJ1W5 z&Axe}FVm$qAoh{fnKf+jdbX*ng#tGUw$C0?qsfcss~b5p2YMUmJS?9wqD$LIeDWmb zg!pM{F#(bdtcbQrhQCwmqw9u?Kr%Glhw@SOMo%lL;7Em0!=P$j(_;3)1}1O~7<6K+Z`hK(qbT2IcFMT)b-oEVITr4@7ptzL@v;dFQt=5?Xd}e05f6*^uEg}fn zJ>esfWqoF?Rt`b6T!ixgBF{E(S|!o^f=fet23*YlRRDKA1nz^J5`Md{D=;BHHEG3D z2Q%JQ=_fi@qdEPKUX>HBc*|T4zGd(9Vq?(}8FnK3qyh_x$RS5@s7m6Mn(kZ+#5<|Ar4$8h3th-Hb70R`URJlH0dWHHhLVqV zL_@E>eVYNkWj3CV-hcD>iTdi;r^u`%L5?BKVhk+Mf#}G|wCe>FNnXah24Q_vW^ z=@ezwMH-fQz-5d8o$7+f`#3|dWsh;V#7m5W3gI=nP3tIsynOww82{NE>+?_dM0sGd zmYrLOyK_7lj!E0NZI5Uq-eTD7MBp(Pe)pvzv%kSsyKZi*2cuy39Lc#)3Jnn7?%mJBR!P9BkX#4 zY%*|A$nk@+%eKq<_f9Dvg5yz~vLGt1OvKL`SLWjH<0tfE&Ec5pkl^vW;TYfB-(-l| zaPKlp)Ch`gN59O}4N;Eent)+JD^XfGYSJ>?c5~t(4KYhe=B*r@f&oPH(8HQr@ZV4a z4E5``*WQX-U4}BukX1+4MwS)n#DUO$FA*YsvLkY4I^?0@5$&|Q+-jpHHda^+rudyz zw$ZQtK_a%`QO4x88))l>^HFi?e#MPWBVN2CnxTn*i|BS9@jMo$A*a4N{8?p1o`3jD zo#wcdIQ78chFT&GBiu;<9Hag;b;EkqT+xG|`7s<*Djhx+<{#touGgF2;}d^qBdJPx zGbfO=ieK>{E4@AF=h>{Z0e<=EHdWIJTXP;UK5avl7U52b+;8v*Nv%_nYTP!Goyl%c z6J_(UDVbi#&w+XW*d>j}A`*CL^)WhIo%m{iXqI&CW$(B=U_$+?h#pzXw)J{0NHIjd~1tmdF@Q=9_JcZb7?bbTvD6dWB#`l{I4 zH?TKQi;axv>zeruLC4;ol0m|M)XTj6rNTQ8+4kXXfRto=2bZ6Bq|c@}7g&M0;?1QR z3$c0d;$6<|i(a+{Mnex_myCa}njd!G?*=^aSsN+G))?o5s1$S4jU>6s*1R$SGAXOz z&Nqxr>+D=@2j`Pt(uk87u$X6EcR)31e@9$Mcg1f!wA%=koqf&G!Qr;S>br$g|GGA^ z3gn~|`w8ch_^!v=@U^yT(Fu1n!N8l9+nI5xL zlae~Epe4ooqav(~(13g7Jv^C@X{fSf6y>_%Q}#?!kq*LTpA1Tsr*&- zzW+M%SeaG8%)npdf5|%hS6@d%2|j$UK^ulf1q_so0xDLOir8Jbx*w|!(DsEZmOQjU z`_2_#klt)=yde;IFPUosLwW+;pk%8r&^H9khr_lzc zgMz6LVIT0h)k-*JZ5e}|*#$b^C>lT^;gZ|hPxB|LnH6_M(gFAAdqOWV`U1j zH2ysrJr)wGKlP2b(Y2=#CXqI_z$0;BA~B8-;o&JnNH)g(G)J79;1^af-nQna^7Hpz zQX|>MSlIFm%%NE}ts?7F;M?TRi_+OWthP;cbHOli&sjo|WvCe)i>j`#!mZFe0+lLW4H>ico4L*gmIWkK zcb@M+aLs{4ZGh+YB&J~!MXz^Li?elldX{ty494f0cpI-Zc7B75V^|gL)nI{vM)ZYA z@z=f&{%sfYUy=68CnWR%N7-q4d3k`eu&(38KK@jYRS}T#KxO9R_?$T%I%wo0I!*a# z`l46&RRb7!`-F&vE>XL#tEI)A<>PMuwDuuZ*dXP_kGkj<2%rzM1Qh11zz!Y<``cwl9cnw_KIG)2n7T==GkMv<- zhlx@BlAHdvDpHSLeAmj)oNm!JRBv9d9DSN2Ds#>bi4MQZQ~CPZgg{t`F!mJm!e546 zCOAnI2frbM*LElFA7eFQ8h(n`fYt94(xPSlXjQ%$PrW+x9~6nYBiS0M>gW4Hot9`r zlw9WT_a5$ie=~Tb)n}5L7rZE_J4U7~XlD@IsIXC% zb+vt`fRWGM@Y8PvS=+ih2kZL-n*75L*ptT|9Z|xzXT~doR$f0Ko0x#E&V5$iXg4ta z9Z+IdpWj5s*M=%`lqmr^os&AWo96)UDcxefRIY5G9uGCt22?L&;mb>z9Fw?%ZzVaX z!2A^zK_D?(DZB=56>y~%z7Rp5%j24scPp#d(v~dMbF-%0gbYb;`B&(pp7>4a zby6p=L7$*Q8Jh>DiNrrXcy6&yitV!36CiItGgg^&R!V`Z9Vd3;%{_^_G|Hip`p$5{ zm4LWej1eGqtK`j~yoB8u-bRa?=fdY(TPIsF7?7;1eTBRwv`%d%|0xI*A2c0)kfV7@ z9Quc4EBeR4t<;U*O~HPmaNP{m{ghzl${Y%EcrdQ7)izr+0xtL5O75HqRpFrCIq0)< zZo&f^HxT)`&(+D!iT4oZ*QbE-puyG4Tt1C7=_FM=s?R%`LVCCVYc5?$PlqO+pI=_4aUPcoOnFhX%C=(XL$ zOplAIkORDnt>>i~orja>XFgFc=OX0WFOzuX7bz~KNEFhmRDe7qOP#~eC|}A}5D=#( zMEK|v#XDh7lBGEse}21YH-|jscjB?}zEX)iPSzuLy8*nkR&Dk=I0plWm!(d-w_O#K z23BiF{8?w$DC)M7E46@2XN~&4y@GSq*&I7p29mUOnHYblPRlVdv#9FYpEltqPg#}63TuVzF!DE0QR^OVEWiQ_y=1$gI76f-+Z7O>?iUq52tnLU$ntvP0f}x7 z@eq87czOSC;l2IMjyzfSTOocHPrywJm%V)0yozX)u8C(-IKDZ9FKa$X^9;isZ$xqL z0+&G!L9e(00;ONGtup2YTXDAw)wiPgGi#OX>m9MM)4Yu<@4AqyT$ck72FGbYhetiTP9!h&9M;GT*4|r!0dv8}HwM-O*^_!N@R)_S z^HolJyIKSvouULA+;#20PIr9l=YRQ6vYRj8sfmL{&rL_A;NZZy8_!*fY<&OuOY0z5 zK54S{t(KvG>%2immX41z;W1B?A#i`c&&Tf0wO!rvik%h57_rV0C2^+8{bcT*c=?-} z*{uZeN(%e$%OWzt*4M!w*MZz%Su&6lZ_2Ccs@^Nd?|^s(TT)U81(y;3L9RNU1v9Gc z{KbgxW4#SOeb;)T=vGGmdaU8L_IFTmJuF34Fn}($nE4A$dJoyGBv+Y?#aQXxJ}m46r9K|rDx>$+4^9Blqmb=fiPO!Fd=tlRSVTiM*CdRH_wW)dt4b;DjRIS}w zJ$1ArH)19f2Lr(f0l{w#&ZDnn1v_@;+l;ME2%j+hD9C^Ng{mpUx%OF`_?C+J$=qwm z2r$nlh?})xyVj{XNQqTF29t2N0g?0#V;+HEdlJggmfwltYLkCV1uC9{7rGNq@S78t z#GNQz%0L$P%EOu~?*RH9RNjjQaFDaSU;9c8lbNcch-GSK*o;AiHS6{ypGJS=24&>7 z!k~FG)!#Po7$|y2Gd~7H!5BPuU=d&&{7{+pffM;9XCq#Ff47{t6c+L&wbr;4%)egw z=F+gB<_kSiMDHi?!EW9U}9UGw}JceOa1B z9^d|2-DYo@1n-|<1CP)4TW@fJUPAf4OCxXZ29`-HmMSWAfbm8FX_3t|70yhm@ezM3y zfjK}*V*noVe*8h;@gLg9G9_vEl>cOPsp@PULN_Terxvv>Z&W>4*DJ0{K)>x}Wab*>!jh5Vx$j2gZ=BghHrj0C#<@crTyTRY&8McPxBFlS~SzYlae#64EdeQm1l-93J z`>5Vn>7&^8)QLfD9@WH^ZKEs$E2iFnfMXw-ey$|~6EPVvh5;-sJEhJtD;i6J?tMq` zr7ED>|MIXf{S(MLnZ|wu8HFGUjEk^aORaoARz~x5R4QkdelKUGCnYn7BhmI-J1Vwk zq&TNyQ%2K49^cq${vztMTr^T*7%A2pn>QqX4W;9WI45$csK}jEJ^X1^!x*QMb`Ol? z_$B`f96$5T@=TeY5JxK_$l3Xt>*_0;BKRk2P;gvKQYY1zZE|HL@o|H7iS4JkPHLhl zF&)eLMiyDJZCsK8cva?nyU!)Z_?maUI@i|+K1kIF#4RypIZ+%Zca!~Q__s%=Lrbq{ zZ6qsIsn*`PGj=PNp-y)BV!^f_`i%R>iJ-d0x|!>@x524jT>q#xP)|Nhz|Gl5A6-NR zzS(Kl;CwgIT|>?EZ*8N>4@XkI9Ab``?IsqyE`dwSzTF_HZVmposDwHXRZ8^uO3bK# z+LbRKX=rykn*(=a++7Su{Wh~Gnh6m?=bNI2_)^S+1=4gEA0qlF}KCF;mn1p1)I za2tkm#%uYST}O^T*4_(goB2C~;>=+PIXuVwxu5}b$J6U3HWr&es99y9Wem7?_QY5E z4lkav7xnl$Eo9Y^=Sw16GkfS|ELY8$Nx}!_5ykj z-s$jOY4T^fS>Whjg@Nu*0<2vI2f&-XRymA~xV%ij_Fe&GFAi{jzL<0F9=s=>t6H9e zJUV_~VHv;eJMKT{2|vE$lXdpsz2b_)we62ydbhoOD!<$(+opRh?$z-(Ea-g$Nj5I9 ztPnWsk=>WvjeL&duKbT`>PKefS`m*MI_$;00cO9^pBk$3kpWUt?p{(y$JvOTmr}6R z7wWUEk^<_FHN?o&vV0_x4cO-PFTkkTuKPfp$)wu{*_g4h%!vK{t0PZ^(ww_GH46A} zZ;DHfS2+y!J{M+RrA{jI?Hh6$9wb zWm^5&UBY{{C6(Bk48ikU<9dc?lkF-Un`ggb+MYA}s$sy-2Sc(&9XKmh483BZ?2+BB zdsRX1jZw!nggi}key8QqPKuDQwYOH+XEb8v1G!XWzii-6ACvR|lDo=`0~9T-rI#>^ zS~}!=kLK}ZB0jBxhX_mR3&o&X2;F_^`Y_|7r%}e?k0pCy>P>z@ozw&0-c4Xq(C>>+ zT+BEO+OP(p3n8#Oauu!&7K!Lu<$CG3+5-z#@>oML-Xj?+FSX`3}s#6=xdvsECBUMqNCQ&6f=T zOfz1vC`TQKlHw#4XM>~>h5JK0VXZKg*QdHploW&iAM)(`mhg?i>;KvW(r}YQY-_U4 zKk#T3k!j=Y9!%UhC3aldq2WY{;WHss=5+HRC4Tg1eR{pM;T%Kci~WQzy-6M&uFt@a z5Z%F)u>Rp+M^-*w2U{&g@~vBX#}0*bqV7^R-?C1I{|JOhqKmxLcz+%Vx_Z@tdr22G zr8`WEVOto-77Vkmqc+2P<2FH7I?_35({)ii?4g#5|77USE;DPl>$d!Gzq_$zpl;LV zI~{@TO-_fe^JH9|EH+{)e;Ff%rHIFfbk zlaQ-x@dw`uIm}tud!5rMqwkO@Ycy^Iq9L=cUex!opwsQQB}_wnhW@}7@*lwC3c<#t ztVhoE{v54ehj;O$;0NhccOL%b%z$LHpwlE_g^Vw8LEQC!^DqWaWdu3BBm2Z1MVBnB zJ&^rWyin-U3-z+Tmwl`OYhD_htQ#IX7p0{1>GwAJ9*$yZ^>7eiMcZ|uU)dDBJ7|@9 zArrcMBIvz+`c`+cMrTIYl-AOfo%J|k&GXbD^II1nCC=Mgxpy(flBL0>k$#8Tn%;sR ziO;!FdPaCtG)QBWKf*^~LVQ=4cTS8ZOgMQh%0~g*x{r^!%{sZyrDnaZa;6b+oQfJ~ zSQU(xMeKCk{NjaYX$+I5W@hj)I}c9?i{)>P*zb|3T$$sA->iJpwC(JyG5wKq&Db$h zk}4j6|LfoB?EldcAnZWr3Bn3xdlFpS5U1?<%F)r$LSbm6tS9{S%q#CjjVG_m17{D~ z!EG&OZDXl=;7dz>k!zYSNX|v35-%%CFSaB8J7-WBCcV$d!K2dhfk)w1`lhl*Vn=Cc|=K{$efwP)hdvW7Ml%l8J^G~o1QV~=h7d~Z18V<+t(uv zjOW@meC4WZ!@Z5`P5%wB9=*E=<{x*0v&$z*g!8}X)$@a%JHxp#1A8rIMn>9$cCD?X zCsFWeP>Bs?VZ>Ys`PC8e3d=DJsslAGW1RtuD8a6RMsFWn+PC`#OWoRl$*TIWti`X4 zxhBzeLH!{S&ez}qcflo*v{DB|wM?fy;vmEcS!`hEIL_6yv*Uf+Laj{s2JauBa;i#* zRLl~=fSs0WjHNt*B=tu$7aGbH)NZDoX9aVW0ba(QtEW!LjR-s6}x%%Gd%N4NizRBq1RwQiS|Hz|P z@M5CGcKhc-hQ%T6RP4>*nZy1~{*NN!8-+H9m9#^`K^NZIFpg;Ss7U57fl~=$eK;f4 zOjj`v3M!tA^vXY&NPw5tAFhsFkUuHI@Nkkp#!|tc(IpLCE(d}+NRBa51=m`rQ3)=x zH3_23J&pj%kc_ObvI*KQyiKp{-?`CRoLt-rU2)}SpH&v$Jst7!n$9wvEBsZvSjmZ6 zLS@N9Mcd~@9-2#%=AV!nG+}}G4^Zz$oKWhi6z{;M{n@FAQ!@37y|E7ClG7`J?;N^p zg};irZnT;f-*rgtP%s3b^g5=6;e(Np4UJcMC%VK3vta8je7b--wC)*+VF_&9!BmXk zTbz}|m1l^~<=CPxB~32+qHMcp)0VLz%{Gc!Z}K{a$e!c!&4Hj6zJHp_!C^# z@b%MAckj7NGe(DQa3AR2jJfB4Nbu%V&+B&!OY8Y`r0${h@@F;C7ptToEp=K&pSFvc6$6hKXrtIQ3hWHutK*8&jcFu$3U9 z@2!`0_ZB8_M$UzfGZ_Anw6nlaI7o-Lv?DfOU-5S~&kUGbgNE zz7|U!PeiNOy8tWf@L_G^ZK<=wE?pcUV2TocG~K`#Od2~kU>h6Fz}t7fb{E)9>A`-r zgfYNvZNxPTDYk7!X25ib%1RJ@1|GNgh|ShHHZc@m(?2G(BlWjU&|gn9*6k-mG)=to zjUVauTG&RIGijTxt6*NdbwNOBc%PvEYxAJk=Q^bXvCA3!x+09=x8FkOyXUIvW3XZ4 zXbkLPs*xmK?{AWJi?=}o#7!ms=;FQ#*@ntE+#IRu)!nAg4G@MdGxAOYB^idD_Tgd6 zHVN_#0M6gFj08kUmaKTGgG2v!T+pw7>2~^$PVn$MC-Aw_9R8xH$$Lk{KQ7RKg9sq2 zQ|{g`>3W7rczCd%rux9+pmj(1OXpH;PnL)?sAkcfaQ7F!tVAI{5}==d*vI^Jyp}B0 z`;B|KQ7m~@mO=r$Gh>X*b9lZ3EQ|Fd#793bZKt2ifYM(UzWGH z0`~&md0w-LCvZk}Mnbcd>qG{#z#`Izjas2kbJ6uD&_5G_WS*zhKF8l zH;TGu{C=+_;g?cIMm&N|HfM(eIZX(G3p@4U`sAf`KWBx4bNmqmv*Ny9r^=lPmEsb; z4Q0jpfW{=DM1^)r>|FEl!T-OhOMZ#YyZ$Rv?rPRy-_6w*S&~)<=)K9@UeX&D7l@nm z+S?=v>TO13v;t{!RjcP}yR%%ETa|7HhE27F^i#3}RISWbpt}4jRG7Lz3LkY{HT>PQ z{3lfm9Bhhd+-FJ8;nw$2GO?`PClZzcy%)b& zIs8c!K7M7*2B}ivPj!*v^IfY2Ep$>2Ih&C^^vTU1%N_OAr#@KRGfH`ZT z&hx_yOSi)R5$Z|eJ6tTZPlpX#NVcuggU*WwCF=@E9$zd(-$Z4|FLVkKlpT$!yL{47 z8nhKm&Z*fgwwKN57ekgAy0Mt?_H2d9uF3Zy9~T7pGl|YBu2|Ow7hC6RC>({I;xWZe zdA+Dkd3{kJAM!Yd0vri0shHf{(AuxACLq+5152iLqFQC(n*{jI?c0|Ly8B?n7!8#8 znX1Rt7=NW}X%|r0_D42P#(5g>v-L&3edc_l)NiK3IBJ4Fa5}boy?MB$%F6rH4|@Zx zwh9xqK+4fJ{2n{a#c_#GEqG&#K^W_wURW-azFMEfHBHD8QUp+63URL4TMN+%mATU! zdz%YdNA?|o3Yz_pwadkEy}14z2LA`wEBIUSXhYREBk5hO0ohYl#vwLR!7Jt`B@7aO z1VNV;djbt%t9vCg2)40h{@%FESY2AKrsQXZ?QP!sLYsvF6_#dlMFr*qOUIujt^oT~ zc)Fa=r#@C<8G_D-(mh5L##Lr`wH^0TNPT>PbR2Yv6j zNvjr}#@QfJAIIM&(xU=UB<}+OFlB(w%U@2=Luj=KGtOiVD(40;e73e58jcA8B(B zP9GQigi!mL!!@PRyVc$$V5LG1#-m1T5anj0Ya|j#Murg^F##PfJ4)6?Y{dTSjL7O; zb2%NK)3Rixeorcm)(2wl*^FPI>sJqp!aOC1h2zvJTgbVr`+8lx#%mTUU^6`P{;1sC zXX>-A%8vrJIgi#?g(%kXF5EnT8N5Gab2!oFux1_}NxdC1=c?O6=ZsT^+P+@V1MI2> zJon}aNil6dojG|ki&*PzSjO&*74Sj(9vk-z^~GIlkFnTILA65@tYZQ! z;Ynecp|^86k{tA$E~TJOgI{J{(4gN3i7ESlk19<-+^OEhy5x)e(1kR|R2-Twb!xvl zghqAx+?-vD=%a5M>;+g)lR*Cn{sEXjdFA1M(0sjS!6555KwYqT?W)Iga{I_e-$t5b zTWtmg>OQw#$KcmSNYdt(*IEyTOGCKB+uPEp=q`X_r8s;UkYSh_Vn#kPYz<%>l3MkW z4~%V53CH$ov;5t=Zra!|+GO7Ddo%NIM=tmXNu3D)kyh=iN!FkPcH4Lb!5cnWW?WmY z3h!FA>l)hhRoBu^J+o08arYQ0q~7n+W%({#g}-FI7UKw}ANQGrbu19P5==$unY#HS z2ieLY=0)@*Goe7W(KMmUsh7_4tQDDd{vx^bxdIwy$F)FSOD-9dS9Te&%-lk;DRoMV zeqBX!J5xW0LOAJkb`S50MrR8~NZfK<5!b(Wu~JdZA$l+1p{0s=|FG4q(+?iVhZ7hi zYJ{DVl4T6s*Bfr+Xt;s?m)G#AKTB#%r+MHj0 zCC2>k;GBbmZok=%pq~9|MaSVmz25QBz0U294NGU)@Ufk?3(Tn}ws@$wCY?s9-hZ`3 zYgF~#Co-oGA~ursv$H{xBV8W)UYpD~Rpl>~bRkV*kfzf9;3*2}E;`6W02Y?UxIKg%W9k0l7`etVDA2^9l z;RPQ({{yQe&HJQpWbo{nD$2UZ3a-Y!7~~s}L(gE1fKW&=i$)1w%968B_gNFv`b@_w zlpieV{XTn8z27~s&OQOldP}d`NwT+b7S>Tg;+CvQPTa|`b14?;3&4g)QX(B{*xm;F z+{He%I{`GXOx0k$*G`S@V`j|-NSSt5GIK1bQhfjKBW=gsd^U^7U}jYzbLKe6VyJ+K zDE_@*{~Xc5hS9ikJolw(8`#Ah^S6~S zPYK!zG_3Zn+RAVr{0Osw04(fm=ud+qw@45DS9kQ8OAMZgqtZu8L2mB1zuEW&E)xxp zYHB9#Rn@yjA?x=AR1U05h94jP#o}>vOEhL*>ca!7Mg5+AWLzH0>MM9l8I_O_eN9*E z5LuUa@-@ypnAm$tW>Mt9lijFGvONFZ9U4-rKc!@=MrKf6P@7l!dzSbB(&ga>Eh%9YQbW=HT1J;J;h@EFwK$W7Op9H z3w1c-C%oBMqadGUoeuxBx_$*xlX7&08f>7x!CVjdhazI-)fL(tnd^P%_i`bh|AURm z^3Rmzd5xWuOv4fp%Y8vX>%g7wda+@o8@vr&_Jsit5aZk@rl6`U=bSl-;a*N3OxOGq zPhPMB8+Yu2-~=|izelJ*B)a9T~<}=LizY8IQ_8KK0Uzu zce~o4Xwcw*S+J6GPcivGnXuEp@s_hFnNTx4CN;={@FFcT=U5J3>qoGkW-!xa8Jn#F zA$6K-YCQMsLD-4N`!0_>bIP(lF<$JpYNaYI?AY#caaO|twnZK(IgSmaeRgnI zw?TWi3Kg%aD(`Xlc*CY&eI(vJ{qG}_^@(3HY(?FawNE)3B33(Xdepjwgbviw zceq}F>os%tUala-#F@M7{EViPoziZdSRt<}Q}%D^KJ7A&Yx4|T{`EUw62eBVcA9P9ekNrzSD|FM2Fd!s-l6MU^;e zC8zKy#vaK%gJ(JrSW-ZeanVNpgDY6V_o1i^W+dDvZYUUS-EWG1hm1m7pfab@Mz(T!z`gB6>ahiXQ>@in;M1>qa z@GPibieAS4Ws>OS=d~k znF;$5mn-(aw0+tf`qO*DzfH8XFVP1J4;1cWA$#*x zXSNQGgg2R+CH+~wgw3DT9Fw8JtWb2eW^{ute-MF5honpz6KHZGDjVsaKYuRB{PZL^ z(0Eu-@(kZEm*0zW7h03v^6;*`*lP6{TmX&-ztz&J^gu3I53a%lC$@mfR7>aWn}CLg z6d4ZbB=bAbm7asn}b%{&D7P> zuB?mDWe`+beAj2Vx8=gb793mR~z4;!d?Bhe3p;uwruO4TZ=cV7;=4JZg-R8{`)NdD%oVT!d0GhKKV*Ww)W{Gfk1ySgh)Us$CFwV%(z#!nJB^0}+3wsbp?4M*3x1-HMOieDI>J zec)c2E$4z>ZYTN0m)$~5!U1vlr-0|oVO|zR(Sd>{{?j&t*0RJt`6+!XIM0vjvVWrM zkCLG){DbK^f;^nZv2)YMYc<_*&Bq&WR-4w|V3qToLN_ek_3xdBT5zziaX)d0__U-~ zZF`YmAiP~v_$(_rPF$J%KIZB#`*LhRBU<)w(X_bC>mm!hmW_0wo6UaD`0<%Ca4=zC zZx4Wq)k2y%A#h1iklB2Rp;Fs$%PrJ2EKaHcF~5{xzx&QOGy9?cWN@cun<+WT-;aLy zqg%zHRq%}B(rR#mAg4F>nKTvVv^RV_15!q2rlwEKbY8C43Zfr|GX6e$(8y$LZvFe5 z=o~WCj_pS1%1_a#kghJl8$k|&hpviuG#kN zHE=rE&BfEFDzlzXR_u6Oy;tSONF>xviTo4}-bz#33?)0&X@YJi?0Tl}5yU*y$N zHJ}?6!pl<7+m)I8#z(Em*S4`a-&L}7aThGYMCx0U^IZKMA2(cuZmy)2;Z@E2r8tXi`T@%tiiQ6B03OJl;@+#)A^?VyOOY6DfctokRPK4EnB zo)$|BGLEZ8*Ox!%I=>;N81HiUt#$Is1{(*dV|ixG(UoZ`=$T4*&!ok2DvGum#kUrh zLT(!FA4@(;k{jPftw|n%qi75W;WJepue7N;{@rZCxmY!;oyLx03Ya}oFYCCldiocB zJcps>U55KPrqo=)XmG3!^MGj0$h0rR!U3W!;$!^xiGs=pqp(7!nAoYSblp5kQcK+( z*E$J=t7d5br)c57|8HuQ`;Y!KT%UWF@^eGVVvOewpx5ENAmhP?Z2FjV2Oy+5S1=-n2x_N|ZEj-51)s;L z50D>3(o1B;BZZyTF;XgzaEzi^LXGKOsJochn&+$5`c*Pp<&nat7+CFMhTL4s8=azM z4160nt!dor;Chc*(0#rJGwy8-EvF!XiGw#YR)mNp+FYMuV2EE^RtY*M14 zAuwn*h!`LD&7Ym!w1aBX9mXR!<_l7?QZS50=}xjI{PM)ugrfC`Nb0&8%1OzXnA>(i z>H|f6P{2Xuv)9ZfOJ2pD2{{n*nWV|?{@`(3$J$ZG34kHLBgja;v?`mI9Q*cXy8joo z>ZIb)Q@`lfl27xw#+&=5c&zukivl@j{--I{eD&M9&kTW5UVGzfnr?7|yeo5W` z-aG%{U!e-8Z1~QiDSylo$AGm`bzWgU2fP4i$LhIyV9XL))tbU$#Sa+Q2!cmsuk}4& zb9xLWkC@kLe7;%2n{@qaxEjOAwWDzZ6x`bz2Y0Y)-^rBvM*Lu!8**F@k^gME&7B|M zF~Oqo(@Y|3y(}S8RSTQb1{|TCokmMOXnR>;3-FQsMvZMQILoLVtR@`3KTrIP! zqkYJVGseX#&*3BuY56AGI$a$7qb~~^)NeB@K0us%JHofnmknxaSQFiGO5ahqtd5vp z17D^iMS})4_A^u`fXpa(^70n6Xn-8#?UA9dgy*uIwU_ zP!f&3BPL63W{zbQ`MZ!xTjz~s8hkIa`K0JnOKdRM@X}V3Jn2t&)5hVGc6hH80rlJ^ zTtSB4zI5!f^`t)$Heo;zu|R!mhp<_3Q@+m1J^~#r+1`fYFWf!t8h+unf^;h2DRqX+ zgj&`H&8*+k?CDXZs~;m@IL&uxXu+t^vBEDv=lN^ZlE*FNdiOrBl`JhPLWaj{W?7KA z?R5+|JX52reEJscgIb$G#h$%c(L?-~Hv6`gJy-7@ERs{uB#+vt#;!V%X3#fMs)yY% z^nuXlOL7Zts?J24XoyA;)z(!$>k;L}{zX(z!X{}Y5zbXp`;9lJ_$R@AgNI*+D>BGm zCY9QPOPLRkIN=KAZk4Ni@bS7BqEl3kNh!g~MABOJJDMoTDkC~$2PM(baUt%+6k&W$ zNPK@iG=3y))oTGr%lR0eK}~&!{duH*a)rgjr(TuqmpC=BkIy#b{QWq3W%%rvnimM@ zUhiYaq{Awr6Y?VV@POuJ^yi9E{|Pb_v5p_F@vC*d!8r2D`FgOx!q+kk7e!g=|XapJS{7mh~~FyS-P$I5bDxrV9^e6MBG@G5%49dAk&4P zU6pBxbkc+6rRtw`vPg#k>`m0@XM8Yr`@3LB)sllBVwV=aI+c*YX1Mhw-?)%4YLN2aA_w(oc^ry}!MCx`&5V%ere>o-cMi?!B z*6=&X)v?vkxnh4z$^H(~-&SZaBwQldKNpqGKOXO;*qan6C~|Dy<+6yzZE(zC=V--9 z^H@hvF{;2Md}(imy${Q>}#N%=@CqCO}J{AQr(=i6iM2n4X0D3QA_+L&Ub6V z1WeJm6M#DKl;Rg!+LBkH=>ARlkLF(GCX)HikngXjPMv{~2Of=laA5VlY2SmjG!*Z0yb9Ddgp-!T!-gW*{y^PFWr+hmu zS5XtDrxh@$-%tx|d(=3zZb;0^O8K>)h4R!?NxHJnO^4kj)d>Rpv&KqS1GH*jW1Kfa zESo{3gSKgs(KaP}!Hmd!<96c$cu7*+(#{C0Zo`p3es+Tyf=F7FhVQb2P-B?&XNTW7 z_w4EI35Fb}Em3hDiNZi&)^A%>db=_o*~2f(Z2KgPzDI3|9SB&dG`*?)E=L4O@9Ak|65=KZGb_`jh5dd&s?SY$hdcT>Jk z2F(nk9$rVp)_5$YfWQ&WL4%zl3}(YPM& zLoW3aja9W;r05{F==GPVdtD92)L;?SwR8)K3I6-;E1kFq%-YSRrRB(ZvYDd2S3I2> z$VDY0TP-{lkI<1{o=#_Ms|Tf4=vrGjHY~1T>mytK)aGl%^Ca7i5JMAfr`b%h)L(3C zAKOqSd5!qcFbr)uD}zy0X6H>Nqz$%X*Vaob_yG-L45ncfL|cm5&buhbXV<*o}0-^{4bXlrJAHLAGukoO6A`yog`E$s;}QT0Nyl zYZU@~vZ>Zo&^oF|{_bICKT8$A3|P#$D7e3^(T=sD^ENHsdz5_)qpmCSA0oN`;p?7K z6Mm5?n_2UrU~jQ|qmG}SA9Ftixb$8QMHvM*|4*Jo z!li%uIionDl8&T`$jG?dQfdGstaRvo6-nf9I)=6N8tub)tOIuUF5A(<7W#pGP%aPS zXGuq#1H#7RtfiK24+rIEd3iSk=yoKI01Zk37UZUI<3?Foy|y^}h|WS3VYK)0SYCPn z>Af|f9uC%*vqc(Zx2+pAjF2%3+=1cKs}+5|G8S&c7kBotP|Eidg$FOKlb7J&%LTwI z4-=2jlk`8Wo2Bf-iTLLVr&);j-8@O^f(0R@Tb4>YgYynSQ#7-MaA%Yo?2lo{z z8W8P=FTI_dKBq-|K9R7d7Q7)Q%<(`5)fQYi52C9aPia28kFiRAfnHI{h1YwhlDgF} z4n$8FuEJ(oR!df@MMY&ZEgKG9y1m(U``sjUf}PbPMn@9mL{%?35P>Mu|ICr>3;$PHL9NOTi2{3tWxPn zC#%6)m_loZklgFn+iw(WyO$gS0A~9US~_R3BHF0O70yPlB457=tvA_>a#ZOzgPEQ@1gf@m|{9) zj+o4dyXK`FetF!pa6QfH0atUk6iV#CS8%VFzITNbU=XKIOEL4hxmz&vl$ zczQ?enikEMg9T+0m$d*Z!S*f{?>UY(XebQ@2^m8|_A>>{;*~hb%DE>qBBI_0fLPZK z-8Ec!A$uzDl5Ak6Iv8dJqd>jAL$JyP(`mi(+>?CqZ`KgDo@XNZS7AO%M==h*Tx&rE z!Mv>>=Kj>3a9D6)Esj6_|B)5ryO<8e*b8!8)yd zjI%tPQ(9xP!8E1^uQWg-lcx^b;Zkn3P+%R$#rG}qiuW>ubpwd8`xERsi)erIX(P|M`_0Q*;Z&jXy~-sm$C-`xAA;c z{nnUDL$J5T6IQV$e5qBHnN?p#C_ZVu*1>T_Eg@xCV?9-+MKQMCUUxTj%HM4iR=rmRs$ERU51hKL5EB;JY7G zk$X+S#trZ^!Da`cA`oe)?_$&UkAA#$5$#p}1Q@5gfF!4d^$0FzJ>@mXFjJo^?H%@O z=0@G*V)ku#v`Z1SV391u<8M})WtG@uSuUI*arG>3=TxIOD!yCB?1&z}@3gXzHvAh8 z*1L1&+_x-f?IwatHwZ1V<)zCWp%V8j(vb)#nn|qg+o^vq>#1>n@Q;3%&vDdksg|z=uWg4o9Lqalhorl|7b{sDQL* zD!R5(yC!k8_JOk(t-^Lsa7{TX=*A&^B3pBN7&nI0iurh_x)pHMApO4hy#5jXe7%aG zX<8%e)CPSf9DXLuwh#LSUt`@iUCElS3RG1b`<9ch*9a5+ns2rOXar_JlpD0gzp?1{ zJVJ8l;>-GHhuS%l|G^>!<)$40>>~j1rz2P-a%BX0Or)_2E?#$NuNMEkf0W&x%baqu zmh|mv%~-rz?81EUSDI200!>N+JRvmv^!S-(?NID2HI%#R(631?U$13O<57 zGn#!`l4}=bH2;W&VtEH%05Q+nSZ2h-q37}x%4PzR@S4gr(aWmwqZsx zl_$(DiSzf?PyJ!To^AYkB&zG-OA%7nM*epDVGG)?MvHXOz4|53`5yg?Z(}>@+o#pq zd{oTD=CuUSzL20ihX(iM_F1kce^V+hcGKRxY{#aI8nTzJ&v3NtIPFsZ%LntH4h?Yu+K7=w`mE*Pf&2YYLmSd9Sw~T8Jw$Fm8 znr-h8nQ4KW;0I^32_1Ll7}4VV1)lj%=deI8T9JP+ z;A8Mpm|aa)?!?Wv{eaR5M}9m}3}1S_z$0$umiT_>TDS`@)P=Vn)O-D_JA1DsH-^~C z#vaVa+&eAoG_3XC@!^}B1-e$ZAI$%5qL*i8v14jZ(S?yB7~xL>8JA8tqlhezxz1{7 z+e)!$5rkh}-PS$g_;|%$=j@(UV)FcJ){`97(aaBCHAFj0fe)>O-WKN=W~5dCqQ-MR z+&Icb+s%7_aST+87Ig;%QkO28Bj;OVw!bd|BPs+}HnAIzN0tFTRTB}nH6q^V1K5Ey zT0Y72$KW-RbwWG)P+S;QwnL({epsn&_inD$k~e*~rzlmKtuA?BLn$MyanISxi7OTw zm6R<0eD~+LQ1XKF{)`NM{?QFLLPqSFRCPD0n`>93Jz;zFMsmLH!= zIR7GcxweSb*zGyLJ+n-?M~G`buI{=KVNX|A^CHx)u%msl8%V`9BTB-Qy{rtG`To+8 z(y};|4_b}d(rq}4@39peyD_`~rL0|3qH=j*FG+vedg5qRbLq|?!Fs36iCuj6Aj;rq@9{EJ3adxjkzKJ zmfsGCG0n=pxm=8-v;@3KGuE?6A70l385<>vtjN_=2eVC4g z3av5Gs$zG&!Z4$_9!4mx54S9)om%icp0zC2yf19j!!9o%r|gEf*6sAvX#y|XT^3#P zg&s;Cr9|^aWZx_Cxn-_Cbe30Z>K6AuocnI%nXu=FTRADqqm~F&@<+9IJ~FWy+K!OE zQJ=p21Q=rX>pcW^;*&HNif%*6%k8 zO?ulm-ObvIohCWSu*rog>aUz-!nHy=$ycAO!BY2qfUnINj=_Iyk4iKubT!>S+^{$n z9~^72rCL=&oYY%Y1BkxHJyu4=5Ku^-hc~?Jl3tV5ha8ivlL%)`5yt&YXY^_w_q-hP z3W3~PnfG+snNVV$-Nkvp3r%dQP7!N`Rkjq|diici&8Gf|kXNhSh--jdcw_GcsZ1{; zi&*&7udcmYH?zd_JvftcihAe6R?g-^{VQ;NNRikaHS#Y)=(fFgc~>X)nRx}75wnH* zYtI%0#+WS^_U?T38x_1>+)9yvt#ENyIg8dbuwxYx>B?zJOu~O1IG00!^%62x*Pyt?eaOBRHE|uZP46O#9b7W~^J%thjON zEgA2f6O5;kAlg1)vOxVTxzU#0?MXW%@7u=`uc`|l-q@owhzUU@`J|8uu!(>80q|&J zkNN6H$$PhcCi#f(n%kL675eKnv(CfxZ?mndkwWoVXV_Ycp6b~ouf8_0;5Z29HJ(t& zYmXt<>2d)7W?c^x>BYh=mZMC+xfJ1a@r#(xUk~keNrU(g-L+!)5*~}U-h47Z(C8STKJ+GR zjI!@kxAA1UTZN*iC!k5Kdhg_<6)T%UwEiow2`so^?zggi-QRJqj~wH%VZaX7{bSW? zhwSvqvwz(X`T%HL<+L2wGDp8ge-wRaiOqJdb7^|#6VlO=6B*}Vo#Vx$aaXn^9nXLd(T(z&-IKOO~eM73*$z)|N1SK{8XMkJ~ z5Rdj?H64B?k}bDpMH*)(9oi-$oX+0s>jLAYTRWEbPQ^_ z8$Ne5Tb7h*1PZ@l1D%w~xljyQH=U(W=WjDAym7+TgP1OE*PHy#76KYH=y0FALS0)w$e{p^RhbM1$ESN+z6tRfpv5?} z8HLjV?7_x;Xwptut+QGseL`7k!=g(4l+(>D5Iqo=v_xblO_L%7leg^f!pqQS=QO8O zS+%op6hD|)+^Xl@Fl78>cB%C-HxUl%=m-4*q|Z+B#} zkI}VQ5kEX#MO=6gX2y@9MRWxS?ux~Rxeog_d{rbg+(RaM_BGlQjyJQd*ITyrRBR`i zNLQ(t_H~Q}_(MLRkmYUFLXXQLTG-NEXkVvHx5=~jF58rh+XZYlocVFZu9I2hXS!k} z$KtPJ7O&QSNrQ6_DKq_Qk$jl^$JccuP^Fd)wE4-;`xQ3bLFEDmY-g>g%A~W}ywisz z=vaN2QA?YLQGHP7Qj%Yp7cLE?^Km7Jm2QLe#V$UAtj?18dy+Qu^$1ieZ8Ixs_xw-6 zsvDc6+B|4)cyPAcHD2YMy0z26AKbc#w_{HxA8|hCkoziUD|(Yp0k~13|B~K*naFbW z)v2x1Wy{q)K4LA!V59e)J^(LQn)Z>X_#2v>k-ET$4E{s)?NJ5}ze>o|$0Hvhr^&C# zIm@`sR7=a-WIyMn z(9kNvCD~&q0}Z22&~*o71*6OlyOjA7KQ`jntyR>R6CFdCblNfOK%jb7nWm^col5Nk zhL^u+yBE>UccMAydZq_E!f!m`QwshB$c-0}fL=QuhpTq@d^|71bTm};iL<4;a|vfd z&-lthoBS4uDRsB~?YI+#wwFHa>lQ)~5O7@^ms=S9a>^X2v|FDWL04Ht(oPLX`j6EqT?i^Q%?v>Ry}#RERECAwA4s}7QMtc71%uD z?cbC*ikbAahv6{0<5e{PtLL2&D_T_()|e;9>TAZuXjU)CZxpOc;GS9d!`8J(n^%uU~pBlKp0F?PuV3_jZ65F`cKMB}u`@K$# z4ZY}z&_1MdS4*O!y7E=Xgu+=+euaKDIymn+nYx`h4fjEJr$t9pP4J-}*)o8b3jAV% z|L`T@O1L-?52#Awp4V{6^fwylzu(lRfqC+n3@@`<$4@hQK6xqBX92TbjU38!xuiwK z4&+hA&g@m;+0Ow9^co9G7`WU57E-hCm>1d3)q62LGnXcC)2{UAZS|?D^KUd@G_)RnLy7PoU_;txBtsH zWjr~jdTy>P*WF$!x#KlIqc5a?EXZp=s#@Dotv-38@UoY1ZH>H_{A$# zk}1?oOKdcn8QQ*~B(8DdtEjf$>rTQ!>sP-z#$U#0wz-QG+r^N{pqh0YU8wSfQYT~s@?SM)48yo zh7Yc@oFNS$&3ctXTkS0M_J2TtK5IU}$1CEe#Z4$-AM{IL5dLQ*oJoF(MLMA?uujqw zUbs*0#5IUEH#IKLjc{k`6qNA18Ds5{t%E9mRrSprd|ZNQ>ag^kyH8PlwlMjNK>$I< z{>;>l7(eV-Jdh>gYdZ;l`^d`BhKh;k3}3O|d^#y_AXn?6Nv%DG^o5X5t z%pcMt=ea7ktjp@20D46ZAFjHGU?oJHRA-=cO@wA*gDNEZ-eH}YDa9`j_*UwQ;2MGI z(1t6Hd%?*3>p_263cQu5q3+r>`L`Eavl9tleY#XxeET;`Gj7R6(YwL=y}RSCr+Zk{ zT#cWn-lFmxPt$+NF7;(AG>k!5*E(-}CQ2PpX7QYiH&0*FG;?fw)FGQ0FUaQ*X3qWF zKUpIgTsH>#`S$aC%=Q6m6F4aa{h1ZQKszzY>m**vm+~Y`*_*{2RvKzjXD?!?>LCDJ zD1B;U^;MtPNe8C$>Jy)*Rb!p7#s2x8V6WV& zRGaDO>kYgUBs+8J`{MOTE9Z$#=}kdp^;}E6$-nG}UmZtQ%j>?cT&ocMKAe;iM*K65yDJ`&M{5xIygQn-6bHYJ4$1ofZtTh|Zxl$@A zpu)7w5&U#BBxfHZ>Y1aTYb{uC(9~ysoZD0~E~VTLVzKW51P;(Ltg@@zl|Tn-KkmUx z{SDm7FW!ga=c_H4daaMu>sNwRr{qrfj_z!_N?Id!@4LHyHzkZgs?z++C$w#`0)Aa< zHDS$9Q}ENFUW|I@{)MB3aB(|E!Y?vLZpaCduR0d$T^Ke}`Yu{=iJeWm_^Ef*qbk!s zZi|JM;fsl{3x)>nL=J&DIxkryrFcWGVP`Te=gA+Y0MVlrtJ>ioy}lkSM1}{0Bgpo6 z;q&fLq`IcTF^P+lH~jGrvAl%UC#fK_mgHr;dCb!AmrXW7nmc7v57J5Tx~cIX^+k=t z@#qJte;)fIZ*93lr2Cs1+l! z{OcF5ZJFIc?bg#qpIDZv-xEbwk*OU5T22>Q!UB3SgS}O}#R}F-&=mlB$%lp+{^>E5 zvB{tV2_}u%y_?Y!b5z?fq@xBK3={5usNVnY%~t)Kx${g@YD&6>4?PQBkaa`)B0Qnd zzWkx(!2Q@i8*jJ>mhoYid&O@3(U4YZw2ET9NUX zJ5O4-GQuZL4TCwIdT29^KVS7ZliF(ktc!VoL6C8kC!G8Du7fplG1fU@Cta-KoYV4_ zhXhNODreX!mcp1Jy$zL*RNM_EgtFVprA=FJ&U%#K;6fhNO7)UCBU+=ZPJLp+N=S(v z4y^t$KK51!+kUf_VuN9kMyv&+7IcfD-q2ADUM2I3{i2C^a!WSjx7e<9r{0jt=r*h1 zw)A-YWkIgxx0L#V))h&qRLM#o9&nw&i;|UThuw9ph6)LvM|N3|EuaH@FWF^Itj;U( z=e7aF1G34oQ}Jc|Z-Nmay>fkQ<~5QQ0pEXt(kei&@pL!YV2u*W2GjK0ere^mIQPio zxRZ5n7oPErx78T_mr6=gYV+@GE%LHG*xBMIK1|wJnqpMjY7C9x`W009mcfwS(Nf_N z*8U2cP9-SJPOx`d<{)gI7QfufHkfAc4ToZnaHdlg^#dx-fpx`d3<3MXxeXSssXo5LWB+%D_BZTX9?}`0VP)*gx@2YBqk{!7O z-wW=nf}spVQSZ!Zy22{;;QZUtUpEQ_Mm*xpSJ;Mnb{H)CF#Cy|-?r77q8oIVurIj4 zMyyj|_Bt0Vy+M9_zVkh=hTnM7j*3rc3C+Q8*?~bUWD~1_~$@?ttom9?E3sthYhlO7KGjE9X?x8&?5FicmO65el9@hbqi3YFNJ}_iH%T zEC_OELk%jexD^;WfR0Opx}E_{keW%j3h6s4AE+;Sg)gq>Op^@jRO{u9_j7$!-g?qX z)$1OQeT!1hAnGPH zCMy%bt#_W!3&>e}rZJ=cWtgb>&KB+m7xEln+#+yB_Ntp(%T~!Pj~?*ZA@&mtNtjhu zdPYjbqq3G9p2M|V==gKK$Zo}Q)LrIi>gqUbHo@dOH`$Gaf1IO>G zt#tXM$*lIb4)^gHu?FKM0tBs(yI-x^bKKC}Sgv8EJ>oUhTlWS|nn#A(m5hpiH>3~0 z{Jv&Y>Tl$Onrcb>J+B|1vLzL?(9vkhone8UlCzPH{;>N0Wf!=27h$qEZ6jf7xEVr{ z#GK1Q$SYtOHKF#>t#!UFxjvbhOJctSt#J*GnRM*XUf(`18d+g{9@irepIed0grt4a z+km7|zhR3%R*0^66}KAH$joIeI2i$A88S-DB!j{w@V|?Vu+ZX+G`EQre)&sO@)7M) zEc@ZM)5#32sFYn^g$#x^;DUHFXqt-iN1qGWb{rHusc;liOLJ(3bk;xj#B$whPT^h! z+=FWH` z;J@v!=Ih}{V31v&T-GHw2DqnID?i*y!GC`Loza63&Nb=QLx|TE-3_$jAH86w5ceot#>kX%k z3vb7{bhM!Dx<=5Gx#$>kL0V-JqQ`TQhauxws`ok60ks%NVLG_3xF?tZNolw?N*fVL zJ}+3ruHf7$OmOSs_Y8fOfOPjZr@P@zj~w9+*VDdh;cpT@G-zeY4-{SP2?>g)r zh(>Dur}snf)$#}QG#u&w2E- zPC(8c^vn;07W8`;>eS|e)(`usK09If+qqw1QY}S)>6CaBmQIMb-^tPn5B;K7Gn7j) zs$6#9z7v7&U%6+YuJN!hvjF($Q4&(gkf;)8Yzv=#<(jhu*$g);w6aXfUiJ_2t8u7Y zBGMzEW$8kar zhbMD2IyFK+PE!US;a9V6#jeFO{3#=)4>wa-BnJr92Yn7dZUvt4&DD#~Rc{Bg^<~u$ zUr`o!Ac`@l4Yw35Z1%=-{%K$y@shmIMtQuwr;0tKjVE#rQS6R%X{2EGE(Wa)(00wfz^pDtx*BzMqKK4jh69*ZeoBY;XOFoV;6I`J$v9_oER>7|a^>R-diqryAz z>uDvx&?zvym@PYNWc4VX03pqVbORaCHfuw)yoj?tNaHbMGN$~`UpYndkHo9W9VT=C zQsO3g@6xhIZ-#umle_%NV&6)15}b7=OW0Htih2UmZ9NY#OZ*44zA;O@ZJ9}%FcaAC z7)phl8*aRrSF&rzIoXnujADY@zKVX9==&q^{u`6;h{`aWuDgHe$d+MWHa66o@Gcz_ z_S}S4X>aj(|6lJ&DX3+xyUBExi)8dsj*C=G`A)O+-44E6z;nhG zL4&>&V5>B+WF{Fir#qcwi$2*ZX5IU-&fV(u>3whkn980aDg3x|=o$74g1)`Y(Z&1s z(c!0e8M@Pjm(_4|`+-;K^H^6PHT zz{2wGz6yTfBp3BLkf09;3!oKIf}VSO6fu#bAPJFxV?e4UNK-_BU|}eAP4&l%?Gfoa zMa`sv?ruZZS-vi7zE*1^u}nNa#5LT9fmJ5orw2|x=F>Swmwwkq>kyo5mzrFg`7lsl zwSHTY;aaf37J|3Bd~8d4`7V|m0U17d@}&K>7Eo2V+Jf0!SI3xFb#2OtXGs5=3 j@hlYWgV4rCEt#d{mRArWu2mNw3NeC={Y2-K9CFH$q`p zWU&C7!T~&1gVC%g6*faHttoJSu3D=0qX3dm(&dsbXDJT{xdnoeUC}*GBcbsX&MT)3 zgX=UPqubvoLio^G#Xl+pd4}h%z!MVR^eisVrICr2ag2`kDEa)eQ^CJAn(UWuLmX?Y z>OQ@@Y!5{u;gv{ahpEChk62#=omT1mF~=8xsuCY9Sf;E#H{*_M!27>f zS&W-s`KhMhddNr0q(Y*cYQ%5EOdl13k?;4uxgB#c^QY5!cj?=GFPbAfV{O%{Ji1G7 zn$ZRZzXbI7eLx!w-K!&$kC(>070R)2+wT0nONME!S)l}E8XyU^VH6mPY7Ppx#T^_b_HDPo{m32vp-D+CEGqVrNlMr5*yVa-m2j7ljt@$P}ojuu$=#4PNyr%drR&&YR^-nBj@PL$ecN$W@X*zJ53iba|;+#%PIEYS6Ab8A57v zUCPKu&?HNO9)96^XLO*dyOoD8rNFDx&NM+|aPkqVl4}WaO7axLc4GNBGWk;9t+KI{ zYP3_b6H}{ufWO(4A4WyIDTW-6p>}S-y}zeV9JG%ufUKeqi?hqYFH4MOVCWK)=QzY_+3MIT=c4kJukD#% zM0hgMKKDk=br3M(sO^n{B~ppqb(1gR`OJNlzLXBZI~CanT4t#*!7l_vLdOfYE?y*CimubQt%#k z7~)nhr8Mb{;|ajJE9X?Ynd{{Po1Lck1A1;2c9lc&`GO^-DHj7p3ES_Z@ zOVh(QYQ^m8*=ZcO27%uX^ipM?054wC{`-VsG>b###@&DjwOc;za;FsPbgb>`y>Kkr z{@_J7DO8-APxj76=Bnv8WKF<}zbA61_E~QewTiYum(~vXWh^|3-e9!!u`KOvS+=ag zOQEHz#zFTQ;&SQ>zYl~v4up@4W%Mj+c)n?;Z}SF#GpNaO7Kv`H-h0nwW7oobLSj<0 zoGD6TPu87*un41y#1kFhVfg|VUU&68BLEfhJ0i$@`{Lh|(ABq@4y3Aj-K=Abx%`i* z!l|q0ezb@KAmA-Re`g@S^Wup5(;*4K+uFP!w6}S>;(@1T<42Xb(XIM5d@#eU*igSb zFMYa_?wv5LB4Z<3+?IL@AB3%jvxUJOX{{>7^sy^Pold3{NF<8g>&aWO671{l&Rcyr%$L+IqmAn0lH($G^!k-eFOg{I(6qkzyb5p~=a< zJ&!Pw;m2T@KMubdUtab5E%QY&KeF8wotwxZJN&ov3PF5Fju;rV!qSU%4U}?!bewYd zJ5$vw2Rh#vo%_iDn^^rHQ~Qq^^Gw^WvoG2g6%pZXPvMcsl5Xx#Y)ls)5rMMQd7sKF zf&FMZeiDdr>lyKBEm3LJ>q4Ot5j%9B!2AQ<84yLQSBeMZ88pb|6)`; z!{3oq`GCQ>Kmo5{zppu}8V0A9ZNJhmg%4S4y9B3&#UFqhNErQj?|GH0L7CUcC1M@) z0}blls%X9{thHYkk=rE3-FEj{WOL0&@DV(h zxe@~>M}q${kvDf)W*C0oPbs5Th9iG{OVKxfY20x!mpylwy>ujMgXv(2n+41ZJt)V~ zTp_+>v}-L$eH^E-3S5B>(=)vhs3z0L@CKh>g74)MM{-M0_WTC6&lKyRHFy33HkRXg z=ZB$~*UbM$M7bFQvs=BAJ*55Q1yikIdgSXMr(l=Kd$~K{rV>}21Q577!IyKoj7MNs zC;r(B_Upx+2bN&jzoHnQgRhpyNVA~HUT+-Nmj_D!{5acX`|58R)+|0~C*?1){^wcc zU>7~LJqSy%I5^WIbIB>h^PNk{sw=-&UntaN$2KGNnRc?^W#>9yYZqSpYzgs`BTLCJ z)p5c&5C8Rmeqwa7@mCMLH(}-(T!&eNf0|CI-tyUy<7Uw3cI*tWA^4Q|VdJfkoC0v? zdCdgimkT0Q5f)A{v46Ls)mAb<&1~^ci)R?Q4!(Ku8bi(uNm6K0Iuue=&igf~r%}EA zRqgwq@X)fW`@12|PLKG#y!PFlmNKPl(Ze|h#%DFMNXF#X&ztX)whEF*HW>vJUMa{S z+aFVRM(Y7S=%8I?e1uf+QQCCvD3$|vs8_+NMVKx?!)HH+W{X3oo0yuRO?Bu&Us5wF z|GZ9%E=* z+qjQ@^zk|hZW#GNr(>r=WmoUyfy-@>i_aRw9;DIwZ=fv}9xTR?Lfhd^Z!71$gv?;5 zh-5Ey{2WnCfqvv@(Ada+Qf;y9?%&r zZG7(I-Ji#Mp*qDNwePl{=owF>sSK>sQj`32f2a0c{;%a^KA@l8RJF_fhjaMvga_J0 zX}vv11y91;1ov_AV?f`fuL}Yqt>-?Y;MQPkSi}5V)SDM;DQ3JqJ-AE%E?P- + 'wonderful-mongodb:27017' diff --git a/deploy/kubernetes/configmap/production/movies.yaml b/deploy/kubernetes/configmap/production/movies.yaml new file mode 100644 index 0000000..c20db31 --- /dev/null +++ b/deploy/kubernetes/configmap/production/movies.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: env-wonderful-movies + namespace: production +data: + PORT: '3000' + DB: movies +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: certs-wonderful-movies + namespace: production +data: + server.crt: |- + -----BEGIN CERTIFICATE----- + + -----END CERTIFICATE----- + server.key: |- + -----BEGIN PRIVATE KEY----- + + -----END PRIVATE KEY----- diff --git a/deploy/kubernetes/configmap/production/notification.yaml b/deploy/kubernetes/configmap/production/notification.yaml new file mode 100644 index 0000000..33d6c30 --- /dev/null +++ b/deploy/kubernetes/configmap/production/notification.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: env-wonderful-notification + namespace: production +data: + PORT: '3000' + DB: notification +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: certs-wonderful-notification + namespace: production +data: + server.crt: |- + -----BEGIN CERTIFICATE----- + + -----END CERTIFICATE----- + server.key: |- + -----BEGIN PRIVATE KEY----- + + -----END PRIVATE KEY----- diff --git a/deploy/kubernetes/configmap/production/payment.yaml b/deploy/kubernetes/configmap/production/payment.yaml new file mode 100644 index 0000000..0a51008 --- /dev/null +++ b/deploy/kubernetes/configmap/production/payment.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: env-wonderful-payment + namespace: production +data: + PORT: '3000' + DB: payment +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: certs-wonderful-payment + namespace: production +data: + server.crt: |- + -----BEGIN CERTIFICATE----- + + -----END CERTIFICATE----- + server.key: |- + -----BEGIN PRIVATE KEY----- + + -----END PRIVATE KEY----- diff --git a/deploy/kubernetes/configmap/staging/booking.yaml b/deploy/kubernetes/configmap/staging/booking.yaml new file mode 100644 index 0000000..3693e17 --- /dev/null +++ b/deploy/kubernetes/configmap/staging/booking.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: env-wonderful-booking + namespace: staging +data: + PORT: '3000' + DB: booking +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: certs-wonderful-booking + namespace: staging +data: + server.crt: |- + -----BEGIN CERTIFICATE----- + + -----END CERTIFICATE----- + server.key: |- + -----BEGIN PRIVATE KEY----- + + -----END PRIVATE KEY----- diff --git a/deploy/kubernetes/configmap/staging/cinema-catalog.yaml b/deploy/kubernetes/configmap/staging/cinema-catalog.yaml new file mode 100644 index 0000000..3f61ff7 --- /dev/null +++ b/deploy/kubernetes/configmap/staging/cinema-catalog.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: env-wonderful-cinema-catalog + namespace: staging +data: + PORT: '3000' + DB: cinema-catalog +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: certs-wonderful-cinema-catalog + namespace: staging +data: + server.crt: |- + -----BEGIN CERTIFICATE----- + + -----END CERTIFICATE----- + server.key: |- + -----BEGIN PRIVATE KEY----- + + -----END PRIVATE KEY----- diff --git a/deploy/kubernetes/configmap/staging/database.yaml b/deploy/kubernetes/configmap/staging/database.yaml new file mode 100644 index 0000000..f0668aa --- /dev/null +++ b/deploy/kubernetes/configmap/staging/database.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: env-wonderful-database + namespace: staging +data: + DB_USER: michaelact + DB_PASS: michaelactMenjawab100 + DB_REPLS: rs1 + DB_SERVERS: >- + 'wonderful-mongodb:27017' diff --git a/deploy/kubernetes/configmap/staging/movies.yaml b/deploy/kubernetes/configmap/staging/movies.yaml new file mode 100644 index 0000000..f45dae6 --- /dev/null +++ b/deploy/kubernetes/configmap/staging/movies.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: env-wonderful-movies + namespace: staging +data: + PORT: '3000' + DB: movies +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: certs-wonderful-movies + namespace: staging +data: + server.crt: |- + -----BEGIN CERTIFICATE----- + + -----END CERTIFICATE----- + server.key: |- + -----BEGIN PRIVATE KEY----- + + -----END PRIVATE KEY----- diff --git a/deploy/kubernetes/configmap/staging/notification.yaml b/deploy/kubernetes/configmap/staging/notification.yaml new file mode 100644 index 0000000..9cdaa3d --- /dev/null +++ b/deploy/kubernetes/configmap/staging/notification.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: env-wonderful-notification + namespace: staging +data: + PORT: '3000' + DB: notification +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: certs-wonderful-notification + namespace: staging +data: + server.crt: |- + -----BEGIN CERTIFICATE----- + + -----END CERTIFICATE----- + server.key: |- + -----BEGIN PRIVATE KEY----- + + -----END PRIVATE KEY----- + diff --git a/deploy/kubernetes/configmap/staging/payment.yaml b/deploy/kubernetes/configmap/staging/payment.yaml new file mode 100644 index 0000000..0287667 --- /dev/null +++ b/deploy/kubernetes/configmap/staging/payment.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: env-wonderful-payment + namespace: staging +data: + PORT: '3000' + DB: payment +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: certs-wonderful-payment + namespace: staging +data: + server.crt: |- + -----BEGIN CERTIFICATE----- + + -----END CERTIFICATE----- + server.key: |- + -----BEGIN PRIVATE KEY----- + + -----END PRIVATE KEY----- diff --git a/deploy/kubernetes/deploy.sh b/deploy/kubernetes/deploy.sh new file mode 100755 index 0000000..220f1e7 --- /dev/null +++ b/deploy/kubernetes/deploy.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -e + +kubectl $1 -f configmap/$NAMESPACE/ +kubectl -n $NAMESPACE $1 --recursive -f application/ +kubectl $1 -f ingress/$NAMESPACE/ diff --git a/deploy/kubernetes/ingress/production/ingress-nginx.yaml b/deploy/kubernetes/ingress/production/ingress-nginx.yaml new file mode 100644 index 0000000..431fb2b --- /dev/null +++ b/deploy/kubernetes/ingress/production/ingress-nginx.yaml @@ -0,0 +1,52 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: wonderful-cinema + namespace: production + labels: + app.kubernetes.io/name: wonderful-cinema-ingress + app.kubernetes.io/component: front-tier + app.kubernetes.io/part-of: wonderful-cinema + app.kubernetes.io/version: latest + app.kubernetes.io/instance: all +spec: + ingressClassName: nginx + rules: + - host: wonderful.id + http: + paths: + - pathType: Prefix + path: '/cinemas' + backend: + service: + name: wonderful-cinema-catalog + port: + number: 3000 + - pathType: Prefix + path: '/movies' + backend: + service: + name: wonderful-movies + port: + number: 3000 + - pathType: Prefix + path: '/booking' + backend: + service: + name: wonderful-booking + port: + number: 3000 + - pathType: Prefix + path: '/notification' + backend: + service: + name: wonderful-notification + port: + number: 3000 + - pathType: Prefix + path: '/payment' + backend: + service: + name: wonderful-payment + port: + number: 3000 diff --git a/deploy/kubernetes/ingress/staging/ingress-nginx.yaml b/deploy/kubernetes/ingress/staging/ingress-nginx.yaml new file mode 100644 index 0000000..e1140d3 --- /dev/null +++ b/deploy/kubernetes/ingress/staging/ingress-nginx.yaml @@ -0,0 +1,52 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: wonderful-cinema + namespace: staging + labels: + app.kubernetes.io/name: wonderful-cinema-ingress + app.kubernetes.io/component: front-tier + app.kubernetes.io/part-of: wonderful-cinema + app.kubernetes.io/version: latest + app.kubernetes.io/instance: all +spec: + ingressClassName: nginx + rules: + - host: staging.wonderful.id + http: + paths: + - pathType: Prefix + path: '/cinemas' + backend: + service: + name: wonderful-cinema-catalog + port: + number: 3000 + - pathType: Prefix + path: '/movies' + backend: + service: + name: wonderful-movies + port: + number: 3000 + - pathType: Prefix + path: '/booking' + backend: + service: + name: wonderful-booking + port: + number: 3000 + - pathType: Prefix + path: '/notification' + backend: + service: + name: wonderful-notification + port: + number: 3000 + - pathType: Prefix + path: '/payment' + backend: + service: + name: wonderful-payment + port: + number: 3000 diff --git a/kraken.sh b/kraken.sh deleted file mode 100644 index 0fd375f..0000000 --- a/kraken.sh +++ /dev/null @@ -1,88 +0,0 @@ -#!/usr/bin/env bash - -function setup-swarm { - # first we go to our docker folder - cd _docker_setup - - echo '···························' - echo '·· setting up the swarm >>>> ··' - echo '···························' - - # we create and init the swarm cluster - (bash < ./setup-swarm.sh) - - # we go back to the root project - cd .. -} - -function setup-mongo { - echo '···························' - echo '·· <<<< git clone the mongodb cluster ··' - echo '···························' - - rm -rf mongo-replica-with-docker - - # next we download our mongo-replica-set configuration - git clone https://github.com/Crizstian/mongo-replica-with-docker.git - - echo '···························' - echo '·· setting up the mongodb cluster >>>> ··' - echo '···························' - # we go into the folder - cd mongo-replica-with-docker - - # we create and init our mongodb replica set cluster - (bash < create-replica-set.sh) - - # we go back to the root project - cd .. -} - -function setup-images { - - # go inside the docker folder again - cd _docker_setup - - echo '···························' - echo '·· creating microservices images >>>> ··' - echo '···························' - - # we start all our microservices - (bash < create-images.sh) - - cd .. -} - -function setup-services { - - # go inside the docker folder again - cd _docker_setup - - echo '···························' - echo '·· starting up the microservices >>>> ··' - echo '···························' - - # we start all our microservices - (bash < start-services.sh) - - cd .. -} - -function status { - eval `docker-machine env manager1` - # we verify the docker swarm - docker node ls - - # we verify our docker services - docker service ls -} - -function main { - setup-swarm - setup-mongo - setup-images - setup-services - status -} - -main diff --git a/movies-service/.eslintrc.json b/movies-service/.eslintrc.json deleted file mode 100644 index a755cdb..0000000 --- a/movies-service/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": ["standard"] -} diff --git a/movies-service/Dockerfile b/movies-service/Dockerfile deleted file mode 100644 index 523816b..0000000 --- a/movies-service/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM node:7.5.0-alpine - -RUN addgroup -S nupp && adduser -S -g nupp nupp - -ENV HOME=/home/nupp - -COPY package.json npm-shrinkwrap.json $HOME/app/ - -COPY src/ $HOME/app/src - -ADD https://github.com/Yelp/dumb-init/releases/download/v1.1.1/dumb-init_1.1.1_amd64 /usr/local/bin/dumb-init - -WORKDIR $HOME/app - -RUN chown -R nupp:nupp $HOME/* /usr/local/ && \ - chmod +x /usr/local/bin/dumb-init && \ - npm cache clean && \ - npm install --silent --progress=false --production && \ - chown -R nupp:nupp $HOME/* - -USER nupp - -EXPOSE 3000 - -CMD ["dumb-init", "npm", "start"] diff --git a/movies-service/create-image.sh b/movies-service/create-image.sh deleted file mode 100644 index 9e45917..0000000 --- a/movies-service/create-image.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -docker rm -f movies-service - -docker rmi movies-service - -docker image prune - -docker volume prune - -docker build -t movies-service . diff --git a/movies-service/integration-test/index.js b/movies-service/integration-test/index.js deleted file mode 100644 index 2818086..0000000 --- a/movies-service/integration-test/index.js +++ /dev/null @@ -1,10 +0,0 @@ -/* eslint-env mocha */ -const supertest = require('supertest') - -describe('movies-service', () => { - const api = supertest('http://192.168.99.100:3000') - it('returns a 200 for a known movies', (done) => { - api.get('/movies/premieres') - .expect(200, done) - }) -}) diff --git a/movies-service/integration-test/movie-service-api.jmeter.test.jmx b/movies-service/integration-test/movie-service-api.jmeter.test.jmx deleted file mode 100644 index d8f1de3..0000000 --- a/movies-service/integration-test/movie-service-api.jmeter.test.jmx +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - false - false - - - - - - - - - - - - continue - - false - 1000 - - 100 - 100 - 1485133702000 - 1485133702000 - false - - - - - - - - - localhost - 3000 - - - http - - - 6 - - - - - - - - - - - - - /movies - GET - true - false - true - false - false - - - - - - - - - - - - - - /movies/premiers - GET - true - false - true - false - false - - - - - - - - false - 1 - = - true - id - - - - - - - - - - /movies/${id} - GET - true - false - true - false - false - - - - - - - diff --git a/movies-service/npm-shrinkwrap.json b/movies-service/npm-shrinkwrap.json deleted file mode 100644 index 2581895..0000000 --- a/movies-service/npm-shrinkwrap.json +++ /dev/null @@ -1,520 +0,0 @@ -{ - "name": "movies-service", - "version": "1.0.0", - "dependencies": { - "accepts": { - "version": "1.3.3", - "from": "accepts@>=1.3.3 <1.4.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz" - }, - "array-flatten": { - "version": "1.1.1", - "from": "array-flatten@1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" - }, - "basic-auth": { - "version": "1.0.4", - "from": "basic-auth@>=1.0.3 <1.1.0", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz" - }, - "bson": { - "version": "0.4.23", - "from": "bson@>=0.4.23 <0.5.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-0.4.23.tgz" - }, - "buffer-shims": { - "version": "1.0.0", - "from": "buffer-shims@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" - }, - "camelize": { - "version": "1.0.0", - "from": "camelize@1.0.0", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz" - }, - "connect": { - "version": "3.5.0", - "from": "connect@3.5.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.5.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "content-disposition": { - "version": "0.5.1", - "from": "content-disposition@0.5.1", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz" - }, - "content-security-policy-builder": { - "version": "1.1.0", - "from": "content-security-policy-builder@1.1.0", - "resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-1.1.0.tgz" - }, - "content-type": { - "version": "1.0.2", - "from": "content-type@>=1.0.2 <1.1.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz" - }, - "cookie": { - "version": "0.3.1", - "from": "cookie@0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz" - }, - "cookie-signature": { - "version": "1.0.6", - "from": "cookie-signature@1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" - }, - "core-util-is": { - "version": "1.0.2", - "from": "core-util-is@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" - }, - "dasherize": { - "version": "2.0.0", - "from": "dasherize@2.0.0", - "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz" - }, - "dashify": { - "version": "0.2.2", - "from": "dashify@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/dashify/-/dashify-0.2.2.tgz" - }, - "debug": { - "version": "2.6.0", - "from": "debug@>=2.1.1 <3.0.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz" - }, - "depd": { - "version": "1.1.0", - "from": "depd@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz" - }, - "destroy": { - "version": "1.0.4", - "from": "destroy@>=1.0.4 <1.1.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" - }, - "dns-prefetch-control": { - "version": "0.1.0", - "from": "dns-prefetch-control@0.1.0", - "resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz" - }, - "dont-sniff-mimetype": { - "version": "1.0.0", - "from": "dont-sniff-mimetype@1.0.0", - "resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.0.0.tgz" - }, - "ee-first": { - "version": "1.1.1", - "from": "ee-first@1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" - }, - "encodeurl": { - "version": "1.0.1", - "from": "encodeurl@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz" - }, - "es6-promise": { - "version": "3.0.2", - "from": "es6-promise@3.0.2", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz" - }, - "escape-html": { - "version": "1.0.3", - "from": "escape-html@>=1.0.3 <1.1.0", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" - }, - "etag": { - "version": "1.7.0", - "from": "etag@>=1.7.0 <1.8.0", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz" - }, - "express": { - "version": "4.14.0", - "from": "express@latest", - "resolved": "https://registry.npmjs.org/express/-/express-4.14.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - }, - "qs": { - "version": "6.2.0", - "from": "qs@6.2.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz" - } - } - }, - "finalhandler": { - "version": "0.5.0", - "from": "finalhandler@0.5.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@~2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "forwarded": { - "version": "0.1.0", - "from": "forwarded@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz" - }, - "frameguard": { - "version": "3.0.0", - "from": "frameguard@3.0.0", - "resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.0.0.tgz" - }, - "fresh": { - "version": "0.3.0", - "from": "fresh@0.3.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz" - }, - "handle-thing": { - "version": "1.2.5", - "from": "handle-thing@>=1.2.4 <2.0.0", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz" - }, - "helmet": { - "version": "3.4.0", - "from": "helmet@>=3.4.0 <4.0.0", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.4.0.tgz" - }, - "helmet-csp": { - "version": "2.3.0", - "from": "helmet-csp@2.3.0", - "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.3.0.tgz" - }, - "hide-powered-by": { - "version": "1.0.0", - "from": "hide-powered-by@1.0.0", - "resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.0.0.tgz" - }, - "hpack.js": { - "version": "2.1.6", - "from": "hpack.js@>=2.1.6 <3.0.0", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz" - }, - "hpkp": { - "version": "2.0.0", - "from": "hpkp@2.0.0", - "resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz" - }, - "hsts": { - "version": "2.0.0", - "from": "hsts@2.0.0", - "resolved": "https://registry.npmjs.org/hsts/-/hsts-2.0.0.tgz" - }, - "http-deceiver": { - "version": "1.2.7", - "from": "http-deceiver@>=1.2.4 <2.0.0", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" - }, - "http-errors": { - "version": "1.5.1", - "from": "http-errors@>=1.5.0 <1.6.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz" - }, - "http-status": { - "version": "0.2.5", - "from": "http-status@latest", - "resolved": "https://registry.npmjs.org/http-status/-/http-status-0.2.5.tgz" - }, - "ienoopen": { - "version": "1.0.0", - "from": "ienoopen@1.0.0", - "resolved": "https://registry.npmjs.org/ienoopen/-/ienoopen-1.0.0.tgz" - }, - "inherits": { - "version": "2.0.3", - "from": "inherits@>=2.0.3 <3.0.0", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - }, - "ipaddr.js": { - "version": "1.2.0", - "from": "ipaddr.js@1.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.2.0.tgz" - }, - "isarray": { - "version": "1.0.0", - "from": "isarray@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - }, - "lodash.reduce": { - "version": "4.6.0", - "from": "lodash.reduce@4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz" - }, - "media-typer": { - "version": "0.3.0", - "from": "media-typer@0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" - }, - "merge-descriptors": { - "version": "1.0.1", - "from": "merge-descriptors@1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" - }, - "methods": { - "version": "1.1.2", - "from": "methods@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" - }, - "mime": { - "version": "1.3.4", - "from": "mime@>=1.3.4 <2.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" - }, - "mime-db": { - "version": "1.26.0", - "from": "mime-db@>=1.26.0 <1.27.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.26.0.tgz" - }, - "mime-types": { - "version": "2.1.14", - "from": "mime-types@>=2.1.10 <3.0.0", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.14.tgz" - }, - "minimalistic-assert": { - "version": "1.0.0", - "from": "minimalistic-assert@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" - }, - "mongodb": { - "version": "2.1.18", - "from": "mongodb@2.1.18", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.1.18.tgz", - "dependencies": { - "isarray": { - "version": "0.0.1", - "from": "isarray@0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" - }, - "readable-stream": { - "version": "1.0.31", - "from": "readable-stream@1.0.31", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.31.tgz" - } - } - }, - "mongodb-core": { - "version": "1.3.18", - "from": "mongodb-core@1.3.18", - "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-1.3.18.tgz" - }, - "morgan": { - "version": "1.7.0", - "from": "morgan@latest", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.7.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@~2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "ms": { - "version": "0.7.2", - "from": "ms@0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz" - }, - "negotiator": { - "version": "0.6.1", - "from": "negotiator@0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz" - }, - "nocache": { - "version": "2.0.0", - "from": "nocache@2.0.0", - "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.0.0.tgz" - }, - "obuf": { - "version": "1.1.1", - "from": "obuf@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz" - }, - "on-finished": { - "version": "2.3.0", - "from": "on-finished@>=2.3.0 <2.4.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" - }, - "on-headers": { - "version": "1.0.1", - "from": "on-headers@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" - }, - "parseurl": { - "version": "1.3.1", - "from": "parseurl@>=1.3.1 <1.4.0", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz" - }, - "path-to-regexp": { - "version": "0.1.7", - "from": "path-to-regexp@0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" - }, - "platform": { - "version": "1.3.3", - "from": "platform@1.3.3", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.3.tgz" - }, - "process-nextick-args": { - "version": "1.0.7", - "from": "process-nextick-args@>=1.0.6 <1.1.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" - }, - "proxy-addr": { - "version": "1.1.3", - "from": "proxy-addr@>=1.1.2 <1.2.0", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.3.tgz" - }, - "range-parser": { - "version": "1.2.0", - "from": "range-parser@>=1.2.0 <1.3.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz" - }, - "readable-stream": { - "version": "2.2.2", - "from": "readable-stream@>=2.2.2 <3.0.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.2.tgz" - }, - "referrer-policy": { - "version": "1.1.0", - "from": "referrer-policy@1.1.0", - "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.1.0.tgz" - }, - "require_optional": { - "version": "1.0.0", - "from": "require_optional@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.0.tgz", - "dependencies": { - "resolve-from": { - "version": "2.0.0", - "from": "resolve-from@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz" - } - } - }, - "select-hose": { - "version": "2.0.0", - "from": "select-hose@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" - }, - "semver": { - "version": "5.3.0", - "from": "semver@>=5.1.0 <6.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz" - }, - "send": { - "version": "0.14.1", - "from": "send@0.14.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.14.1.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@~2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "serve-static": { - "version": "1.11.1", - "from": "serve-static@>=1.11.1 <1.12.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.11.1.tgz" - }, - "setprototypeof": { - "version": "1.0.2", - "from": "setprototypeof@1.0.2", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz" - }, - "spdy": { - "version": "3.4.4", - "from": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz" - }, - "spdy-transport": { - "version": "2.0.18", - "from": "spdy-transport@>=2.0.15 <3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.18.tgz" - }, - "statuses": { - "version": "1.3.1", - "from": "statuses@>=1.3.0 <1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz" - }, - "string_decoder": { - "version": "0.10.31", - "from": "string_decoder@>=0.10.0 <0.11.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - }, - "type-is": { - "version": "1.6.14", - "from": "type-is@>=1.6.13 <1.7.0", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.14.tgz" - }, - "unpipe": { - "version": "1.0.0", - "from": "unpipe@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" - }, - "util-deprecate": { - "version": "1.0.2", - "from": "util-deprecate@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - }, - "utils-merge": { - "version": "1.0.0", - "from": "utils-merge@1.0.0", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" - }, - "vary": { - "version": "1.1.0", - "from": "vary@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.0.tgz" - }, - "wbuf": { - "version": "1.7.2", - "from": "wbuf@>=1.4.0 <2.0.0", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz" - }, - "x-xss-protection": { - "version": "1.0.0", - "from": "x-xss-protection@1.0.0", - "resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.0.0.tgz" - } - } -} diff --git a/movies-service/package.json b/movies-service/package.json deleted file mode 100644 index 02261c1..0000000 --- a/movies-service/package.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "movies-service", - "version": "1.0.0", - "description": "A movie service, microservice example with nodejs", - "author": "Cristian Ramirez Rosas ", - "license": "ISC", - "main": "index.js", - "standard": { - "env": [ - "mocha" - ], - "ignore": [ - "mock" - ] - }, - "scripts": { - "test": "mocha -R spec src/**/*.spec.js", - "start": "node src/index.js", - "lint": "standard --verbose | snazzy", - "node-debug": "DEBUG=express* node src/index.js", - "chrome-debug": "node --debug-brk --inspect src/index.js" - }, - "keywords": [ - "express", - "mongodb", - "docker", - "microservice" - ], - "devDependencies": { - "eslint": "^3.13.1", - "mocha": "^3.2.0", - "should": "^11.1.2", - "snazzy": "^6.0.0", - "standard": "^8.6.0", - "supertest": "^2.0.1" - }, - "dependencies": { - "express": "^4.14.0", - "helmet": "^3.4.0", - "http-status": "^0.2.5", - "mongodb": "^2.1.18", - "morgan": "^1.7.0" - } -} diff --git a/movies-service/readme.md b/movies-service/readme.md deleted file mode 100644 index 8e2d0c4..0000000 --- a/movies-service/readme.md +++ /dev/null @@ -1,14 +0,0 @@ -## Build a NodeJS microservice and deploy it to Docker - -[![Standard - JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/) - -Example of the **movie service** microservice and API. - -![](https://cdn-images-1.medium.com/max/1600/1*Zf2QVw1EHUNebJ1hNcT51Q.png) - -### Stack -- NodeJS V7 -- MongoDB 3.4.1 -- Docker for Mac 1.12.6 - -[![Standard - JavaScript Style Guide](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard) diff --git a/movies-service/src/api/movies.js b/movies-service/src/api/movies.js deleted file mode 100644 index b657e58..0000000 --- a/movies-service/src/api/movies.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict' -const status = require('http-status') - -module.exports = (app, options) => { - const {repo} = options - - app.get('/movies', (req, res, next) => { - repo.getAllMovies().then(movies => { - res.status(status.OK).json(movies) - }).catch(next) - }) - - app.get('/movies/premieres', (req, res, next) => { - repo.getMoviePremiers().then(movies => { - res.status(status.OK).json(movies) - }).catch(next) - }) - - app.get('/movies/:id', (req, res, next) => { - repo.getMovieById(req.params.id).then(movie => { - res.status(status.OK).json(movie) - }).catch(next) - }) -} diff --git a/movies-service/src/api/movies.spec.js b/movies-service/src/api/movies.spec.js deleted file mode 100644 index d1c0c24..0000000 --- a/movies-service/src/api/movies.spec.js +++ /dev/null @@ -1,103 +0,0 @@ -/* eslint-env mocha */ -const request = require('supertest') -const server = require('../server/server') - -describe('Movies API', () => { - let app = null - let testMovies = [{ - 'id': '3', - 'title': 'xXx: Reactivado', - 'format': 'IMAX', - 'releaseYear': 2017, - 'releaseMonth': 1, - 'releaseDay': 20 - }, { - 'id': '4', - 'title': 'Resident Evil: Capitulo Final', - 'format': 'IMAX', - 'releaseYear': 2017, - 'releaseMonth': 1, - 'releaseDay': 27 - }, { - 'id': '1', - 'title': 'Assasins Creed', - 'format': 'IMAX', - 'releaseYear': 2017, - 'releaseMonth': 1, - 'releaseDay': 6 - }] - - let testRepo = { - getAllMovies () { - return Promise.resolve(testMovies) - }, - getMoviePremiers () { - return Promise.resolve(testMovies.filter(movie => movie.releaseYear === 2017)) - }, - getMovieById (id) { - return Promise.resolve(testMovies.find(movie => movie.id === id)) - } - } - - beforeEach(() => { - return server.start({ - port: 3000, - repo: testRepo - }).then(serv => { - app = serv - }) - }) - - afterEach(() => { - app.close() - app = null - }) - - it('can return all movies', (done) => { - request(app) - .get('/movies') - .expect((res) => { - res.body.should.containEql({ - 'id': '1', - 'title': 'Assasins Creed', - 'format': 'IMAX', - 'releaseYear': 2017, - 'releaseMonth': 1, - 'releaseDay': 6 - }) - }) - .expect(200, done) - }) - - it('can get movie premiers', (done) => { - request(app) - .get('/movies/premieres') - .expect((res) => { - res.body.should.containEql({ - 'id': '1', - 'title': 'Assasins Creed', - 'format': 'IMAX', - 'releaseYear': 2017, - 'releaseMonth': 1, - 'releaseDay': 6 - }) - }) - .expect(200, done) - }) - - it('returns 200 for an known movie', (done) => { - request(app) - .get('/movies/1') - .expect((res) => { - res.body.should.containEql({ - 'id': '1', - 'title': 'Assasins Creed', - 'format': 'IMAX', - 'releaseYear': 2017, - 'releaseMonth': 1, - 'releaseDay': 6 - }) - }) - .expect(200, done) - }) -}) diff --git a/movies-service/src/config/config.js b/movies-service/src/config/config.js deleted file mode 100644 index 3f35c93..0000000 --- a/movies-service/src/config/config.js +++ /dev/null @@ -1,45 +0,0 @@ -const dbSettings = { - db: process.env.DB || 'movies', - user: process.env.DB_USER || 'cristian', - pass: process.env.DB_PASS || 'cristianPassword2017', - repl: process.env.DB_REPLS || 'rs1', - servers: (process.env.DB_SERVERS) ? process.env.DB_SERVERS.split(' ') : [ - '192.168.99.100:27017', - '192.168.99.101:27017', - '192.168.99.102:27017' - ], - dbParameters: () => ({ - w: 'majority', - wtimeout: 10000, - j: true, - readPreference: 'ReadPreference.SECONDARY_PREFERRED', - native_parser: false - }), - serverParameters: () => ({ - autoReconnect: true, - poolSize: 10, - socketoptions: { - keepAlive: 300, - connectTimeoutMS: 30000, - socketTimeoutMS: 30000 - } - }), - replsetParameters: (replset = 'rs1') => ({ - replicaSet: replset, - ha: true, - haInterval: 10000, - poolSize: 10, - socketoptions: { - keepAlive: 300, - connectTimeoutMS: 30000, - socketTimeoutMS: 30000 - } - }) -} - -const serverSettings = { - port: process.env.PORT || 3000, - ssl: require('./ssl') -} - -module.exports = Object.assign({}, { dbSettings, serverSettings }) diff --git a/movies-service/src/config/index.js b/movies-service/src/config/index.js deleted file mode 100644 index c7e7993..0000000 --- a/movies-service/src/config/index.js +++ /dev/null @@ -1,4 +0,0 @@ -const {dbSettings, serverSettings} = require('./config') -const db = require('./mongo') - -module.exports = Object.assign({}, {dbSettings, serverSettings, db}) diff --git a/movies-service/src/config/mongo.js b/movies-service/src/config/mongo.js deleted file mode 100644 index 18fce0f..0000000 --- a/movies-service/src/config/mongo.js +++ /dev/null @@ -1,32 +0,0 @@ -const MongoClient = require('mongodb') - -const getMongoURL = (options) => { - const url = options.servers - .reduce((prev, cur) => prev + cur + ',', 'mongodb://') - - return `${url.substr(0, url.length - 1)}/${options.db}` -} - -const connect = (options, mediator) => { - mediator.once('boot.ready', () => { - MongoClient.connect( - getMongoURL(options), { - db: options.dbParameters(), - server: options.serverParameters(), - replset: options.replsetParameters(options.repl) - }, (err, db) => { - if (err) { - mediator.emit('db.error', err) - } - - db.admin().authenticate(options.user, options.pass, (err, result) => { - if (err) { - mediator.emit('db.error', err) - } - mediator.emit('db.ready', db) - }) - }) - }) -} - -module.exports = Object.assign({}, {connect}) diff --git a/movies-service/src/config/mongo.spec.js b/movies-service/src/config/mongo.spec.js deleted file mode 100644 index 6226394..0000000 --- a/movies-service/src/config/mongo.spec.js +++ /dev/null @@ -1,29 +0,0 @@ -/* eslint-env mocha */ -const {EventEmitter} = require('events') -const test = require('assert') -const mongo = require('./mongo') -const {dbSettings} = require('./config') - -describe('Mongo Connection', () => { - it('should emit db Object with an EventEmitter', (done) => { - const mediator = new EventEmitter() - - mediator.on('db.ready', (db) => { - db.admin().listDatabases((err, dbs) => { - test.equal(null, err) - test.ok(dbs.databases.length > 0) - console.log(dbs.databases) - db.close() - done() - }) - }) - - mediator.on('db.error', (err) => { - console.log(err) - }) - - mongo.connect(dbSettings, mediator) - - mediator.emit('boot.ready') - }) -}) diff --git a/movies-service/src/config/ssl/index.js b/movies-service/src/config/ssl/index.js deleted file mode 100644 index 63e4cd3..0000000 --- a/movies-service/src/config/ssl/index.js +++ /dev/null @@ -1,6 +0,0 @@ -const fs = require('fs') - -module.exports = { - key: fs.readFileSync(`${__dirname}/server.key`), - cert: fs.readFileSync(`${__dirname}/server.crt`) -} diff --git a/movies-service/src/config/ssl/server.crt b/movies-service/src/config/ssl/server.crt deleted file mode 100644 index 1bb4065..0000000 --- a/movies-service/src/config/ssl/server.crt +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDBjCCAe4CCQCBEXWr9dPFYTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJV -UzETMBEGA1UECBMKQ2FsaWZvcm5pYTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0 -cyBQdHkgTHRkMB4XDTE3MDEyNDE1MDk0OVoXDTE4MDEyNDE1MDk0OVowRTELMAkG -A1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExITAfBgNVBAoTGEludGVybmV0 -IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -ALcuRgSCQM5C/ZZ8ry706gg9Y8Y4X84VrQBBVhUSjg+UbT/dvB+i0txMwVYUs1X5 -st9P6co6yoPbHBjmKxMCJXlXl65erDyoqQIeIHE6uOLpOefmXdp4YPJN9WvgB0gt -M7p0oAou5Z9IWlQpvlCG43S1LqELOVEJJDQsHaW6PnK/WV7a4ZWuVPbAvLWE7aIb -6C8/Zp/WeaQUHNOMtmOR6PVozgjm1gZUikGJFJpOHTgLVyHvO8WfY9KlM+yjKf8w -M1Z9VjZUsKHJwhG8CILha7uzO4MJi3tV9PkQvpTsGoovSAGR4uQ0maDa6XFfvvaW -d/vPG5jkZ1UvZcaDH+hOa4MCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAX65QrUcv -+UmgsNopeBAUNtfBNbGsLaMlBKOE97oqYnVNUuYvHXWOa88bM1k82lnpBQwk3FCp -kDWgCzzhwmXmSbEMe7sdlYdQ2yu9L+lzUXM9H3RJPPz9qqnb36mjzkpBSZSm3+GP -Rq14dcz6shQHcGkSrgRaDkxuMjCQz5TrtqU5BtlTOsbkEUlrJJsSnAgv4iQJO1FL -m0RYm3/hHyt2TIp+1Na7MDdvYhIl2okOFKjirkbvQwo3DRe0fYht9XQ7gQMIYqC2 -Taect86m2tAfkt/1jANxQZPJbziF8uU0MMfZDnPkXxPbGqdLJ+6KuAdTb04Dc+J9 -wyV1E9UYUr9urQ== ------END CERTIFICATE----- diff --git a/movies-service/src/config/ssl/server.csr b/movies-service/src/config/ssl/server.csr deleted file mode 100644 index 4162d61..0000000 --- a/movies-service/src/config/ssl/server.csr +++ /dev/null @@ -1,17 +0,0 @@ ------BEGIN CERTIFICATE REQUEST----- -MIICozCCAYsCAQAwRTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWEx -ITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBALcuRgSCQM5C/ZZ8ry706gg9Y8Y4X84VrQBBVhUS -jg+UbT/dvB+i0txMwVYUs1X5st9P6co6yoPbHBjmKxMCJXlXl65erDyoqQIeIHE6 -uOLpOefmXdp4YPJN9WvgB0gtM7p0oAou5Z9IWlQpvlCG43S1LqELOVEJJDQsHaW6 -PnK/WV7a4ZWuVPbAvLWE7aIb6C8/Zp/WeaQUHNOMtmOR6PVozgjm1gZUikGJFJpO -HTgLVyHvO8WfY9KlM+yjKf8wM1Z9VjZUsKHJwhG8CILha7uzO4MJi3tV9PkQvpTs -GoovSAGR4uQ0maDa6XFfvvaWd/vPG5jkZ1UvZcaDH+hOa4MCAwEAAaAZMBcGCSqG -SIb3DQEJBzEKEwgxMjM0Y2NjYzANBgkqhkiG9w0BAQUFAAOCAQEAjfTnbOnZmQrk -yewPclJA2Qh+OHryTf5mI5pXk1vVc88pjq5DB0SsZXsO9RUxQf7fuC+lHhQWISCX -0c//Xc/Ns3JU17q/CwY1sJ2GkBxq9qd+wTH6o9WL0gkPTC9CS3ddZlpWxpc6K2u6 -WY3/1COya8pgWM+uxdRymWVtg1ZPXnGcNA2tUJFNDRZkRScW/LynD364dYIJmDcp -oxjBLZ0RmnmvD2B0Zp1RhElHW5mEvgsFgn4c6fv122U8Zsk62NfpIMSOnLWVTycG -LKxxvDrLOwcIRD72Hp5HPDqR/jY0y5oibglkIYY1bwedikbx5gvvGHL+N/Pheo84 -6sK8ClfKCQ== ------END CERTIFICATE REQUEST----- diff --git a/movies-service/src/config/ssl/server.key b/movies-service/src/config/ssl/server.key deleted file mode 100644 index f4d1ac3..0000000 --- a/movies-service/src/config/ssl/server.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAty5GBIJAzkL9lnyvLvTqCD1jxjhfzhWtAEFWFRKOD5RtP928 -H6LS3EzBVhSzVfmy30/pyjrKg9scGOYrEwIleVeXrl6sPKipAh4gcTq44uk55+Zd -2nhg8k31a+AHSC0zunSgCi7ln0haVCm+UIbjdLUuoQs5UQkkNCwdpbo+cr9ZXtrh -la5U9sC8tYTtohvoLz9mn9Z5pBQc04y2Y5Ho9WjOCObWBlSKQYkUmk4dOAtXIe87 -xZ9j0qUz7KMp/zAzVn1WNlSwocnCEbwIguFru7M7gwmLe1X0+RC+lOwaii9IAZHi -5DSZoNrpcV++9pZ3+88bmORnVS9lxoMf6E5rgwIDAQABAoIBAGI8VJxSZgK3dltf -3mrmOSPWGE3TKb3Rbge3Aj0myDyessAPX7XvkflGyGArlclDsaOErbIgOT7hIH5R -4UO+YO5kBRoj92ZIZOqX0XonrcMypDUzG53v9L29BSKm8ADLDPSvWqxbXhU/rgF4 -qXFyBUUvbSQ8aq6Eon/AMN4RtS+/eTsfn9oH4eBnaomccJnrGl+qTAhgzkLho7Ra -D6Czenr3fF/udZP8ped+URyazmmmJ41Qwy3GCkSS8YrO5qONvr1ARnNTSmxzaB9E -o14WXWfdOpw3CRow0bVqcd0ZoYtM0YyRgTc3DCpcWm+P5GYyUDkeATMlKdrlH9qM -Kj3REsECgYEA7GcfBPd9RloCRS9H4AQVepo6GP5aG8QrWB09njv7jlyF/HtQo5Ky -XVJ1gWqIc6pQARYRA7HT7LXAdP8Wa22Tp/YklecvBGxv+YqiMyTxMYsHmPXjeiQg -+pwQi350v6L81hB2c6yqFnRT/j2TDoT8qsxPolxqwuHpn8bdvA4GZTMCgYEAxl2w -Ckpe1G0n+YFhWsfDlr7AqXYYxstTXw7eS8cCYU9KKtfn0vTc4nKbiCbuGFpgSw0x -ARgzMA+r9azwN6cvAcpvxUAk6r/278S7U9beH4s/mMBT9hcFkzi2FXXNNoj8A3qI -OnYx/QX6EknS3cN3dk6r37oXNwuwNwSdEOsVQHECgYEAhh1Kn8q4K31M5GsaX6Bx -fwiYBS3nePElleug1XA6Gl2rNb3P1byXrBHnz+/cUaJBmRwnsuzjydqiwL0mvvN/ -XT5rKw/owJ20OOHJezJuEylIuiJlVxnAC+0WBc1L9pxEzDyytpUyOWLtc8MC9q3D -mjImy3map8z6eUac7N8YCbkCgYAhYqc8NCQdsHln3sSZ2MEsX9JhMwUcgB/6AbCc -JFRcOFINP+U+dgOvAQb4NUUhSCSovQGgY4hJ8HlKkd6kHzkkHgQNuKv97m0LEZtN -kv4zZOZBOS1oX5uKmaLbncX6BbgUhczjufzTzuu1pEMfG8TBXqBCuTkrBIaV2+rr -bAVZoQKBgQDeMKV+A9y/vo6Uy63cC8kBUR4bGFqNIgTc8WWmo7wpjAeRsve10cTt -br72GRqvCByQqjqYXhw0uQIKL6eSUeiXOBIz2xBkxb2F7NapeI84Gt0v1qBb27fl -4qEMBxUI/9cP34b8459cFN/eBcBkyqVMeTtZqva0rn++aVifkyTnYw== ------END RSA PRIVATE KEY----- diff --git a/movies-service/src/index.js b/movies-service/src/index.js deleted file mode 100644 index 86a48c6..0000000 --- a/movies-service/src/index.js +++ /dev/null @@ -1,45 +0,0 @@ -'use strict' -const {EventEmitter} = require('events') -const server = require('./server/server') -const repository = require('./repository/repository') -const config = require('./config/') -const mediator = new EventEmitter() - -console.log('--- Movies Service ---') -console.log('Connecting to movies repository...') - -process.on('uncaughtException', (err) => { - console.error('Unhandled Exception', err) -}) - -process.on('uncaughtRejection', (err, promise) => { - console.error('Unhandled Rejection', err) -}) - -mediator.on('db.ready', (db) => { - let rep - repository.connect(db) - .then(repo => { - console.log('Connected. Starting Server') - rep = repo - return server.start({ - port: config.serverSettings.port, - ssl: config.serverSettings.ssl, - repo - }) - }) - .then(app => { - console.log(`Server started succesfully, running on port: ${config.serverSettings.port}.`) - app.on('close', () => { - rep.disconnect() - }) - }) -}) - -mediator.on('db.error', (err) => { - console.error(err) -}) - -config.db.connect(config.dbSettings, mediator) - -mediator.emit('boot.ready') diff --git a/movies-service/src/mock/movies.js b/movies-service/src/mock/movies.js deleted file mode 100644 index b59106d..0000000 --- a/movies-service/src/mock/movies.js +++ /dev/null @@ -1,46 +0,0 @@ -module.exports = [{ - id: '1', - title: 'Assasins Creed', - runtime: 115, - format: 'IMAX', - plot: 'Lorem ipsum dolor sit amet', - releaseYear: 2017, - releaseMonth: 1, - releaseDay: 6 -}, { - id: '2', - title: 'Aliados', - runtime: 124, - format: 'IMAX', - plot: 'Lorem ipsum dolor sit amet', - releaseYear: 2017, - releaseMonth: 1, - releaseDay: 13 -}, { - id: '3', - title: 'xXx: Reactivado', - runtime: 107, - format: 'IMAX', - plot: 'Lorem ipsum dolor sit amet', - releaseYear: 2017, - releaseMonth: 1, - releaseDay: 20 -}, { - id: '4', - title: 'Resident Evil: Capitulo Final', - runtime: 107, - format: 'IMAX', - plot: 'Lorem ipsum dolor sit amet', - releaseYear: 2017, - releaseMonth: 1, - releaseDay: 27 -}, { - id: '5', - title: 'Moana: Un Mar de Aventuras', - runtime: 114, - format: 'IMAX', - plot: 'Lorem ipsum dolor sit amet', - releaseYear: 2016, - releaseMonth: 12, - releaseDay: 2 -}] diff --git a/movies-service/src/repository/repository.js b/movies-service/src/repository/repository.js deleted file mode 100644 index 3c5f559..0000000 --- a/movies-service/src/repository/repository.js +++ /dev/null @@ -1,88 +0,0 @@ -'use strict' - -const repository = (db) => { - const collection = db.collection('movies') - - const getAllMovies = () => { - return new Promise((resolve, reject) => { - const movies = [] - const cursor = collection.find({}, {title: 1, id: 1}) - const addMovie = (movie) => { - movies.push(movie) - } - const sendMovies = (err) => { - if (err) { - reject(new Error('An error occured fetching all movies, err:' + err)) - } - resolve(movies.slice()) - } - cursor.forEach(addMovie, sendMovies) - }) - } - - const getMoviePremiers = () => { - return new Promise((resolve, reject) => { - const movies = [] - const currentDay = new Date() - const query = { - releaseYear: { - $gt: currentDay.getFullYear() - 1, - $lte: currentDay.getFullYear() - }, - releaseMonth: { - $gte: currentDay.getMonth() + 1, - $lte: currentDay.getMonth() + 2 - }, - releaseDay: { - $lte: currentDay.getDate() - } - } - const cursor = collection.find(query) - const addMovie = (movie) => { - movies.push(movie) - } - const sendMovies = (err) => { - if (err) { - reject(new Error('An error occured fetching all movies, err:' + err)) - } - resolve(movies) - } - cursor.forEach(addMovie, sendMovies) - }) - } - - const getMovieById = (id) => { - return new Promise((resolve, reject) => { - const projection = { _id: 0, id: 1, title: 1, format: 1 } - const sendMovie = (err, movie) => { - if (err) { - reject(new Error(`An error occured fetching a movie with id: ${id}, err: ${err}`)) - } - resolve(movie) - } - collection.findOne({id: id}, projection, sendMovie) - }) - } - - const disconnect = () => { - db.close() - } - - return Object.create({ - getAllMovies, - getMoviePremiers, - getMovieById, - disconnect - }) -} - -const connect = (connection) => { - return new Promise((resolve, reject) => { - if (!connection) { - reject(new Error('connection db not supplied!')) - } - resolve(repository(connection)) - }) -} - -module.exports = Object.assign({}, {connect}) diff --git a/movies-service/src/repository/repository.spec.js b/movies-service/src/repository/repository.spec.js deleted file mode 100644 index 2ff7bb2..0000000 --- a/movies-service/src/repository/repository.spec.js +++ /dev/null @@ -1,10 +0,0 @@ -/* eslint-env mocha */ -const should = require('should') -const repository = require('./repository') - -describe('Repository', () => { - it('should connect with a promise', (done) => { - repository.connect({}).should.be.a.Promise() - done() - }) -}) diff --git a/movies-service/src/server/server.js b/movies-service/src/server/server.js deleted file mode 100644 index 3b83e0e..0000000 --- a/movies-service/src/server/server.js +++ /dev/null @@ -1,29 +0,0 @@ -const express = require('express') -const morgan = require('morgan') -const helmet = require('helmet') -const api = require('../api/movies') - -const start = (options) => { - return new Promise((resolve, reject) => { - if (!options.repo) { - reject(new Error('The server must be started with a connected repository')) - } - if (!options.port) { - reject(new Error('The server must be started with an available port')) - } - - const app = express() - app.use(morgan('dev')) - app.use(helmet()) - app.use((err, req, res, next) => { - reject(new Error('Something went wrong!, err:' + err)) - res.status(500).send('Something went wrong!') - }) - - api(app, options) - - const server = app.listen(options.port, () => resolve(server)) - }) -} - -module.exports = Object.assign({}, {start}) diff --git a/movies-service/src/server/server.spec.js b/movies-service/src/server/server.spec.js deleted file mode 100644 index f552ac9..0000000 --- a/movies-service/src/server/server.spec.js +++ /dev/null @@ -1,16 +0,0 @@ -/* eslint-env mocha */ -const server = require('./server') - -describe('Server', () => { - it('should require a port to start', () => { - return server.start({ - repo: {} - }).should.be.rejectedWith(/port/) - }) - - it('should require a repository to start', () => { - return server.start({ - port: {} - }).should.be.rejectedWith(/repository/) - }) -}) diff --git a/movies-service/start-service.sh b/movies-service/start-service.sh deleted file mode 100644 index 96fb07c..0000000 --- a/movies-service/start-service.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -docker service create --replicas 1 --name movies-service -l=apiRoute='/movies' -p 3000:3000 crizstian/movies-service diff --git a/notification-service/.eslintrc.json b/notification-service/.eslintrc.json deleted file mode 100644 index a755cdb..0000000 --- a/notification-service/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": ["standard"] -} diff --git a/notification-service/Dockerfile b/notification-service/Dockerfile deleted file mode 100644 index 523816b..0000000 --- a/notification-service/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM node:7.5.0-alpine - -RUN addgroup -S nupp && adduser -S -g nupp nupp - -ENV HOME=/home/nupp - -COPY package.json npm-shrinkwrap.json $HOME/app/ - -COPY src/ $HOME/app/src - -ADD https://github.com/Yelp/dumb-init/releases/download/v1.1.1/dumb-init_1.1.1_amd64 /usr/local/bin/dumb-init - -WORKDIR $HOME/app - -RUN chown -R nupp:nupp $HOME/* /usr/local/ && \ - chmod +x /usr/local/bin/dumb-init && \ - npm cache clean && \ - npm install --silent --progress=false --production && \ - chown -R nupp:nupp $HOME/* - -USER nupp - -EXPOSE 3000 - -CMD ["dumb-init", "npm", "start"] diff --git a/notification-service/create-image.sh b/notification-service/create-image.sh deleted file mode 100644 index c198db3..0000000 --- a/notification-service/create-image.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -docker rm -f notification-service - -docker rmi notification-service - -docker image prune - -docker volume prune - -docker build -t notification-service . diff --git a/notification-service/env b/notification-service/env deleted file mode 100644 index ac29194..0000000 --- a/notification-service/env +++ /dev/null @@ -1,6 +0,0 @@ -DB=booking -DB_USER=cristian -DB_PASS=cristianPassword2017 -DB_REPLS=rs1 -DB_SERVERS='192.168.99.100:27017 192.168.99.101:27017 192.168.99.102:27017' -PORT=3000 diff --git a/notification-service/integration-test/index.js b/notification-service/integration-test/index.js deleted file mode 100644 index 5d6110a..0000000 --- a/notification-service/integration-test/index.js +++ /dev/null @@ -1,36 +0,0 @@ -/* eslint-env mocha */ -const supertest = require('supertest') - -describe('Notification Service', () => { - const api = supertest('http://192.168.99.100:3004') - const payload = { - city: 'Morelia', - userType: 'loyal', - totalAmount: 71, - cinema: { - name: 'Plaza Morelia', - room: '1', - seats: '53, 54' - }, - movie: { - title: 'Assasins Creed', - format: 'IMAX', - schedule: new Date() - }, - orderId: '1aa90cx', - description: 'some description', - user: { - name: 'Cristian Ramirez', - email: 'cristiano.rosetti@gmail.com' - } - } - - it('can send a notification via email', (done) => { - api.post('/notification/sendEmail') - .send({payload}) - .expect((res) => { - console.log(res.body) - }) - .expect(200, done) - }) -}) diff --git a/notification-service/npm-shrinkwrap.json b/notification-service/npm-shrinkwrap.json deleted file mode 100644 index d164fa1..0000000 --- a/notification-service/npm-shrinkwrap.json +++ /dev/null @@ -1,726 +0,0 @@ -{ - "name": "movies-service", - "version": "1.0.0", - "dependencies": { - "accepts": { - "version": "1.3.3", - "from": "accepts@>=1.3.3 <1.4.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz" - }, - "array-flatten": { - "version": "1.1.1", - "from": "array-flatten@1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" - }, - "awilix": { - "version": "2.2.2", - "from": "awilix@latest", - "resolved": "https://registry.npmjs.org/awilix/-/awilix-2.2.2.tgz" - }, - "balanced-match": { - "version": "0.4.2", - "from": "balanced-match@>=0.4.1 <0.5.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz" - }, - "basic-auth": { - "version": "1.0.4", - "from": "basic-auth@>=1.0.3 <1.1.0", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz" - }, - "body-parser": { - "version": "1.16.0", - "from": "body-parser@latest", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.16.0.tgz", - "dependencies": { - "qs": { - "version": "6.2.1", - "from": "qs@6.2.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.1.tgz" - } - } - }, - "brace-expansion": { - "version": "1.1.6", - "from": "brace-expansion@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz" - }, - "bson": { - "version": "0.4.23", - "from": "bson@>=0.4.23 <0.5.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-0.4.23.tgz" - }, - "buffer-shims": { - "version": "1.0.0", - "from": "buffer-shims@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" - }, - "bytes": { - "version": "2.4.0", - "from": "bytes@2.4.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz" - }, - "camel-case": { - "version": "3.0.0", - "from": "camel-case@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz" - }, - "camelize": { - "version": "1.0.0", - "from": "camelize@1.0.0", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz" - }, - "concat-map": { - "version": "0.0.1", - "from": "concat-map@0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" - }, - "connect": { - "version": "3.5.0", - "from": "connect@3.5.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.5.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "content-disposition": { - "version": "0.5.1", - "from": "content-disposition@0.5.1", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz" - }, - "content-security-policy-builder": { - "version": "1.1.0", - "from": "content-security-policy-builder@1.1.0", - "resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-1.1.0.tgz" - }, - "content-type": { - "version": "1.0.2", - "from": "content-type@>=1.0.2 <1.1.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz" - }, - "cookie": { - "version": "0.3.1", - "from": "cookie@0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz" - }, - "cookie-signature": { - "version": "1.0.6", - "from": "cookie-signature@1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" - }, - "core-util-is": { - "version": "1.0.2", - "from": "core-util-is@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" - }, - "cors": { - "version": "2.8.1", - "from": "cors@latest", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.1.tgz" - }, - "dasherize": { - "version": "2.0.0", - "from": "dasherize@2.0.0", - "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz" - }, - "dashify": { - "version": "0.2.2", - "from": "dashify@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/dashify/-/dashify-0.2.2.tgz" - }, - "debug": { - "version": "2.6.0", - "from": "debug@>=2.1.1 <3.0.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz" - }, - "depd": { - "version": "1.1.0", - "from": "depd@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz" - }, - "destroy": { - "version": "1.0.4", - "from": "destroy@>=1.0.4 <1.1.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" - }, - "dns-prefetch-control": { - "version": "0.1.0", - "from": "dns-prefetch-control@0.1.0", - "resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz" - }, - "dont-sniff-mimetype": { - "version": "1.0.0", - "from": "dont-sniff-mimetype@1.0.0", - "resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.0.0.tgz" - }, - "ee-first": { - "version": "1.1.1", - "from": "ee-first@1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" - }, - "encodeurl": { - "version": "1.0.1", - "from": "encodeurl@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz" - }, - "es6-promise": { - "version": "3.0.2", - "from": "es6-promise@3.0.2", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz" - }, - "escape-html": { - "version": "1.0.3", - "from": "escape-html@>=1.0.3 <1.1.0", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" - }, - "etag": { - "version": "1.7.0", - "from": "etag@>=1.7.0 <1.8.0", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz" - }, - "express": { - "version": "4.14.0", - "from": "express@latest", - "resolved": "https://registry.npmjs.org/express/-/express-4.14.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - }, - "qs": { - "version": "6.2.0", - "from": "qs@6.2.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz" - } - } - }, - "finalhandler": { - "version": "0.5.0", - "from": "finalhandler@0.5.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@~2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "forwarded": { - "version": "0.1.0", - "from": "forwarded@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz" - }, - "frameguard": { - "version": "3.0.0", - "from": "frameguard@3.0.0", - "resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.0.0.tgz" - }, - "fresh": { - "version": "0.3.0", - "from": "fresh@0.3.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz" - }, - "fs.realpath": { - "version": "1.0.0", - "from": "fs.realpath@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" - }, - "glob": { - "version": "7.1.1", - "from": "glob@>=7.0.3 <8.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz" - }, - "handle-thing": { - "version": "1.2.5", - "from": "handle-thing@>=1.2.4 <2.0.0", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz" - }, - "helmet": { - "version": "3.4.0", - "from": "helmet@>=3.4.0 <4.0.0", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.4.0.tgz" - }, - "helmet-csp": { - "version": "2.3.0", - "from": "helmet-csp@2.3.0", - "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.3.0.tgz" - }, - "hide-powered-by": { - "version": "1.0.0", - "from": "hide-powered-by@1.0.0", - "resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.0.0.tgz" - }, - "hpack.js": { - "version": "2.1.6", - "from": "hpack.js@>=2.1.6 <3.0.0", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz" - }, - "hpkp": { - "version": "2.0.0", - "from": "hpkp@2.0.0", - "resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz" - }, - "hsts": { - "version": "2.0.0", - "from": "hsts@2.0.0", - "resolved": "https://registry.npmjs.org/hsts/-/hsts-2.0.0.tgz" - }, - "http-deceiver": { - "version": "1.2.7", - "from": "http-deceiver@>=1.2.4 <2.0.0", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" - }, - "http-errors": { - "version": "1.5.1", - "from": "http-errors@>=1.5.0 <1.6.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz" - }, - "http-status": { - "version": "0.2.5", - "from": "http-status@latest", - "resolved": "https://registry.npmjs.org/http-status/-/http-status-0.2.5.tgz" - }, - "httpntlm": { - "version": "1.6.1", - "from": "httpntlm@1.6.1", - "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz" - }, - "httpreq": { - "version": "0.4.22", - "from": "httpreq@>=0.4.22", - "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.22.tgz" - }, - "iconv-lite": { - "version": "0.4.15", - "from": "iconv-lite@0.4.15", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz" - }, - "ienoopen": { - "version": "1.0.0", - "from": "ienoopen@1.0.0", - "resolved": "https://registry.npmjs.org/ienoopen/-/ienoopen-1.0.0.tgz" - }, - "inflight": { - "version": "1.0.6", - "from": "inflight@>=1.0.4 <2.0.0", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" - }, - "inherits": { - "version": "2.0.3", - "from": "inherits@>=2.0.3 <3.0.0", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - }, - "ipaddr.js": { - "version": "1.2.0", - "from": "ipaddr.js@1.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.2.0.tgz" - }, - "is-class": { - "version": "0.0.4", - "from": "is-class@0.0.4", - "resolved": "https://registry.npmjs.org/is-class/-/is-class-0.0.4.tgz" - }, - "is-plain-object": { - "version": "2.0.1", - "from": "is-plain-object@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.1.tgz" - }, - "is-string": { - "version": "1.0.4", - "from": "is-string@>=1.0.4 <2.0.0", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.4.tgz" - }, - "isarray": { - "version": "1.0.0", - "from": "isarray@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - }, - "isemail": { - "version": "2.2.1", - "from": "isemail@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/isemail/-/isemail-2.2.1.tgz" - }, - "isobject": { - "version": "1.0.2", - "from": "isobject@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-1.0.2.tgz" - }, - "items": { - "version": "2.1.1", - "from": "items@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/items/-/items-2.1.1.tgz" - }, - "joi": { - "version": "10.2.0", - "from": "joi@latest", - "resolved": "https://registry.npmjs.org/joi/-/joi-10.2.0.tgz", - "dependencies": { - "hoek": { - "version": "4.1.0", - "from": "hoek@>=4.0.0 <5.0.0", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.1.0.tgz" - } - } - }, - "lodash.reduce": { - "version": "4.6.0", - "from": "lodash.reduce@4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz" - }, - "lower-case": { - "version": "1.1.3", - "from": "lower-case@>=1.1.1 <2.0.0", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.3.tgz" - }, - "media-typer": { - "version": "0.3.0", - "from": "media-typer@0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" - }, - "merge-descriptors": { - "version": "1.0.1", - "from": "merge-descriptors@1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" - }, - "methods": { - "version": "1.1.2", - "from": "methods@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" - }, - "mime": { - "version": "1.3.4", - "from": "mime@>=1.3.4 <2.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" - }, - "mime-db": { - "version": "1.26.0", - "from": "mime-db@>=1.26.0 <1.27.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.26.0.tgz" - }, - "mime-types": { - "version": "2.1.14", - "from": "mime-types@>=2.1.10 <3.0.0", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.14.tgz" - }, - "minimalistic-assert": { - "version": "1.0.0", - "from": "minimalistic-assert@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" - }, - "minimatch": { - "version": "3.0.3", - "from": "minimatch@>=3.0.2 <4.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz" - }, - "mongodb": { - "version": "2.1.18", - "from": "mongodb@2.1.18", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.1.18.tgz", - "dependencies": { - "isarray": { - "version": "0.0.1", - "from": "isarray@0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" - }, - "readable-stream": { - "version": "1.0.31", - "from": "readable-stream@1.0.31", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.31.tgz" - } - } - }, - "mongodb-core": { - "version": "1.3.18", - "from": "mongodb-core@1.3.18", - "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-1.3.18.tgz" - }, - "morgan": { - "version": "1.7.0", - "from": "morgan@latest", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.7.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@~2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "ms": { - "version": "0.7.2", - "from": "ms@0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz" - }, - "negotiator": { - "version": "0.6.1", - "from": "negotiator@0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz" - }, - "no-case": { - "version": "2.3.1", - "from": "no-case@>=2.2.0 <3.0.0", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.1.tgz" - }, - "nocache": { - "version": "2.0.0", - "from": "nocache@2.0.0", - "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.0.0.tgz" - }, - "nodemailer": { - "version": "3.0.2", - "from": "nodemailer@latest", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-3.0.2.tgz" - }, - "nodemailer-fetch": { - "version": "1.6.0", - "from": "nodemailer-fetch@1.6.0", - "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz" - }, - "nodemailer-shared": { - "version": "1.1.0", - "from": "nodemailer-shared@1.1.0", - "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz" - }, - "nodemailer-smtp-transport": { - "version": "2.7.2", - "from": "nodemailer-smtp-transport@latest", - "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.2.tgz" - }, - "nodemailer-wellknown": { - "version": "0.1.10", - "from": "nodemailer-wellknown@0.1.10", - "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz" - }, - "obuf": { - "version": "1.1.1", - "from": "obuf@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz" - }, - "on-finished": { - "version": "2.3.0", - "from": "on-finished@>=2.3.0 <2.4.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" - }, - "on-headers": { - "version": "1.0.1", - "from": "on-headers@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" - }, - "once": { - "version": "1.4.0", - "from": "once@>=1.3.0 <2.0.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - }, - "parseurl": { - "version": "1.3.1", - "from": "parseurl@>=1.3.1 <1.4.0", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz" - }, - "path-is-absolute": { - "version": "1.0.1", - "from": "path-is-absolute@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - }, - "path-to-regexp": { - "version": "0.1.7", - "from": "path-to-regexp@0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" - }, - "platform": { - "version": "1.3.3", - "from": "platform@1.3.3", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.3.tgz" - }, - "process-nextick-args": { - "version": "1.0.7", - "from": "process-nextick-args@>=1.0.6 <1.1.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" - }, - "proxy-addr": { - "version": "1.1.3", - "from": "proxy-addr@>=1.1.2 <1.2.0", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.3.tgz" - }, - "range-parser": { - "version": "1.2.0", - "from": "range-parser@>=1.2.0 <1.3.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz" - }, - "raw-body": { - "version": "2.2.0", - "from": "raw-body@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz" - }, - "readable-stream": { - "version": "2.2.2", - "from": "readable-stream@>=2.2.2 <3.0.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.2.tgz" - }, - "referrer-policy": { - "version": "1.1.0", - "from": "referrer-policy@1.1.0", - "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.1.0.tgz" - }, - "require_optional": { - "version": "1.0.0", - "from": "require_optional@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.0.tgz", - "dependencies": { - "resolve-from": { - "version": "2.0.0", - "from": "resolve-from@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz" - } - } - }, - "select-hose": { - "version": "2.0.0", - "from": "select-hose@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" - }, - "semver": { - "version": "5.3.0", - "from": "semver@>=5.1.0 <6.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz" - }, - "send": { - "version": "0.14.1", - "from": "send@0.14.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.14.1.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@~2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "serve-static": { - "version": "1.11.1", - "from": "serve-static@>=1.11.1 <1.12.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.11.1.tgz" - }, - "setprototypeof": { - "version": "1.0.2", - "from": "setprototypeof@1.0.2", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz" - }, - "smtp-connection": { - "version": "2.12.0", - "from": "smtp-connection@2.12.0", - "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz" - }, - "spdy": { - "version": "3.4.4", - "from": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz" - }, - "spdy-transport": { - "version": "2.0.18", - "from": "spdy-transport@>=2.0.15 <3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.18.tgz" - }, - "statuses": { - "version": "1.3.1", - "from": "statuses@>=1.3.0 <1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz" - }, - "string_decoder": { - "version": "0.10.31", - "from": "string_decoder@>=0.10.0 <0.11.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - }, - "topo": { - "version": "2.0.2", - "from": "topo@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", - "dependencies": { - "hoek": { - "version": "4.1.0", - "from": "hoek@4.x.x", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.1.0.tgz" - } - } - }, - "type-is": { - "version": "1.6.14", - "from": "type-is@>=1.6.13 <1.7.0", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.14.tgz" - }, - "underscore": { - "version": "1.7.0", - "from": "underscore@>=1.7.0 <1.8.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz" - }, - "unpipe": { - "version": "1.0.0", - "from": "unpipe@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" - }, - "upper-case": { - "version": "1.1.3", - "from": "upper-case@>=1.1.1 <2.0.0", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz" - }, - "util-deprecate": { - "version": "1.0.2", - "from": "util-deprecate@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - }, - "utils-merge": { - "version": "1.0.0", - "from": "utils-merge@1.0.0", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" - }, - "vary": { - "version": "1.1.0", - "from": "vary@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.0.tgz" - }, - "wbuf": { - "version": "1.7.2", - "from": "wbuf@>=1.4.0 <2.0.0", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz" - }, - "wrappy": { - "version": "1.0.2", - "from": "wrappy@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - }, - "x-xss-protection": { - "version": "1.0.0", - "from": "x-xss-protection@1.0.0", - "resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.0.0.tgz" - } - } -} diff --git a/notification-service/package.json b/notification-service/package.json deleted file mode 100644 index ad6810a..0000000 --- a/notification-service/package.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "name": "movies-service", - "version": "1.0.0", - "description": "A movie service, microservice example with nodejs", - "author": "Cristian Ramirez Rosas ", - "license": "ISC", - "main": "index.js", - "standard": { - "ignore": [ - "mock/**.js" - ] - }, - "scripts": { - "test": "mocha -R spec src/**/*.spec.js", - "start": "node src/index.js", - "lint": "standard --verbose | snazzy", - "node-debug": "DEBUG=express* node src/index.js", - "chrome-debug": "node --debug-brk --inspect src/index.js", - "coverage": "istanbul cover _mocha $(find ./src -name \"*.spec.js\" -not -path \"./node_modules/*\") ", - "metric": "nodejs-dashboard -- node -r nodejs-dashboard src/index.js" - }, - "keywords": [ - "express", - "mongodb", - "docker", - "microservice" - ], - "devDependencies": { - "eslint": "^3.13.1", - "mocha": "^3.2.0", - "nodejs-dashboard": "^0.3.0", - "should": "^11.1.2", - "snazzy": "^6.0.0", - "standard": "^8.6.0", - "supertest": "^2.0.1" - }, - "dependencies": { - "awilix": "^2.2.2", - "body-parser": "^1.16.0", - "cors": "^2.8.1", - "express": "^4.14.0", - "helmet": "^3.4.0", - "http-status": "^0.2.5", - "joi": "^10.2.0", - "mongodb": "^2.1.18", - "morgan": "^1.7.0", - "nodemailer": "^3.0.2", - "nodemailer-smtp-transport": "^2.7.2", - "spdy": "^3.4.4" - } -} diff --git a/notification-service/readme.md b/notification-service/readme.md deleted file mode 100644 index b0f5656..0000000 --- a/notification-service/readme.md +++ /dev/null @@ -1,40 +0,0 @@ -## Build a NodeJS microservice and deploy it to Docker - -[![Standard - JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/) - -Example of the **notification service** microservice and API. - -![](https://cdn-images-1.medium.com/max/1600/1*jxFIFA8WI8TkMmdbOorOsA.png) - -### Stack -- NodeJS 7.5.0 -- MongoDB 3.4.1 -- Docker for Mac 1.13 - -### how to run it - -**This to run our microservice in a docker container** -we need docker installed -``` -$ bash < start-service.sh -``` - -**To run in locally** -we need nodejs installed - -- install the dependencies -``` -$ npm i --silent -``` - -- run the tests -``` -$ npm test -``` - -- start the service -``` -$ npm start -``` - -[![Standard - JavaScript Style Guide](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard) diff --git a/notification-service/src/api/notification.js b/notification-service/src/api/notification.js deleted file mode 100644 index e052f17..0000000 --- a/notification-service/src/api/notification.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict' -const status = require('http-status') - -module.exports = ({repo}, app) => { - app.post('/notification/sendEmail', (req, res, next) => { - const {validate} = req.container.cradle - - validate(req.body.payload, 'notification') - .then(payload => { - return repo.sendEmail(payload) - }) - .then(ok => { - res.status(status.OK).json({msg: 'ok'}) - }) - .catch(next) - }) - - app.post('/notification/sendSMS', (req, res, next) => { - const {validate} = req.container.cradle - - validate(req.body.payload, 'notification') - .then(payload => { - return repo.sendSMS(payload) - }) - .then(ok => { - res.status(status.OK).json({msg: 'ok'}) - }) - .catch(next) - }) -} diff --git a/notification-service/src/api/notification.spec.js b/notification-service/src/api/notification.spec.js deleted file mode 100644 index 01ec88e..0000000 --- a/notification-service/src/api/notification.spec.js +++ /dev/null @@ -1,122 +0,0 @@ -/* eslint-env mocha */ -const { createContainer, asValue } = require('awilix') -const nodemailer = require('nodemailer') -const smtpTransport = require('nodemailer-smtp-transport') -const should = require('should') -const request = require('supertest') -const server = require('../server/server') -const models = require('../models') -const {smtpSettings} = require('../config/config') - -describe('Booking API', () => { - let app = null - - const serverSettings = { - port: 3000 - } - - const container = createContainer() - - container.register({ - validate: asValue(models.validate), - serverSettings: asValue(serverSettings), - smtpSettings: asValue(smtpSettings), - nodemailer: asValue(nodemailer), - smtpTransport: asValue(smtpTransport) - }) - - let _testRepo = { - sendEmail ({container}, payload) { - return new Promise((resolve, reject) => { - const {smtpSettings, smtpTransport, nodemailer} = container.cradle - - const transporter = nodemailer.createTransport( - smtpTransport({ - service: smtpSettings.service, - auth: { - user: smtpSettings.user, - pass: smtpSettings.pass - } - })) - - const mailOptions = { - from: '"Do Not Reply, Cinemas Company 👥" ', - to: `${payload.user.email}`, - subject: `Tickects for movie ${payload.movie.title}`, - html: ` -

Tickest for ${payload.movie.title}

- -

Cinema: ${payload.cinema.name}

-

Room: ${payload.cinema.room}

-

Seat(s): ${payload.cinema.seats}

- -

description: ${payload.description}

- -

Total: ${payload.totalAmount}

-

number of order: ${payload.orderId}

- -

Cinemas Microserivce 2017, Enjoy your movie 🍿🎥!

- ` - } - - transporter.sendMail(mailOptions, (err, info) => { - if (err) { - reject(new Error('An error occured sending an email, err:' + err)) - } - transporter.close() - resolve(info) - }) - }) - } - } - - const testRepo = {} - - testRepo.sendEmail = _testRepo.sendEmail.bind(null, {container}) - - container.registerValue({repo: testRepo}) - - beforeEach(() => { - return server.start(container) - .then(serv => { - app = serv - }) - }) - - afterEach(() => { - app.close() - app = null - }) - - it('can make a booking and return the ticket(s)', (done) => { - const payload = { - city: 'Morelia', - userType: 'loyal', - totalAmount: 71, - cinema: { - name: 'Plaza Morelia', - room: '1', - seats: '53, 54' - }, - movie: { - title: 'Assasins Creed', - format: 'IMAX', - schedule: new Date() - }, - orderId: '1aa90cx', - description: 'some description', - user: { - name: 'Cristian Ramirez', - email: 'cristiano.rosetti@gmail.com' - } - } - - request(app) - .post('/notification/sendEmail') - .send({payload}) - .expect((res) => { - should.ok(res.body) - }) - .expect(200, done) - }) -}) diff --git a/notification-service/src/config/config.js b/notification-service/src/config/config.js deleted file mode 100644 index 0e4fbe9..0000000 --- a/notification-service/src/config/config.js +++ /dev/null @@ -1,13 +0,0 @@ -const serverSettings = { - port: process.env.PORT || 3000, - ssl: require('./ssl') -} - -// as a better practice we can pass this values via env variables -const smtpSettings = { - service: 'Gmail', - user: process.env.EMAIL, - pass: process.env.EMAIL_PASS -} - -module.exports = Object.assign({}, { serverSettings, smtpSettings }) diff --git a/notification-service/src/config/di/di.js b/notification-service/src/config/di/di.js deleted file mode 100644 index d934d0f..0000000 --- a/notification-service/src/config/di/di.js +++ /dev/null @@ -1,21 +0,0 @@ -const { createContainer, asValue } = require('awilix') -const nodemailer = require('nodemailer') -const smtpTransport = require('nodemailer-smtp-transport') - -function initDI ({serverSettings, models, smtpSettings}, mediator) { - mediator.once('init', () => { - const container = createContainer() - - container.register({ - validate: asValue(models.validate), - serverSettings: asValue(serverSettings), - smtpSettings: asValue(smtpSettings), - nodemailer: asValue(nodemailer), - smtpTransport: asValue(smtpTransport) - }) - - mediator.emit('di.ready', container) - }) -} - -module.exports.initDI = initDI diff --git a/notification-service/src/config/di/di.proto.js b/notification-service/src/config/di/di.proto.js deleted file mode 100644 index 82e6df1..0000000 --- a/notification-service/src/config/di/di.proto.js +++ /dev/null @@ -1,82 +0,0 @@ -/* - const container = createContainer() - - container.register({ - transient(user), - transient(ticket), - transient(booking), - singleton(objectID), - singleton(notifications), - singleton(payments) - }) - - function ({ User, Booking }) { - make some stuff with the user - Promise.all([ - user.validate(object), - booking.validate(object) - ]) - .then([user, booking] => { - - }) - } - -*/ - -const createContainer = () => { - // DI store - const registrations = {} - // returns the DI - const container = { - get registrations () { - return Object.assign({}, registrations) - } - } - - // DI cache systems - container.cache = {} - - const getDI = new Proxy({}, { - get: (taget, name) => resolve(name), - set: (target, name, value) => { - throw new Error('cannot set a value to the container') - } - }) - - container.getDI = getDI - - const register = (name, registration, opts) => { - const key = Symbol(name) - registrations[key] = Object.assign({}, {fn: registration}, {lifetime: opts}) - return container - } - - container.register = register - - const resolve = (name) => { - const di = registrations[name] - switch (di.lifetime) { - case 'TRANSIENT': - return container.registrations[name].fn - case 'SINGLETON': - if (!container.cache[name]) { - container.cache[name] = container.registrations[name] - } - return container.cache[name].fn - } - } - - const listDependencies = () => { - const list = [] - for (var key in registrations) { - if (registrations.hasOwnProperty(key)) { - list.push(key) - } - } - return list - } - - return Object.create(container) -} - -module.exports.createContainer = createContainer diff --git a/notification-service/src/config/di/index.js b/notification-service/src/config/di/index.js deleted file mode 100644 index ff2d63c..0000000 --- a/notification-service/src/config/di/index.js +++ /dev/null @@ -1,3 +0,0 @@ -const di = require('./di') - -module.exports = Object.assign({}, di) diff --git a/notification-service/src/config/index.di.spec.js b/notification-service/src/config/index.di.spec.js deleted file mode 100644 index 0324825..0000000 --- a/notification-service/src/config/index.di.spec.js +++ /dev/null @@ -1,25 +0,0 @@ -/* eslint-env mocha */ -const {EventEmitter} = require('events') -const test = require('assert') -const {init} = require('./') - -describe('DI configuration', () => { - it('can init dependencies to the container', (done) => { - const mediator = new EventEmitter() - - mediator.on('di.ready', (container) => { - console.log(database) - console.log(container) - done() - }) - - mediator.on('di.error', err => { - console.log(err) - done() - }) - - init(mediator) - - mediator.emit('init') - }) -}) diff --git a/notification-service/src/config/index.js b/notification-service/src/config/index.js deleted file mode 100644 index f780c9e..0000000 --- a/notification-service/src/config/index.js +++ /dev/null @@ -1,7 +0,0 @@ -const {smtpSettings, serverSettings} = require('./config') -const {initDI} = require('./di') -const models = require('../models') - -const init = initDI.bind(null, {serverSettings, smtpSettings, models}) - -module.exports = Object.assign({}, {init}) diff --git a/notification-service/src/config/ssl/index.js b/notification-service/src/config/ssl/index.js deleted file mode 100644 index 63e4cd3..0000000 --- a/notification-service/src/config/ssl/index.js +++ /dev/null @@ -1,6 +0,0 @@ -const fs = require('fs') - -module.exports = { - key: fs.readFileSync(`${__dirname}/server.key`), - cert: fs.readFileSync(`${__dirname}/server.crt`) -} diff --git a/notification-service/src/index.js b/notification-service/src/index.js deleted file mode 100644 index 19ed938..0000000 --- a/notification-service/src/index.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict' -const {EventEmitter} = require('events') -const server = require('./server/server') -const repository = require('./repository/repository') -const di = require('./config') -const mediator = new EventEmitter() - -console.log('--- Notification Service ---') -console.log('Connecting to notification repository...') - -process.on('uncaughtException', (err) => { - console.error('Unhandled Exception', err) -}) - -process.on('uncaughtRejection', (err, promise) => { - console.error('Unhandled Rejection', err) -}) - -mediator.on('di.ready', (container) => { - repository.connect(container) - .then(repo => { - console.log('Connected. Starting Server') - container.registerValue({repo}) - return server.start(container) - }) - .then(app => { - console.log(`Server started succesfully, running on port: ${container.cradle.serverSettings.port}.`) - app.on('close', () => { - container.resolve('repo').disconnect() - }) - }) -}) - -di.init(mediator) - -mediator.emit('init') diff --git a/notification-service/src/models/index.js b/notification-service/src/models/index.js deleted file mode 100644 index cf2fadc..0000000 --- a/notification-service/src/models/index.js +++ /dev/null @@ -1,24 +0,0 @@ -const joi = require('joi') -const notification = require('./notification.model')(joi) - -const schemas = Object.create({notification}) - -const schemaValidator = (object, type) => { - return new Promise((resolve, reject) => { - if (!object) { - reject(new Error('object to validate not provided')) - } - if (!type) { - reject(new Error('schema type to validate not provided')) - } - - const {error, value} = joi.validate(object, schemas[type]) - - if (error) { - reject(new Error(`invalid ${type} data, err: ${error}`)) - } - resolve(value) - }) -} - -module.exports = Object.create({validate: schemaValidator, schemas}) diff --git a/notification-service/src/models/index.spec.js b/notification-service/src/models/index.spec.js deleted file mode 100644 index 763f7a8..0000000 --- a/notification-service/src/models/index.spec.js +++ /dev/null @@ -1,42 +0,0 @@ -/* eslint-env mocha */ -const test = require('assert') -const {validate} = require('./') - -console.log(Object.getPrototypeOf(validate)) - -describe('Schemas Validation', () => { - it('can validate a notification object', (done) => { - const notificationSchema = { - city: 'Morelia', - userType: 'loyal', - totalAmount: 71, - cinema: { - name: 'Plaza Morelia', - room: '1', - seats: '53, 54' - }, - movie: { - title: 'Assasins Creed', - format: 'IMAX', - schedule: new Date() - }, - orderId: '1aa90cx', - description: 'some description', - user: { - name: 'Cristian Ramirez', - email: 'cristiano.rosetti@gmail.com' - } - } - - validate(notificationSchema, 'notification') - .then(value => { - test.ok(value) - console.log(value) - done() - }) - .catch(err => { - console.log(err) - done() - }) - }) -}) diff --git a/notification-service/src/models/notification.model.js b/notification-service/src/models/notification.model.js deleted file mode 100644 index 7d1c73d..0000000 --- a/notification-service/src/models/notification.model.js +++ /dev/null @@ -1,25 +0,0 @@ - -const notificationSchema = (joi) => ({ - city: joi.string(), - userType: joi.string(), - totalAmount: joi.number(), - cinema: joi.object().keys({ - name: joi.string(), - room: joi.number(), - seats: joi.string() - }), - movie: joi.object().keys({ - title: joi.string(), - format: joi.string(), - schedule: joi.date() - }), - orderId: joi.string(), - _id: joi.string(), - description: joi.string(), - user: joi.object().keys({ - name: joi.string(), - email: joi.string().email() - }) -}) - -module.exports = notificationSchema diff --git a/notification-service/src/repository/repository.js b/notification-service/src/repository/repository.js deleted file mode 100644 index f3a1fed..0000000 --- a/notification-service/src/repository/repository.js +++ /dev/null @@ -1,65 +0,0 @@ -'use strict' -const repository = (container) => { - const sendEmail = (payload) => { - return new Promise((resolve, reject) => { - const {smtpSettings, smtpTransport, nodemailer} = container.cradle - - const transporter = nodemailer.createTransport( - smtpTransport({ - service: smtpSettings.service, - auth: { - user: smtpSettings.user, - pass: smtpSettings.pass - } - })) - - const mailOptions = { - from: '"Do Not Reply, Cinemas Company 👥" ', - to: `${payload.user.email}`, - subject: `Tickects for movie ${payload.movie.title}`, - html: ` -

Tickest for ${payload.movie.title}

- -

Cinem: ${payload.cinema.name}

-

Room: ${payload.cinema.room}

-

Seats: ${payload.cinema.seats}

- -

description: ${payload.description}

- -

Total: ${payload.totalAmount}

-

Total: ${payload.orderId}

- -

Cinemas Microserivce 2017, Enjoy your movie !

- ` - } - - transporter.sendMail(mailOptions, (err, info) => { - if (err) { - reject(new Error('An error occured sending an email, err:' + err)) - } - transporter.close() - resolve(info) - }) - }) - } - - const sendSMS = (payload) => { - // TODO: code for some sms service - } - - return Object.create({ - sendSMS, - sendEmail - }) -} - -const connect = (container) => { - return new Promise((resolve, reject) => { - if (!container) { - reject(new Error('dependencies not supplied!')) - } - resolve(repository(container)) - }) -} - -module.exports = Object.assign({}, {connect}) diff --git a/notification-service/src/repository/repository.spec.js b/notification-service/src/repository/repository.spec.js deleted file mode 100644 index b423fc2..0000000 --- a/notification-service/src/repository/repository.spec.js +++ /dev/null @@ -1,9 +0,0 @@ -/* eslint-env mocha */ -const should = require('should') -const repository = require('./repository') - -describe('Repository', () => { - it('should connect with a promise', () => { - repository.connect({}).should.be.a.Promise() - }) -}) diff --git a/notification-service/src/server/server.js b/notification-service/src/server/server.js deleted file mode 100644 index b145788..0000000 --- a/notification-service/src/server/server.js +++ /dev/null @@ -1,42 +0,0 @@ -const express = require('express') -const morgan = require('morgan') -const helmet = require('helmet') -const bodyparser = require('body-parser') -const cors = require('cors') -const _api = require('../api/notification') - -const start = (container) => { - return new Promise((resolve, reject) => { - const {port} = container.resolve('serverSettings') - const repo = container.resolve('repo') - - if (!repo) { - reject(new Error('The server must be started with a connected repository')) - } - if (!port) { - reject(new Error('The server must be started with an available port')) - } - - const app = express() - app.use(morgan('dev')) - app.use(bodyparser.json()) - app.use(cors()) - app.use(helmet()) - app.use((err, req, res, next) => { - reject(new Error('Something went wrong!, err:' + err)) - res.status(500).send('Something went wrong!') - next() - }) - app.use((req, res, next) => { - req.container = container.createScope() - next() - }) - - const api = _api.bind(null, {repo}) - api(app) - - const server = app.listen(port, () => resolve(server)) - }) -} - -module.exports = Object.assign({}, {start}) diff --git a/notification-service/src/server/server.spec.js b/notification-service/src/server/server.spec.js deleted file mode 100644 index f552ac9..0000000 --- a/notification-service/src/server/server.spec.js +++ /dev/null @@ -1,16 +0,0 @@ -/* eslint-env mocha */ -const server = require('./server') - -describe('Server', () => { - it('should require a port to start', () => { - return server.start({ - repo: {} - }).should.be.rejectedWith(/port/) - }) - - it('should require a repository to start', () => { - return server.start({ - port: {} - }).should.be.rejectedWith(/repository/) - }) -}) diff --git a/notification-service/start-service.sh b/notification-service/start-service.sh deleted file mode 100644 index 2921ef3..0000000 --- a/notification-service/start-service.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -docker service create --replicas 1 --name notification-service -l=apiRoute='/notification' -p 3004:3000 --env-file env --env-file env2 crizstian/notification-service diff --git a/payment-service/.eslintrc.json b/payment-service/.eslintrc.json deleted file mode 100644 index a755cdb..0000000 --- a/payment-service/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": ["standard"] -} diff --git a/payment-service/Dockerfile b/payment-service/Dockerfile deleted file mode 100644 index 523816b..0000000 --- a/payment-service/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM node:7.5.0-alpine - -RUN addgroup -S nupp && adduser -S -g nupp nupp - -ENV HOME=/home/nupp - -COPY package.json npm-shrinkwrap.json $HOME/app/ - -COPY src/ $HOME/app/src - -ADD https://github.com/Yelp/dumb-init/releases/download/v1.1.1/dumb-init_1.1.1_amd64 /usr/local/bin/dumb-init - -WORKDIR $HOME/app - -RUN chown -R nupp:nupp $HOME/* /usr/local/ && \ - chmod +x /usr/local/bin/dumb-init && \ - npm cache clean && \ - npm install --silent --progress=false --production && \ - chown -R nupp:nupp $HOME/* - -USER nupp - -EXPOSE 3000 - -CMD ["dumb-init", "npm", "start"] diff --git a/payment-service/create-image.sh b/payment-service/create-image.sh deleted file mode 100644 index 349c114..0000000 --- a/payment-service/create-image.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -docker rm -f payment-service - -docker rmi payment-service - -docker image prune - -docker volume prune - -docker build -t payment-service . diff --git a/payment-service/env b/payment-service/env deleted file mode 100644 index ac29194..0000000 --- a/payment-service/env +++ /dev/null @@ -1,6 +0,0 @@ -DB=booking -DB_USER=cristian -DB_PASS=cristianPassword2017 -DB_REPLS=rs1 -DB_SERVERS='192.168.99.100:27017 192.168.99.101:27017 192.168.99.102:27017' -PORT=3000 diff --git a/payment-service/integration-test/index.js b/payment-service/integration-test/index.js deleted file mode 100644 index 9568a17..0000000 --- a/payment-service/integration-test/index.js +++ /dev/null @@ -1,28 +0,0 @@ -/* eslint-env mocha */ -const supertest = require('supertest') - -describe('Payment Servie', () => { - const api = supertest('http://192.168.99.100:3003') - const testPayment = { - userName: 'Cristian Ramirez', - currency: 'mxn', - number: '4242424242424242', - cvc: '123', - exp_month: '12', - exp_year: '2017', - amount: 71, - description: ` - Tickect(s) for movie "Assasins Creed", - with seat(s) 47, 48 - at time 8 / feb / 17` - } - - it('can make a paymentOrder', (done) => { - api.post('/payment/makePurchase') - .send({paymentOrder: testPayment}) - .expect((res) => { - console.log(res.body) - }) - .expect(200, done) - }) -}) diff --git a/payment-service/npm-shrinkwrap.json b/payment-service/npm-shrinkwrap.json deleted file mode 100644 index 8954d24..0000000 --- a/payment-service/npm-shrinkwrap.json +++ /dev/null @@ -1,708 +0,0 @@ -{ - "name": "movies-service", - "version": "1.0.0", - "dependencies": { - "accepts": { - "version": "1.3.3", - "from": "accepts@>=1.3.3 <1.4.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz" - }, - "array-flatten": { - "version": "1.1.1", - "from": "array-flatten@1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" - }, - "awilix": { - "version": "2.2.2", - "from": "awilix@latest", - "resolved": "https://registry.npmjs.org/awilix/-/awilix-2.2.2.tgz" - }, - "balanced-match": { - "version": "0.4.2", - "from": "balanced-match@>=0.4.1 <0.5.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz" - }, - "basic-auth": { - "version": "1.0.4", - "from": "basic-auth@>=1.0.3 <1.1.0", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.0.4.tgz" - }, - "bluebird": { - "version": "2.11.0", - "from": "bluebird@>=2.10.2 <3.0.0", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz" - }, - "body-parser": { - "version": "1.16.0", - "from": "body-parser@latest", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.16.0.tgz", - "dependencies": { - "qs": { - "version": "6.2.1", - "from": "qs@6.2.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.1.tgz" - } - } - }, - "brace-expansion": { - "version": "1.1.6", - "from": "brace-expansion@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz" - }, - "bson": { - "version": "0.4.23", - "from": "bson@>=0.4.23 <0.5.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-0.4.23.tgz" - }, - "buffer-shims": { - "version": "1.0.0", - "from": "buffer-shims@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz" - }, - "bytes": { - "version": "2.4.0", - "from": "bytes@2.4.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz" - }, - "camel-case": { - "version": "3.0.0", - "from": "camel-case@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz" - }, - "camelize": { - "version": "1.0.0", - "from": "camelize@1.0.0", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz" - }, - "concat-map": { - "version": "0.0.1", - "from": "concat-map@0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" - }, - "connect": { - "version": "3.5.0", - "from": "connect@3.5.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.5.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "content-disposition": { - "version": "0.5.1", - "from": "content-disposition@0.5.1", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.1.tgz" - }, - "content-security-policy-builder": { - "version": "1.1.0", - "from": "content-security-policy-builder@1.1.0", - "resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-1.1.0.tgz" - }, - "content-type": { - "version": "1.0.2", - "from": "content-type@>=1.0.2 <1.1.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz" - }, - "cookie": { - "version": "0.3.1", - "from": "cookie@0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz" - }, - "cookie-signature": { - "version": "1.0.6", - "from": "cookie-signature@1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" - }, - "core-util-is": { - "version": "1.0.2", - "from": "core-util-is@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" - }, - "cors": { - "version": "2.8.1", - "from": "cors@latest", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.1.tgz" - }, - "dasherize": { - "version": "2.0.0", - "from": "dasherize@2.0.0", - "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz" - }, - "dashify": { - "version": "0.2.2", - "from": "dashify@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/dashify/-/dashify-0.2.2.tgz" - }, - "debug": { - "version": "2.6.0", - "from": "debug@>=2.1.1 <3.0.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz" - }, - "depd": { - "version": "1.1.0", - "from": "depd@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz" - }, - "destroy": { - "version": "1.0.4", - "from": "destroy@>=1.0.4 <1.1.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" - }, - "dns-prefetch-control": { - "version": "0.1.0", - "from": "dns-prefetch-control@0.1.0", - "resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz" - }, - "dont-sniff-mimetype": { - "version": "1.0.0", - "from": "dont-sniff-mimetype@1.0.0", - "resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.0.0.tgz" - }, - "ee-first": { - "version": "1.1.1", - "from": "ee-first@1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" - }, - "encodeurl": { - "version": "1.0.1", - "from": "encodeurl@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz" - }, - "es6-promise": { - "version": "3.0.2", - "from": "es6-promise@3.0.2", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz" - }, - "escape-html": { - "version": "1.0.3", - "from": "escape-html@>=1.0.3 <1.1.0", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" - }, - "etag": { - "version": "1.7.0", - "from": "etag@>=1.7.0 <1.8.0", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz" - }, - "express": { - "version": "4.14.0", - "from": "express@latest", - "resolved": "https://registry.npmjs.org/express/-/express-4.14.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - }, - "qs": { - "version": "6.2.0", - "from": "qs@6.2.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz" - } - } - }, - "finalhandler": { - "version": "0.5.0", - "from": "finalhandler@0.5.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@~2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "forwarded": { - "version": "0.1.0", - "from": "forwarded@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz" - }, - "frameguard": { - "version": "3.0.0", - "from": "frameguard@3.0.0", - "resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.0.0.tgz" - }, - "fresh": { - "version": "0.3.0", - "from": "fresh@0.3.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz" - }, - "fs.realpath": { - "version": "1.0.0", - "from": "fs.realpath@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" - }, - "glob": { - "version": "7.1.1", - "from": "glob@>=7.0.3 <8.0.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz" - }, - "handle-thing": { - "version": "1.2.5", - "from": "handle-thing@>=1.2.4 <2.0.0", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz" - }, - "helmet": { - "version": "3.4.0", - "from": "helmet@>=3.4.0 <4.0.0", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.4.0.tgz" - }, - "helmet-csp": { - "version": "2.3.0", - "from": "helmet-csp@2.3.0", - "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.3.0.tgz" - }, - "hide-powered-by": { - "version": "1.0.0", - "from": "hide-powered-by@1.0.0", - "resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.0.0.tgz" - }, - "hpack.js": { - "version": "2.1.6", - "from": "hpack.js@>=2.1.6 <3.0.0", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz" - }, - "hpkp": { - "version": "2.0.0", - "from": "hpkp@2.0.0", - "resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz" - }, - "hsts": { - "version": "2.0.0", - "from": "hsts@2.0.0", - "resolved": "https://registry.npmjs.org/hsts/-/hsts-2.0.0.tgz" - }, - "http-deceiver": { - "version": "1.2.7", - "from": "http-deceiver@>=1.2.4 <2.0.0", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" - }, - "http-errors": { - "version": "1.5.1", - "from": "http-errors@>=1.5.0 <1.6.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz" - }, - "http-status": { - "version": "0.2.5", - "from": "http-status@latest", - "resolved": "https://registry.npmjs.org/http-status/-/http-status-0.2.5.tgz" - }, - "iconv-lite": { - "version": "0.4.15", - "from": "iconv-lite@0.4.15", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz" - }, - "ienoopen": { - "version": "1.0.0", - "from": "ienoopen@1.0.0", - "resolved": "https://registry.npmjs.org/ienoopen/-/ienoopen-1.0.0.tgz" - }, - "inflight": { - "version": "1.0.6", - "from": "inflight@>=1.0.4 <2.0.0", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" - }, - "inherits": { - "version": "2.0.3", - "from": "inherits@>=2.0.3 <3.0.0", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" - }, - "ipaddr.js": { - "version": "1.2.0", - "from": "ipaddr.js@1.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.2.0.tgz" - }, - "is-class": { - "version": "0.0.4", - "from": "is-class@0.0.4", - "resolved": "https://registry.npmjs.org/is-class/-/is-class-0.0.4.tgz" - }, - "is-plain-object": { - "version": "2.0.1", - "from": "is-plain-object@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.1.tgz" - }, - "is-string": { - "version": "1.0.4", - "from": "is-string@>=1.0.4 <2.0.0", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.4.tgz" - }, - "isarray": { - "version": "1.0.0", - "from": "isarray@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - }, - "isemail": { - "version": "2.2.1", - "from": "isemail@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/isemail/-/isemail-2.2.1.tgz" - }, - "isobject": { - "version": "1.0.2", - "from": "isobject@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-1.0.2.tgz" - }, - "items": { - "version": "2.1.1", - "from": "items@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/items/-/items-2.1.1.tgz" - }, - "joi": { - "version": "10.2.0", - "from": "joi@latest", - "resolved": "https://registry.npmjs.org/joi/-/joi-10.2.0.tgz", - "dependencies": { - "hoek": { - "version": "4.1.0", - "from": "hoek@>=4.0.0 <5.0.0", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.1.0.tgz" - } - } - }, - "lodash.isplainobject": { - "version": "4.0.6", - "from": "lodash.isplainobject@>=4.0.6 <5.0.0", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz" - }, - "lodash.reduce": { - "version": "4.6.0", - "from": "lodash.reduce@4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz" - }, - "lower-case": { - "version": "1.1.3", - "from": "lower-case@>=1.1.1 <2.0.0", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.3.tgz" - }, - "media-typer": { - "version": "0.3.0", - "from": "media-typer@0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" - }, - "merge-descriptors": { - "version": "1.0.1", - "from": "merge-descriptors@1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" - }, - "methods": { - "version": "1.1.2", - "from": "methods@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" - }, - "mime": { - "version": "1.3.4", - "from": "mime@>=1.3.4 <2.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" - }, - "mime-db": { - "version": "1.26.0", - "from": "mime-db@>=1.26.0 <1.27.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.26.0.tgz" - }, - "mime-types": { - "version": "2.1.14", - "from": "mime-types@>=2.1.10 <3.0.0", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.14.tgz" - }, - "minimalistic-assert": { - "version": "1.0.0", - "from": "minimalistic-assert@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz" - }, - "minimatch": { - "version": "3.0.3", - "from": "minimatch@>=3.0.2 <4.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz" - }, - "mongodb": { - "version": "2.1.18", - "from": "mongodb@2.1.18", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.1.18.tgz", - "dependencies": { - "isarray": { - "version": "0.0.1", - "from": "isarray@0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" - }, - "readable-stream": { - "version": "1.0.31", - "from": "readable-stream@1.0.31", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.31.tgz" - } - } - }, - "mongodb-core": { - "version": "1.3.18", - "from": "mongodb-core@1.3.18", - "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-1.3.18.tgz" - }, - "morgan": { - "version": "1.7.0", - "from": "morgan@latest", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.7.0.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@~2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "ms": { - "version": "0.7.2", - "from": "ms@0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz" - }, - "negotiator": { - "version": "0.6.1", - "from": "negotiator@0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz" - }, - "no-case": { - "version": "2.3.1", - "from": "no-case@>=2.2.0 <3.0.0", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.1.tgz" - }, - "nocache": { - "version": "2.0.0", - "from": "nocache@2.0.0", - "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.0.0.tgz" - }, - "object-assign": { - "version": "4.1.1", - "from": "object-assign@>=4.0.1 <5.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" - }, - "obuf": { - "version": "1.1.1", - "from": "obuf@>=1.1.0 <2.0.0", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz" - }, - "on-finished": { - "version": "2.3.0", - "from": "on-finished@>=2.3.0 <2.4.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" - }, - "on-headers": { - "version": "1.0.1", - "from": "on-headers@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz" - }, - "once": { - "version": "1.4.0", - "from": "once@>=1.3.0 <2.0.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - }, - "parseurl": { - "version": "1.3.1", - "from": "parseurl@>=1.3.1 <1.4.0", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz" - }, - "path-is-absolute": { - "version": "1.0.1", - "from": "path-is-absolute@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - }, - "path-to-regexp": { - "version": "0.1.7", - "from": "path-to-regexp@0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" - }, - "platform": { - "version": "1.3.3", - "from": "platform@1.3.3", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.3.tgz" - }, - "process-nextick-args": { - "version": "1.0.7", - "from": "process-nextick-args@>=1.0.6 <1.1.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz" - }, - "proxy-addr": { - "version": "1.1.3", - "from": "proxy-addr@>=1.1.2 <1.2.0", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.3.tgz" - }, - "range-parser": { - "version": "1.2.0", - "from": "range-parser@>=1.2.0 <1.3.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz" - }, - "raw-body": { - "version": "2.2.0", - "from": "raw-body@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz" - }, - "readable-stream": { - "version": "2.2.2", - "from": "readable-stream@>=2.2.2 <3.0.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.2.tgz" - }, - "referrer-policy": { - "version": "1.1.0", - "from": "referrer-policy@1.1.0", - "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.1.0.tgz" - }, - "require_optional": { - "version": "1.0.0", - "from": "require_optional@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.0.tgz", - "dependencies": { - "resolve-from": { - "version": "2.0.0", - "from": "resolve-from@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz" - } - } - }, - "select-hose": { - "version": "2.0.0", - "from": "select-hose@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" - }, - "semver": { - "version": "5.3.0", - "from": "semver@>=5.1.0 <6.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz" - }, - "send": { - "version": "0.14.1", - "from": "send@0.14.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.14.1.tgz", - "dependencies": { - "debug": { - "version": "2.2.0", - "from": "debug@~2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz" - }, - "ms": { - "version": "0.7.1", - "from": "ms@0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz" - } - } - }, - "serve-static": { - "version": "1.11.1", - "from": "serve-static@>=1.11.1 <1.12.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.11.1.tgz" - }, - "setprototypeof": { - "version": "1.0.2", - "from": "setprototypeof@1.0.2", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz" - }, - "spdy": { - "version": "3.4.4", - "from": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.4.tgz" - }, - "spdy-transport": { - "version": "2.0.18", - "from": "spdy-transport@>=2.0.15 <3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.18.tgz" - }, - "statuses": { - "version": "1.3.1", - "from": "statuses@>=1.3.0 <1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz" - }, - "string_decoder": { - "version": "0.10.31", - "from": "string_decoder@>=0.10.0 <0.11.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - }, - "stripe": { - "version": "4.15.0", - "from": "stripe@latest", - "resolved": "https://registry.npmjs.org/stripe/-/stripe-4.15.0.tgz", - "dependencies": { - "qs": { - "version": "2.4.2", - "from": "qs@>=2.4.2 <3.0.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-2.4.2.tgz" - } - } - }, - "topo": { - "version": "2.0.2", - "from": "topo@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", - "dependencies": { - "hoek": { - "version": "4.1.0", - "from": "hoek@4.x.x", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.1.0.tgz" - } - } - }, - "type-is": { - "version": "1.6.14", - "from": "type-is@>=1.6.13 <1.7.0", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.14.tgz" - }, - "unpipe": { - "version": "1.0.0", - "from": "unpipe@>=1.0.0 <1.1.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" - }, - "upper-case": { - "version": "1.1.3", - "from": "upper-case@>=1.1.1 <2.0.0", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz" - }, - "util-deprecate": { - "version": "1.0.2", - "from": "util-deprecate@>=1.0.1 <1.1.0", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - }, - "utils-merge": { - "version": "1.0.0", - "from": "utils-merge@1.0.0", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" - }, - "vary": { - "version": "1.1.0", - "from": "vary@>=1.1.0 <1.2.0", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.0.tgz" - }, - "wbuf": { - "version": "1.7.2", - "from": "wbuf@>=1.4.0 <2.0.0", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz" - }, - "wrappy": { - "version": "1.0.2", - "from": "wrappy@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - }, - "x-xss-protection": { - "version": "1.0.0", - "from": "x-xss-protection@1.0.0", - "resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.0.0.tgz" - } - } -} diff --git a/payment-service/package.json b/payment-service/package.json deleted file mode 100644 index 81e79a8..0000000 --- a/payment-service/package.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "name": "movies-service", - "version": "1.0.0", - "description": "A movie service, microservice example with nodejs", - "author": "Cristian Ramirez Rosas ", - "license": "ISC", - "main": "index.js", - "standard": { - "ignore": [ - "mock/**.js" - ] - }, - "scripts": { - "test": "mocha -R spec src/**/*.spec.js", - "start": "node src/index.js", - "lint": "standard --verbose | snazzy", - "node-debug": "DEBUG=express* node src/index.js", - "chrome-debug": "node --debug-brk --inspect src/index.js", - "coverage": "istanbul cover _mocha $(find ./src -name \"*.spec.js\" -not -path \"./node_modules/*\") ", - "metric": "nodejs-dashboard -- node -r nodejs-dashboard src/index.js" - }, - "keywords": [ - "express", - "mongodb", - "docker", - "microservice" - ], - "devDependencies": { - "eslint": "^3.13.1", - "mocha": "^3.2.0", - "nodejs-dashboard": "^0.3.0", - "should": "^11.1.2", - "snazzy": "^6.0.0", - "standard": "^8.6.0", - "supertest": "^2.0.1" - }, - "dependencies": { - "awilix": "^2.2.2", - "body-parser": "^1.16.0", - "cors": "^2.8.1", - "express": "^4.14.0", - "helmet": "^3.4.0", - "http-status": "^0.2.5", - "joi": "^10.2.0", - "mongodb": "^2.1.18", - "morgan": "^1.7.0", - "spdy": "^3.4.4", - "stripe": "^4.15.0" - } -} diff --git a/payment-service/readme.md b/payment-service/readme.md deleted file mode 100644 index 88e5f0e..0000000 --- a/payment-service/readme.md +++ /dev/null @@ -1,40 +0,0 @@ -## Build a NodeJS microservice and deploy it to Docker - -[![Standard - JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/) - -Example of the **payment service** microservice and API. - -![](https://cdn-images-1.medium.com/max/1600/1*jxFIFA8WI8TkMmdbOorOsA.png) - -### Stack -- NodeJS 7.5.0 -- MongoDB 3.4.1 -- Docker for Mac 1.13 - -### how to run it - -**This to run our microservice in a docker container** -we need docker installed -``` -$ bash < start-service.sh -``` - -**To run in locally** -we need nodejs installed - -- install the dependencies -``` -$ npm i --silent -``` - -- run the tests -``` -$ npm test -``` - -- start the service -``` -$ npm start -``` - -[![Standard - JavaScript Style Guide](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard) diff --git a/payment-service/src/api/payment.js b/payment-service/src/api/payment.js deleted file mode 100644 index e26993a..0000000 --- a/payment-service/src/api/payment.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict' -const status = require('http-status') - -module.exports = ({repo}, app) => { - app.post('/payment/makePurchase', (req, res, next) => { - const {validate} = req.container.cradle - - validate(req.body.paymentOrder, 'payment') - .then(payment => { - return repo.registerPurchase(payment) - }) - .then(paid => { - res.status(status.OK).json({paid}) - }) - .catch(next) - }) - - app.get('/payment/getPurchaseById/:id', (req, res, next) => { - repo.getPurchaseById(req.params.id) - .then(payment => { - res.status(status.OK).json({payment}) - }) - .catch(next) - }) -} diff --git a/payment-service/src/api/payment.spec.js b/payment-service/src/api/payment.spec.js deleted file mode 100644 index 8c3d8ff..0000000 --- a/payment-service/src/api/payment.spec.js +++ /dev/null @@ -1,115 +0,0 @@ -/* eslint-env mocha */ -const { createContainer, asValue } = require('awilix') -const {stripeSettings} = require('../config/config') -const stripe = require('stripe') -const should = require('should') -const request = require('supertest') -const models = require('../models') -const server = require('../server/server') - -describe('Payment API', () => { - let app = null - let paid = null - - const serverSettings = { - port: 3000 - } - - const container = createContainer() - - container.register({ - validate: asValue(models.validate), - serverSettings: asValue(serverSettings), - stripe: asValue(stripe(stripeSettings.secret)) - }) - - let _testRepo = { - registerPurchase ({container}, payment) { - return new Promise((resolve, reject) => { - container.cradle.stripe.charges.create({ - amount: Math.ceil(payment.amount * 100), - currency: payment.currency, - source: { - number: payment.number, - cvc: payment.cvc, - exp_month: payment.exp_month, - exp_year: payment.exp_year - }, - description: payment.description - }, (err, charge) => { - if (err && err.type === 'StripeCardError') { - reject(new Error('An error occuered procesing payment with stripe, err: ' + err)) - } else { - const paid = Object.assign({}, {user: payment.userName, amount: payment.amount, charge}) - resolve(paid) - } - }) - }) - }, - getPurchaseById ({container}, orderId) { - return new Promise((resolve, reject) => { - container.cradle.stripe.charges.retrieve(orderId, (err, charge) => { - if (err) { - reject(err) - } else { - resolve(charge) - } - }) - }) - } - } - - const testRepo = {} - - testRepo.registerPurchase = _testRepo.registerPurchase.bind(null, {container}) - testRepo.getPurchaseById = _testRepo.getPurchaseById.bind(null, {container}) - - container.registerValue({repo: testRepo}) - - beforeEach(() => { - return server.start(container) - .then(serv => { - app = serv - }) - }) - - afterEach(() => { - app.close() - app = null - }) - - it('can make a purchase', (done) => { - const testPayment = { - userName: 'Cristian Ramirez', - currency: 'mxn', - number: '4242424242424242', - cvc: '123', - exp_month: '12', - exp_year: '2017', - amount: 71, - description: ` - Tickect(s) for movie "Assasins Creed", - with seat(s) 47, 48 - at time 8 / feb / 17` - } - - request(app) - .post('/payment/makePurchase') - .send({paymentOrder: testPayment}) - .expect((res) => { - should.ok(res.body.paid) - paid = res.body.paid - }) - .expect(200, done) - }) - - it('can get purchase', (done) => { - request(app) - .get('/payment/getPurchaseById/' + paid.charge.id) - .expect((res) => { - should.ok(res.body.payment) - should.equal(res.body.payment.amount, 71 * 100) - }) - .expect(200, done) - }) -}) diff --git a/payment-service/src/config/config.js b/payment-service/src/config/config.js deleted file mode 100644 index d0197a3..0000000 --- a/payment-service/src/config/config.js +++ /dev/null @@ -1,50 +0,0 @@ -const dbSettings = { - db: process.env.DB || 'payment', - user: process.env.DB_USER || 'cristian', - pass: process.env.DB_PASS || 'cristianPassword2017', - repl: process.env.DB_REPLS || 'rs1', - servers: (process.env.DB_SERVERS) ? process.env.DB_SERVERS.substr(1, process.env.DB_SERVERS.length - 2).split(' ') : [ - '192.168.99.100:27017', - '192.168.99.101:27017', - '192.168.99.102:27017' - ], - dbParameters: () => ({ - w: 'majority', - wtimeout: 10000, - j: true, - readPreference: 'ReadPreference.SECONDARY_PREFERRED', - native_parser: false - }), - serverParameters: () => ({ - autoReconnect: true, - poolSize: 10, - socketoptions: { - keepAlive: 300, - connectTimeoutMS: 30000, - socketTimeoutMS: 30000 - } - }), - replsetParameters: (replset = 'rs1') => ({ - replicaSet: replset, - ha: true, - haInterval: 10000, - poolSize: 10, - socketoptions: { - keepAlive: 300, - connectTimeoutMS: 30000, - socketTimeoutMS: 30000 - } - }) -} - -const serverSettings = { - port: process.env.PORT || 3000, - ssl: require('./ssl') -} - -const stripeSettings = { - secret: 'sk_test_lPPoJjmmbSjymtgo4r0O3z89', - public: 'pk_test_l10342hIODZmOJsBpY6GVPHj' -} - -module.exports = Object.assign({}, { dbSettings, serverSettings, stripeSettings }) diff --git a/payment-service/src/config/db/index.js b/payment-service/src/config/db/index.js deleted file mode 100644 index 8a1a1d3..0000000 --- a/payment-service/src/config/db/index.js +++ /dev/null @@ -1,4 +0,0 @@ -const {ObjectID} = require('mongodb') -const {connect} = require('./mongo') - -module.exports = Object.assign({}, {connect, ObjectID}) diff --git a/payment-service/src/config/db/mongo.js b/payment-service/src/config/db/mongo.js deleted file mode 100644 index 18fce0f..0000000 --- a/payment-service/src/config/db/mongo.js +++ /dev/null @@ -1,32 +0,0 @@ -const MongoClient = require('mongodb') - -const getMongoURL = (options) => { - const url = options.servers - .reduce((prev, cur) => prev + cur + ',', 'mongodb://') - - return `${url.substr(0, url.length - 1)}/${options.db}` -} - -const connect = (options, mediator) => { - mediator.once('boot.ready', () => { - MongoClient.connect( - getMongoURL(options), { - db: options.dbParameters(), - server: options.serverParameters(), - replset: options.replsetParameters(options.repl) - }, (err, db) => { - if (err) { - mediator.emit('db.error', err) - } - - db.admin().authenticate(options.user, options.pass, (err, result) => { - if (err) { - mediator.emit('db.error', err) - } - mediator.emit('db.ready', db) - }) - }) - }) -} - -module.exports = Object.assign({}, {connect}) diff --git a/payment-service/src/config/db/mongo.spec.js b/payment-service/src/config/db/mongo.spec.js deleted file mode 100644 index 6226394..0000000 --- a/payment-service/src/config/db/mongo.spec.js +++ /dev/null @@ -1,29 +0,0 @@ -/* eslint-env mocha */ -const {EventEmitter} = require('events') -const test = require('assert') -const mongo = require('./mongo') -const {dbSettings} = require('./config') - -describe('Mongo Connection', () => { - it('should emit db Object with an EventEmitter', (done) => { - const mediator = new EventEmitter() - - mediator.on('db.ready', (db) => { - db.admin().listDatabases((err, dbs) => { - test.equal(null, err) - test.ok(dbs.databases.length > 0) - console.log(dbs.databases) - db.close() - done() - }) - }) - - mediator.on('db.error', (err) => { - console.log(err) - }) - - mongo.connect(dbSettings, mediator) - - mediator.emit('boot.ready') - }) -}) diff --git a/payment-service/src/config/di/di.js b/payment-service/src/config/di/di.js deleted file mode 100644 index 9a0f05a..0000000 --- a/payment-service/src/config/di/di.js +++ /dev/null @@ -1,30 +0,0 @@ -const { createContainer, asValue } = require('awilix') -const stripe = require('stripe') - -function initDI ({serverSettings, dbSettings, database, models, stripeSettings}, mediator) { - mediator.once('init', () => { - mediator.on('db.ready', (db) => { - const container = createContainer() - - container.register({ - database: asValue(db), - validate: asValue(models.validate), - ObjectID: asValue(database.ObjectID), - serverSettings: asValue(serverSettings), - stripe: asValue(stripe(stripeSettings.secret)) - }) - - mediator.emit('di.ready', container) - }) - - mediator.on('db.error', (err) => { - mediator.emit('di.error', err) - }) - - database.connect(dbSettings, mediator) - - mediator.emit('boot.ready') - }) -} - -module.exports.initDI = initDI diff --git a/payment-service/src/config/di/di.proto.js b/payment-service/src/config/di/di.proto.js deleted file mode 100644 index 82e6df1..0000000 --- a/payment-service/src/config/di/di.proto.js +++ /dev/null @@ -1,82 +0,0 @@ -/* - const container = createContainer() - - container.register({ - transient(user), - transient(ticket), - transient(booking), - singleton(objectID), - singleton(notifications), - singleton(payments) - }) - - function ({ User, Booking }) { - make some stuff with the user - Promise.all([ - user.validate(object), - booking.validate(object) - ]) - .then([user, booking] => { - - }) - } - -*/ - -const createContainer = () => { - // DI store - const registrations = {} - // returns the DI - const container = { - get registrations () { - return Object.assign({}, registrations) - } - } - - // DI cache systems - container.cache = {} - - const getDI = new Proxy({}, { - get: (taget, name) => resolve(name), - set: (target, name, value) => { - throw new Error('cannot set a value to the container') - } - }) - - container.getDI = getDI - - const register = (name, registration, opts) => { - const key = Symbol(name) - registrations[key] = Object.assign({}, {fn: registration}, {lifetime: opts}) - return container - } - - container.register = register - - const resolve = (name) => { - const di = registrations[name] - switch (di.lifetime) { - case 'TRANSIENT': - return container.registrations[name].fn - case 'SINGLETON': - if (!container.cache[name]) { - container.cache[name] = container.registrations[name] - } - return container.cache[name].fn - } - } - - const listDependencies = () => { - const list = [] - for (var key in registrations) { - if (registrations.hasOwnProperty(key)) { - list.push(key) - } - } - return list - } - - return Object.create(container) -} - -module.exports.createContainer = createContainer diff --git a/payment-service/src/config/di/index.js b/payment-service/src/config/di/index.js deleted file mode 100644 index ff2d63c..0000000 --- a/payment-service/src/config/di/index.js +++ /dev/null @@ -1,3 +0,0 @@ -const di = require('./di') - -module.exports = Object.assign({}, di) diff --git a/payment-service/src/config/index.di.spec.js b/payment-service/src/config/index.di.spec.js deleted file mode 100644 index e3dfa51..0000000 --- a/payment-service/src/config/index.di.spec.js +++ /dev/null @@ -1,24 +0,0 @@ -/* eslint-env mocha */ -const {EventEmitter} = require('events') -const test = require('assert') -const {init} = require('./') - -describe('DI configuration', () => { - it('can init dependencies to the container', (done) => { - const mediator = new EventEmitter() - - mediator.on('di.ready', (container) => { - console.log(container) - done() - }) - - mediator.on('di.error', err => { - console.log(err) - done() - }) - - init(mediator) - - mediator.emit('init') - }) -}) diff --git a/payment-service/src/config/index.js b/payment-service/src/config/index.js deleted file mode 100644 index 73d976a..0000000 --- a/payment-service/src/config/index.js +++ /dev/null @@ -1,8 +0,0 @@ -const {dbSettings, serverSettings, stripeSettings} = require('./config') -const database = require('./db') -const {initDI} = require('./di') -const models = require('../models') - -const init = initDI.bind(null, {serverSettings, dbSettings, database, models, stripeSettings}) - -module.exports = Object.assign({}, {init}) diff --git a/payment-service/src/config/ssl/index.js b/payment-service/src/config/ssl/index.js deleted file mode 100644 index 63e4cd3..0000000 --- a/payment-service/src/config/ssl/index.js +++ /dev/null @@ -1,6 +0,0 @@ -const fs = require('fs') - -module.exports = { - key: fs.readFileSync(`${__dirname}/server.key`), - cert: fs.readFileSync(`${__dirname}/server.crt`) -} diff --git a/payment-service/src/index.js b/payment-service/src/index.js deleted file mode 100644 index 9a1c783..0000000 --- a/payment-service/src/index.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict' -const {EventEmitter} = require('events') -const server = require('./server/server') -const repository = require('./repository/repository') -const di = require('./config') -const mediator = new EventEmitter() - -console.log('--- Payment Service ---') -console.log('Connecting to payment repository...') - -process.on('uncaughtException', (err) => { - console.error('Unhandled Exception', err) -}) - -process.on('uncaughtRejection', (err, promise) => { - console.error('Unhandled Rejection', err) -}) - -mediator.on('di.ready', (container) => { - repository.connect(container) - .then(repo => { - console.log('Connected. Starting Server') - container.registerValue({repo}) - return server.start(container) - }) - .then(app => { - console.log(`Server started succesfully, running on port: ${container.cradle.serverSettings.port}.`) - app.on('close', () => { - container.resolve('repo').disconnect() - }) - }) -}) - -di.init(mediator) - -mediator.emit('init') diff --git a/payment-service/src/models/index.js b/payment-service/src/models/index.js deleted file mode 100644 index df204a4..0000000 --- a/payment-service/src/models/index.js +++ /dev/null @@ -1,24 +0,0 @@ -const joi = require('joi') -const payment = require('./payment.model')(joi) - -const schemas = Object.create({payment}) - -const schemaValidator = (object, type) => { - return new Promise((resolve, reject) => { - if (!object) { - reject(new Error('object to validate not provided')) - } - if (!type) { - reject(new Error('schema type to validate not provided')) - } - - const {error, value} = joi.validate(object, schemas[type]) - - if (error) { - reject(new Error(`invalid ${type} data, err: ${error}`)) - } - resolve(value) - }) -} - -module.exports = Object.create({validate: schemaValidator, schemas}) diff --git a/payment-service/src/models/index.spec.js b/payment-service/src/models/index.spec.js deleted file mode 100644 index 2602ef2..0000000 --- a/payment-service/src/models/index.spec.js +++ /dev/null @@ -1,34 +0,0 @@ -/* eslint-env mocha */ -const test = require('assert') -const {validate} = require('./') - -console.log(Object.getPrototypeOf(validate)) - -describe('Schemas Validation', () => { - it('can validate a user object', (done) => { - const testPayment = { - userName: 'Cristian Ramirez', - currency: 'mxn', - number: '4242424242424242', - cvc: '123', - exp_month: '12', - exp_year: '2017', - amount: 71, - description: ` - Tickect(s) for movie "Assasins Creed", - with seat(s) 47, 48 - at time 8 / feb / 17` - } - - validate(testPayment, 'payment') - .then(value => { - console.log('validated') - console.log(value) - done() - }) - .catch(err => { - console.log(err) - done() - }) - }) -}) diff --git a/payment-service/src/models/payment.model.js b/payment-service/src/models/payment.model.js deleted file mode 100644 index b30ff96..0000000 --- a/payment-service/src/models/payment.model.js +++ /dev/null @@ -1,12 +0,0 @@ -const paymentSchema = (joi) => ({ - userName: joi.string(), - currency: joi.string(), - number: joi.string().creditCard(), - cvc: joi.number(), - exp_month: joi.number(), - exp_year: joi.number(), - amount: joi.number(), - description: joi.string() -}) - -module.exports = paymentSchema diff --git a/payment-service/src/repository/repository.js b/payment-service/src/repository/repository.js deleted file mode 100644 index 5eb7443..0000000 --- a/payment-service/src/repository/repository.js +++ /dev/null @@ -1,76 +0,0 @@ -'use strict' -const repository = (container) => { - const {database: db} = container.cradle - - const makePurchase = (payment) => { - return new Promise((resolve, reject) => { - const {stripe} = container.cradle - stripe.charges.create({ - amount: Math.ceil(payment.amount * 100), - currency: payment.currency, - source: { - number: payment.number, - cvc: payment.cvc, - exp_month: payment.exp_month, - exp_year: payment.exp_year - }, - description: payment.description - }, (err, charge) => { - if (err && err.type === 'StripeCardError') { - reject(new Error('An error occuered procesing payment with stripe, err: ' + err)) - } else { - const paid = Object.assign({}, {user: payment.userName, amount: payment.amount, charge}) - resolve(paid) - } - }) - }) - } - - const registerPurchase = (payment) => { - return new Promise((resolve, reject) => { - makePurchase(payment) - .then(paid => { - db.collection('payments').insertOne(paid, (err, result) => { - if (err) { - reject(new Error('an error occuered registring payment at db, err:' + err)) - } - resolve(paid) - }) - }) - .catch(err => reject(err)) - }) - } - - const getPurchaseById = (paymentId) => { - return new Promise((resolve, reject) => { - const response = (err, payment) => { - if (err) { - reject(new Error('An error occuered retrieving a order, err: ' + err)) - } - resolve(payment) - } - db.collection('payments').findOne({'charge.id': paymentId}, {}, response) - }) - } - - const disconnect = () => { - db.close() - } - - return Object.create({ - registerPurchase, - getPurchaseById, - disconnect - }) -} - -const connect = (container) => { - return new Promise((resolve, reject) => { - if (!container.resolve('database')) { - reject(new Error('connection db not supplied!')) - } - resolve(repository(container)) - }) -} - -module.exports = Object.assign({}, {connect}) diff --git a/payment-service/src/repository/repository.spec.js b/payment-service/src/repository/repository.spec.js deleted file mode 100644 index b423fc2..0000000 --- a/payment-service/src/repository/repository.spec.js +++ /dev/null @@ -1,9 +0,0 @@ -/* eslint-env mocha */ -const should = require('should') -const repository = require('./repository') - -describe('Repository', () => { - it('should connect with a promise', () => { - repository.connect({}).should.be.a.Promise() - }) -}) diff --git a/payment-service/src/server/server.js b/payment-service/src/server/server.js deleted file mode 100644 index 866aa7f..0000000 --- a/payment-service/src/server/server.js +++ /dev/null @@ -1,42 +0,0 @@ -const express = require('express') -const morgan = require('morgan') -const helmet = require('helmet') -const bodyparser = require('body-parser') -const cors = require('cors') -const _api = require('../api/payment') - -const start = (container) => { - return new Promise((resolve, reject) => { - const {port} = container.resolve('serverSettings') - const repo = container.resolve('repo') - - if (!repo) { - reject(new Error('The server must be started with a connected repository')) - } - if (!port) { - reject(new Error('The server must be started with an available port')) - } - - const app = express() - app.use(morgan('dev')) - app.use(bodyparser.json()) - app.use(cors()) - app.use(helmet()) - app.use((err, req, res, next) => { - reject(new Error('Something went wrong!, err:' + err)) - res.status(500).send('Something went wrong!') - next() - }) - app.use((req, res, next) => { - req.container = container.createScope() - next() - }) - - const api = _api.bind(null, {repo}) - api(app) - - const server = app.listen(port, () => resolve(server)) - }) -} - -module.exports = Object.assign({}, {start}) diff --git a/payment-service/src/server/server.spec.js b/payment-service/src/server/server.spec.js deleted file mode 100644 index f552ac9..0000000 --- a/payment-service/src/server/server.spec.js +++ /dev/null @@ -1,16 +0,0 @@ -/* eslint-env mocha */ -const server = require('./server') - -describe('Server', () => { - it('should require a port to start', () => { - return server.start({ - repo: {} - }).should.be.rejectedWith(/port/) - }) - - it('should require a repository to start', () => { - return server.start({ - port: {} - }).should.be.rejectedWith(/repository/) - }) -}) diff --git a/payment-service/start-service.sh b/payment-service/start-service.sh deleted file mode 100644 index 546f6cb..0000000 --- a/payment-service/start-service.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -docker service create --replicas 1 --name payment-service -l=apiRoute='/payment' -p 3003:3000 --env-file env crizstian/payment-service diff --git a/readme.md b/readme.md index 514c906..1e6e3c7 100644 --- a/readme.md +++ b/readme.md @@ -1,14 +1,10 @@ -# Build a NodeJS microservice and deploy it to Docker - -![](./cover.png) - -This is the repo example for the article. +# Build a NodeJS microservice and deploy it to Kubernetes ### Stack We’ll use a simple NodeJS service with a MongoDB for our backend. - NodeJS 7.5.0 - MongoDB 3.4.2 -- Docker for Mac 1.13.0 +- Docker 20.10.11 ### Microservices @@ -21,27 +17,24 @@ We’ll use a simple NodeJS service with a MongoDB for our backend. ### How to run the cinema microservice -We need to have docker installed previously. +We need to have docker and kubernetes installed previously. + +Please input server.crt and server.key contents in `deploy/kubernetes/configmap/**/*.yaml` ``` -$ bash < kraken.sh +$ ./build.sh setup-container-images +$ ./deploy.sh kubernetes apply|delete|diff ``` -This will basically install every microservice and setup the docker swarm cluster +This will basically create every microservice container image and deploy every docker service in the swarm. To monitor the cluster in a graphic mode we can go and visit the following url: `http://192.168.99.100:9000` -and this will give us the rancherOS web interface. - -### Blog posts +### TODO -- [Build a NodeJS cinema microservice and deploying it with docker (part 1)](https://medium.com/@cramirez92/build-a-nodejs-cinema-microservice-and-deploying-it-with-docker-part-1-7e28e25bfa8b) -- [Build a NodeJS cinema microservice and deploying it with docker (part 2)](https://medium.com/@cramirez92/build-a-nodejs-cinema-microservice-and-deploying-it-with-docker-part-2-e05cc7b126e0) -- [Build a NodeJS cinema booking microservice and deploying it with docker (part 3)](https://medium.com/@cramirez92/build-a-nodejs-cinema-booking-microservice-and-deploying-it-with-docker-part-3-9c384e21fbe0) -- [Build a NodeJS cinema microservice and deploying it with docker (part 4)](https://medium.com/@cramirez92/build-a-nodejs-cinema-api-gateway-and-deploying-it-to-docker-part-4-703c2b0dd269#.en6g5buwl) -- [Deploy a Nodejs microservices to a Docker Swarm Cluster (Docker from zero to hero)](https://medium.com/@cramirez92/deploy-a-nodejs-microservices-to-a-docker-swarm-cluster-docker-from-zero-to-hero-464fa1369ea0#.548ni3uxv) +- Persistent Volume for MongoDB ### LICENSE The MIT License (MIT) From 0ebc76422c3c82ea0e4337609fab94b39fe210d5 Mon Sep 17 00:00:00 2001 From: michaelact <86778470+michaelact@users.noreply.github.com> Date: Sat, 14 May 2022 01:47:24 +0700 Subject: [PATCH 3/5] docs: remove wrong access url --- readme.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/readme.md b/readme.md index 1e6e3c7..c411810 100644 --- a/readme.md +++ b/readme.md @@ -30,8 +30,6 @@ This will basically create every microservice container image and deploy every docker service in the swarm. -To monitor the cluster in a graphic mode we can go and visit the following url: `http://192.168.99.100:9000` - ### TODO - Persistent Volume for MongoDB From 2a2c29c6f10c6cdd8eab8a541041f7017b8b2e6b Mon Sep 17 00:00:00 2001 From: michaelact <86778470+michaelact@users.noreply.github.com> Date: Sat, 14 May 2022 01:50:14 +0700 Subject: [PATCH 4/5] docs: replace api-gateway with kubernetes ingress --- readme.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/readme.md b/readme.md index c411810..f4599a5 100644 --- a/readme.md +++ b/readme.md @@ -5,15 +5,15 @@ We’ll use a simple NodeJS service with a MongoDB for our backend. - NodeJS 7.5.0 - MongoDB 3.4.2 - Docker 20.10.11 +- Kubernetes 1.22.4 ### Microservices -- [Movies Service example](./movies-service) -- [Cinema Catalog Service example](./cinema-catalog-service) -- [Booking Service example](./booking-service) -- [Payment Service example](./payment-service) -- [Notification Service example](./notification-service) -- [API Gateway Service example](./api-gateway) +- [Movies Service example](./movies) +- [Cinema Catalog Service example](./cinema-catalog) +- [Booking Service example](./booking) +- [Payment Service example](./payment) +- [Notification Service example](./notification) ### How to run the cinema microservice From 419c51efb94db876b8574c78e9666fa148e31844 Mon Sep 17 00:00:00 2001 From: michaelact <86778470+michaelact@users.noreply.github.com> Date: Sat, 14 May 2022 01:50:59 +0700 Subject: [PATCH 5/5] docs: replace swarm with kubernetes --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index f4599a5..50676f6 100644 --- a/readme.md +++ b/readme.md @@ -28,7 +28,7 @@ $ ./deploy.sh kubernetes apply|delete|diff This will basically create every microservice container image -and deploy every docker service in the swarm. +and deploy every docker service in the kubernetes. ### TODO

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