├── .gitignore
├── .npmignore
├── .eslintrc.json
├── tsconfig.json
├── .github
├── workflows
│ ├── ci.yml
│ └── auto-deployer.yml
├── dependabot.yml
└── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
├── package.json
├── README.md
├── tests
├── unit-test.ts
└── mock.ts
├── index.ts
└── LICENSE
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | lib
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .github
2 | node_modules
3 | package-lock.json
4 | index.ts
5 | tests
6 | **/tests/*.ts
7 | **/tests/*.js
8 | tsconfig.json
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "@typescript-eslint/parser",
3 | "plugins": ["@typescript-eslint"],
4 | "extends": ["plugin:@typescript-eslint/recommended"]
5 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es6",
4 | "module": "commonjs",
5 | "declaration": true,
6 | "outDir": "./lib",
7 | "strict": true,
8 | "moduleResolution": "node"
9 | }
10 | }
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on:
3 | pull_request:
4 | branches: [ master ]
5 |
6 | jobs:
7 | Tests:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/checkout@v2
11 | - name: Setting up the environment
12 | run: npm install
13 | - name: Verifying linting
14 | run: npm run lint
15 | - name: Building
16 | run: npm run build
17 | - name: Running tests
18 | run: npm run unit-tests
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "npm" # See documentation for possible values
9 | directory: "/" # Location of package manifests
10 | schedule:
11 | interval: "monthly"
12 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/workflows/auto-deployer.yml:
--------------------------------------------------------------------------------
1 | name: Deployment Bot
2 | on:
3 | push:
4 | branches: [ master ]
5 | jobs:
6 | deploy:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v2
10 | - name: Setting up the environment
11 | run: npm install
12 | - name: Verifying linting
13 | run: npm run lint
14 | - name: Building
15 | run: npm run build
16 | - name: Running tests
17 | run: npm run unit-tests
18 | - name: Deploying version
19 | uses: danitseitlin/package-deployer@master
20 | with:
21 | pkg_name: dmock-server
22 | npm_access_token: ${{secrets.NPM_AUTH_TOKEN}}
23 | github_access_token: ${{secrets.G_AUTH_TOKEN}}
24 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dmock-server",
3 | "version": "1.2.0",
4 | "description": "This NodeJS module is a delightful mock server built for automation and ongoing development",
5 | "main": "lib/index.js",
6 | "types": "lib/index.d.ts",
7 | "scripts": {
8 | "build": "tsc",
9 | "test": "mocha -r ts-node/register",
10 | "unit-tests": "npm run test tests/unit-test.ts",
11 | "lint": "eslint .",
12 | "pre-deploy": "npm run unit-tests && npm run build",
13 | "clean": "rmdir lib /s/q"
14 | },
15 | "keywords": [],
16 | "author": "Dani Tseitlin",
17 | "license": "Apache 2.0",
18 | "dependencies": {
19 | "@types/express": "4.17.14",
20 | "body-parser": "1.20.3",
21 | "express": "4.21.0"
22 | },
23 | "devDependencies": {
24 | "@types/axios": "0.14.0",
25 | "@types/chai": "4.3.4",
26 | "@types/mocha": "9.0.0",
27 | "@types/node": "18.15.11",
28 | "@typescript-eslint/eslint-plugin": "4.0.0",
29 | "@typescript-eslint/parser": "3.10.1",
30 | "axios": "1.7.7",
31 | "chai": "4.3.7",
32 | "eslint": "7.32.0",
33 | "mocha": "9.2.2",
34 | "ts-node": "10.4.0",
35 | "typescript": "5.0.3"
36 | },
37 | "repository": {
38 | "type": "git",
39 | "url": "git+https://github.com/danitseitlin/dmock-server.git"
40 | },
41 | "bugs": {
42 | "url": "https://github.com/danitseitlin/dmock-server/issues"
43 | },
44 | "homepage": "https://github.com/danitseitlin/dmock-server#readme"
45 | }
46 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | ## About
23 | This NodeJS module is a delightful mock server built for automation and ongoing development
24 | ## Quick Start
25 |
26 | ### Install the module
27 | Run the following command in your terminal:
28 |
29 | `npm i dmock-server`
30 |
31 | ### Setup your mock
32 | ```
33 | import { MockServer } from 'dmock-server';
34 |
35 | //Initializing the mock server
36 | const server = new MockServer({
37 | hostname: 'localhost',
38 | port: 3000,
39 | routes: [{
40 | method: 'get',
41 | path: '/users',
42 | response: this.users
43 | },{
44 | method: 'get',
45 | path: '/users/:id',
46 | response: (req) => this.getUser(req.params.id)
47 | }]
48 | });
49 | ```
50 | You can setup a function or a simple JS object as a response for a URL.
51 | Once ready, you will need to run `server.start()` to start the server and `server.stop()` to stop it.
52 |
--------------------------------------------------------------------------------
/tests/unit-test.ts:
--------------------------------------------------------------------------------
1 | import Axios from 'axios';
2 | import { expect } from 'chai';
3 | import { Application } from './mock'
4 | const httpClient = Axios.create({
5 | baseURL: 'http://localhost:3000',
6 | responseType: 'json',
7 | headers: {
8 | 'Content-Type': 'application/json'
9 | }
10 | });
11 |
12 | const application = new Application();
13 |
14 | describe('Mock server testing', async function() {
15 | this.timeout(10 * 60 * 60);
16 | before(async () => {
17 | application.start();
18 | });
19 |
20 | after(async () => {
21 | application.stop();
22 | });
23 |
24 | it('JS Object based mock response', async () => {
25 | let response = await httpClient.get('/users');
26 | expect(response.data.length).eql(0, 'Users count');
27 | await httpClient.post('/users', {
28 | name: 'user1',
29 | email: 'user1@gmail.com'
30 | });
31 | await httpClient.post('/users', {
32 | name: 'user2',
33 | email: 'user2@gmail.com'
34 | });
35 | response = await httpClient.get('/users');
36 | expect(response.headers.cookie).to.equal('my-key', 'The cookie of the response')
37 | expect(response.data.length).eql(2, 'Users count');
38 | response = await httpClient.get('/users/1');
39 | expect(response.data.name).eql('user1', 'User name');
40 | expect(response.data.email).eql('user1@gmail.com', 'User email address');
41 | expect(response.headers.cookie).not.to.equal('my-key', 'The cookie of the response')
42 | await httpClient.put('/users/1', {
43 | name: 'user1-updated',
44 | email: 'user1-updated@gmail.com'
45 | });
46 | response = await httpClient.get('/users/1');
47 | expect(response.data.name).eql('user1-updated', 'User updated name');
48 | expect(response.data.email).eql('user1-updated@gmail.com', 'User updated email address');
49 | await httpClient.delete('/users/1');
50 | response = await httpClient.get('/users');
51 | expect(response.data.length).eql(1, 'Users count');
52 | });
53 | });
--------------------------------------------------------------------------------
/tests/mock.ts:
--------------------------------------------------------------------------------
1 | import { MockServer, Response } from '../index';
2 |
3 | export class Application {
4 | server: MockServer
5 | users: User[];
6 | constructor() {
7 | this.users = [];
8 | this.server = new MockServer({
9 | hostname: 'localhost',
10 | port: 3000,
11 | routes: [{
12 | method: 'post',
13 | path: '/users',
14 | response: (req) => this.createUser(req.body)
15 | },{
16 | method: 'put',
17 | path: '/users/:id',
18 | response: (req, res) => this.updateUser(parseInt(req.params.id), req.body, res)
19 | },{
20 | method: 'get',
21 | path: '/users',
22 | headers: {'cookie': 'my-key'},
23 | response: this.users
24 | },{
25 | method: 'delete',
26 | path: '/users/:id',
27 | response: (req, res) => this.deleteUser(parseInt(req.params.id), res)
28 | },{
29 | method: 'get',
30 | path: '/users/:id',
31 | response: (req, res) => this.getUser(parseInt(req.params.id), res)
32 | }]
33 | });
34 | }
35 | /**
36 | * Retrieving a user
37 | * @param id The id of the user
38 | * @param res The response of the request
39 | */
40 | getUser(id: number, res: Response): User | undefined {
41 | const user = this.users.find((user: User) => user.id === id);
42 | if(user === undefined) res.status(404).send(this.generateError(id, 'user'))
43 | return user;
44 | }
45 |
46 | /**
47 | * Creating a user
48 | * @param details The parameters used to create the user
49 | */
50 | createUser(details: UserInformation): void{
51 | this.users.push({
52 | id: this.users.length+1,
53 | name: details.name,
54 | email: details.email
55 | });
56 | }
57 |
58 | /**
59 | * Updating a user
60 | * @param id The if of the user
61 | * @param details The parameters used to update the user
62 | * @param res The response of the request
63 | */
64 | updateUser(id: number, details: UserInformation, res: Response): void{
65 | const user = this.users.find((user: User) => user.id == id);
66 | if(user === undefined) res.status(404).send(this.generateError(id, 'user'))
67 | else if(user !== undefined) {
68 | if(details.email !== undefined) user.email = details.email;
69 | if(details.name !== undefined) user.name = details.name;
70 | const index = this.users.indexOf(user);
71 | this.users[index] = user;
72 | }
73 | }
74 |
75 | /**
76 | * Deleting a user
77 | * @param id The id of the user
78 | * @param res The response of the request
79 | */
80 | deleteUser(id: number, res: Response): void {
81 | const user = this.users.find((user: User) => user.id === id);
82 | if(user === undefined) res.status(404).send(this.generateError(id, 'user'))
83 | else this.users.splice(this.users.indexOf(user), 1);
84 | }
85 |
86 | /**
87 | * Generating an error message
88 | * @param id The id of the entity
89 | * @param entity The entity type
90 | */
91 | private generateError(id: number, entity: string){
92 | return {
93 | code: 404,
94 | message: `Cannot find ${entity} with ${id}`
95 | }
96 | }
97 |
98 | /**
99 | * Starting the application
100 | */
101 | start(): void { this.server.start(); }
102 |
103 | /**
104 | * Stopping the application
105 | */
106 | stop(): void { this.server.stop(); }
107 | }
108 |
109 | /**
110 | * The user object
111 | * @param id The id of the user
112 | * @param name The name of the user
113 | * @param email The email of the user
114 | */
115 | export interface User extends UserInformation {
116 | id: number
117 | }
118 |
119 | /**
120 | * The user information object
121 | * @param name The name of the user
122 | * @param email The email of the user
123 | */
124 | export type UserInformation = {
125 | name?: string,
126 | email?: string
127 | };
--------------------------------------------------------------------------------
/index.ts:
--------------------------------------------------------------------------------
1 | import { createServer, Server } from 'http';
2 | import * as express from 'express';
3 | import * as parser from 'body-parser'
4 |
5 | export class MockServer {
6 | private handler: express.Express = express();
7 | private server: Server | undefined;
8 | private hostname = 'localhost';
9 | private port = 3000;
10 | private routes: Route[];
11 |
12 | /**
13 | * The constructor of the Mock Server
14 | * @param parameters The parameters of the mock server
15 | * @param parameters.hostname Optional. The hostname of the server, default is localhost
16 | * @param parameters.port Optional. The port the server listens to, default is 3000
17 | * @param parameters.routes Required. An array of the routes the server will mock
18 | * @param parameters.routes.method Required. The request method, for example: get
19 | * @param parameters.routes.path Required. The path of the url, for example: /user
20 | * @param parameters.routes.statusCode Optional. The status code of the response
21 | * @param parameters.routes.headers Optional. The response headers
22 | * @param parameters.routes.response Required. The response body, for example: { id: 1 }
23 | */
24 | constructor(parameters: ServerParameters) {
25 | if(parameters.hostname !== undefined) this.hostname = parameters.hostname;
26 | if(parameters.port !== undefined) this.port = parameters.port;
27 | if(typeof parameters.routes === 'string')
28 | this.routes = require(`${process.env.INIT_CWD}/${parameters.routes}`);
29 | else this.routes = parameters.routes;
30 | }
31 |
32 | /**
33 | * Starting the mock server
34 | */
35 | start(): void {
36 | this.handler.use(parser.urlencoded({ extended: true }));
37 | this.handler.use(parser.json());
38 | for(const route of this.routes) {
39 | if(route.method === 'get') this.handler.get(route.path, (req, res) => this.handleResponse(req, res, route));
40 | else if(route.method === 'post') this.handler.post(route.path, (req, res) => this.handleResponse(req, res, route));
41 | else if(route.method === 'put') this.handler.put(route.path, (req, res) => this.handleResponse(req, res, route));
42 | else if(route.method === 'delete') this.handler.delete(route.path, (req, res) => this.handleResponse(req, res, route));
43 | else if(route.method === 'patch') this.handler.patch(route.path, (req, res) => this.handleResponse(req, res, route));
44 | else if(route.method === 'options') this.handler.options(route.path, (req, res) => this.handleResponse(req, res, route));
45 | else if(route.method === 'head') this.handler.head(route.path, (req, res) => this.handleResponse(req, res, route));
46 | }
47 | this.server = createServer(this.handler).listen(this.port, this.hostname, () => {
48 | console.log(`Starting server ${this.hostname}:${this.port}`)
49 | });
50 | }
51 |
52 | /**
53 | * Handling the response
54 | * @param request The request object
55 | * @param response The response object
56 | * @param route The route object
57 | */
58 | private handleResponse(request: express.Request, response: express.Response, route: Route) {
59 | for(const header in route.headers) response.set(header, route.headers[header]);
60 | response.status((route.statusCode !== undefined) ? route.statusCode: 200)
61 | response.send((typeof route.response === 'function') ? route.response(request, response): route.response)
62 | }
63 |
64 | /**
65 | * Stopping the mock server
66 | */
67 | stop(): void {
68 | if(this.server !== undefined) this.server.close();
69 | }
70 |
71 | /**
72 | * Returning the mock server object
73 | */
74 | getServer(): Server | undefined { return this.server; }
75 | }
76 |
77 | /**
78 | * The parameters of the mock server that are passed over in the constructor
79 | * @param hostname Optional. The hostname of the server, default is localhost
80 | * @param port Optional. The port the server listens to, default is 3000
81 | * @param routes Required. An array of the routes the server will mock / A string of the json file path.
82 | */
83 | export type ServerParameters = {
84 | hostname?: string,
85 | port?: number,
86 | routes: Route[] | string
87 | }
88 |
89 | /**
90 | * A type for each route defined and passed over to the mock server.
91 | * @param method Required. The request method, for example: get
92 | * @param path Required. The path of the url, for example: /user
93 | * @param statusCode Optional. The status code of the response
94 | * @param headers Optional. The response headers
95 | * @param response Required. The response body, for example: { id: 1 }
96 | */
97 | export type Route = {
98 | method: RequestMethod,
99 | path: string
100 | statusCode?: number,
101 | headers?: {[key: string]: any},
102 | response: {[key: string]: any} | ResponseFunction;
103 | }
104 |
105 | /**
106 | * Available request methods
107 | */
108 | type RequestMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'options' | 'head';
109 |
110 | /**
111 | * A generic flexible function for function response handling
112 | */
113 | type ResponseFunction = (request: Request, response: Response) => void;
114 |
115 | /**
116 | * The request object
117 | */
118 | export type Request = express.Request;
119 |
120 | /**
121 | * The response object
122 | */
123 | export type Response = express.Response;
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------