Skip to content

Commit

Permalink
[RELEASE] v1.1.0 Release
Browse files Browse the repository at this point in the history
EXPTEA-7:  Fixes issue of multiple middlewares into boot stages.
EXPTEA-5:  Adding Pour decorator to get all the plugins.
EXPTEA-10: Publish changed to only use js and eliminate the include part
from typescript projects.
EXPTEA-9:  Adding Tooling for publishing project.
  • Loading branch information
chrnx-dev committed Oct 19, 2019
2 parents 502f1c6 + a050c84 commit d0c56c5
Show file tree
Hide file tree
Showing 19 changed files with 174 additions and 74 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,6 @@ build/*
examples/

.data

*.d.ts
*.js.map
27 changes: 27 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# source
**/*.ts
*.ts

# definitions
!**/*.d.ts
!*.d.ts

# configuration
package-lock.json
tslint.json
tsconfig.json
.prettierrc
.nycrc
__test__
benchmark
docs
jest.config.js
node_modules
.github
coverage
.nyc_output
.idea
tasks
gulpfile.js
jest.config.js
jsdocs.json
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
![GitHub issues](https://img.shields.io/github/issues/Zero-OneIT/expresive-tea)
![GitHub](https://img.shields.io/github/license/Zero-OneIT/expresive-tea)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FZero-OneiT%2Fexpresive-tea.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2FZero-OneiT%2Fexpresive-tea?ref=badge_shield)

![Expressive Tea](./banner.png "Expressive Tea")
> A Typescript library to create RESTful Services.
## Description
Expand Down Expand Up @@ -211,3 +213,6 @@ This project is licensed under the Apache-2.0 License - see the [LICENSE](LICENS


[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FZero-OneiT%2Fexpresive-tea.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2FZero-OneiT%2Fexpresive-tea?ref=badge_large)

## Disclaimers
The banner and the logo is a derivate work [Designed by Freepik](http://www.freepik.com)
17 changes: 17 additions & 0 deletions __test__/__mocks__/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export const mockRegister = jest.fn((appSettings, registeredPlugins) => {
registeredPlugins.push({
name: 'Mocked',
priority: this.priority || 999
});
return registeredPlugins;
});
export const mockGetRegisteredStage = jest.fn(() => []);

const Plugin = jest.fn().mockImplementation(() => {
return {
getRegisteredStage: mockGetRegisteredStage,
register: mockRegister
};
});

export default Plugin as any;
File renamed without changes.
2 changes: 1 addition & 1 deletion __test__/unit/classes/boot.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Metadata from '../../../classes/MetaData';
import Settings from '../../../classes/Settings';
import { Plug, RegisterModule } from '../../../decorators/server';
import { BOOT_STAGES } from '../../../libs/constants';
import Module, { registerMock } from '../../test-clases/module';
import Module, { registerMock } from '../../test-classes/module';

const serverMock = {
listen: jest.fn().mockImplementation((port, cb) => {
Expand Down
73 changes: 34 additions & 39 deletions __test__/unit/decorators/server.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { last } from 'lodash';
import Boot from '../../../classes/Boot';
import Metadata from '../../../classes/MetaData';
import ExpressiveTeaPlugin from '../../../classes/Plugin';
import Settings from '../../../classes/Settings';
import { Plug, Pour, RegisterModule, ServerSettings, Setting } from '../../../decorators/server';
import { BOOT_STAGES, BOOT_STAGES_KEY, REGISTERED_MODULE_KEY } from '../../../libs/constants';
import { BOOT_STAGES, BOOT_STAGES_KEY, PLUGINS_KEY, REGISTERED_MODULE_KEY } from '../../../libs/constants';
import Plugin, { mockRegister } from '../../__mocks__/plugin';

describe('ServerSettings Decorator', () => {
test('should modify server settings', () => {
Expand Down Expand Up @@ -63,57 +64,51 @@ describe('Plug Decorator', () => {
});

describe('Pour Decorator', () => {
beforeAll(() => {
beforeEach(() => {
this.spyMetadataSet = jest.spyOn(Metadata, 'set');
});

class TestPlugin extends ExpressiveTeaPlugin {
readonly name = 'Test';
readonly stage = BOOT_STAGES.INITIALIZE_MIDDLEWARES;

async register(server, settings) {
}
}
afterEach(() => {
this.spyMetadataSet.mockRestore();
});

class TestFailPlugin extends ExpressiveTeaPlugin {
readonly name = 'Test';
readonly stage = BOOT_STAGES.INITIALIZE_MIDDLEWARES;
readonly required = true;
test('should attach plug to respective level', () => {
class TestPlugin extends Plugin {
}

@Pour(TestPlugin)
@Pour(new TestPlugin())
class Test {
}

@Pour(TestFailPlugin)
class TestFail extends Boot {
}

this.TestClass = Test;
this.TestFailClass = TestFail;
});

afterAll(() => {
this.spyMetadataSet.mockRestore();
});

test('should attach plug to respective level', () => {
this.testInstance = new this.TestClass();
const args = this.spyMetadataSet.mock.calls[0];
this.testInstance = new Test();
const args: any[] = last(this.spyMetadataSet.mock.calls) || [];

expect(args[0]).toEqual(BOOT_STAGES_KEY);
expect(args[1]['1'][0]).toEqual(
expect(args).toBeDefined();
expect(args[0]).toEqual(PLUGINS_KEY);
expect(args[1][0]).toEqual(
expect.objectContaining({
isPlugin: true,
name: 'Test',
required: false
name: 'Mocked',
priority: 999
})
);
expect(args[2]).toEqual(this.TestClass);
expect(args[2]).toEqual(Test);
});

test('should attach plug to respective level', () => {
this.testInstance = new this.TestFailClass();
expect(this.testInstance.start()).rejects.toEqual(expect.anything());
test.skip('should attach plug to respective level', () => {
mockRegister.mockImplementation(() => {
throw new Error();
return;
});

class TestFailPlugin extends Plugin {
}

@Pour(new TestFailPlugin())
class TestFail extends Boot {
}

this.testInstance = new TestFail();
expect(this.testInstance.start()).toThrow();
});
});

Expand Down
Binary file added banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 7 additions & 10 deletions classes/Boot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,13 @@ abstract class Boot {
}

async function resolveStage(stage: BOOT_STAGES, ctx: Boot, server: Express): Promise<void> {
for (const stage of BOOT_ORDER) {
try {
await bootloaderResolve(stage, server, ctx);
if (stage === BOOT_STAGES.APPLICATION) {
await resolveModules(ctx, server);
}
} catch (e) {
checkIfStageFails(e);
try {
await bootloaderResolve(stage, server, ctx);
if (stage === BOOT_STAGES.APPLICATION) {
await resolveModules(ctx, server);
}
} catch (e) {
checkIfStageFails(e);
}
}

Expand All @@ -101,8 +99,7 @@ async function bootloaderResolve(STAGE: BOOT_STAGES, server: Express, instance:
}

async function selectLoaderType(loader, server: Express) {
return loader.isPlugin ? loader.method(server, Settings.getInstance()) :
loader.method(server);
return loader.isPlugin ? loader.method(server, Settings.getInstance()) : loader.method(server);
}

function checkIfStageFails(e: BootLoaderRequiredExceptions | BootLoaderSoftExceptions | Error) {
Expand Down
34 changes: 21 additions & 13 deletions decorators/server.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { Express } from 'express';
import { orderBy } from 'lodash';
import MetaData from '../classes/MetaData';
import ExpressiveTeaPlugin from '../classes/Plugin';
import Settings from '../classes/Settings';
import { BOOT_STAGES, BOOT_STAGES_KEY, REGISTERED_MODULE_KEY } from '../libs/constants';
import { ExpressiveTeaServerProps } from '../libs/interfaces';
import { Constructor, PluginConstructor } from '../libs/types';
import { BOOT_ORDER, BOOT_STAGES, BOOT_STAGES_KEY, PLUGINS_KEY, REGISTERED_MODULE_KEY } from '../libs/constants';
import { ExpressiveTeaPluginProps, ExpressiveTeaServerProps } from '../libs/interfaces';

/**
* @module Decorators/Server
Expand All @@ -14,6 +13,10 @@ function getStages(target) {
return MetaData.get(BOOT_STAGES_KEY, target) || {};
}

function getRegisteredPlugins(target) {
return MetaData.get(PLUGINS_KEY, target) || [];
}

function getStage(stage, target) {
const stages = getStages(target);
if (!stages[stage]) {
Expand All @@ -29,6 +32,9 @@ function setStage(stage, value, target) {
MetaData.set(BOOT_STAGES_KEY, stages, target);
}

function setPlugins(plugins: ExpressiveTeaPluginProps[], target) {
MetaData.set(PLUGINS_KEY, plugins, target);
}
/**
* Plug Class Decorator
*
Expand All @@ -53,17 +59,19 @@ export function Plug(
};
}

export function Pour(Plugin: Constructor<ExpressiveTeaPlugin>) {
export function Pour(plugin) {
return (target: any): void => {
const plugin = new Plugin();
const selectedStage = getStage(plugin.stage, target);
selectedStage.unshift({
isPlugin: true,
method: plugin.register.bind(plugin),
name: plugin.name,
required: plugin.required
const stages = getStages(target);
const plugins: ExpressiveTeaPluginProps[] = plugin.register(
Settings.getInstance().getOptions(),
getRegisteredPlugins(target)
);

BOOT_ORDER.forEach(STAGE => {
setStage(STAGE, (stages[STAGE] || []).concat(plugin.getRegisteredStage(STAGE)), target);
});
setStage(plugin.stage, selectedStage, target);

setPlugins(orderBy(plugins, ['priority'], ['asc']), target);
};
}

Expand Down
2 changes: 2 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
require('./tasks/clean');
require('./tasks/pre-publish');
1 change: 1 addition & 0 deletions libs/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,4 @@ export const ROUTER_HANDLERS_KEY = 'app:routes:handlers';
export const ROUTER_MIDDLEWARES_KEY = 'app:routes:middlewares';
export const REGISTERED_MODEL_KEY = 'app:models:registered';
export const REGISTERED_MODULE_KEY = 'app:modules:registered';
export const PLUGINS_KEY = 'boot:app-plugins';
5 changes: 5 additions & 0 deletions libs/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ export interface ExpressiveTeaServerProps {
[key: string]: any;
}

export interface ExpressiveTeaPluginProps {
name: string;
priority: number;
}

/**
* @typedef {Object} ExpressiveTeaServerProps
* @property {Object[]} controllers Controllers Assigned to Module
Expand Down
4 changes: 0 additions & 4 deletions libs/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
import ExpressiveTeaPlugin from '../classes/Plugin';

export type Resolvable<R> = R | PromiseLike<R>;
export type Resolver<R> = (thenableOrResult?: Resolvable<R>) => void;
export type Rejector= (error?: any) => void;
export type Constructor<T> = new(...args: any[]) => T;
export type PluginConstructor<T extends ExpressiveTeaPlugin> = new (...args: any[]) => T;
Binary file added logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 11 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
{
"name": "@zerooneit/expressive-tea",
"version": "1.0.0",
"version": "1.1.0",
"description": "A REST API over Express and Typescript",
"main": "classes/Boot.ts",
"main": "classes/Boot.js",
"scripts": {
"doc": "rimraf build && rimraf docs && tsc -p tsconfig.json && jsdoc -c jsdocs.json",
"test": "npm run linter && jest --coverage",
"linter": "tslint -c tslint.json -p tsconfig.json"
"linter": "tslint -c tslint.json -p tsconfig.json",
"clean:build": "gulp clean",
"publish:prepare": "gulp clean build",
"postpublish": "gulp clean",
"prepublishOnly": "npm test && npm run publish:prepare"
},
"author": "Diego Resendez <[email protected]>",
"license": "Apache-2.0",
"devDependencies": {
"@types/bluebird": "^3.5.27",
"@types/express": "^4.17.0",
"@types/jest": "^24.0.16",
"@types/lodash": "^4.14.144",
"gulp": "^4.0.2",
"gulp-clean": "^0.4.0",
"gulp-typescript": "^5.0.1",
"jest": "^24.8.0",
"minami": "^1.2.3",
"reflect-metadata": "^0.1.12",
Expand Down
24 changes: 24 additions & 0 deletions tasks/clean.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const { task, src } = require('gulp');
const clean = require('gulp-clean');

function cleanOutput() {
return src(
[
'**/*.js',
'**/*.d.ts',
'**/*.js.map',
'**/*.d.ts.map',
'!node_modules/**/*',
'!docs/**/*',
'!coverage/**/*',
'!gulpfile.js',
'!tasks/*.js',
'!jest.config.js'
],
{
read: false
}
).pipe(clean());
}

task('clean', cleanOutput);
13 changes: 13 additions & 0 deletions tasks/pre-publish.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const {task, dest} = require('gulp');
const {createProject} = require('gulp-typescript');

const project = createProject('tsconfig.json');

function buildPackage() {
return project
.src()
.pipe(project())
.pipe(dest('./'));
}

task('build', () => buildPackage());
7 changes: 3 additions & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
{
"compilerOptions": {
"outDir": "build/",
"sourceMap": true,
"noImplicitAny": false,
"module": "commonjs",
"target": "es2017",
Expand All @@ -12,13 +10,14 @@
"allowSyntheticDefaultImports": true,
"importHelpers": true,
"baseUrl": ".",
"declaration": false,
"declaration": true,
"lib": [
"es2017",
"dom"
]
},
"exclude": [
"node_modules"
"node_modules",
"__test__"
]
}

0 comments on commit d0c56c5

Please sign in to comment.