ノードの展開タイプスクリプト


皆さんこんにちは!
この最初のポストでは、ノードを使用して基本的なバックエンドを開発する方法について話します.メイン開発者の言語としてJSとTypesScriptは、まず第一に私たちは詳細を入力する基本的な側面と、なぜあなたのアプリケーションの既定の言語として使用することは非常に興味深いです.
この記事を通して我々は一緒にルート、コントローラと応答を基本的なバックエンドを構築することができます、次のポストでは、我々はユニットのテストを使用してJestを使用して、このアプリケーションを使用して続行する必要がありますどのようにカバレッジを増やす方法を学び、どのように入力スクリプトを使用します.

さあ、ディスカバリーに行きましょう。


どのようなタイプスクリプトですか?
TypesScript言語はJavaScriptの型付けされたスーパーセットであり、より多くの凝集性でクリーンなコードを作成することを可能にします.タイプエラーは開発時間で発見されることができます.
JavaScriptコードの例と、typemcriptコードの同等の例を挙げましょう.
function sum(num1, num2) {

    return num1 + num2;
}
上記の2つの値を合計し、結果を返すJavaScriptコードを持っています.これは入力された言語で動作しないときに問題を示すことができる単純な関数です.
// Returns 4
sum(2, 2)

// Returns '22'
sum('2', 2)
sum関数を呼び出し、2つのパラメータが数値の場合、レスポンスは4になりますが、この2つのパラメータの一部が文字列である場合、JavaScriptは2文字列のコンテクストであると解釈し、応答' 22 'を返します.
この単純な例では、コード化されていない言語が理解できない人々にとって、非タイプの言語が理解するのが難しいということを私たちに示しています.この問題のため、マイクロソフトはオープンソース言語のtypescriptを開発した.
function sum(num1: number, num2: number) {

    return num1 + num2;
}
上記はJavaScriptで開発されたのと同じコードですが、パラメーター型を使用すると、すべての開発者は、型と入力を正しい値を参照することができます.
// Returns 4
sum(2, 2)

// Error in development time
sum('2', 2)
番目の呼び出しはsum関数を使用するのにより有効ではありません.エラーが発生し、開発者は文字列ではなく2つの数字を入れる必要があることを知っています.
TypeScriptを使用するもう一つの良い側面は、最新のECMAScript仕様で利用可能な新機能を使用することができます古いブラウザや古いノードで実行する問題はありません.JSのバージョンは、すべてのコードをECMAScript 5仕様に変換します.

を使ってバックエンドを構築する


ここでは、基本的なバックエンドをメイン言語として使って基本的なバックエンドを作りましょう.

ここで
class -アプリケーションが使用するすべてのジェネリッククラスを含むフォルダです.
コントローラ-アプリケーションのすべてのコントローラを含むフォルダです.
ルート-私たちが定義するすべてのルートを含むフォルダです.
Services -いくつかの外部APIのリクエストのような別のシステムとの統合を含むフォルダーです.
我々のアプリケーションを構築するには、アプリケーションを起動するためにいくつかのパッケージが必要です、パッケージ.JSONの下には、設定を始める前にインストールする必要があるすべての必要なリファレンスがあります.
{
    "name": "typescript-node-api",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "start": "npm run build && node dist/index.js",
        "build": "gulp scripts",
        "test": "echo \"Error: no test specified\" && exit 1"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
        "@babel/core": "^7.7.7",
        "@types/body-parser": "1.17.1",
        "@types/debug": "4.1.5",
        "@types/express": "4.17.2",
        "@types/morgan": "1.7.37",
        "@types/node": "13.1.4",
        "gulp": "4.0.2",
        "gulp-babel": "8.0.0",
        "gulp-typescript": "5.0.1",
        "typescript": "3.7.4"
    },
    "dependencies": {
        "body-parser": "1.19.0",
        "debug": "4.1.1",
        "express": "4.17.1",
        "morgan": "1.9.1"
    }
}
私たちは、タイプスクリプトを使用してコードを書くべきです、しかし、ノード.JSコアは、JavaScriptファイルを作成し、設定するためにGulpファイルを作成し、設定するすべてのコマンドを実行するには、Javascriptファイルを必要とします.
以下に、基本設定ファイルがあります.アプリケーションのルートのJS :
const gulp = require('gulp');
const babel = require('gulp-babel');
const ts = require('gulp-typescript');
const JSON_FILES = ['src/*.json', 'src/**/*.json'];

// Indicates to gulp the typescript configuration
const tsProject = ts.createProject('tsconfig.json');

const scripts = () => {

    return tsProject.src()
        .pipe(tsProject()).js
        .pipe(babel())
        .pipe(gulp.dest('dist'));
};

const watch = () => {

    gulp.watch('src/**/*.ts', scripts);
};

const assets = () => {

    return gulp.src(JSON_FILES).pipe(gulp.dest('dist'));
};

exports.scripts = scripts;
exports.watch = watch;
exports.assets = assets;

const build = gulp.series(gulp.parallel(scripts));
gulp.task('build', build);
gulp.task('default', build);
このファイルでは、どこにファイルが転写されるか、そしてどこでこの転写物によって作成されたJavaScriptファイルのままでいるかのようないくつかの設定があります.
次のステップはtsconfigを定義します.JSON、このファイルには、あなたのtypescriptsコードをjavascriptコードに転写するためのコンパイルオプションが含まれています.以下にこのファイルの例を示します.
{
    "compilerOptions": {
        "target": "es6",
        "module": "commonjs",
        "sourceMap": true
    },
    "exclude": [
        "node_modules"
    ]
}
この例では、コンパイラによってどのようなバージョンのECMAScriptが使用されるかを示す情報が含まれます.
ターゲット-転写される必要があるECMAScriptバージョン.
module - "None ", "CommonJs , "system "などのモジュールコード生成を指定します.
sourceCap -生成する必要がある場合.マップファイル.
excludeプロパティは、このプロセスが起動されたときにコンパイルする必要がないすべてのフォルダを含む配列です.この場合、モジュールが必要とされません.

タイプファイルの作成


次のステップは、アプリケーションを作成する必要があります入力スクリプトを使用してコードを開始します.“src”フォルダーの内部では、このファイルではミドルウェア、ルートの設定があり、システムの他のポイントで使用するExpressを公開します.
import * as express from 'express';
import * as logger from 'morgan';
import * as bodyParser from 'body-parser';
import { Utility } from './classes/helpers/utility';

class App {

    public express: express.Application;

    constructor() {

        this.express = express();
        this.middleware();
        this.routes();
    }

    private middleware(): void {

        this.express.use(logger('dev'));
        this.express.use(bodyParser.json());
        this.express.use(bodyParser.urlencoded({ extended: false }));
    }

    private routes(): void {

        this.setAllRoutes();
        this.setDefaultRoute();
    }

    private setAllRoutes(): void {

        const utility = new Utility();
        let arrayFileRoutes = utility.readRecursiveDirectory('routes');

        arrayFileRoutes.forEach(file => {

            let routeInstance = require(`./${file.replace(/\.[^/.]+$/, '')}`);
            let fn = `/api${file.replace('routes', '').split('\\').join('/').replace(/\.[^/.]+$/, '')}`;

            this.express.use(fn, routeInstance.default.getRouter());
            console.log(`Route ${fn} --> OK`);
        });
    }

    private setDefaultRoute(): void {

        this.express.get('/api', (req, res, next) => {

            res.status(200).json({
                title: 'API Test',
                version: '1.0.0',
                path: '/api/v1'
            });
        });
    }
}

export default new App().express;
このプロジェクトでは、以下の例のようにルートファイルが存在するルートを作成します.

このイメージでは、ルートフォルダがあり、内部にV 1とV 2フォルダがあります.これはAPI開発の一般的なパターンで、APIリソースのバージョンを指定するためにフォルダを作成します.このAPIでは、API APIの動作を修正することができます.
この自動定義されたルートで、アプリケーションを起動するときのログは次のようになります.

すべてのルートは、ファイルがルートフォルダにある場所に基づいて自動的にアプリケーションによって作成されました.ts、フォルダ構造を読み込み、必要なすべてのルートを作成しました.
そして最後にインデックスを作成しましょう.我々のアプリケーションを決定的に起動する責任があるファイルです.
import * as http from 'http';
import * as debug from 'debug';

import App from './App';

debug('ts-express:server');

const port = normalizePort(process.env.PORT || 3000);
App.set('port', port);

const server = http.createServer(App);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

console.log(`Online in port ${port}`);

function normalizePort(val: number | string): number | string | boolean {

    let port: number = (typeof val === 'string') ? parseInt(val, 10) : val;

    if (isNaN(port))
        return val;
    else if (port >= 0)
        return port;
    else
        return false;
}

function onError(error: NodeJS.ErrnoException): void {

    if (error.syscall !== 'listen')
        throw error;

    let bind = (typeof port === 'string') ? 'Pipe ' + port : 'Port ' + port;
    switch (error.code) {

        case 'EACCES':
            console.error(`${bind} requires elevated privileges`);
            process.exit(1);
            break;

        case 'EADDRINUSE':
            console.error(`${bind} is already in use`);
            process.exit(1);
            break;

        default:
            throw error;
    }
}

function onListening(): void {

    let addr = server.address();
    let bind = (typeof addr === 'string') ? `pipe ${addr}` : `port ${addr.port}`;

    debug(`Listening on ${bind}`);
}

ルート、コントローラ、サービス!


以下に、すべてのクライアントの情報をコンサルティングするためのポイントとなるように作成された基本的なルートがあり、APIのエンドポイントに対してより多くのアクションを追加する機能を追加できます.
import * as express from 'express';
import { ClientController } from '../../controllers/v1/ClientController';
import { IRouterApi } from '../../classes/interfaces/IRouterApi';

class ClientRouter implements IRouterApi {

    public getRouter(): express.Router {

        const clientController = new ClientController();

        let router = express.Router();
        router.route('/').get(clientController.getClients);

        return router;
    }
}

export default new ClientRouter();
とiRailterAPIインタフェース:
import { Router } from "express";

export interface IRouterApi {

    getRouter(): Router;
}
今、我々はルートとインターフェイスを定義しています、我々は我々の終点をテストすることができて、クライアントのルートがどのように戻るかについて見ることができるためにコントローラとサービスを作成する必要があります.
import { NextFunction, Request, Response } from "express";
import { ClientService } from '../../services/v1/ClientService';

export class ClientController {

    public getClients(req: Request, res: Response, next: NextFunction): void {

        const clientService = new ClientService();
        res.status(200).json(clientService.searchClients());
    }
}
このファイルでは基本的に、すべてのクライアントを検索する基本関数を作成し、クライアントサービスをインスタンス化し、アプリケーションの応答にこの値を返します.
export class ClientService {

    public searchClients(): Array<any> {

        return [
            {
                message: 'Client name'
            }
        ];
    }
}
最後に、単純なオブジェクトを持つ配列を返す関数を含むClientServiceを持っています!

テスト


TypeScriptを使用して最初の基本的なバックエンドを作成するこの旅の後、私たちは、応答が我々が必要とする方法であるかどうかをテストする必要があります.

とレスポンス.

戻ってきます。


次のポストでは、このタイプスクリプトの基本的なバックエンドを使用して他の技術や概念を適用します.閉じるこの動画はお気に入りから削除されています.
バイ!

参考文献
〔1〕https://www.typescriptlang.org/
〔2〕https://ionicframework.com/docs/v3/developer-resources/typescript/
[ 3 ]https://medium.com/swlh/the-major-benefits-of-using-typescript-aa8553f5e2ed
〔4〕https://www.typescriptlang.org/docs/handbook/compiler-options.html