Skip to content

Instantly share code, notes, and snippets.

@bathtimefish
Last active September 3, 2019 12:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bathtimefish/4fb2140763a1ce83715345ca9170a142 to your computer and use it in GitHub Desktop.
Save bathtimefish/4fb2140763a1ce83715345ca9170a142 to your computer and use it in GitHub Desktop.
restify + TypeScript + Jestの開発環境をセットアップしてみる ref: https://qiita.com/bathtimefish/items/82f886f6d2353af14e7a
npm i -g typescript webpack webpack-cli
mkdir restify-typescript-example && cd $_
mkdir -p src/__tests__
npm init -f
npm i --save restify node-fetch
npm i --save-dev typescript ts-loader tslint tslint-loader tslint-config-airbnb jest ts-jest @types/restify @types/jest @types/node-fetch
npm i --save-dev webpack webpack-cli webpack-node-externals
npm test
> restify-typescript-example@0.1.0 test /Users/user/work/restify-typescript-example
> jest
PASS src/__tests__/index.test.ts
Index
server name
✓ should be valid server name (7ms)
GET hello
✓ should be greet (63ms)
✓ content-type should be text/plain (6ms)
HEAD hello
✓ connection should be close (4ms)
console.log src/index.ts:17
Restify TypeScript Echo Server listening at http://[::]:8080
console.log src/__tests__/index.test.ts:9
afterAll: server.close()
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 4 passed, 4 total
Snapshots: 0 total
Time: 4.718s
Ran all test suites.
webpack --config webpack.config.dev.js
Hash: e19b805b0d985055c5b0
Version: webpack 4.16.4
Time: 3107ms
Built at: 2018-08-04 16:56:52
Asset Size Chunks Chunk Names
index.js 11 KiB main [emitted] main
Entrypoint main = index.js
[./src/index.ts] 425 bytes {main} [built]
[restify] external "restify" 42 bytes {main} [built]
npm start
> restify-typescript-example@0.1.0 start /Users/user/work/restify-typescript-example
> node dist/index.js
Restify TypeScript Echo Server listening at http://[::]:8080
curl -is http://localhost:8080/hello/bathtimefish -H 'accept: text/plain'
HTTP/1.1 200 OK
Server: Restify TypeScript Echo Server
Content-Type: text/plain
Content-Length: 18
Date: Sat, 04 Aug 2018 08:00:53 GMT
Connection: keep-alive
hello bathtimefish
curl -is http://localhost:8080/hello/bathtimefish
HTTP/1.1 200 OK
Server: Restify TypeScript Echo Server
Content-Type: application/json
Content-Length: 20
Date: Sat, 04 Aug 2018 08:02:10 GMT
Connection: keep-alive
"hello bathtimefish"
curl -is http://localhost:8080/hello/bathtimefish -X HEAD -H 'connection: close'
HTTP/1.1 200 OK
Server: Restify TypeScript Echo Server
Date: Sat, 04 Aug 2018 08:03:15 GMT
Connection: close
import * as index from '../index';
import fetch from 'node-fetch';
describe('Index', () => {
const server = index.server;
afterAll(() => {
console.log('afterAll: server.close()');
server.close();
});
describe('server name', () => {
it('should be valid server name', () => {
const serverName = 'Restify TypeScript Echo Server';
expect(server.name).toBe(serverName);
});
});
describe('GET hello', () => {
it('should be greet', async() => {
const url = 'http://localhost:8080/hello/';
const name = 'bathtimefish';
const res = await fetch(url + name, {method: 'GET'});
const json = await res.json();
expect(json).toBe('hello ' + name);
});
it('content-type should be text/plain', async() => {
const url = 'http://localhost:8080/hello/';
const name = 'bathtimefish';
const res = await fetch(url + name, {
method: 'GET',
headers: {'accept': 'text/plain'}
});
const contentType = res.headers.get('content-type');
expect(contentType).toBe('text/plain');
const json = await res.text();
expect(json).toBe('hello ' + name);
});
});
describe('HEAD hello', () => {
it('connection should be close', async() => {
const url = 'http://localhost:8080/hello/';
const name = 'bathtimefish';
const res = await fetch(url + name, {
method: 'HEAD',
headers: {'connection': 'close'}
});
const connection = res.headers.get('connection');
expect(connection).toBe('close');
});
});
});
import * as restify from 'restify';
const respond: restify.RequestHandlerType = (req, res, next) => {
res.send('hello ' + req.params.name);
next();
};
export const server = restify.createServer({
name: 'Restify TypeScript Echo Server',
version: '0.1.0',
});
server.get('/hello/:name', respond);
server.head('/hello/:name', respond);
server.listen(8080, () => {
console.log('%s listening at %s', server.name, server.url);
});
{
"name": "restify-typescript-example",
"version": "0.1.0",
"description": "Restify TypeScript Example",
"main": "index.js",
"scripts": {
"start": "node dist/index.js",
"test": "jest"
},
"jest": {
"globals": {
"ts-jest": {
"tsConfigFile": "tsconfig.jest.json"
}
},
"transform": {
"^.+\\.(ts|tsx)$": "ts-jest"
},
"testURL": "http://localhost/",
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(ts?|jsx?|tsx?)$",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json",
"node"
],
"collectCoverage": true,
"collectCoverageFrom": [
"src/**/*.ts"
]
},
"keywords": [],
"author": "bathtimefish",
"license": "MIT",
"dependencies": {
"node-fetch": "^2.2.0",
"restify": "^7.2.1"
},
"devDependencies": {
"@types/jest": "^23.3.1",
"@types/node-fetch": "^2.1.2",
"@types/restify": "^7.2.3",
"jest": "^23.4.2",
"ts-jest": "^23.1.2",
"ts-loader": "^4.4.2",
"tslint": "^5.11.0",
"tslint-config-airbnb": "^5.9.2",
"tslint-loader": "^3.6.0",
"typescript": "^3.0.1",
"webpack": "^4.16.4",
"webpack-cli": "^3.1.0",
"webpack-node-externals": "^1.7.2"
}
}
{
"compilerOptions": {
"sourceMap": true,
"noImplicitAny": true,
"module": "es6",
"target": "es5",
"jsx": "react",
"lib": ["es2018", "dom"],
"moduleResolution": "node",
"removeComments": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": false,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"strictFunctionTypes": false
}
}
{
"extends": "./tsconfig.dev.json",
"compilerOptions": {
"module": "commonjs"
}
}
{
"compilerOptions": {
"noImplicitAny": true,
"module": "es6",
"target": "es5",
"jsx": "react",
"lib": ["es2018", "dom"],
"moduleResolution": "node",
"removeComments": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": false,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"strictFunctionTypes": false
}
}
{
"extends": "tslint-config-airbnb",
"rules": {
"ter-indent": [true, 2],
"no-boolean-literal-compare": false
}
}
const path = require('path');
const nodeExternals = require('webpack-node-externals');
module.exports = {
mode: 'development',
entry: './src/index.ts',
target: 'node', // Module not found: Error: Can't resolve 'fs' 対策
externals: [nodeExternals()],
devtool: 'inline-source-map',
module: {
rules: [
{
enforce: 'pre',
loader: 'tslint-loader',
test: /\.ts$/,
exclude: [
/node_modules/,
"**/*.test.ts"
],
options: {
emitErrors: true
}
},
{
loader: 'ts-loader',
test: /\.ts$/,
exclude: [
/node_modules/,
"**/*.test.ts"
],
options: {
configFile: 'tsconfig.dev.json'
}
}
]
},
resolve: {
extensions: [ '.ts', '.js' ]
},
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist')
}
};
const path = require('path');
const nodeExternals = require('webpack-node-externals');
module.exports = {
mode: 'production',
entry: './src/index.ts',
target: 'node', // Module not found: Error: Can't resolve 'fs' 対策
externals: [nodeExternals()],
module: {
rules: [
{
enforce: 'pre',
loader: 'tslint-loader',
test: /\.ts$/,
exclude: [
/node_modules/,
"**/*.test.ts"
],
options: {
emitErrors: true
}
},
{
loader: 'ts-loader',
test: /\.ts$/,
exclude: [
/node_modules/,
"**/*.test.ts"
],
options: {
configFile: 'tsconfig.prod.json'
}
}
]
},
resolve: {
extensions: [ '.ts', '.js' ]
},
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist')
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment