Compare commits

..

38 Commits

Author SHA1 Message Date
c1a03fec0f 1.0.19 2018-05-24 16:55:25 +02:00
8b650c5ea7 fix(UniverseChannel): improve channel handling 2018-05-24 16:55:24 +02:00
4fc6e327ec 1.0.18 2018-05-24 00:14:57 +02:00
7991baf2bf fix(core): improve channel handling 2018-05-24 00:14:57 +02:00
d033780015 1.0.17 2018-05-23 23:50:46 +02:00
eae46e6461 fix(structure): format TypeScript 2018-05-23 23:50:45 +02:00
785acfaba4 1.0.16 2018-05-20 00:41:59 +02:00
5a4dceb75d fix(core): prepare for release 2018-05-20 00:41:59 +02:00
a17834a8f0 1.0.15 2018-05-07 18:50:07 +02:00
01765fa50f feat(message): refactor 2018-05-07 18:50:07 +02:00
547c159dc4 1.0.14 2018-04-29 17:30:03 +02:00
046d7d646d update to latest standards 2018-04-29 17:30:00 +02:00
f6985bd7b2 1.0.13 2018-04-29 17:00:18 +02:00
241e44e19d update 2018-04-29 17:00:13 +02:00
99561166e2 1.0.12 2018-04-29 16:38:28 +02:00
0e95774f30 update ci 2018-04-29 16:38:23 +02:00
011af15866 1.0.11 2018-04-29 14:34:47 +02:00
77a13786d1 update ci config 2018-04-29 14:34:33 +02:00
d0e4c1c44a 1.0.10 2018-04-29 14:17:33 +02:00
1c8d6bf96e update to latest standards 2018-04-29 14:17:26 +02:00
95c5fb7e83 move to typescript predominance 2018-04-13 15:45:48 +02:00
2165a8f677 1.0.9 2018-04-05 17:39:47 +02:00
aa52ceeeca add better readme 2018-04-05 17:39:39 +02:00
78e57394c9 1.0.8 2018-04-05 10:34:57 +02:00
5f9f670546 add access level for npm 2018-04-05 10:34:54 +02:00
4cac5c1b1c 1.0.7 2018-04-05 10:33:09 +02:00
8d6c8494c4 1.0.6 2018-04-04 17:39:54 +02:00
3fb7375a42 update to new pushrocks scope 2018-04-04 17:39:48 +02:00
c64a72ea9d 1.0.5 2018-03-28 00:38:37 +02:00
c8c481fda0 now opening and closing correclty on server and client side 2018-03-28 00:38:32 +02:00
bafa94c6ac update 2018-03-20 08:16:54 +01:00
a28c96356f 1.0.4 2018-03-17 16:52:32 +01:00
bc7069e72c fix rxjs incompatibility 2018-03-17 16:52:27 +01:00
5ba41150be update 2018-03-17 16:36:36 +01:00
317a9f2189 now sends messages correctly 2018-03-15 01:16:16 +01:00
850032bd03 1.0.3 2018-03-15 01:05:18 +01:00
c009cd337d now running 2018-03-15 01:05:13 +01:00
76cb8a36fc update 2018-03-13 06:15:40 +01:00
28 changed files with 3059 additions and 1638 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
.nogit/ .nogit/
node_modules/ node_modules/
dist/
coverage/ coverage/
public/ public/
pages/ pages/

View File

@ -10,15 +10,18 @@ stages:
- security - security
- test - test
- release - release
- trigger - metadata
- pages
# ====================
# security stage
# ====================
mirror: mirror:
stage: security stage: security
script: script:
- npmci git mirror - npmci git mirror
tags: tags:
- docker - docker
- notpriv
snyk: snyk:
stage: security stage: security
@ -28,7 +31,11 @@ snyk:
- npmci command snyk test - npmci command snyk test
tags: tags:
- docker - docker
- notpriv
# ====================
# test stage
# ====================
testLEGACY: testLEGACY:
stage: test stage: test
script: script:
@ -38,6 +45,7 @@ testLEGACY:
coverage: /\d+.?\d+?\%\s*coverage/ coverage: /\d+.?\d+?\%\s*coverage/
tags: tags:
- docker - docker
- notpriv
allow_failure: true allow_failure: true
testLTS: testLTS:
@ -49,6 +57,7 @@ testLTS:
coverage: /\d+.?\d+?\%\s*coverage/ coverage: /\d+.?\d+?\%\s*coverage/
tags: tags:
- docker - docker
- notpriv
testSTABLE: testSTABLE:
stage: test stage: test
@ -59,34 +68,60 @@ testSTABLE:
coverage: /\d+.?\d+?\%\s*coverage/ coverage: /\d+.?\d+?\%\s*coverage/
tags: tags:
- docker - docker
- notpriv
release: release:
stage: release stage: release
script: script:
- npmci npm prepare - npmci node install stable
- npmci npm publish - npmci npm publish
only: only:
- tags - tags
tags: tags:
- docker - docker
- notpriv
# ====================
# metadata stage
# ====================
codequality:
stage: metadata
image: docker:stable
allow_failure: true
services:
- docker:stable-dind
script:
- export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
- docker run
--env SOURCE_CODE="$PWD"
--volume "$PWD":/code
--volume /var/run/docker.sock:/var/run/docker.sock
"registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
artifacts:
paths: [codeclimate.json]
tags:
- docker
- priv
trigger: trigger:
stage: trigger stage: metadata
script: script:
- npmci trigger - npmci trigger
only: only:
- tags - tags
tags: tags:
- docker - docker
- notpriv
pages: pages:
image: hosttoday/ht-docker-node:npmci image: hosttoday/ht-docker-node:npmci
stage: pages stage: metadata
script: script:
- npmci command yarn global add npmpage - npmci command yarn global add npmpage
- npmci command npmpage - npmci command npmpage
tags: tags:
- docker - docker
- notpriv
only: only:
- tags - tags
artifacts: artifacts:

1
dist/index.d.ts vendored
View File

@ -1 +0,0 @@
export * from './smartuniverse.classes.smartuniverse';

7
dist/index.js vendored
View File

@ -1,7 +0,0 @@
"use strict";
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
Object.defineProperty(exports, "__esModule", { value: true });
__export(require("./smartuniverse.classes.smartuniverse"));
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDJEQUFzRCJ9

View File

@ -1,11 +0,0 @@
export interface ISmartUniverseConstructorOptions {
port: number | string;
}
export declare class SmartUniverse {
private options;
private universeVersionStore;
private readonly universeVersion;
private smartexpressServer;
constructor(optionsArg: ISmartUniverseConstructorOptions);
init(): Promise<void>;
}

View File

@ -1,45 +0,0 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const plugins = require("./smartuniverse.plugins");
const smartexpress_1 = require("smartexpress");
const paths = require("./smartuniverse.paths");
class SmartUniverse {
get universeVersion() {
if (this.universeVersionStore) {
return this.universeVersionStore;
}
else {
const packageJson = plugins.smartfile.fs.toObjectSync(paths.packageJson);
this.universeVersionStore = packageJson.version;
return this.universeVersionStore;
}
}
constructor(optionsArg) {
this.options = optionsArg;
}
init() {
return __awaiter(this, void 0, void 0, function* () {
this.smartexpressServer = new plugins.smartexpress.Server({
cors: true,
defaultAnswer: `smartuniverse server ${this.universeVersion}`,
forceSsl: false,
port: this.options.port
});
const addRoute = new smartexpress_1.Route(this.smartexpressServer, 'addMessage');
const addHandler = new smartexpress_1.Handler('PUT', requestBody => {
return 'hi';
});
// await this.smartexpressServer.addRoute()
});
}
}
exports.SmartUniverse = SmartUniverse;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnR1bml2ZXJzZS5jbGFzc2VzLnNtYXJ0dW5pdmVyc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHVuaXZlcnNlLmNsYXNzZXMuc21hcnR1bml2ZXJzZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUEsbURBQW1EO0FBRW5ELCtDQUFzRDtBQUV0RCwrQ0FBK0M7QUFNL0M7SUFHRSxJQUFZLGVBQWU7UUFDekIsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLENBQUMsQ0FBQztZQUM5QixNQUFNLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDO1FBQ25DLENBQUM7UUFBQyxJQUFJLENBQUMsQ0FBQztZQUNOLE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDekUsSUFBSSxDQUFDLG9CQUFvQixHQUFHLFdBQVcsQ0FBQyxPQUFPLENBQUM7WUFDaEQsTUFBTSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQztRQUNuQyxDQUFDO0lBQ0gsQ0FBQztJQUVELFlBQVksVUFBNEM7UUFDdEQsSUFBSSxDQUFDLE9BQU8sR0FBRyxVQUFVLENBQUM7SUFDNUIsQ0FBQztJQUVZLElBQUk7O1lBQ2YsSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUM7Z0JBQ3hELElBQUksRUFBRSxJQUFJO2dCQUNWLGFBQWEsRUFBRSx3QkFBd0IsSUFBSSxDQUFDLGVBQWUsRUFBRTtnQkFDN0QsUUFBUSxFQUFFLEtBQUs7Z0JBQ2YsSUFBSSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSTthQUN4QixDQUFDLENBQUM7WUFFSCxNQUFNLFFBQVEsR0FBRyxJQUFJLG9CQUFLLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLFlBQVksQ0FBQyxDQUFDO1lBQ2xFLE1BQU0sVUFBVSxHQUFHLElBQUksc0JBQU8sQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLEVBQUU7Z0JBQ2xELE1BQU0sQ0FBQyxJQUFJLENBQUM7WUFDZCxDQUFDLENBQUMsQ0FBQztZQUNILDJDQUEyQztRQUM3QyxDQUFDO0tBQUE7Q0FDRjtBQS9CRCxzQ0ErQkMifQ==

View File

@ -1 +0,0 @@
export {};

View File

@ -1,12 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const plugins = require("./smartuniverse.plugins");
const index_1 = require("./index");
process.env.CLI = 'true';
const universeCli = new plugins.smartcli.Smartcli();
universeCli.standardTask().then(argvArg => {
const standardUniverse = new index_1.SmartUniverse({
port: 8765
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnR1bml2ZXJzZS5jbGkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9zbWFydHVuaXZlcnNlLmNsaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLG1EQUFtRDtBQUVuRCxtQ0FBd0M7QUFFeEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEdBQUcsTUFBTSxDQUFDO0FBRXpCLE1BQU0sV0FBVyxHQUFHLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztBQUVwRCxXQUFXLENBQUMsWUFBWSxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFO0lBQ3hDLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxxQkFBYSxDQUFDO1FBQ3pDLElBQUksRUFBRSxJQUFJO0tBQ1gsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMifQ==

View File

@ -1 +0,0 @@
export declare const packageJson: string;

View File

@ -1,5 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const plugins = require("./smartuniverse.plugins");
exports.packageJson = plugins.path.join(__dirname, '../package.json');
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnR1bml2ZXJzZS5wYXRocy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0dW5pdmVyc2UucGF0aHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxtREFBbUQ7QUFFdEMsUUFBQSxXQUFXLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLGlCQUFpQixDQUFDLENBQUMifQ==

View File

@ -1,5 +0,0 @@
import * as path from 'path';
import * as smartcli from 'smartcli';
import * as smartexpress from 'smartexpress';
import * as smartfile from 'smartfile';
export { path, smartcli, smartexpress, smartfile };

View File

@ -1,11 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
exports.path = path;
const smartcli = require("smartcli");
exports.smartcli = smartcli;
const smartexpress = require("smartexpress");
exports.smartexpress = smartexpress;
const smartfile = require("smartfile");
exports.smartfile = smartfile;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnR1bml2ZXJzZS5wbHVnaW5zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvc21hcnR1bml2ZXJzZS5wbHVnaW5zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsNkJBQTZCO0FBS3BCLG9CQUFJO0FBSmIscUNBQXFDO0FBSXRCLDRCQUFRO0FBSHZCLDZDQUE2QztBQUdwQixvQ0FBWTtBQUZyQyx1Q0FBdUM7QUFFQSw4QkFBUyJ9

View File

@ -1,7 +1,9 @@
{ {
"npmci": { "npmci": {
"npmGlobalTools": [ "npmGlobalTools": [
"npmts" "@gitzone/npmts",
] "ts-node"
],
"npmAccessLevel": "public"
} }
} }

2491
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,35 @@
{ {
"name": "smartuniverse", "name": "@pushrocks/smartuniverse",
"version": "1.0.2", "version": "1.0.19",
"private": false,
"description": "messaging service for your micro services", "description": "messaging service for your micro services",
"main": "dist/index.js", "main": "dist/index.js",
"typings": "dist/index.d.ts", "typings": "dist/index.d.ts",
"author": "Lossless GmbH", "author": "Lossless GmbH",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"test": "(npmts)", "test": "(ts-node -O '{\"lib\": [ \"es2015\" ]}' test/test.ts)",
"build": "(npmts)",
"format": "(gitzone format)" "format": "(gitzone format)"
}, },
"devDependencies": { "devDependencies": {
"tapbundle": "^2.0.0" "@types/node": "^9.6.0",
"tapbundle": "^2.0.0",
"ts-node": "^6.0.3",
"typescript": "^2.8.3"
}, },
"dependencies": { "dependencies": {
"lik": "^2.0.5",
"nodehash": "^1.0.4",
"rxjs": "^5.5.8",
"smartcli": "^2.0.12", "smartcli": "^2.0.12",
"smartexpress": "^1.0.19", "smartdelay": "^1.0.4",
"smartfile": "^4.2.28" "smartexpress": "^1.0.21",
"smartfile": "^4.2.28",
"smartq": "^1.1.8",
"smartrequest": "^1.0.8",
"smartrx": "^1.0.5",
"smartsocket": "^1.1.19",
"smarttime": "^2.0.0"
} }
} }

33
readme.md Normal file
View File

@ -0,0 +1,33 @@
# smartuniverse
messaging service for your micro services
## Availabililty
[![npm](https://pushrocks.gitlab.io/assets/repo-button-npm.svg)](https://www.npmjs.com/package/@pushrocks/smartuniverse)
[![git](https://pushrocks.gitlab.io/assets/repo-button-git.svg)](https://GitLab.com/pushrocks/smartuniverse)
[![git](https://pushrocks.gitlab.io/assets/repo-button-mirror.svg)](https://github.com/pushrocks/smartuniverse)
[![docs](https://pushrocks.gitlab.io/assets/repo-button-docs.svg)](https://pushrocks.gitlab.io/smartuniverse/)
## Status for master
[![build status](https://GitLab.com/pushrocks/smartuniverse/badges/master/build.svg)](https://GitLab.com/pushrocks/smartuniverse/commits/master)
[![coverage report](https://GitLab.com/pushrocks/smartuniverse/badges/master/coverage.svg)](https://GitLab.com/pushrocks/smartuniverse/commits/master)
[![npm downloads per month](https://img.shields.io/npm/dm/@pushrocks/smartuniverse.svg)](https://www.npmjs.com/package/@pushrocks/smartuniverse)
[![bitHound Dependencies](https://www.bithound.io/github/pushrocks/smartuniverse/badges/dependencies.svg)](https://www.bithound.io/github/pushrocks/smartuniverse/master/dependencies/npm)
[![bitHound Code](https://www.bithound.io/github/pushrocks/smartuniverse/badges/code.svg)](https://www.bithound.io/github/pushrocks/smartuniverse)
[![Known Vulnerabilities](https://snyk.io/test/npm/@pushrocks/smartuniverse/badge.svg)](https://snyk.io/test/npm/@pushrocks/smartuniverse)
[![TypeScript](https://img.shields.io/badge/TypeScript-2.x-blue.svg)](https://nodejs.org/dist/latest-v6.x/docs/api/)
[![node](https://img.shields.io/badge/node->=%206.x.x-blue.svg)](https://nodejs.org/dist/latest-v6.x/docs/api/)
[![JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)
## Usage
Use TypeScript for best in class instellisense.
For further information read the linked docs at the top of this README.
> licensed | **&copy;** [Lossless GmbH](https://lossless.gmbh)
> | By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy.html)
[![repo-footer](https://pushrocks.gitlab.io/assets/repo-footer.svg)](https://push.rocks)

View File

@ -1,12 +1,49 @@
// tslint:disable-next-line:no-implicit-dependencies
import { expect, tap } from 'tapbundle'; import { expect, tap } from 'tapbundle';
import * as smartuniverse from '../ts/index'; import * as smartuniverse from '../ts/index';
let testSmartUniverse: smartuniverse.SmartUniverse; import { Observable } from 'rxjs';
let testUniverse: smartuniverse.Universe;
let testUniverseClient: smartuniverse.UniverseClient;
let testMessageObservable: Observable<smartuniverse.UniverseMessage>;
tap.test('first test', async () => { tap.test('first test', async () => {
testSmartUniverse = new smartuniverse.SmartUniverse({ testUniverse = new smartuniverse.Universe({
port: 8765 messageExpiryInMilliseconds: 1000
}) });
});
tap.test('add a message to the SmartUniverse', async () => {
await testUniverse.initServer(8765);
});
// testing message handling
tap.test('create smartuniverse client', async () => {
testUniverseClient = new smartuniverse.UniverseClient({
serverAddress: 'http://localhost:8765'
});
expect(testUniverseClient).to.be.instanceof(smartuniverse.UniverseClient);
});
tap.test('should send a message correctly', async () => {
await testUniverseClient.sendMessage('greeting', {
anyBool: true
});
});
tap.test('should get a observable correctly', async () => {
testMessageObservable = testUniverseClient.getMessageObservable();
});
tap.test('should receive a message correctly', async () => {});
tap.test('should disconnect the client correctly', async () => {
testUniverseClient.close();
});
tap.test('should end the server correctly', async tools => {
await testUniverse.stopServer();
}); });
tap.start(); tap.start();

View File

@ -1 +1,3 @@
export * from './smartuniverse.classes.smartuniverse'; export * from './smartuniverse.classes.universe';
export * from './smartuniverse.classes.universeclient';
export * from './smartuniverse.classes.universemessage';

View File

@ -1,42 +0,0 @@
import * as plugins from './smartuniverse.plugins';
import { Handler, Route, Server } from 'smartexpress';
import * as paths from './smartuniverse.paths';
export interface ISmartUniverseConstructorOptions {
port: number | string;
}
export class SmartUniverse {
private options: ISmartUniverseConstructorOptions;
private universeVersionStore: string;
private get universeVersion() {
if (this.universeVersionStore) {
return this.universeVersionStore;
} else {
const packageJson = plugins.smartfile.fs.toObjectSync(paths.packageJson);
this.universeVersionStore = packageJson.version;
return this.universeVersionStore;
}
}
private smartexpressServer: plugins.smartexpress.Server;
constructor(optionsArg: ISmartUniverseConstructorOptions) {
this.options = optionsArg;
}
public async init() {
this.smartexpressServer = new plugins.smartexpress.Server({
cors: true,
defaultAnswer: `smartuniverse server ${this.universeVersion}`,
forceSsl: false,
port: this.options.port
});
const addRoute = new Route(this.smartexpressServer, 'addMessage');
const addHandler = new Handler('PUT', requestBody => {
return 'hi';
});
// await this.smartexpressServer.addRoute()
}
}

View File

@ -0,0 +1,115 @@
import * as plugins from './smartuniverse.plugins';
import { Handler, Route, Server } from 'smartexpress';
import { UniverseChannel } from './smartuniverse.classes.universechannel';
import { UniverseMessage } from './smartuniverse.classes.universemessage';
import { UniverseStore } from './smartuniverse.classes.universestore';
import * as paths from './smartuniverse.paths';
export interface ISmartUniverseConstructorOptions {
messageExpiryInMilliseconds: number;
}
export interface IServerGetMessagesRequestBody {
channel: string;
topic?: string;
youngerThan: number;
}
/**
* the interface for a standard request
*/
export interface IServerPutMessageRequestBody {
channel: string;
passphrase: string;
message: string;
payload: any;
}
/**
* main class that setsup a Universe
*/
export class Universe {
// subinstances
public universeStore: UniverseStore;
// options
private options: ISmartUniverseConstructorOptions;
// Store version handling
private universeVersionStore: string;
private get universeVersion() {
if (this.universeVersionStore) {
return this.universeVersionStore;
} else {
const packageJson = plugins.smartfile.fs.toObjectSync(paths.packageJson);
this.universeVersionStore = packageJson.version;
return this.universeVersionStore;
}
}
private smartexpressServer: plugins.smartexpress.Server;
private smartsocket: plugins.smartsocket.Smartsocket;
constructor(optionsArg: ISmartUniverseConstructorOptions) {
this.options = optionsArg;
this.universeStore = new UniverseStore(this.options.messageExpiryInMilliseconds);
}
/**
* initiates a server
*/
public async initServer(portArg: number | string) {
this.smartexpressServer = new plugins.smartexpress.Server({
cors: true,
defaultAnswer: `smartuniverse server ${this.universeVersion}`,
forceSsl: false,
port: portArg
});
// message handling
// adds messages
const addMessageHandler = new Handler('PUT', request => {
const requestBody: IServerPutMessageRequestBody = request.body;
const message = new UniverseMessage(requestBody.message, requestBody.channel, requestBody.passphrase, requestBody.payload);
this.universeStore.addMessage(message);
console.log(requestBody);
return true;
});
// gets messages
const readMessageHandler = new Handler('GET', request => {
const done = plugins.smartq.defer<UniverseMessage[]>();
const requestBody = request.body;
const messageObservable = this.universeStore.readMessagesYoungerThan(requestBody.since);
messageObservable.toArray().subscribe(universeMessageArrayArg => {
done.resolve(universeMessageArrayArg);
});
return done.promise;
});
// create new Route for messages
const messageRoute = new Route(this.smartexpressServer, 'message');
messageRoute.addHandler(addMessageHandler);
messageRoute.addHandler(readMessageHandler);
const leaderElectionRoute = new Route(this.smartexpressServer, 'leadelection');
// TODO: implement Handlers for leader election
// add websocket upgrade
this.smartsocket = new plugins.smartsocket.Smartsocket({
port: 12345 // fix this within smartsocket
});
this.smartsocket.setExternalServer('express', this.smartexpressServer as any); // should work with express as well
this.smartsocket.start();
await this.smartexpressServer.start();
}
public async stopServer() {
await this.smartsocket.stop();
await this.smartexpressServer.stop();
}
}

View File

@ -0,0 +1,85 @@
import * as plugins from './smartuniverse.plugins';
import { Objectmap } from 'lik';
/**
* enables messages to stay within a certain scope.
*/
export class UniverseChannel {
// ======
// STATIC
// ======
/**
* stores the channels that are available within the universe
*/
public static channelStore = new Objectmap<UniverseChannel>();
/**
* allows messages to be processed in a blacklist mode for further analysis
*/
public static blackListChannel = new UniverseChannel('blacklist', 'nada');
/**
* creates new channels
* @param channelArg the name of the topic
* @param passphraseArg the secret thats used for a certain topic.
*/
public static createChannel (channelNameArg: string, passphraseArg: string) {
const newChannel = new UniverseChannel(channelNameArg, passphraseArg);
return newChannel;
};
/**
* returns boolean wether certain channel exists
*/
public static async doesChannelExists (channelNameArg: string) {
const channel = this.channelStore.find(channelArg => {
return channelArg.name === channelNameArg;
});
if(channel) {
return true;
} else {
return false;
}
}
public static authorizeForChannel (channelNameArg: string, passphraseArg: string) {
const foundChannel = this.channelStore.find(universeChannel => {
const result = universeChannel.authenticate(channelNameArg, passphraseArg);
return result;
});
if(foundChannel) {
return foundChannel;
} else {
return this.blackListChannel;
}
};
// ========
// INSTANCE
// ========
/**
* the name of the channel
*/
public name: string;
/**
* the passphrase for the channel
*/
public passphrase: string;
constructor(channelNameArg: string, passphraseArg: string) {
this.name = channelNameArg;
this.passphrase = passphraseArg;
UniverseChannel.channelStore.add(this);
}
/**
* authenticates a client on the server side
*/
public authenticate(channelNameArg: string, passphraseArg: string): boolean {
return (this.name === channelNameArg && this.passphrase === passphraseArg);
}
}

View File

@ -0,0 +1,60 @@
import * as plugins from './smartuniverse.plugins';
import { Observable } from 'rxjs';
import { Smartsocket, SmartsocketClient } from 'smartsocket';
import * as url from 'url';
import {
IServerGetMessagesRequestBody,
IServerPutMessageRequestBody
} from './smartuniverse.classes.universe';
import { UniverseMessage } from './smartuniverse.classes.universemessage';
export interface IClientOptions {
serverAddress: string;
}
/**
* this class is for client side only!!!
* allows connecting to a universe server
*/
export class UniverseClient {
public options;
private socketClient: plugins.smartsocket.SmartsocketClient;
private observableIntake: plugins.smartrx.ObservableIntake<UniverseMessage>;
constructor(optionsArg: IClientOptions) {
this.options = optionsArg;
}
public async sendMessage(messageArg, payloadArg) {
const requestBody = {
message: messageArg,
payload: payloadArg
};
// TODO: User websocket connection if available
await plugins.smartrequest.post(this.options.serverAddress, {
requestBody
});
}
public getMessageObservable() {
if (!this.socketClient && !this.observableIntake) {
const parsedURL = url.parse(this.options.serverAddress);
this.socketClient = new SmartsocketClient({
alias: process.env.SOCKET_ALIAS || 'someclient',
password: 'UniverseClient',
port: parseInt(parsedURL.port, 10),
role: 'UniverseClient',
url: parsedURL.hostname
});
this.observableIntake = new plugins.smartrx.ObservableIntake();
this.socketClient.connect();
}
return this.observableIntake.observable;
}
public close() {
this.socketClient.disconnect();
}
}

View File

@ -0,0 +1,86 @@
import * as plugins from './smartuniverse.plugins';
import { Timer, TimeStamp } from 'smarttime';
import { UniverseChannel } from './smartuniverse.classes.universechannel';
import { UniverseStore } from './smartuniverse.classes.universestore';
import { Universe } from './smartuniverse.classes.universe';
/**
* represents a message within a universe
*/
export class UniverseMessage {
/**
* public and unique id
* numeric ascending
* adheres to time in milliseconds
* avoids duplications though
*/
public id: number;
/**
* the universe store the message is attached to
*/
public universeStore: UniverseStore;
/**
* enables unprotected grouping of messages for efficiency purposes.
*/
public universeChannel: UniverseChannel;
/**
* time of creation
*/
public timestamp: TimeStamp;
/**
* the actual message
*/
public message: string;
/**
* any attached payloads. Can be of binary format.
*/
public attachedPayload: any;
public destructionTimer: Timer; // a timer to take care of message destruction
/**
* the constructor to create a universe message
* @param messageArg
* @param attachedPayloadArg
*/
constructor(messageArg: string, channelNameArg: string, passphraseArg: string, attachedPayloadArg: any) {
this.timestamp = new TimeStamp();
this.message = messageArg;
this.universeChannel = UniverseChannel.authorizeForChannel(channelNameArg, passphraseArg);
this.attachedPayload = attachedPayloadArg;
this.fallBackDestruction();
}
public setUniverseStore(universeStoreArg: UniverseStore) {
this.universeStore = universeStoreArg;
}
public setDestructionTimer(selfdestructAfterArg: number) {
if (selfdestructAfterArg) {
this.destructionTimer = new Timer(selfdestructAfterArg);
this.destructionTimer.start();
// set up self destruction by removing this from the parent messageStore
this.destructionTimer.completed.then(async () => {
this.universeStore.messageStore.remove(this);
});
} else {
this.fallBackDestruction();
}
}
/**
* prevents memory leaks if channels have no default
*/
private fallBackDestruction() {
plugins.smartdelay.delayFor(1000).then(() => {
if (!this.destructionTimer) {
this.setDestructionTimer(6000);
}
});
}
}

View File

@ -0,0 +1,43 @@
import * as plugins from './smartuniverse.plugins';
import { UniverseMessage } from './smartuniverse.classes.universemessage';
import { Objectmap } from 'lik';
import { Observable } from 'rxjs';
import { rxjs } from 'smartrx';
/**
* universe store handles the creation, storage and retrieval of messages.
*/
export class UniverseStore {
public standardMessageExpiry: number;
public destructionTime: number = 60000;
public messageStore = new Objectmap<UniverseMessage>();
private lastId: number = 0; // stores the last id
constructor(standardMessageExpiryArg: number) {
this.standardMessageExpiry = standardMessageExpiryArg;
}
/**
* add a message to the UniverseStore
* @param messageArg
* @param attachedPayloadArg
*/
public addMessage(messageArg: UniverseMessage) {
this.messageStore.add(messageArg);
}
/**
* Read a message from the UniverseStore
*/
public readMessagesYoungerThan(unixTimeArg?: number): Observable<UniverseMessage> {
const messageObservable = rxjs.Observable.from(this.messageStore.getArray()).filter(
messageArg => {
return messageArg.timestamp.isYoungerThanMilliSeconds(this.destructionTime);
}
);
return messageObservable;
}
}

View File

@ -1,13 +1,14 @@
import * as plugins from './smartuniverse.plugins'; import * as plugins from './smartuniverse.plugins';
import { SmartUniverse } from './index'; import { Universe } from './index';
process.env.CLI = 'true'; process.env.CLI = 'true';
const universeCli = new plugins.smartcli.Smartcli(); const universeCli = new plugins.smartcli.Smartcli();
universeCli.standardTask().then(argvArg => { universeCli.standardTask().then(async argvArg => {
const standardUniverse = new SmartUniverse({ const standardUniverse = new Universe({
port: 8765 messageExpiryInMilliseconds: 60000
}); });
await standardUniverse.initServer(8765);
}); });

View File

@ -1,6 +1,27 @@
import * as lik from 'lik';
import * as nodehash from 'nodehash';
import * as path from 'path'; import * as path from 'path';
import * as smartcli from 'smartcli'; import * as smartcli from 'smartcli';
import * as smartdelay from 'smartdelay';
import * as smartexpress from 'smartexpress'; import * as smartexpress from 'smartexpress';
import * as smartfile from 'smartfile'; import * as smartfile from 'smartfile';
import * as smartq from 'smartq';
import * as smartrequest from 'smartrequest';
import * as smartrx from 'smartrx';
import * as smartsocket from 'smartsocket';
import * as smarttime from 'smarttime';
export { path, smartcli, smartexpress, smartfile }; export {
lik,
nodehash,
path,
smartcli,
smartdelay,
smartexpress,
smartfile,
smartq,
smartrx,
smartrequest,
smartsocket,
smarttime
};

View File

@ -2,5 +2,11 @@
"extends": [ "extends": [
"tslint:latest", "tslint:latest",
"tslint-config-prettier" "tslint-config-prettier"
],
"rules": {
"semicolon": [
true,
"always"
] ]
}
} }

1470
yarn.lock

File diff suppressed because it is too large Load Diff