Пробуем TypeScript на сервере

Доброго времени суток.

В этой статье мы познакомимся с языком программирования TypeScript на примере создания небольшого серверного приложения (простая авторизация), используя такие популярные технологии как Node.js и Express.js. Также вкратце коснёмся рассмотрения довольно интересной embeddeb NoSQL базы данных NeDB.

Статья ориентирована прежде всего на людей уже знакомых с Nodes и Express и не рассматривает самые базовые вещи, относящиеся к этим технологиям. Я не буду подробно описывать и все особенности TypeScript, а код далеко не является эталонным — это всего лишь пример. Однако, если у вас есть желание попробовать TypeScript, но вы не знаете как к нему подобраться, особенно со стороны backend’a,  тогда, возможно, вы найдёте что-то полезное в этой статье. Ссылка на GitHub репозиторий в конце статьи.

TypeScript

TypeScript (далее по тексту TS) — это язык программирования, являющийся надмножеством JavaScript. Начал разрабатываться компанией Microsoft и был впервые представлен в 2012 году. Автор языка — Андреас Хейлсберг, который до TS приложил руку к разработке таких языков как C# и Delphi. В самом Microsoft заявляют о TS  следующим образом: «Язык программирования TypeScript является средством разработки веб-приложений, расширяющим возможности JavaScript».

Технология сама по себе довольно интересная и выгодно отличается от того же JavaScript. Главное, что выделяет TS — это строгая типизация, а также более привычная многим (java-like) реализация ООП. В TS вы можете использовать всё, что есть на данный момент в JavaScript, плюс объявления типов, модификаторы доступа, классы, интерфейсы и ещё много всего. Получается такой JavaScript с человеческим лицом. При этом компилируется TS в тот-же JavaScript. На выбор любой из стандартов: ES3, ES5 или ES6. Как и большинство новых технологий TS является open source проектом, доступным в репозитории на GitHub: https://github.com/Microsoft/TypeScript Ещё одним аргументом в пользу данного языка является тот факт, что на нём написан один из самых популярных frontend фреймворков — Angular2. И его можно использовать с другими библиотеками и фреймворками, например с тем-же React. Ну а мы попробуем разобраться насколько TS применим на сервере. И так, приступим.

Установка TypeScript

TypeScript ставится как обычный npm пакет. Желательно устанавливать глобально:

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

Теперь можно попробовать создать какой-нибудь скрипт и его скомпилировать. Для наглядности, чтобы сразу было видно отличие от JavaScript, создадим простой класс:

Сохраним файл и запустим компилятор:

Если всё прошло удачно, то рядом мы увидим скомпилированный файл Greeting.js, а в нём примерно такой JavaScript:

Как видим — никакой магии.

TypeScript предоставляет возможность настраивать параметры компиляции. Для этого создадим файл tsconfig.json со следующим содержимым:

Мы указали самые базовые параметры. Теперь исходные файлы будут компилироваться в JavaScript версии ES6 (последняя нода его замечательно поддерживает). Более подробно о настройке компиляции можно прочитать в официальной документации.

Что с поддержкой в редакторах и IDE?

Все современные редакторы в достаточной степени поддерживают TypeScript. Лично я рекомендую Visual Studio Code от Microsoft. У него поддержка одна из лучших. Причём из коробки, что и не удивительно, т.к. всё это продукты одной компании.

Пример приложения

Теперь перейдём к созданию нашего простого примера, а заодно посмотрим как использовать TypeScript в связке с другими технологиями, которые написаны на обычном JavaScript. Наше приложение будет представлять из себя простейший API для аутентификации пользователей. Сосредоточимся исключительно на backend части. Прежде чем начнём, хотелось бы уточнить, что API не будет являться RESTful (мы будем использовать сессии) и больше подойдёт для обычный Ajax запросов. Однако саму структуру сильно упрощать не будем. Представим, что в будущем мы захотим расширить приложение.

Собственно, базовая структура проекта будет следующая:

Для простоты понимания было решено сделать структуру по типу всем известного MVC паттерна, только, как уже упоминалось выше, без использования слоя представлений.

Определение зависимостей и настройка компиляции

Добавим файл package.json со следующим содержимым:

Установим зависимости выполнив команду: npm install

Зависимостей у нас по минимуму: Express.js, модули для обработки запросов и работы с сессиями, а также библиотека NeDB для работы с БД. Для автоматизации процесса сборки и перезапуска используем команды, объявленные в блоке scripts:

npm start — будет запускать компилятор TypeScript c флагом --watch для использования кросскомпиляции.

npm run built:watch — запустит уже скомпилированный сервер через утилиту nodemon,которая будет производить перезапуск приложения при каждом изменении JS файлов.

Теперь настроим компиляцию. Создадим новый файл tsconfig.json, в котором укажем следующие параметры:

Собственно, здесь мы указываем, что хотим использовать commonjs загрузку модулей (imports будут конвертированы в require). А также, помимо прочего, директорию, где лежат исходные TypeScript файлы (src), и куда помещать скомпилированные JavaScript файлы (bin). Генерация sourceMap нам пока не нужна, поэтому мы её отключаем. А вот на опции noImplicitAny хотелось бы остановиться подробнее. Одна из особенностей TypeScript — это так называемая точечная типизация и использование внутреннего типа данных any. Суть в том, что мы не обязаны везде объявлять типы данных. А только в тех местах где это имеет смысл. Однако там, где мы не указали тип, компилятор TypeScript будет пытаться этот тип вывести. Ели у него это не получается сделать явно, то, если опция noImplicitAny  выставлена в false (по умолчанию) неявно, будет назначен тип any, иначе каждый раз при компиляции будет производиться проверка на указание типа данных any, и если мы его не укажем явно, то получим ошибку компиляции.

Благодаря наличию таких опций, TypeScript уже из коробки поддерживает линтинг кода. Кроме того, существует отдельное расширение — tslint, которое позволяет ещё более гибко настроить различного рода проверки как в процессе компиляции, так и на лету.

Типизация сторонних библиотек

Если с типизацией наших исходных кодов на TypeScript всё более-менее ясно, то как нам использовать типы в сторонних библиотеках, написанных на JavaScript? К счастью, community давно решило этот вопрос создав вот этот замечательный репозиторий: https://github.com/DefinitelyTyped/DefinitelyTyped

В этом репозитории собраны и описаны типы для самых популярных библиотек и фреймворков, которые можно подключить к проектам на TypeScript. С помощью чего, собственно, происходит описание и добавление внешней библиотеки? Для решения этой задачи у TypeScript существуют так называемые декларативные файлы, имеющие расширение *.d.ts. Данные файлы служат для декларации (описания без реализации) различных компонентов внешней подключаемой библиотеки. Такими компонентами могут быть интерфейсы, переменные, константы, функции и т.д., которые описаны уже с использованием типов TypeScript. Например, так выглядит файл деклараций для Express.js:  https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/express/index.d.ts Естественно, мы можем сами создать .d.ts файл для какой-нибудь библиотеки, описать компоненты и  подключить её в свой проект. Вдогонку ко всему вышесказанному хочу порекомендовать ресурс для быстрого поиска по доступным декларациям различных библиотек и фреймворков: http://microsoft.github.io/TypeSearch/

Теперь мы можем добавить типизацию для наших зависимостей. Так как проверка типов нам нужна только в процессе разработки, то устанавливаем типы как devDependencies:

По умолчанию TypeScript будет искать определения типов в директории node_modules/@types. Разумеется, это можно настроить в tsconfig.json, через параметр typeRoots.

С настройкой вроде бы разобрались. Теперь перейдём к самому приложению. Создадим главный класс:

Главный класс реализован как singleton. Здесь мы подключаем провайдеры и маршрутизацию, создаём экземпляр Express и запускаем приложение. Обратите внимание на то, как импортируются модули, а именно Express. Мы импортируем все компоненты фреймворка в виде функции express, а для типизации этих компонентов только необходимые интерфейсы. Вообще, интерфейсы довольно мощная штука. Например, конфигурация приложения вынесена в отдельный типизированный js объект,  описанный через интерфейс IApplicationConfig. Ещё одной интересной особенностью TypeScript, которую мы использовали, является возможность определить поле класса для передаваемого аргумента непосредственно в сигнатуре конструктора (собственно, так мы конфигурацию и подключаем).

Маршрутизация и контроллеры

Далее нам нужно добавить маршрутизацию и контроллеры. Начнём с интерфейсов маршрутизаторов. Как вы уже могли обратить внимание, интерфейс конфигурации приложения мы подключали из директории core. Добавим туда же два интерфейса, которые описывают маршрутизацию.

IApplicationRoute:

IPathRoute:

Это всего лишь демонстрация использования интерфейсов в TypeScript. С помощью первого описан непосредственно сам объект, который будет создавать и возвращать маршрут. С помощью второго — объект через который будет связан маршрутизатор и корневая точка входа. Подключение корневых маршрутов реализовано в классе AppRoutes.ts.

Далее создадим маршрутизатор пользователя:

Как мы видим, сам по себе маршрутизатор не является классом — это обычный объект, но типизированный с помощью интерфейса. Такие конструкции бывает довольно удобно использовать и здесь это показано исключительно для наглядности. Можете обратить внимание что в обработчиках маршрутов в качестве middleware мы используем методы отдельных контроллеров. Вот так у нас будет выглядеть AuthController:

Модели и провайдеры данных

Теперь перейдём к вопросу хранения и представления данных пользователей. Начнём с провайдера данных. Создадим базовый абстрактный провайдер данных:

TypeScript позволяет использовать абстрактные классы, что собственно мы и сделали в провайдере данных. Что такое абстрактный класс, я думаю, вы прекрасно знаете и без меня. А вот о хранилище данных NeDB, которое мы используем, хотелось бы рассказать подробнее.

NeDB — это встраиваемая NoSQL база данных, написанная на JavaScript с похожим на MongoDB API. БД не имеет бинарных зависимостей. Может быть использована как на клиенте, так и на сервере, а также на платформах NW.js и Electron. Устанавливается как обычный npm пакет или через bower, а данные может хранить в оперативной памяти. При хранении на диске используется JSON.  Ещё одной интересной особенностью является достаточно быстрая скорость работы, для embedded базы. Привожу данные из официальной документации:

  • Insert: 10,680 ops/s
  • Find: 43,290 ops/s
  • Update: 8,000 ops/s
  • Remove: 11,750 ops/s

Иcпользует довольно простой и понятный синтаксис для работы с данными. Вот, например, реализация провайдера пользователя, в котором каждый из методов является обёрткой над методом экземпляра хранилища NeDB:

Механизм наследования TypeScript требует явного вызова метода super() в наследниках. Поэтому при создании экземпляра класса мы передаём наименование хранилища (фактически имя файла) в родительский конструктор: super('User'). Если хранилище с данными на диске не будет обнаружено, то создастся новый файл.  Так как провайдер унаследован от абстрактного класса, мы реализовали метод onLoadStore, в котором обрабатываем возможную ошибку при загрузке хранилища. Вы также можете обратить внимание на то, как объявлены callback функции в сигнатурах методов. Такой способ объявления позволяет нам типизировать любую callback функцию, при этом никто не запрещает вынести её определение в отдельный интерфейс. Для создания и хранения провайдеров реализован класс AppDataProviders, экземпляр которого создаётся один раз при старте приложения и доступен глобально через геттер главного класса (см. UserController). Таким образом мы сможем и дальше расширять слой для работы с данными используя провайдеры-обёртки над NeDB.

Смотрим, что получилось

Для запуска приложения нам понадобится отдельный стартовый скрипт index.ts:

Теперь попробуем скомпилировать это всё и запустить. Сначала выполним команду: npm start. Если ошибок нет, запустим в той же директории ещё один сеанс консоли и выполним npm run built:watch. Результат должен быть таким:

После компиляции директория с проектом будет выглядеть следующим образом:

В директории bin находится наше скомпилированное приложение, а в директории db появился файл хранилища. Попробуем проверить работоспособность. Для тестирования запросов я буду использовать приложение POSTMAN.

Убедимся, что сервер запущен и попробуем перейти по адресу выполнив GET запрос: http://localhost:8080/user

В ответе видим 401 статус. Значит всё ok, ведь мы не зарегистрировались. Пробуем регистрироваться, но уже через POST запрос: http://localhost:8080/user/add

В ответе на регистрацию получаем объект нового пользователя.

Теперь можно пройти аутентификацию. Выполняем POST запрос: http://localhost:8080/user/login:

Вроде бы всё работает) Теперь можно запросить список пользователей выполнив GET запрос: http://localhost:8080/user

Заключение

Нашей целью было понять, можно ли использовать TypeScript при разработке серверных приложений, и насколько это удобно. Даже на таком небольшом примере  мы убедились, что TypeScript уже вполне зрелая технология, позволяющая использовать существующий инструментарий платформы Node.js без особых проблем. Язык активно развивается и поддерживается сообществом. В нём появляются новые фичи, которые по-настоящему облегчают разработку. Те особенности, которые были рассмотрены в этой статье, являются лишь малой частью того, что предоставляет нам TypeScript. Поэтому в будущем хотелось бы вернуться к этой теме. Надеюсь, и вы нашли что-то полезное для себя. Спасибо за внимание)

Ссылка на репозиторий с исходниками: https://github.com/GusNitrous/TypeScriptBackend

Поддержка Multidex для Android в Adobe AIR

Пару слов о поддержке Multidex для Android в AIR, которую Adobe ввела в 25-й версии. С помощью мультидекса можно упаковывать приложения, которые превышают лимит в 64K методов. Это может произойти, если вы пишете своё или используете стороннее ANE, содержащее большое количество библиотек и, соответственно, большое количество методов. В таком случае при сборке вы получите ошибку:

Too many method references max is 65536

AIR 25 наконец-то позволяет включить multidex, чтобы преодолеть эту проблему.

При разработке собственного ANE выставьте флаг поддержки multidex в gradle скрипте проекта

Далее, при упаковке ANE исключите библиотеку com.android.support:multidex. Её можно прописать в зависимостях проекта для компиляции Android библиотеки, но обязательно надо игнорировать при упаковке самого расширения, потому что иначе, при попытке сборки приложения, будет выводиться ошибка:

UNEXPECTED TOP-LEVEL EXCEPTION: java.lang.IllegalArgumentException: already added: Landroid/support/multidex/BuildConfig;

Видимо потому, что библиотека добавляется AIR’ом и повторное включение её в ANE создаёт конфликт.

Для приложения не забудьте прописать поддержку multidex в секции Android манифеста файла-дескриптора (android > manifestAdditions > manifest):

Обратите внимание, что если ANE содержит pre-dex библиотеки, то при попытке упаковки приложения будет выдаваться ошибка.

Unity для новичков. Простая камера от третьего лица. Часть 1

Доброго времени суток!
Сегодня мы рассмотрим пример создания простой игровой камеры от третьего лица в Unity.

Читать →

GDG DevFest Voronezh 2016 — ключевые тренды

3 декабря 2016 года в Воронеже проходила 5-я ежегодная конференция Google developer group, на которой нам впервые удалось побывать. Сразу скажу, что конференция прошла отлично и мы остались очень довольны :)  Поэтому хотелось бы поделиться своими впечатлениями и подробнее рассказать о самой конференции, а также о докладах, которые были на ней представлены.

img_20161203_140430

Эта конференция, в отличие от многих остальных, является абсолютно бесплатной. Для участия достаточно было просто зарегистрироваться на сайте компании-организатора. В Воронеже организаторами были ребята из DataArt. 
Читать →

Поездка на GDG DevFest Voronezh 2016

3 декабря удалось побывать на GDG DevFest Voronezh 2016. GDG DevFest это ежегодная конференция, проводимая сообществами Google Developers Group (GDG) при поддержке компании Google в разных городах мира. В Воронеже она проводится пятый раз.

Я интересуюсь проектами компании Google и операционной системой Android в первую очередь, поэтому данное событие я не мог пропустить, тем более оно проходило не так далеко от моего места проживания.

maxresdefault_live

GDG проходил в актовом зале ВГУ. Сразу на входе нас встречали волонтеры, проводившие нас на регистрацию. Регистрация прошла моментально, а до начала открытия оставалось чуть менее часа. Благодаря тестовым заданиям от компании DataArt удалось скоротать время и получить наклейку с андроидом, которая теперь украшает мой ноутбук.

В первом выступлении Денис Неклюдов (Google Developer Expert и ведущий подкастов androiddev) и Звиад Кардава (также Google Developer Expert) рассказывали о Project Tango. Project Tango — это платформа, которая использует компьютерное зрение, чтобы научить мобильные устройства воспринимать окружающее пространство и движение.
Читать →

Cocos2d JS на примере браузерной игры

Cocos 2d – кросс-платформенный фреймворк с открытым кодом, для разработки игр и приложений, как браузерных, так и для мобильных платформ.  Приложения могут быть запущены на платформах: iOS, Android, Windows Phone, OS X, Windows, Linux.

Главные возможности:

  • OpenGL.
  • Управление сценами.
  • Эффекты смены сцен.
  • Спрайты.
  • Визуальные эффекты, большое количество качественных 3D эффектов.
  • Экшены (движение, масштабирование, повороты).
  • Компоненты, позволяющие конструировать UI (меню, кнопки, ползунки, списки, текстовые поля и т. д.).
  • Поддержка касаний и акселерометра на мобильных устройствах.
  • Поддержка звука, звуковой движок на основе OpenAl.
  • Поддержка физических движков Box2D и Chipmunk.
  • Тестирование и отладка без необходимости установки на мобильное устройство.

Одна из ветвей фреймворка – Cocos2d JS, позволяет писать игры в JavaScript. Рассмотрим логику и возможности фреймворка на примере создания браузерной игры.

Популярный жанр браузерных игр – головоломки. Целью нашей игры будет расставить в правильном порядке шестеренки, чтобы механизм заработал.
Читать →

White Nights Moscow 2016 — Тенденции индустрии

Между тем блог превращается в обзор конференций, так как на написание статей по делу просто не хватает времени. Надеюсь, что скоро у нас все-таки получится опубликовать несколько полезных постов, а пока расскажу о недавней White Nights, проходившей в Москве 11-12 октября.

В этот раз я не буду подробно расписывать доклады, которые прослушал, тексты и видео докладов, как и раньше, будут опубликованы на ресурсах организаторов http://app2top.ru/ и http://wnmag.com немного позже. Я же сосредоточусь на нескольких моментах, которые вынес для себя из этой конференции.

White Nights Moscow 2016 - Innim
Читать →

Конференция White Nights 2016 — Впечатления. День 2

В первой части обзора я рассказал о первом дне конференции White Nights 2016 (Санкт-Петербург, 28-29 июня). На второй день тоже было достаточно хороших докладов. Также хочется отдельно отметить Deconstruction Workshop, который получился весьма интересным. А в завершение конференции была церемония награждения победителей  Indie Game Cup и розыгрыш призов среди всех участников конференции. Ну а теперь подробнее об увиденном. Читать →

Конференция White Nights 2016 — Впечатления. День 1

28-29 июня этого года в Санкт-Петербурге прошла очередная конференция разработчиков игр White Nights. Мероприятие позиционируется как бизнес конференция игровой индустрии, поэтому говорили в основном о монетизации, продвижении, работе с издателями и т.п., по были и некоторые полезные доклады по геймплею и разработке игр в целом. Отдельно хочется отметить очень хороший нетворкинг — это именно то событие, где можно встретиться и обсудить любые интересующие вас аспекты.

В этом году мы были на этой конференции в первый раз и могу сказать, что получили достаточно позитивных впечатлений и вынесли много полезного. Хотелось бы вкратце рассказать об интересных докладах, которые мы прослушали.

IMG_0968

Читать →