From e06ad8c985aff713d685c6861c93bd0931c08c0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Fri, 26 Jan 2018 14:48:11 +0100 Subject: [PATCH 1/3] docs: add example-rpc-server --- packages/example-rpc-server/.prettierignore | 2 + packages/example-rpc-server/LICENSE | 24 +++++ packages/example-rpc-server/README.md | 33 ++++++ packages/example-rpc-server/index.ts | 11 ++ packages/example-rpc-server/package.json | 57 ++++++++++ .../example-rpc-server/src/application.ts | 21 ++++ .../src/controllers/greet.controller.ts | 13 +++ .../src/controllers/index.ts | 1 + packages/example-rpc-server/src/index.ts | 22 ++++ .../example-rpc-server/src/models/index.ts | 1 + .../src/models/person.model.ts | 5 + .../example-rpc-server/src/servers/index.ts | 2 + .../src/servers/rpc-router.ts | 51 +++++++++ .../src/servers/rpc-server.ts | 37 +++++++ packages/example-rpc-server/test/README.md | 4 + .../test/controllers/greet.controller.test.ts | 40 +++++++ packages/example-rpc-server/test/mocha.opts | 1 + .../test/servers/rpc-router.test.ts | 102 ++++++++++++++++++ packages/example-rpc-server/tsconfig.json | 13 +++ packages/example-rpc-server/tslint.build.json | 17 +++ packages/example-rpc-server/tslint.json | 4 + 21 files changed, 461 insertions(+) create mode 100644 packages/example-rpc-server/.prettierignore create mode 100644 packages/example-rpc-server/LICENSE create mode 100644 packages/example-rpc-server/README.md create mode 100644 packages/example-rpc-server/index.ts create mode 100644 packages/example-rpc-server/package.json create mode 100644 packages/example-rpc-server/src/application.ts create mode 100644 packages/example-rpc-server/src/controllers/greet.controller.ts create mode 100644 packages/example-rpc-server/src/controllers/index.ts create mode 100644 packages/example-rpc-server/src/index.ts create mode 100644 packages/example-rpc-server/src/models/index.ts create mode 100644 packages/example-rpc-server/src/models/person.model.ts create mode 100644 packages/example-rpc-server/src/servers/index.ts create mode 100644 packages/example-rpc-server/src/servers/rpc-router.ts create mode 100644 packages/example-rpc-server/src/servers/rpc-server.ts create mode 100644 packages/example-rpc-server/test/README.md create mode 100644 packages/example-rpc-server/test/controllers/greet.controller.test.ts create mode 100644 packages/example-rpc-server/test/mocha.opts create mode 100644 packages/example-rpc-server/test/servers/rpc-router.test.ts create mode 100644 packages/example-rpc-server/tsconfig.json create mode 100644 packages/example-rpc-server/tslint.build.json create mode 100644 packages/example-rpc-server/tslint.json diff --git a/packages/example-rpc-server/.prettierignore b/packages/example-rpc-server/.prettierignore new file mode 100644 index 000000000000..f84e220671a5 --- /dev/null +++ b/packages/example-rpc-server/.prettierignore @@ -0,0 +1,2 @@ +*.js +*.d.ts diff --git a/packages/example-rpc-server/LICENSE b/packages/example-rpc-server/LICENSE new file mode 100644 index 000000000000..d44dd8f08aec --- /dev/null +++ b/packages/example-rpc-server/LICENSE @@ -0,0 +1,24 @@ +Node module: loopback4-example-rpc-server +This project is licensed under the MIT License, full text below. + +-------- + +MIT license + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/example-rpc-server/README.md b/packages/example-rpc-server/README.md new file mode 100644 index 000000000000..bddacc4c63de --- /dev/null +++ b/packages/example-rpc-server/README.md @@ -0,0 +1,33 @@ +# loopback4-example-rpc-server + +An example RPC server and application to demonstrate the creation of your +own custom server. + +[![LoopBack](http://loopback.io/images/overview/powered-by-LB-xs.png)](http://loopback.io/) + +## Usage +Install dependencies and start the app: +```sh +npm install +npm start +``` + +Next, use your favourite REST client to send RPC payloads to the server +(hosted on port 3000). + +## Request Format + +The request body should contain a controller name, method name and input object. +Example: +```json +{ + "controller": "GreetController", + "method": "basicHello", + "input": { + "name": "Janet" + } +} +``` +The router will determine which controller and method will service your request +based on the given names in the payload. + diff --git a/packages/example-rpc-server/index.ts b/packages/example-rpc-server/index.ts new file mode 100644 index 000000000000..863a1b9f053b --- /dev/null +++ b/packages/example-rpc-server/index.ts @@ -0,0 +1,11 @@ +// Copyright IBM Corp. 2017. All Rights Reserved. +// Node module: loopback4-example-rpc-server +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +// NOTE(bajtos) This file is used by TypeScript compiler to resolve imports +// from "test" files against original TypeScript sources in "src" directory. +// As a side effect, `tsc` also produces "dist/index.{js,d.ts,map} files +// that allow test files to import paths pointing to {src,test} root directory, +// which is project root for TS sources but "dist" for transpiled sources. +export * from './src'; diff --git a/packages/example-rpc-server/package.json b/packages/example-rpc-server/package.json new file mode 100644 index 000000000000..25fb4db79154 --- /dev/null +++ b/packages/example-rpc-server/package.json @@ -0,0 +1,57 @@ +{ + "name": "loopback4-example-rpc-server", + "version": "1.0.0", + "description": "A basic RPC server using a made-up protocol.", + "keywords": [ + "loopback-application", + "loopback" + ], + "main": "./dist/src/index.js", + "engines": { + "node": ">=8" + }, + "scripts": { + "build": "lb-tsc", + "build:watch": "lb-tsc --watch", + "clean": "lb-clean", + "lint": "npm run prettier:check && npm run tslint", + "lint:fix": "npm run prettier:fix && npm run tslint:fix", + "prettier:cli": "lb-prettier \"**/*.ts\"", + "prettier:check": "npm run prettier:cli -- -l", + "prettier:fix": "npm run prettier:cli -- --write", + "tslint": "lb-tslint", + "tslint:fix": "npm run tslint -- --fix", + "pretest": "npm run clean && npm run build", + "test": "lb-dist mocha DIST/test", + "posttest": "npm run lint", + "start": "npm run build && node .", + "prepare": "npm run build" + }, + "repository": { + "type": "git" + }, + "author": "", + "license": "MIT", + "files": [ + "README.md", + "index.js", + "index.d.ts", + "dist", + "dist6" + ], + "dependencies": { + "@loopback/context": "^4.0.0-alpha.18", + "@loopback/core": "^4.0.0-alpha.20", + "@types/express": "^4.0.39", + "@types/node": "^8.0.51", + "@types/p-event": "^1.3.0", + "express": "^4.16.2", + "p-event": "^1.3.0" + }, + "devDependencies": { + "@loopback/build": "^4.0.0-alpha.5", + "@loopback/testlab": "^4.0.0-alpha.13", + "@types/mocha": "^2.2.43", + "mocha": "^4.0.1" + } +} diff --git a/packages/example-rpc-server/src/application.ts b/packages/example-rpc-server/src/application.ts new file mode 100644 index 000000000000..6881aa50eecb --- /dev/null +++ b/packages/example-rpc-server/src/application.ts @@ -0,0 +1,21 @@ +import {Application, ApplicationConfig} from '@loopback/core'; +import {RPCServer} from './servers/rpc-server'; +import {GreetController} from './controllers'; + +export class MyApplication extends Application { + options: ApplicationConfig; + constructor(options?: ApplicationConfig) { + // Allow options to replace the defined components array, if desired. + super(options); + this.controller(GreetController); + this.server(RPCServer); + this.options = options || {}; + this.options.port = this.options.port || 3000; + this.bind('rpcServer.config').to(this.options); + } + + async start() { + await super.start(); + console.log(`Server is running on port ${this.options.port}`); + } +} diff --git a/packages/example-rpc-server/src/controllers/greet.controller.ts b/packages/example-rpc-server/src/controllers/greet.controller.ts new file mode 100644 index 000000000000..bfd16fa1a37e --- /dev/null +++ b/packages/example-rpc-server/src/controllers/greet.controller.ts @@ -0,0 +1,13 @@ +import {Person} from '../models'; + +export class GreetController { + basicHello(input: Person) { + return `Hello, ${(input && input.name) || 'World'}!`; + } + + hobbyHello(input: Person) { + return `${this.basicHello(input)} I heard you like ${(input && + input.hobby) || + 'underwater basket weaving'}.`; + } +} diff --git a/packages/example-rpc-server/src/controllers/index.ts b/packages/example-rpc-server/src/controllers/index.ts new file mode 100644 index 000000000000..92608bd0ac0d --- /dev/null +++ b/packages/example-rpc-server/src/controllers/index.ts @@ -0,0 +1 @@ +export * from './greet.controller'; diff --git a/packages/example-rpc-server/src/index.ts b/packages/example-rpc-server/src/index.ts new file mode 100644 index 000000000000..9023262d89b6 --- /dev/null +++ b/packages/example-rpc-server/src/index.ts @@ -0,0 +1,22 @@ +// Copyright IBM Corp. 2017. All Rights Reserved. +// Node module: some-project +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +import {MyApplication} from './application'; +import {ApplicationConfig} from '@loopback/core'; + +export async function main(options?: ApplicationConfig) { + const app = new MyApplication(options); + + try { + await app.start(); + } catch (err) { + console.error(`Unable to start application: ${err}`); + } + return app; +} + +main().catch(err => { + console.error('Unhandled exception!'); +}); diff --git a/packages/example-rpc-server/src/models/index.ts b/packages/example-rpc-server/src/models/index.ts new file mode 100644 index 000000000000..69af9fd6837b --- /dev/null +++ b/packages/example-rpc-server/src/models/index.ts @@ -0,0 +1 @@ +export * from './person.model'; diff --git a/packages/example-rpc-server/src/models/person.model.ts b/packages/example-rpc-server/src/models/person.model.ts new file mode 100644 index 000000000000..ba966334212a --- /dev/null +++ b/packages/example-rpc-server/src/models/person.model.ts @@ -0,0 +1,5 @@ +// Note that this can also be a class! +export type Person = { + name?: string; + hobby?: string; +}; diff --git a/packages/example-rpc-server/src/servers/index.ts b/packages/example-rpc-server/src/servers/index.ts new file mode 100644 index 000000000000..98553f0adcdd --- /dev/null +++ b/packages/example-rpc-server/src/servers/index.ts @@ -0,0 +1,2 @@ +export * from './rpc-router'; +export * from './rpc-server'; diff --git a/packages/example-rpc-server/src/servers/rpc-router.ts b/packages/example-rpc-server/src/servers/rpc-router.ts new file mode 100644 index 000000000000..03603f331da7 --- /dev/null +++ b/packages/example-rpc-server/src/servers/rpc-router.ts @@ -0,0 +1,51 @@ +import {RPCServer} from './rpc-server'; +import * as express from 'express'; +import * as parser from 'body-parser'; + +export function rpcRouter(server: RPCServer) { + const jsonParser = parser.json(); + server.expressServer.post('*', jsonParser, async (request, response) => { + await routeHandler(server, request, response); + }); +} + +export async function routeHandler( + server: RPCServer, + request: express.Request, + response: express.Response, +) { + const ctrl = request.body.controller; + const method = request.body.method; + const input = request.body.input; + let controller; + try { + controller = await server.get(`controllers.${ctrl}`); + if (!controller[method]) { + throw new Error( + `No method was found on controller "${ctrl}" with name "${method}".`, + ); + } + } catch (err) { + sendErrResponse(response, err, 400); + return; + } + try { + response.send(await controller[method](input)); + } catch (err) { + sendErrResponse(response, err, 500); + } +} + +export type Controller = { + [method: string]: Function; +}; + +function sendErrResponse( + resp: express.Response, + // tslint:disable-next-line:no-any + send: any, + statusCode: number, +) { + resp.statusCode = statusCode; + resp.send(send); +} diff --git a/packages/example-rpc-server/src/servers/rpc-server.ts b/packages/example-rpc-server/src/servers/rpc-server.ts new file mode 100644 index 000000000000..66a9ef304032 --- /dev/null +++ b/packages/example-rpc-server/src/servers/rpc-server.ts @@ -0,0 +1,37 @@ +import {inject, Context} from '@loopback/context'; +import {Server, Application, CoreBindings} from '@loopback/core'; +import * as express from 'express'; +import * as http from 'http'; +import * as pEvent from 'p-event'; +import {rpcRouter} from '.'; + +export class RPCServer extends Context implements Server { + _server: http.Server; + expressServer: express.Application; + constructor( + @inject(CoreBindings.APPLICATION_INSTANCE) public app?: Application, + @inject('rpcServer.config') public config?: RPCServerConfig, + ) { + super(app); + this.config = config || {}; + this.expressServer = express(); + rpcRouter(this); + } + + async start(): Promise { + this._server = this.expressServer.listen( + (this.config && this.config.port) || 3000, + ); + return await pEvent(this._server, 'listening'); + } + async stop(): Promise { + this._server.close(); + return await pEvent(this._server, 'close'); + } +} + +export type RPCServerConfig = { + port?: number; + // tslint:disable-next-line:no-any + [key: string]: any; +}; diff --git a/packages/example-rpc-server/test/README.md b/packages/example-rpc-server/test/README.md new file mode 100644 index 000000000000..2243988ea7e1 --- /dev/null +++ b/packages/example-rpc-server/test/README.md @@ -0,0 +1,4 @@ +# Tests + +Please place your tests in this folder. + diff --git a/packages/example-rpc-server/test/controllers/greet.controller.test.ts b/packages/example-rpc-server/test/controllers/greet.controller.test.ts new file mode 100644 index 000000000000..171c30d8aae4 --- /dev/null +++ b/packages/example-rpc-server/test/controllers/greet.controller.test.ts @@ -0,0 +1,40 @@ +import 'mocha'; +import {GreetController} from '../../src/controllers'; +import {expect} from '@loopback/testlab'; + +describe('greet.controller', () => { + const controller = new GreetController(); + describe('basicHello', () => { + it('returns greetings for the world without valid input', () => { + expect(controller.basicHello({})).to.equal('Hello, World!'); + }); + + it('returns greetings for a name', () => { + const input = { + name: 'Aaron', + }; + const expected = `Hello, ${input.name}!`; + expect(controller.basicHello(input)).to.equal(expected); + }); + }); + describe('hobbyHello', () => { + it('returns greetings for a name', () => { + const input = { + name: 'Aaron', + }; + expect(controller.hobbyHello(input)).to.match( + /Hello, Aaron!(.*)underwater basket weaving/, + ); + }); + + it('returns greetings for a name and hobby', () => { + const input = { + name: 'Aaron', + hobby: 'sportsball', + }; + expect(controller.hobbyHello(input)).to.match( + /Hello, Aaron!(.*)sportsball/, + ); + }); + }); +}); diff --git a/packages/example-rpc-server/test/mocha.opts b/packages/example-rpc-server/test/mocha.opts new file mode 100644 index 000000000000..4a5232017818 --- /dev/null +++ b/packages/example-rpc-server/test/mocha.opts @@ -0,0 +1 @@ +--recursive diff --git a/packages/example-rpc-server/test/servers/rpc-router.test.ts b/packages/example-rpc-server/test/servers/rpc-router.test.ts new file mode 100644 index 000000000000..50328afb4881 --- /dev/null +++ b/packages/example-rpc-server/test/servers/rpc-router.test.ts @@ -0,0 +1,102 @@ +import 'mocha'; +import * as express from 'express'; +import * as sinon from 'sinon'; +import {RPCServer, routeHandler} from '../../src/servers'; +import {expect} from '@loopback/testlab'; + +describe('rpcRouter', () => { + describe('routeHandler', () => { + // tslint:disable-next-line:no-any + let server: any; + let request: express.Request; + let response: express.Response; + let responseStub: sinon.SinonStub; + beforeEach(testSetup); + it('routes correctly when controller and method exist', async () => { + await routeHandler(server, request, response); + sinon.assert.called(responseStub); + expect(responseStub.firstCall.args[0]).to.match(/Hello, Janet!/); + }); + + it('throws 400 when controller does not exist', async () => { + const getStub = server.get as sinon.SinonStub; + getStub.rejects(new Error('Does not exist!')); + await routeHandler(server, request, response); + expect(response.statusCode).to.equal(400); + sinon.assert.called(responseStub); + expect(responseStub.firstCall.args[0]).to.match(/Does not exist!/); + }); + + it('throws 400 when method does not exist', async () => { + request = getRequest({ + body: { + controller: 'FakeController', + method: 'notReal', + input: { + name: 'Sad', + }, + }, + }); + await routeHandler(server, request, response); + expect(response.statusCode).to.equal(400); + sinon.assert.called(responseStub); + expect(responseStub.firstCall.args[0]).to.match( + /No method was found on controller/, + ); + }); + + it('throws 500 on unhandled error', async () => { + server.get.resolves( + new class extends FakeController { + // tslint:disable-next-line:no-any + getFoo(input: any): string { + throw new Error('>:('); + } + }(), + ); + await routeHandler(server, request, response); + expect(response.statusCode).to.equal(500); + sinon.assert.called(responseStub); + expect(responseStub.firstCall.args[0].message).to.match('>:('); + }); + function testSetup() { + server = getServer(); + request = getRequest(); + response = getResponse(); + responseStub = response.send as sinon.SinonStub; + } + }); + + function getServer() { + const server = sinon.createStubInstance(RPCServer); + server.get.resolves(FakeController); + return server; + } + function getRequest(req?: Partial) { + return Object.assign( + { + body: { + controller: 'FakeController', + method: 'getFoo', + input: { + name: 'Janet', + }, + }, + }, + req, + ); + } + + function getResponse(res?: Partial) { + const resp = {}; + resp.send = sinon.stub(); + return resp; + } + + class FakeController { + // tslint:disable-next-line:no-any + getFoo(input: any) { + return `Hello, ${input.name}!`; + } + } +}); diff --git a/packages/example-rpc-server/tsconfig.json b/packages/example-rpc-server/tsconfig.json new file mode 100644 index 000000000000..d0c8f649ba31 --- /dev/null +++ b/packages/example-rpc-server/tsconfig.json @@ -0,0 +1,13 @@ +{ + "$schema": "http://json.schemastore.org/tsconfig", + "extends": "./node_modules/@loopback/build/config/tsconfig.common.json", + "include": [ + "src", + "test" + ], + "exclude": [ + "node_modules/**", + "packages/*/node_modules/**", + "**/*.d.ts" + ] +} diff --git a/packages/example-rpc-server/tslint.build.json b/packages/example-rpc-server/tslint.build.json new file mode 100644 index 000000000000..11aa5c89be1e --- /dev/null +++ b/packages/example-rpc-server/tslint.build.json @@ -0,0 +1,17 @@ +{ + "$schema": "http://json.schemastore.org/tslint", + "extends": ["./tslint.json"], + // This configuration files enabled rules which require type checking + // and therefore cannot be run by Visual Studio Code TSLint extension + // See https://github.com/Microsoft/vscode-tslint/issues/70 + "rules": { + // These rules find errors related to TypeScript features. + + // These rules catch common errors in JS programming or otherwise + // confusing constructs that are prone to producing bugs. + + "await-promise": true, + "no-floating-promises": true, + "no-void-expression": [true, "ignore-arrow-function-shorthand"] + } +} diff --git a/packages/example-rpc-server/tslint.json b/packages/example-rpc-server/tslint.json new file mode 100644 index 000000000000..9b70ba61277c --- /dev/null +++ b/packages/example-rpc-server/tslint.json @@ -0,0 +1,4 @@ +{ + "$schema": "http://json.schemastore.org/tslint", + "extends": ["./node_modules/@loopback/build/config/tslint.common.json"] + } From 6a0fb0fce42c1618618ecdcb74cb0b89be176a9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Fri, 26 Jan 2018 15:11:49 +0100 Subject: [PATCH 2/3] fixup! integrate the new example with the rest of the monorepo --- CODEOWNERS | 1 + packages/cli/generators/example/index.js | 1 + packages/example-rpc-server/LICENSE | 3 ++- packages/example-rpc-server/README.md | 23 +++++++++++++++---- packages/example-rpc-server/index.ts | 4 ++-- packages/example-rpc-server/package.json | 21 ++++++++++------- .../example-rpc-server/src/application.ts | 5 ++++ .../src/controllers/greet.controller.ts | 5 ++++ .../src/controllers/index.ts | 5 ++++ packages/example-rpc-server/src/index.ts | 4 ++-- .../example-rpc-server/src/models/index.ts | 5 ++++ .../src/models/person.model.ts | 5 ++++ .../example-rpc-server/src/servers/index.ts | 5 ++++ .../src/servers/rpc-router.ts | 5 ++++ .../src/servers/rpc-server.ts | 5 ++++ .../test/controllers/greet.controller.test.ts | 5 ++++ .../test/servers/rpc-router.test.ts | 8 +++++-- 17 files changed, 91 insertions(+), 19 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index db2a964ee181..b882bb5a4b1d 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -11,6 +11,7 @@ packages/context/* @bajtos @raymondfeng @kjdelisle packages/core/* @bajtos @raymondfeng @kjdelisle packages/example-getting-started/* @bajtos @kjdelisle packages/example-log-extension/* @virkt25 +packages/example-rpc-server/* @kjdelisle packages/metadata/* @raymondfeng packages/openapi-spec/* @bajtos @jannyHou packages/openapi-spec-builder/* @bajtos @raymondfeng diff --git a/packages/cli/generators/example/index.js b/packages/cli/generators/example/index.js index 93dfaeae98d1..8faa04539685 100644 --- a/packages/cli/generators/example/index.js +++ b/packages/cli/generators/example/index.js @@ -16,6 +16,7 @@ const EXAMPLES = { 'An application and tutorial on how to build with LoopBack 4.', 'log-extension': 'An example extension project for LoopBack 4', + 'rpc-server': 'A basic RPC server using a made-up protocol.', }; Object.freeze(EXAMPLES); diff --git a/packages/example-rpc-server/LICENSE b/packages/example-rpc-server/LICENSE index d44dd8f08aec..065cc147fcce 100644 --- a/packages/example-rpc-server/LICENSE +++ b/packages/example-rpc-server/LICENSE @@ -1,4 +1,5 @@ -Node module: loopback4-example-rpc-server +Copyright (c) IBM Corp. 2018. All Rights Reserved. +Node module: @loopback/example-rpc-server This project is licensed under the MIT License, full text below. -------- diff --git a/packages/example-rpc-server/README.md b/packages/example-rpc-server/README.md index bddacc4c63de..21599346479f 100644 --- a/packages/example-rpc-server/README.md +++ b/packages/example-rpc-server/README.md @@ -1,4 +1,4 @@ -# loopback4-example-rpc-server +# @loopback/example-rpc-server An example RPC server and application to demonstrate the creation of your own custom server. @@ -6,9 +6,24 @@ own custom server. [![LoopBack](http://loopback.io/images/overview/powered-by-LB-xs.png)](http://loopback.io/) ## Usage -Install dependencies and start the app: -```sh -npm install + +1. Install the new loopback CLI toolkit. +``` +npm i -g @loopback/cli +``` + +2. Download the "getting-started" application. +``` +lb4 example getting-started +``` + +3. Switch to the directory and install dependencies. +``` +cd loopback4-example-getting-started && npm i +``` + +4. Start the app! +``` npm start ``` diff --git a/packages/example-rpc-server/index.ts b/packages/example-rpc-server/index.ts index 863a1b9f053b..3e1026e0d517 100644 --- a/packages/example-rpc-server/index.ts +++ b/packages/example-rpc-server/index.ts @@ -1,5 +1,5 @@ -// Copyright IBM Corp. 2017. All Rights Reserved. -// Node module: loopback4-example-rpc-server +// Copyright IBM Corp. 2018. All Rights Reserved. +// Node module: @loopback/example-rpc-server // This file is licensed under the MIT License. // License text available at https://opensource.org/licenses/MIT diff --git a/packages/example-rpc-server/package.json b/packages/example-rpc-server/package.json index 25fb4db79154..153b049fd188 100644 --- a/packages/example-rpc-server/package.json +++ b/packages/example-rpc-server/package.json @@ -1,6 +1,6 @@ { - "name": "loopback4-example-rpc-server", - "version": "1.0.0", + "name": "@loopback/example-rpc-server", + "version": "4.0.0-alpha.0", "description": "A basic RPC server using a made-up protocol.", "keywords": [ "loopback-application", @@ -8,10 +8,13 @@ ], "main": "./dist/src/index.js", "engines": { - "node": ">=8" + "node": ">=6" }, "scripts": { - "build": "lb-tsc", + "build": "npm run build:dist && npm run build:dist6", + "build:current": "lb-tsc", + "build:dist": "lb-tsc es2017", + "build:dist6": "lb-tsc es2015", "build:watch": "lb-tsc --watch", "clean": "lb-clean", "lint": "npm run prettier:check && npm run tslint", @@ -21,14 +24,15 @@ "prettier:fix": "npm run prettier:cli -- --write", "tslint": "lb-tslint", "tslint:fix": "npm run tslint -- --fix", - "pretest": "npm run clean && npm run build", - "test": "lb-dist mocha DIST/test", + "pretest": "npm run clean && npm run build:current", + "test": "lb-dist mocha --opts node_modules/@loopback/build/mocha.ts.opts DIST/test", "posttest": "npm run lint", "start": "npm run build && node .", "prepare": "npm run build" }, "repository": { - "type": "git" + "type": "git", + "url": "https://github.com/strongloop/loopback-next.git" }, "author": "", "license": "MIT", @@ -52,6 +56,7 @@ "@loopback/build": "^4.0.0-alpha.5", "@loopback/testlab": "^4.0.0-alpha.13", "@types/mocha": "^2.2.43", - "mocha": "^4.0.1" + "mocha": "^5.0.0", + "source-map-support": "^0.5.2" } } diff --git a/packages/example-rpc-server/src/application.ts b/packages/example-rpc-server/src/application.ts index 6881aa50eecb..fff6c9ed4f95 100644 --- a/packages/example-rpc-server/src/application.ts +++ b/packages/example-rpc-server/src/application.ts @@ -1,3 +1,8 @@ +// Copyright IBM Corp. 2018. All Rights Reserved. +// Node module: @loopback/example-rpc-server +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + import {Application, ApplicationConfig} from '@loopback/core'; import {RPCServer} from './servers/rpc-server'; import {GreetController} from './controllers'; diff --git a/packages/example-rpc-server/src/controllers/greet.controller.ts b/packages/example-rpc-server/src/controllers/greet.controller.ts index bfd16fa1a37e..7405b08ee36c 100644 --- a/packages/example-rpc-server/src/controllers/greet.controller.ts +++ b/packages/example-rpc-server/src/controllers/greet.controller.ts @@ -1,3 +1,8 @@ +// Copyright IBM Corp. 2018. All Rights Reserved. +// Node module: @loopback/example-rpc-server +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + import {Person} from '../models'; export class GreetController { diff --git a/packages/example-rpc-server/src/controllers/index.ts b/packages/example-rpc-server/src/controllers/index.ts index 92608bd0ac0d..a9cd16687a64 100644 --- a/packages/example-rpc-server/src/controllers/index.ts +++ b/packages/example-rpc-server/src/controllers/index.ts @@ -1 +1,6 @@ +// Copyright IBM Corp. 2018. All Rights Reserved. +// Node module: @loopback/example-rpc-server +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + export * from './greet.controller'; diff --git a/packages/example-rpc-server/src/index.ts b/packages/example-rpc-server/src/index.ts index 9023262d89b6..c2c78068b553 100644 --- a/packages/example-rpc-server/src/index.ts +++ b/packages/example-rpc-server/src/index.ts @@ -1,5 +1,5 @@ -// Copyright IBM Corp. 2017. All Rights Reserved. -// Node module: some-project +// Copyright IBM Corp. 2018. All Rights Reserved. +// Node module: @loopback/example-rpc-server // This file is licensed under the MIT License. // License text available at https://opensource.org/licenses/MIT diff --git a/packages/example-rpc-server/src/models/index.ts b/packages/example-rpc-server/src/models/index.ts index 69af9fd6837b..01eb22361169 100644 --- a/packages/example-rpc-server/src/models/index.ts +++ b/packages/example-rpc-server/src/models/index.ts @@ -1 +1,6 @@ +// Copyright IBM Corp. 2018. All Rights Reserved. +// Node module: @loopback/example-rpc-server +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + export * from './person.model'; diff --git a/packages/example-rpc-server/src/models/person.model.ts b/packages/example-rpc-server/src/models/person.model.ts index ba966334212a..885bc16eda1f 100644 --- a/packages/example-rpc-server/src/models/person.model.ts +++ b/packages/example-rpc-server/src/models/person.model.ts @@ -1,3 +1,8 @@ +// Copyright IBM Corp. 2018. All Rights Reserved. +// Node module: @loopback/example-rpc-server +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + // Note that this can also be a class! export type Person = { name?: string; diff --git a/packages/example-rpc-server/src/servers/index.ts b/packages/example-rpc-server/src/servers/index.ts index 98553f0adcdd..a273af0a0ae6 100644 --- a/packages/example-rpc-server/src/servers/index.ts +++ b/packages/example-rpc-server/src/servers/index.ts @@ -1,2 +1,7 @@ +// Copyright IBM Corp. 2018. All Rights Reserved. +// Node module: @loopback/example-rpc-server +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + export * from './rpc-router'; export * from './rpc-server'; diff --git a/packages/example-rpc-server/src/servers/rpc-router.ts b/packages/example-rpc-server/src/servers/rpc-router.ts index 03603f331da7..4340c4f17e0b 100644 --- a/packages/example-rpc-server/src/servers/rpc-router.ts +++ b/packages/example-rpc-server/src/servers/rpc-router.ts @@ -1,3 +1,8 @@ +// Copyright IBM Corp. 2018. All Rights Reserved. +// Node module: @loopback/example-rpc-server +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + import {RPCServer} from './rpc-server'; import * as express from 'express'; import * as parser from 'body-parser'; diff --git a/packages/example-rpc-server/src/servers/rpc-server.ts b/packages/example-rpc-server/src/servers/rpc-server.ts index 66a9ef304032..5a6bfddcf878 100644 --- a/packages/example-rpc-server/src/servers/rpc-server.ts +++ b/packages/example-rpc-server/src/servers/rpc-server.ts @@ -1,3 +1,8 @@ +// Copyright IBM Corp. 2018. All Rights Reserved. +// Node module: @loopback/example-rpc-server +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + import {inject, Context} from '@loopback/context'; import {Server, Application, CoreBindings} from '@loopback/core'; import * as express from 'express'; diff --git a/packages/example-rpc-server/test/controllers/greet.controller.test.ts b/packages/example-rpc-server/test/controllers/greet.controller.test.ts index 171c30d8aae4..6ccb50f00f03 100644 --- a/packages/example-rpc-server/test/controllers/greet.controller.test.ts +++ b/packages/example-rpc-server/test/controllers/greet.controller.test.ts @@ -1,3 +1,8 @@ +// Copyright IBM Corp. 2018. All Rights Reserved. +// Node module: @loopback/example-rpc-server +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + import 'mocha'; import {GreetController} from '../../src/controllers'; import {expect} from '@loopback/testlab'; diff --git a/packages/example-rpc-server/test/servers/rpc-router.test.ts b/packages/example-rpc-server/test/servers/rpc-router.test.ts index 50328afb4881..402839f89c51 100644 --- a/packages/example-rpc-server/test/servers/rpc-router.test.ts +++ b/packages/example-rpc-server/test/servers/rpc-router.test.ts @@ -1,8 +1,12 @@ +// Copyright IBM Corp. 2018. All Rights Reserved. +// Node module: @loopback/example-rpc-server +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + import 'mocha'; import * as express from 'express'; -import * as sinon from 'sinon'; import {RPCServer, routeHandler} from '../../src/servers'; -import {expect} from '@loopback/testlab'; +import {expect, sinon} from '@loopback/testlab'; describe('rpcRouter', () => { describe('routeHandler', () => { From 84dcb6dfdc8f2818b25a5ae37c6e55a6a1f6d09a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Mon, 29 Jan 2018 09:46:09 +0100 Subject: [PATCH 3/3] fixup! address code review comments --- packages/example-getting-started/README.md | 2 +- packages/example-rpc-server/README.md | 6 +++--- packages/example-rpc-server/index.d.ts | 6 ++++++ packages/example-rpc-server/index.js | 14 ++++++++++++++ packages/example-rpc-server/package.json | 1 - packages/example-rpc-server/test/mocha.opts | 1 - packages/example-rpc-server/tslint.build.json | 17 ----------------- packages/example-rpc-server/tslint.json | 4 ---- 8 files changed, 24 insertions(+), 27 deletions(-) create mode 100644 packages/example-rpc-server/index.d.ts create mode 100644 packages/example-rpc-server/index.js delete mode 100644 packages/example-rpc-server/test/mocha.opts delete mode 100644 packages/example-rpc-server/tslint.build.json delete mode 100644 packages/example-rpc-server/tslint.json diff --git a/packages/example-getting-started/README.md b/packages/example-getting-started/README.md index 558b6360b212..cc8700d62b3f 100644 --- a/packages/example-getting-started/README.md +++ b/packages/example-getting-started/README.md @@ -28,7 +28,7 @@ lb4 example getting-started 3. Switch to the directory and install dependencies. ``` -cd loopback4-example-getting-started && npm i +cd loopback-example-getting-started && npm i ``` 4. Start the app! diff --git a/packages/example-rpc-server/README.md b/packages/example-rpc-server/README.md index 21599346479f..a39fed335724 100644 --- a/packages/example-rpc-server/README.md +++ b/packages/example-rpc-server/README.md @@ -12,14 +12,14 @@ own custom server. npm i -g @loopback/cli ``` -2. Download the "getting-started" application. +2. Download the "rpc-server" application. ``` -lb4 example getting-started +lb4 example rpc-server ``` 3. Switch to the directory and install dependencies. ``` -cd loopback4-example-getting-started && npm i +cd loopback-example-rpc-server && npm i ``` 4. Start the app! diff --git a/packages/example-rpc-server/index.d.ts b/packages/example-rpc-server/index.d.ts new file mode 100644 index 000000000000..13ed083fde3a --- /dev/null +++ b/packages/example-rpc-server/index.d.ts @@ -0,0 +1,6 @@ +// Copyright IBM Corp. 2017,2018. All Rights Reserved. +// Node module: @loopback/example-getting-started +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +export * from './dist'; diff --git a/packages/example-rpc-server/index.js b/packages/example-rpc-server/index.js new file mode 100644 index 000000000000..20cb263c2a1f --- /dev/null +++ b/packages/example-rpc-server/index.js @@ -0,0 +1,14 @@ +// Copyright IBM Corp. 2017,2018. All Rights Reserved. +// Node module: @loopback/example-getting-started +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +const nodeMajorVersion = +process.versions.node.split('.')[0]; +const dist = nodeMajorVersion >= 7 ? './dist' : './dist6'; + +const application = (module.exports = require(dist)); + +if (require.main === module) { + // Run the application + application.main(); +} diff --git a/packages/example-rpc-server/package.json b/packages/example-rpc-server/package.json index 153b049fd188..3dce267ab204 100644 --- a/packages/example-rpc-server/package.json +++ b/packages/example-rpc-server/package.json @@ -6,7 +6,6 @@ "loopback-application", "loopback" ], - "main": "./dist/src/index.js", "engines": { "node": ">=6" }, diff --git a/packages/example-rpc-server/test/mocha.opts b/packages/example-rpc-server/test/mocha.opts deleted file mode 100644 index 4a5232017818..000000000000 --- a/packages/example-rpc-server/test/mocha.opts +++ /dev/null @@ -1 +0,0 @@ ---recursive diff --git a/packages/example-rpc-server/tslint.build.json b/packages/example-rpc-server/tslint.build.json deleted file mode 100644 index 11aa5c89be1e..000000000000 --- a/packages/example-rpc-server/tslint.build.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "http://json.schemastore.org/tslint", - "extends": ["./tslint.json"], - // This configuration files enabled rules which require type checking - // and therefore cannot be run by Visual Studio Code TSLint extension - // See https://github.com/Microsoft/vscode-tslint/issues/70 - "rules": { - // These rules find errors related to TypeScript features. - - // These rules catch common errors in JS programming or otherwise - // confusing constructs that are prone to producing bugs. - - "await-promise": true, - "no-floating-promises": true, - "no-void-expression": [true, "ignore-arrow-function-shorthand"] - } -} diff --git a/packages/example-rpc-server/tslint.json b/packages/example-rpc-server/tslint.json deleted file mode 100644 index 9b70ba61277c..000000000000 --- a/packages/example-rpc-server/tslint.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "http://json.schemastore.org/tslint", - "extends": ["./node_modules/@loopback/build/config/tslint.common.json"] - }