• BSA Lab.
      home

  • apps
    Главная
  • contacts
    Об авторе
  • library_books
    Блог
  • shop
    Портфолио
    keyboard_arrow_down
    • Google API
    • Gapi-People
      wc
    • Gapi-Email
      mail_outline
    • Gapi-Examples
      more

    • Silex (PHP micro-framework)
    • Silex-MVC
      desktop_windows
    • Silex-UBKI
      last_page

    • Zend (PHP framework)
    • ZF-MyBlog
      library_books
    • ZF2-ASM
      show_chart

    • Node.js
    • Express-Passport
      verified_user
    • Feathers-Examples
      more

    • Vue.js (JavaScript framework)
    • Vue-Resume
      account_circle
    • Vue-Business-Light
      work
    • Vue-Examples
      more
    • Vuex-Examples
      more

    • Nuxt (JavaScript framework)
    • Nuxt-Business-Light
      work
    • Nuxt-Vuetify-Start
      picture_in_picture

  • Темы
  • message
    WEB ресурсы
    keyboard_arrow_down
    • Обзор
      filter_none

  • message
    Google Client API
    keyboard_arrow_down
    • Обзор
      filter_none
    • Gmail-Send
      contact_mail
    • Gmail-Inbox
      mail_outline
BSA / Portfolio-node-feathers-exx
  • Информация

  • contact_mail
    Контакты
  • contacts
    Об авторе
  • public
    Мои проекты на GitHub
Feathers Examples
Примеры работы с сервисами, базами данных, аутентификация/авторизация пользователей.

2018-08-28

shop

Введение.

Этот проект был написан чтобы продемонстрировать возможности работы "Feathers" фреймворка. По своей сути Feathers представляет собой набор инструментов и шаблон архитектуры, который упрощает создание масштабируемых API REST приложений реального времени. Сравнение с другими фреймворками можно посмотреть здесь.

Этот проект на GitHub можно посмотреть здесь

Демонстрацию этого проекта можно посмотреть здесь

Обзор

Основная идея Feathers фреймворка уйти от концепции MVC и использовать концепцию работы с сервисами и “hooks”. Это дало возможность создать структуру, которая может расти вместе с вами по мере роста вашего продукта. Он достаточно гибкий, чтобы быстро адаптироваться к меняющимся потребностям бизнеса, достаточно мощный для создания современных приложений и достаточно простой, чтобы быстро создавать и работать.

Возможности

  • Работа с сервисами на стороне сервера и на стороне клиента
  • Использование “Hooks” при работе с сервисами
  • Создание Real-time APIs
  • Процесс аутентификации и авторизации создан на базе Express Password стратегий
  • JWT Authentication используется JSON Web Token
  • Local Authentication используется Email и Password
  • OAuth 1.0a Authentication через Twitter
  • OAuth 2.0 Authentication через Facebook, Google, GitHub, Instagram
  • Работа с базами данных: NeDB, MongoDB, Elasticsearch, RethinkDB
  • Работа с базами данных: MySQL, PostgreSQL, MariaDB, SQLite, MSSQL (с помощью ORM - Knex, Sequelize)
  • Пользовательский интерфейс выполнен на базе клиенского фрейморка "Bulma"
  • Gravatar
  • Реализован пример Chat (обмена сообщениями между пользователями) в реальном времени

Ресурсы

Node.js (Chrome's V8 JavaScript engine)
Документация
Express (Node.js framework)
Документация
API
Passport.js
Документация
Feathers
Документация
Блог
Ресурсы, плагины, примеры
Клиентский фреймворк "Bulma"
Документация
Схемы
Шаблоны
Расширения
Font Awesome - the iconic font and CSS toolkit
Icons
MongoDB (noSQL DataBase)
Документация
Atlas (облачный хостинг)
mLab (облачный хостинг 500MB FREE)
Сompass (инструмент для визуализации данных)
Mongoosejs (NPM компонент для работы с моделями базы данных)
NeDB (noSQL DataBase)
Документация
ElasticSearch (noSQL DataBase)
Документация
Bonsai - hosting for ElasticSearch
RethinkDB (noSQL DataBase)
Документация
Knex (SQL DataBase ORM for Postgres, MSSQL, MySQL, MariaDB, SQLite3, Oracle)
Документация
Sequelize (SQL DataBase ORM for PostgreSQL, MySQL, SQLite and MSSQL)
Документация
Интересные статьи
Why we built the best web framework you’ve probably never heard of (until now)
Feathers.js — реактивный JavaScript-фреймворк поверх Express

Установка приложения

Предварительные требования

  1. Убедитесь в том, что у вас установлен NodeJS 8.0+ и MongoDB, RethinkDB, Elasticsearch.

  2. Клонируйте или загрузите feathers-exx проект с GitHub.

  3. Инсталируйте ваши зависимости
    cd <project-name> npm install # Or yarn install

Переменные окружения

Файл .env должен находиться в корне проекта, если он отсутствует, то его нужно создать на основе примера файла .env.example, иначе приложение будет выдавать ошибку. Файл .env устанавливает переменные окружения. В переменных окружения обычно указываются секретные данные пользователя например user_id, user_secret и т.д.

Запуск вашего проекта

Development

Вначале нужно создать пакет клиентского приложения для этого нужно выполнить команду:
npm run build
или
npm run watch
чтобы работать с MongoDB базой данных нужно выполнить команду
npm run start-mongod
чтобы работать с RethinkDB базой данных нужно выполнить команду
npm run start-rethinkdb
чтобы работать с ElasticSearch базой данных нужно вначале установить локально ElasticSearch, а затем запустить ее на выполнение... После этого нужно выполнить приложение в режиме разработки.
npm run dev

Приложение будет запущено в режиме Разработки и будет выполнятся на http://localhost:3000

Production

npm start

Приложение будет запущено в Рабочем режиме и будет выполнятся на рабочем хостинге пример можно посмотреть здесь

Структура приложения

Файловая структура

пр.1
Имя файлаОписание
client/publicПапка для публичных данных (css, js, images).
client/scr/js/app.client.jsОсновная точка входа клиентского приложения.
client/scr/js/client.class.jsClient класс
client/scr/js/polyfills.jsМодуль где собраны необходимые полифилы для клиента
client/scr/js/controllersПапка с контроллерами для клиента.
client/scr/js/pluginsПапка с плагинами для клиента.
client/scr/js/routesПапка с роутерами для клиента.
client/scr/js/tmplsПапка с шаблонами для клиента.
config/db/mongod.config.ymlКонфигурация базы данных MongoDB.
config/db/rethinkdb.configКонфигурация базы данных RethinkDB.
config/default.jsonКонфигурация приложения по умолчанию.
config/production.jsonКонфигурация приложения в режиме "Production".
plugins/utils.class.jsUtils класс для общих функций сервера и клиента.
server/app.server.jsМодуль инициализации серверного приложения.
server/start.jsОсновная точка входа серверного приложения.
server/bootПапка с модулями промежуточных обработчиков для инициализации сервера.
server/controllersПапка с контроллерами для сервера.
server/data/dbПапка с базами данных: MongoDB, NeDB, RethinkDB, Sqlite3.
server/data/logПапка c логами для сервера.
server/hooksПапка с "Hooks" для сервера.
server/middlewareПапка с "middleware" для сервера.
server/pluginsПапка с плагинами для сервера.
server/routesПапка с роутерами для сервера.
server/servicesПапка с сервисами для сервера.
server/viewsПапка с шаблонами для сервера.
validationsПапка со схемами валидации для сервера и клиента.
.envВаши реальные API ключи, уникальные данные, пароли и URI базы данных.
.env.exampleПримеры API ключей, уникальных данных, паролей и URI базы данных.
.gitignoreПапки и файлы, которые будут игнорироваться системой управления версиями Git.
package.jsonNPM зависимости.
package-lock.jsonСодержит точные версии зависимостей NPM в package.json.
ProcfileФайл для конфигурации хостинга "Heroku".
README.mdИнформация о приложении.
webpack.config.jsКонфигурация для WebPack.

Замечание: Здесь представлен мой вариант организации структуры приложения. Вы можете изменять структуру приложения по своему усмотрению...

Список NPM пакетов

пр.2
ПакетОписание
Dependencies
@feathersjs/authenticationFeathers local, token, and OAuth authentication over REST and Websockets using JSON Web Tokens (JWT) with PassportJS.
@feathersjs/authentication-jwtJWT authentication strategy for feathers-authentication using Passport.
@feathersjs/authentication-localLocal authentication strategy for feathers-authentication using Passport.
@feathersjs/authentication-oauth1An OAuth1 authentication strategy for feathers-authentication using Passport.
@feathersjs/authentication-oauth2An OAuth2 authentication strategy for feathers-authentication using Passport.
@feathersjs/authentication-clientThe authentication plugin for feathers-client.
@feathersjs/configurationA plugin for configuring a Feathers application.
@feathersjs/errorsFeathers errors for server and client.
@feathersjs/expressFeathers Express framework bindings and REST transport plugin.
@feathersjs/feathersA REST and realtime API layer for modern applications.
@feathersjs/socketioThe Feathers Socket.io websocket transport plugin.
ajvThe fastest JSON Schema validator for Node.js and browser. Supports draft-04/06/07.
axiosPromise based HTTP client for the browser and node.js.
babel-polyfillBrowser Polyfill for Babel.
body-parserNode.js body parsing middleware.
browser-cookiesTiny cookies library for the browser.
compressionNode.js compression middleware.
cookie-parserParse HTTP request cookies.
corsNode.js CORS middleware.
cross-envCross platform setting of environment scripts.
debugA tiny JavaScript debugging utility modelled after Node.js core's debugging technique. Works in Node.js and web browsers.
dotenvLoads environment variables from .env for nodejs projects.
dotenv-webpackA secure webpack plugin that supports dotenv and other environment variables and only exposes what you choose and use.
elasticsearchOpen Source, Distributed, RESTful Search Engine.
expressFast, unopinionated, minimalist web framework for node.
express-sessionSimple session middleware for Express.
feathers-elasticsearchFeathersjs adapter for Elasticsearch.
feathers-hooks-commonUseful hooks for use with Feathersjs services.
feathers-knexService adapters for KnexJS a query builder for PostgreSQL, MySQL, MariaDB, Oracle and SQLite3.
feathers-localstorageA client side service based on feathers-memory that persists to LocalStorage.
feathers-memoryAn in memory feathers service.
feathers-mongodbA mongodb service for feathers.
feathers-mongooseEasily create a Mongoose Service for Feathersjs.
feathers-nedbA service using NeDB, an embedded datastore for Node.js.
feathers-rethinkdbA Feathers service adapter for RethinkDB.
feathers-sequelizeA Feathers service adapter for the Sequelize ORM. Supporting MySQL, MariaDB, Postgres, SQLite, and SQL Server.
fetch-polyfillA window.fetch JavaScript polyfill.
helmetHelp secure Express apps with various HTTP headers.
highlight.jsJavascript syntax highlighter.
jstoragejStorage is a simple key/value database to store data on browser side.
knexA query builder for PostgreSQL, MySQL and SQLite3, designed to be flexible, portable, and fun to use.
lodashA modern JavaScript utility library delivering modularity, performance, & extras.
momentParse, validate, manipulate, and display dates in javascript.
mongodbMongoDB Abstraction Layer.
mongooseMongoDB object modeling designed to work in an asynchronous environment.
morganHTTP request logger middleware for node.js.
mysqlA pure node.js JavaScript Client implementing the MySql protocol.
mysql2A modern, simple and very fast Mysql library for Ruby - binding to libmysql.
nedbThe JavaScript Database, for Node.js, nw.js, electron and the browser.
passport-facebookFacebook authentication strategy for Passport and Node.js.
passport-githubGitHub authentication strategy for Passport and Node.js.
passport-google-oauth20Types for https://github.com/jaredhanson/passport-google-oauth2.
passport-instagramInstagram authentication strategy for Passport and Node.js.
passport-twitterTwitter authentication strategy for Passport and Node.js.
rethinkdbdashAn advanced Node.js driver for RethinkDB with a connection pool, support for streams etc.
sequelizeAn easy-to-use multi SQL dialect ORM for Node.js.
serve-faviconfavicon serving middleware.
socket.io-clientRealtime application framework (client).
sqlite3sqlite3 driver for go using database/sql.
twigTwig, the flexible, fast, and secure template language.
devDependencies
babel-coreBabel is a compiler for writing next generation JavaScript.
babel-loaderWebpack plugin for Babel.
babel-preset-envA Babel preset that compiles ES2015+ down to ES5 by automatically determining the Babel plugins and polyfills you need based on your targeted browser or runtime environments.
bulmaModern CSS framework based on Flexbox.
bulmaswatchThemes for Bulma.
css-loaderCSS Loader for Webpack.
node-sassNode.js bindings to libsass.
nodemonMonitor for any changes in your node.js application and automatically restart the server - perfect for development.
style-loaderStyle Loader for Webpack.
twig-loaderWebpack loader for compiling Twig.js templates.
webpackWebpack is a module bundler.

Конфигурация

.env

Файл .env должен находиться в корне проекта, если он отсутствует, то его нужно создать на основе примера файла .env.example, иначе приложение будет выдавать ошибку. Файл .env устанавливает переменные окружения. В переменных окружения обычно указываются секретные данные пользователя например user_id, user_secret и т.д.

пр.3 для .env.example

### System ###
NODE_ENV=development
# default(Bulma as-is); cerulean(A calm blue sky); darkly(Flatly in night-mode)
COLOR_THEME=darkly
DEBUG=app:*

### HTTP ###
BASE_URL=http://localhost

### AUTH ###
SESSION_SECRET=expressFeathersExxSecretKey
AUTH_SECRET=13e504e1023381f2475b895183ca6fa0e3858d4302083695d708a159ea7979dbe780d2c0207e86f5c9e48cbea177caf2ba36f6821e648afcf14017ddbca3a20b8f2918608c8422f67dcd70fb9b2c7d60d92edf2aa95fd3ed26fd2aaff2a67319dd395a71aab1cab1578ab5757474904fca6f954835dce764dc17950952740db129bbbc3ce5e76b06fc36ef93d09699ccb3a68df2e5cd5a39412c1e8952d5feaaba779a3f638366176493cc7387e0c52e009a3f1b7383f3b5fcc528e4754419cfa3730550e72343b8b7adfbd2148323cfc34c411329245d9c979b98489025f074af28e72e54875e295933861e60dad850be57f0c2e68e4b16a163f2435c126988

FACEBOOK_ID=XXXXXXXXXXXXXXX
FACEBOOK_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

INSTAGRAM_ID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
INSTAGRAM_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

GITHUB_ID=XXXXXXXXXXXXXXXXXXXX
GITHUB_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

TWITTER_KEY=XXXXXXXXXXXXXXXXXXXXXXXXX
TWITTER_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

GOOGLE_ID=XXXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.apps.googleusercontent.com
GOOGLE_SECRET=XXXXXXXXXXXXXXXXXXXXXXXX

### Personal Data ###
PERSONAL_LOGO_IMAGE=/images/bsa-logo/4_bsa-logo_229x75.png
PERSONAL_COPYRIGHT=© 2018 BSA Lab.
PERSONAL_WEBSITE=http://bsa-git.github.io

### DataBase ###
# sqlite, mysql, postgres, mssql
DB_CURRENT=sqlite

DB_NEDB_FILENAME=/server/data/db/nedb/messages.db

DB_MONGOOSE_URI=mongodb://localhost:27017/dbFeathersExx

DB_MONGODB_URI=mongodb://localhost:27017/dbFeathersExx

DB_ELASTICSEARCH_URI=http://localhost:9200

DB_ELASTICSEARCH_INDEX=db_feathers_exx
DB_ELASTICSEARCH_TYPE=messages

DB_RETHINKDB_DATABASE=dbFeathersExx
DB_RETHINKDB_TABLE=messages

DB_KNEX_SQLITE_FILENAME=/server/data/db/sqlite3/messages.db

DB_KNEX_MYSQL_HOST=localhost
DB_KNEX_MYSQL_USER=root
DB_KNEX_MYSQL_PASSWORD=
DB_KNEX_MYSQL_DATABASE=dbFeathersExx

DB_KNEX_POSTGRES_HOST=localhost
DB_KNEX_POSTGRES_USER=your_database_user
DB_KNEX_POSTGRES_PASSWORD=your_database_password
DB_KNEX_POSTGRES_DATABASE=myapp_test

DB_SEQUELIZE_SQLITE_DATABASE=messages
DB_SEQUELIZE_SQLITE_USERNAME=
DB_SEQUELIZE_SQLITE_PASSWORD=
DB_SEQUELIZE_SQLITE_STORAGE=/server/data/db/sqlite3/messages.db

DB_SEQUELIZE_MYSQL_URI=mysql://root@localhost:3306/dbFeathersExx
DB_SEQUELIZE_MYSQL_DATABASE=dbFeathersExx
DB_SEQUELIZE_MYSQL_USERNAME=root
DB_SEQUELIZE_MYSQL_PASSWORD=
DB_SEQUELIZE_MYSQL_HOST=localhost
DB_SEQUELIZE_MYSQL_PORT=3306

DB_SEQUELIZE_POSTGRES_URI=postgres://user:pass@example.com:5432/dbname
DB_SEQUELIZE_POSTGRES_DATABASE=myapp_test
DB_SEQUELIZE_POSTGRES_USERNAME=user
DB_SEQUELIZE_POSTGRES_PASSWORD=pass
DB_SEQUELIZE_POSTGRES_HOST=localhost

    

Замечание: Чтобы иметь реальные ключи для доступа к API различных сервисов нужно зарегистрировать ваше приложение в этих сервисах. Примеры регистрации приложения и получения ключей API в разных сервисах можно посмотреть здесь.

Работа серверного приложения

  • В приложении демонстрируется работа фреймворка Feathers в трех аспектах: работа с сервисами, работа с базами данных и аутентификация пользователей.
  • В примерах показана работа с различными базами данных.

    Например в приложении я использую базу данных MongoDB. Можно установить MongoDB локально на компьютер или использовать MongoDB на облачном хостинге Atlas или mLab.

    Также используется база данных ElasticSearch Можно установить ElasticSearch локально на компьютер или использовать ElasticSearch на облачном хостинге Bonsai - hosting for ElasticSearch.

    Используется база данных RethinkDB Можно установить RethinkDB локально на компьютер, а вот бесплатного хостинга для RethinkDB я пока не нашел...

    Для Knex (SQL DataBase ORM for Postgres, MSSQL, MySQL, MariaDB, SQLite3, Oracle) и для Sequelize (SQL DataBase ORM for PostgreSQL, MySQL, SQLite and MSSQL) я использую бузу данных - SQLite3, которая находиться в папке /server/data/db/sqlite3 в виде файла messages.db

    База данных NeDB находится в папке /server/data/db/nedb в виде файлов messages.db, users.db, posts.db. Файл messages.db используется для демонстрации работы с сервисами, а файлы users.db, posts.db используются для демонстрации аутентификации пользователей и демонстрации приложения Chat (обмен сообщениями между пользователями).

  • Чтобы тестировать в приложении возможность логирования с помощью таких сервисов как Facebook, Google, GitHub, Instagram и т.д. нужно быть там зарегистрированным и иметь свой аккаунт.
  • Если вы разработчик и хотите создавать приложения с возможностью логирования и доступа других пользователей к API различных сервисов, нужно зарегистрировать ваше приложение в этих сервисах. Примеры регистрации приложения и получения ключей API в разных сервисах можно посмотреть здесь
  • Для построения пользовательского интерфейса используется Bulma, это один из популярных HTML, CSS фреймворков и используется, для разработки интерактивных мобильных проектов в Интернете.

Инициализация серверного приложения

Инициализация приложения происходит в модуле server/app.server.js см. пр.4

пр.4

"use strict";
const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const configuration = require('@feathersjs/configuration');
const dotenv = require('dotenv');// Loads environment variables from .env file.
const debug = require('debug')('app:app');

// Load environment variables
dotenv.load();

// Create APP
const app = express(feathers());
app.configure(configuration());

// Boot
require('./boot/index')(app);

// Routing
require('./routes/index')(app);

debug('Bootstrap application - OK');

module.exports = app;

    
Из структуры модуля app.server.js видно, что происходят следующие действия:
  • Загрузка переменных окружения из файла .env.
  • Создание самого приложения app и его конфигурация. Данные по конфигурации берутся из файлов config/default.json, config/production.json и сохраняются в приложении app. Их можно получить например так. app.get('authentication').
  • Установка промежуточных обработчиков в приложение в модуле server/boot/index.js.
  • Установка и настройка путей запросов в приложение в модуле server/routes/index.js.

Промежуточные обработчики серверного приложения

Установка промежуточных обработчиков в приложение происходит в модуле server/boot/index.js. см. пр.5

пр.5

'use strict';

const express = require("./express");
const transports = require("./transports");
const middleware = require("../middleware");
const authentication = require("./authentication");
const services = require("../services");
const channels = require("./channels");
const appHooks = require("./app.hooks");
const errorHandler = require("./error-handler");

module.exports = function (app) {
    express(app);
    transports(app);
    middleware(app);
    authentication(app);
    services(app);
    channels(app);
    appHooks(app);
    errorHandler(app);
};
    

Замечание: Здесь важна последовательность выполнения промежуточных обработчиков в приложении.

Express обработчики

К ним относятся такие модули: cors, helmet, compress, express.json, express.urlencoded, favicon, express.static. см. пр.6

пр.6

'use strict';

const express = require('@feathersjs/express');
const favicon = require('serve-favicon');
const compress = require('compression');
const helmet = require('helmet');
const cors = require('cors');

module.exports = function (app) {

    // view engine setup
    app.set('views', app.get('views'));
    app.set('view engine', 'twig');

    app.use(cors());
    app.use(helmet());
    app.use(compress());
    // Turn on JSON body parsing for REST services
    app.use(express.json());
    // Turn on URL-encoded body parsing for REST services
    app.use(express.urlencoded({extended: true}));
    app.use(favicon(`${app.get('public')}/images/favicon.ico`));
    app.use(express.static(app.get('public')));

};
    

Транспортные обработчики

К ним относятся такие модули: express.rest, socketio. Здесь мы устанавливаем REST транспорт используя Express, а также Socket.io транспорт. см. пр.7

пр.7

'use strict';

const express = require('@feathersjs/express');
const socketio = require('@feathersjs/socketio');

module.exports = function (app) {
    // Set up REST transport using Express
    app.configure(express.rest());
    // Configure the Socket.io transport
    app.configure(socketio());
};
    

Обработчики для аутентификации

К ним относятся такие модули: authentication, jwt, local, oauth1, oauth2. А также стратегии на основе Express Password такие как: TwitterStrategy, FacebookStrategy, GitHubStrategy, InstagramStrategy, GoogleStrategy. см. пр.8

пр.8

'use strict';

const authentication = require('@feathersjs/authentication');
const jwt = require('@feathersjs/authentication-jwt');
const local = require('@feathersjs/authentication-local');
const oauth1 = require('@feathersjs/authentication-oauth1');
const oauth2 = require('@feathersjs/authentication-oauth2');
const TwitterStrategy = require('passport-twitter').Strategy;
const FacebookStrategy = require('passport-facebook').Strategy;
const GitHubStrategy = require('passport-github').Strategy;
const InstagramStrategy = require('passport-instagram').Strategy;
const GoogleStrategy = require('passport-google-oauth20').Strategy;

const debug = require('debug')('app:boot.authentication');

module.exports = function (app) {

    // Get config for authentication
    const config = app.get('authentication');
    const twitterConfig = Object.assign(config['twitter'], {
        Strategy: TwitterStrategy
    });
    const facebookConfig = Object.assign(config['facebook'], {
        Strategy: FacebookStrategy
    });
    const githubConfig = Object.assign(config['github'], {
        Strategy: GitHubStrategy
    });
    const instagramConfig = Object.assign(config['instagram'], {
        Strategy: InstagramStrategy
    });
    const googleConfig = Object.assign(config['google'], {
        Strategy: GoogleStrategy
    });

    // Set up authentication with the secret
    app.configure(authentication(config));
    app.configure(jwt());
    app.configure(local());
    app.configure(oauth1(twitterConfig));
    app.configure(oauth2(facebookConfig));
    app.configure(oauth2(githubConfig));
    app.configure(oauth2(instagramConfig));
    app.configure(oauth2(googleConfig));

    app.service('authentication').hooks({
        before: {
            create: [
                authentication.hooks.authenticate(config.strategies)
            ],
            remove: [
                authentication.hooks.authenticate('jwt')
            ]
        }
    });


};

    

Замечание: В этом модуле получаем параметры аутентификации для разных стратегий (см. config/default.json), затем происходит конфигурирование и установка самих обработчиков в приложение. Для сервиса authentication устанавливаются соответствующие hooks при создании и удалении сервиса.

Обработчики событий реального времени

В этом модуле происходит установка и публикация событий для клиентов. Такими событиями могут быть: событие connection, событие login, событие authenticated и т.д. см. пр.9

пр.9

module.exports = function(app) {
  if(typeof app.channel !== 'function') {
    // If no real-time functionality has been configured just return
    return;
  }

  app.on('connection', connection => {
    // On a new real-time connection, add it to the anonymous channel
    app.channel('anonymous').join(connection);
  });

  app.on('login', (authResult, { connection }) => {
    // connection can be undefined if there is no
    // real-time connection, e.g. when logging in via REST
    if(connection) {
      // Obtain the logged in user from the connection
      // const user = connection.user;

      // The connection is no longer anonymous, remove it
      app.channel('anonymous').leave(connection);

      // Add it to the authenticated user channel
      app.channel('authenticated').join(connection);
    }
  });

  app.publish((data, hook) => {
    // e.g. to publish all service events to all authenticated users use
    return app.channel('authenticated');
  });
};

    

Сервисные обработчики

К ним относятся сервисы: users, posts см. пр.10.

пр.10

'use strict';

const users = require('./users/users.service');
const posts = require('./posts/posts.service');

module.exports = function (app) {
    app.configure(users);
    app.configure(posts);
};

    

Замечание: Сервисы users, posts используются для демонстрации аутентификации пользователей и демонстрации приложения Chat (обмен сообщениями между пользователями). Модули, которые определяют работу сервисов users, posts находяться в папках server/services/users и server/services/posts соответственно.

app.hooks обработчики

Здесь задается возможность логирования в самом приложении - когда идет обращение к любому сервису или возникает ошибка см. пр.11.

пр.11

// Application hooks that run for every service
const logger = require('../hooks/logger');

const hooks = {
    before: {
        all: [logger()],
        find: [],
        get: [],
        create: [],
        update: [],
        patch: [],
        remove: []
    },

    after: {
        all: [logger()],
        find: [],
        get: [],
        create: [],
        update: [],
        patch: [],
        remove: []
    },

    error: {
        all: [logger()],
        find: [],
        get: [],
        create: [],
        update: [],
        patch: [],
        remove: []
    }
};

module.exports = function (app) {
    app.hooks(hooks);
};


    

Middleware обработчики

Здесь можно подключить свои обработчики например server/middleware/init-app.js. В этом обработчике устанавливаются общие данные для шаблонов. Проверяется наличие файла .env в режиме разработки и если этот файл отсутствует, то выдается ошибка. Проверяется режим технического обслуживания и если сайт находится в режиме технического обслуживания, то происходит переход на соответствующую страницу сайта см. пр.12.

пр.12

"use strict";

const debug = require('debug')('app:middleware.init-app');

module.exports = function (req, res, next) {

    const Base = require('../controllers/base.server.class');

    // Get controller/action
    Object.assign(req, Base.getControllerAction(req.path));

    // Check maintenance mode
    if ( req.app.get('maintenance') && req.action !== 'maintenance') {
        return res.redirect('/maintenance')
    }

    // Set values for view
    res.locals.port = req.app.get('port');
    res.locals.req = req;
    res.locals.controllers = req.app.get('controllers');
    res.locals.actions = req.app.get('actions');
    res.locals.color_theme = req.app.get('color_theme');
    res.locals.logo_img = req.app.get('personal')['logo_image'];
    res.locals.contact_website = req.app.get('personal')['website'];
    res.locals.copyright = req.app.get('personal')['copyright'];

    // Check .env
    if(req.app.get('env') === 'development'){
        Base.isEnvJs();
    }

    next()
};

    

Работа клиенского приложения

Клиенсткое приложение строится пакетным обработчиком WebPack и обработчиком каскадных стилей node-sass. Конфигурация WebPack задается файлом webpack.config.js см. пр 13.

пр.13

const path = require('path');
const Dotenv = require('dotenv-webpack');

module.exports = {
    // context: path.resolve(__dirname, 'client/src'), // source directory
    context: path.resolve(__dirname), // source directory
    entry: { // file for assembly, if several - specify hash (entry name => filename)
        'polyfills': './client/src/js/polyfills.js',
        'app.client': './client/src/js/app.client.js'
    },
    output: {
        path: path.resolve(__dirname, 'client/public/js'), // output directory
        filename: '[name].bundle.js'
    },
    devtool: 'source-map',
    module: {
        rules: [
            {test: /\.twig$/, use: "twig-loader"},
            {test: /\.css$/, use: ['style-loader', 'css-loader']},
            {
                test: /\.js$/,
                // exclude: /(node_modules|bower_components)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['env']
                    }
                }
            }
        ]
    },
    plugins: [
        new Dotenv({
            path: './.env', // Path to .env file (this is the default)
            systemvars: true // It makes it possible to work in production mode on Heroku hosting
        })
    ],
    resolve: {
        alias: {
            joi: 'joi-browser'
        }
    },
    node: {
        fs: "empty" // avoids error messages
    }
};


    

Замечание: Модуль dotenv-webpack используется в конфигурации для того чтобы секретные данные с файла .env попали в параметры окружения на клиетне, при условии если эти параметры будут использоваться в коде клиентского приложения.

Инициализация клиентского приложения

Входной точкой клиентского приложения является модуль client/src/js/app.client.js см. пр 14.

В модуле app.client.js создается экземпляр класса Client, свойствами которого являются обьект хранилища jStorage, экземпляр класса Bulma, экземпляр класса HttpBox и данные полученные от сервера через интерфейсный элемент. Происходит инициализация пользовательского интерфейса с помощью функции client.bulma.init(); и выполняется вызов соответствующего действия контроллера через роутер const result = await indexRouter(client);

пр.14

import indexRouter from './routes/index.router'

const debug = require('debug')('app:client');

const bootstrap = async () => {
    // Create client
    const client = new Client();
    // Initializing the User Interface
    client.bulma.init();
    debug('Path controller/action: ', `${client.req.controller}/${client.req.action}`);
    // Run router
    const result = await indexRouter(client);
    if (result === 'ok') {
        return `Result: "OK"; Controller: "${client.req.controller}"; Action: "${client.req.action}";`;
    } else {
        return result;
    }
};

// Run bootstrap
bootstrap().then(
    result => {
        debug(result)
    },
    error => {
        new Bulma()
            .init()
            .showError(error)
    }
);
    

Инициализация API REST и аутентификация клиента

Модуль client/src/js/controllers/base.client.class.js является дочерним классом Base, для всех контроллеров. Из экземпляра этого класса вызывается функция const app = this.setRestTransport();. Пример реализации этой функции можно посмотреть см. пр 15.

пр.15

 /**
 * Set rest transport
 * @return {*}
 */
setRestTransport() {
    let restURL = `${this.req.protocol}//${this.req.hostname}`;
    if (process.env.NODE_ENV === 'development') {
        restURL += `:${this.data.port}`;
    }
    const feathers = require('@feathersjs/client/index');
    const axios = require('axios');
    //---------------------------------
    // Create app
    const app = feathers();
    // Connect to URL
    const restClient = feathers.rest(restURL);
    // Configure an AJAX library (see below) with that client
    app.configure(restClient.axios(axios));

    const authentication = require('@feathersjs/client/authentication');
    app.configure(authentication({
        storage: window.localStorage
    }));
    return app
}
    

Замечание: В дальнейшем переменную app можно использовать для доступа к сервисам и работе с ними. Можно выполнять все операции с сервисами такие как: create, get, find, delete, а также производить аутентификацию к защищенным сервисам и работу с ними в защищенном режиме. Примеры реализации работы с сервисами можно посмотреть в котроллерах, находящихся в папке client/src/js/controllers.

© 2017 Сергей Бескоровайный
language Разработчик:
BSA Lab.