Stefan Huber

init

node_modules/
.vscode/
# Digsig Services
Reusable and generic digsig Services
## Repository
- replicate
- findById
- findByIds
- findByType
## Rest
- register
- heartbeat
\ No newline at end of file
export interface DeviceInfo {
id?: string;
hostname?: string;
platform?: string;
arch?: string;
type?: string;
release?: string;
code?: string;
}
export * from './services/rest';
export * from './services/repository';
export * from './services/device';
export * from './api/device-info';
"use strict";
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
__export(require("./services/rest"));
__export(require("./services/repository"));
__export(require("./services/device"));
export declare class Device {
reload(): void;
exit(): void;
}
"use strict";
var Device = (function () {
function Device() {
}
Device.prototype.reload = function () {
if (window && window.location) {
window.location.reload();
}
};
Device.prototype.exit = function () {
if (window && window['require']) {
var electron = window['require']('electron');
if (electron && electron.ipcRenderer) {
electron.ipcRenderer.send('exit');
}
}
};
return Device;
}());
exports.Device = Device;
import { Rest } from './rest';
import { Device } from './device';
import { DeviceInfo } from '../api/device-info';
export declare class Repository {
protected rest: Rest;
protected device: Device;
protected _db: any;
protected _params: any;
readonly db: any;
constructor(rest: Rest, device: Device);
findById(id: string): Promise<any>;
findByIds(ids: Array<string>): Promise<Array<any>>;
findByType(type: string): Promise<Array<any>>;
replicate(deviceInfo: DeviceInfo): Promise<boolean>;
prepare(url: string): Promise<any>;
init(db_name: string): Promise<any>;
parseUrl(url: string): {
url: string;
user: string;
pass: string;
domain: string;
db_name: string;
};
prepareDocs(res: any): Array<any>;
}
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var core_1 = require("@angular/core");
var Repository = (function () {
function Repository(rest, device) {
this.rest = rest;
this.device = device;
}
Object.defineProperty(Repository.prototype, "db", {
get: function () {
return this._db;
},
enumerable: true,
configurable: true
});
Repository.prototype.findById = function (id) {
return this._db.get(id);
};
Repository.prototype.findByIds = function (ids) {
var _this = this;
return new Promise(function (resolve, reject) {
_this._db
.allDocs({
include_docs: true,
keys: ids
}).then(function (res) {
resolve(_this.prepareDocs(res));
}).catch(function (error) {
reject(error);
});
});
};
Repository.prototype.findByType = function (type) {
var _this = this;
var options = {
include_docs: true
};
if (type != "") {
options['key'] = type;
}
return new Promise(function (resolve, reject) {
_this._db
.query('index_type/type', options)
.then(function (res) {
resolve(_this.prepareDocs(res));
}).catch(function (error) {
reject(error);
});
});
};
Repository.prototype.replicate = function (deviceInfo) {
var _this = this;
return new Promise(function (resolve, reject) {
_this.rest.heartbeat(deviceInfo)
.then(function (response) {
if (response && response.restart == 1) {
_this.device.reload();
}
else if (response && response.exit == 1) {
_this.device.exit();
}
else {
return _this.prepare(response.db_url);
}
}).then(function () {
var changes = false;
_this._db.replicate.from(_this._params.url)
.once('change', function (info) { changes = true; })
.once('complete', function () { resolve(changes); })
.once('error', function (error) { reject('replication error'); });
})
.catch(function (error) { reject(error); });
});
};
Repository.prototype.prepare = function (url) {
var _this = this;
return new Promise(function (resolve, reject) {
_this._params = _this.parseUrl(url);
if (!_this._params) {
reject();
}
if (_this._db && _this._db.name == _this._params.db_name) {
resolve();
}
else if (!_this._db) {
_this.init(_this._params.db_name).then(function () {
resolve();
});
}
else {
_this._db.destroy()
.then(function () {
return _this.init(_this._params.db_name);
}).then(function () {
resolve();
});
}
});
};
Repository.prototype.init = function (db_name) {
if (window['PouchDB']) {
this._db = new window['PouchDB'](db_name);
}
return this._db.putIfNotExists("_design/index_type", {
views: {
type: {
map: (function (doc) {
if (doc.type) {
emit(doc.type);
}
}).toString()
}
}
});
};
Repository.prototype.parseUrl = function (url) {
// matches: 0:user,1:password,2:domain,3:db_name
var exp = /^https?:\/\/(\w+?):(\w+?)@([a-zA-Z0-9.\-_:]+?)\/([a-zA-Z0-9\-_]+?)$/;
var match = url.match(exp);
if (match) {
return {
url: match[0],
user: match[1],
pass: match[2],
domain: match[3],
db_name: 'local_' + match[4]
};
}
return null;
};
Repository.prototype.prepareDocs = function (res) {
var docs = [];
if (res.total_rows > 0) {
for (var _i = 0, _a = res.rows; _i < _a.length; _i++) {
var row = _a[_i];
docs.push(row.doc);
}
}
return docs;
};
return Repository;
}());
Repository = __decorate([
core_1.Injectable()
], Repository);
exports.Repository = Repository;
import { Http } from '@angular/http';
import { DeviceInfo } from './../api/device-info';
export declare const ERROR_CODE_UNAUTHORIZED: string;
export declare const ERROR_CODE_NOT_FOUND: string;
export declare const ERROR_CODE_SERVER_ERROR: string;
export declare class Rest {
private http;
static serviceUrl: string;
constructor(http: Http);
prepareDeviceInfo(deviceInfo: DeviceInfo, prefixed?: boolean): string;
register(registerCode: string, deviceInfo: DeviceInfo): Promise<any>;
heartbeat(deviceInfo: DeviceInfo): Promise<any>;
}
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var core_1 = require("@angular/core");
var http_1 = require("@angular/http");
exports.ERROR_CODE_UNAUTHORIZED = "unauthorized";
exports.ERROR_CODE_NOT_FOUND = "not-found";
exports.ERROR_CODE_SERVER_ERROR = "server-error";
var Rest = Rest_1 = (function () {
function Rest(http) {
this.http = http;
}
Rest.prototype.prepareDeviceInfo = function (deviceInfo, prefixed) {
if (prefixed === void 0) { prefixed = true; }
var output = "";
if (deviceInfo.id) {
output += '&device_id=' + deviceInfo.id;
}
if (deviceInfo.hostname) {
output += '&device_hostname=' + deviceInfo.hostname;
}
if (deviceInfo.platform) {
output += '&device_platform=' + deviceInfo.platform;
}
if (deviceInfo.type) {
output += '&device_type=' + deviceInfo.type;
}
if (deviceInfo.release) {
output += '&device_release=' + deviceInfo.release;
}
if (deviceInfo.arch) {
output += '&device_arch=' + deviceInfo.arch;
}
if (deviceInfo.code) {
output += '&register_code=' + deviceInfo.code;
}
// prefixed with & for url
if (!prefixed) {
output = output.substr(1);
}
return output;
};
Rest.prototype.register = function (registerCode, deviceInfo) {
var _this = this;
return new Promise(function (resolve, reject) {
var headers = new http_1.Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
deviceInfo.code = registerCode;
_this.http.post(Rest_1.serviceUrl + "/config/register", _this.prepareDeviceInfo(deviceInfo), { headers: headers }).subscribe(function (response) {
resolve();
}, function (error) {
if (error.status == 401) {
reject(exports.ERROR_CODE_UNAUTHORIZED);
}
else {
reject(exports.ERROR_CODE_SERVER_ERROR);
}
});
});
};
Rest.prototype.heartbeat = function (deviceInfo) {
var _this = this;
return new Promise(function (resolve, reject) {
var headers = new http_1.Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
_this.http.post(Rest_1.serviceUrl + "/config/heartbeat", _this.prepareDeviceInfo(deviceInfo, false), { headers: headers })
.subscribe(function (response) {
resolve(response.json());
}, function (error) {
switch (error.status) {
case 401:
reject(exports.ERROR_CODE_UNAUTHORIZED);
break;
case 404:
reject(exports.ERROR_CODE_NOT_FOUND);
break;
default:
reject(exports.ERROR_CODE_SERVER_ERROR);
break;
}
});
});
};
return Rest;
}());
Rest.serviceUrl = "http://someurl.com";
Rest = Rest_1 = __decorate([
core_1.Injectable()
], Rest);
exports.Rest = Rest;
var Rest_1;
{
"name": "digsig-services",
"version": "1.0.0",
"description": "",
"main": "dist/index.js",
"module": "dist/index.js",
"typings": "dist/index.d.ts",
"scripts": {
"build": "npm run clean && tsc",
"clean": "rm -rf ./dist",
"pretest": "tsc -p ./spec",
"test": "jasmine .tmp/spec/index.js",
"posttest": "rm -rf .tmp"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@angular/common": "^2.4.8",
"@angular/core": "^2.4.8",
"@angular/http": "^2.4.8",
"@angular/platform-browser": "^2.4.8",
"@types/jasmine": "^2.5.43",
"jasmine": "^2.5.3",
"pouchdb": "^6.1.2",
"pouchdb-upsert": "^2.0.2",
"reflect-metadata": "^0.1.9",
"rxjs": "^5.1.1",
"typescript": "^2.1.6",
"zone.js": "^0.7.7"
},
"peerDependencies": {
"@angular/core": "*",
"@angular/http": "*",
"rxjs": "*",
"pouchdb": "*",
"pouchdb-upsert": "*"
}
}
import 'reflect-metadata';
import './rest';
\ No newline at end of file
import {Rest} from '../src/services/rest';
describe('Rest API', () => {
Rest.serviceUrl = "http://digsig.local/config/register";
let restService : Rest = new Rest(null);
it('Prepare Device Info', () => {
let deviceString = restService.prepareDeviceInfo({
id : 'some-id' ,
hostname : 'some-hostname' ,
arch : 'some-arch' ,
platform : 'some-platform' ,
type : 'some-type' ,
release : 'some-release' ,
code : 'some-code'
}, false);
expect(deviceString).toEqual('device_id=some-id&device_hostname=some-hostname&device_platform=some-platform&device_type=some-type&device_release=some-release&device_arch=some-arch&register_code=some-code');
});
});
\ No newline at end of file
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": [ "es2015", "dom" ],
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"outDir": "../.tmp"
}
}
\ No newline at end of file
export interface DeviceInfo {
id?: string;
hostname?: string;
platform?: string;
arch?: string;
type?: string;
release?: string;
code?: string;
}
\ No newline at end of file
export * from './services/rest';
export * from './services/repository';
export * from './services/device';
export * from './api/device-info';
\ No newline at end of file
export class Device {
reload() {
if (window && window.location) {
window.location.reload();
}
}
exit() {
if (window && window['require']) {
let electron = window['require']('electron');
if (electron && electron.ipcRenderer) {
electron.ipcRenderer.send('exit');
}
}
}
}
\ No newline at end of file
import {Injectable} from '@angular/core';
import {Rest} from './rest';
import { Device } from './device';
import {DeviceInfo} from '../api/device-info';
declare var emit:any;
@Injectable()
export class Repository {
protected _db;
protected _params;
get db() {
return this._db;
}
constructor(
protected rest:Rest ,
protected device:Device
) {}
findById(id:string) : Promise<any> {
return this._db.get(id);
}
findByIds(ids:Array<string>) : Promise<Array<any>> {
return new Promise<Array<any>>((resolve, reject) => {
this._db
.allDocs({
include_docs: true ,
keys : ids
}).then((res) => {
resolve(this.prepareDocs(res));
}).catch(error => {
reject(error);
});
});
}
findByType(type:string) : Promise<Array<any>> {
let options = {
include_docs : true
};
if (type != "") {
options['key'] = type;
}
return new Promise<Array<any>>((resolve, reject) => {
this._db
.query('index_type/type', options)
.then((res) => {
resolve(this.prepareDocs(res));
}).catch(error => {
reject(error);
});
});
}
replicate(deviceInfo: DeviceInfo) : Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
this.rest.heartbeat(deviceInfo)
.then(response => {
if (response && response.restart == 1) {
this.device.reload();
} else if (response && response.exit == 1) {
this.device.exit()
} else {
return this.prepare(response.db_url);
}
}).then(() => {
let changes = false;
this._db.replicate.from(this._params.url)
.once('change', (info) => { changes = true; })
.once('complete', () => { resolve(changes); })
.once('error', (error) => { reject('replication error'); });
})
.catch(error => { reject(error); });
});
}
prepare(url:string) : Promise<any> {
return new Promise<any>((resolve,reject) => {
this._params = this.parseUrl(url);
if (!this._params) {
reject();
}
if (this._db && this._db.name == this._params.db_name) {
resolve();
} else if(!this._db) {
this.init(this._params.db_name).then(() => {
resolve();
});
} else {
this._db.destroy()
.then(() => {
return this.init(this._params.db_name);
}).then(() => {
resolve();
});
}
});
}
init(db_name:string) : Promise<any> {
if (window['PouchDB']) {
this._db = new window['PouchDB'](db_name);
}
return this._db.putIfNotExists("_design/index_type", {
views : {
type : {
map : (function(doc) {
if (doc.type) { emit(doc.type); }
}).toString()
}
}
});
}
parseUrl(url:string) {
// matches: 0:user,1:password,2:domain,3:db_name
let exp = /^https?:\/\/(\w+?):(\w+?)@([a-zA-Z0-9.\-_:]+?)\/([a-zA-Z0-9\-_]+?)$/;
let match = url.match(exp);
if (match) {
return {
url : match[0] ,
user : match[1] ,
pass : match[2] ,
domain : match[3] ,
db_name : 'local_' + match[4]
}
}
return null;
}
prepareDocs(res) : Array<any> {
let docs = [];
if (res.total_rows > 0) {
for(let row of res.rows) {
docs.push(row.doc);
}
}
return docs;
}
}
\ No newline at end of file
import {Injectable} from '@angular/core';
import {Http,Response,Headers} from '@angular/http';
import { DeviceInfo } from './../api/device-info';
export const ERROR_CODE_UNAUTHORIZED:string = "unauthorized";
export const ERROR_CODE_NOT_FOUND:string = "not-found";
export const ERROR_CODE_SERVER_ERROR:string = "server-error";
@Injectable()
export class Rest {
public static serviceUrl: string = "http://someurl.com";
constructor(private http:Http) {}
prepareDeviceInfo(deviceInfo:DeviceInfo, prefixed:boolean = true) : string {
let output = "";
if (deviceInfo.id) {
output += '&device_id='+deviceInfo.id;
}
if (deviceInfo.hostname) {
output += '&device_hostname='+deviceInfo.hostname;
}
if (deviceInfo.platform) {
output += '&device_platform='+deviceInfo.platform;
}
if (deviceInfo.type) {
output += '&device_type='+deviceInfo.type;
}
if (deviceInfo.release) {
output += '&device_release='+deviceInfo.release;
}
if (deviceInfo.arch) {
output += '&device_arch='+deviceInfo.arch;
}
if (deviceInfo.code) {
output += '&register_code='+deviceInfo.code;
}
// prefixed with & for url
if (!prefixed) {
output = output.substr(1);
}
return output;
}
register(registerCode: string, deviceInfo:DeviceInfo) : Promise<any> {
return new Promise<any>((resolve, reject) => {
var headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
deviceInfo.code = registerCode;
this.http.post(Rest.serviceUrl+"/config/register",
this.prepareDeviceInfo(deviceInfo),
{ headers: headers }).subscribe((response:Response) => {
resolve();
}, (error:Response) => {
if (error.status == 401) {
reject(ERROR_CODE_UNAUTHORIZED);
} else {
reject(ERROR_CODE_SERVER_ERROR);
}
});
});
}
heartbeat(deviceInfo:DeviceInfo) : Promise<any> {
return new Promise<any>((resolve, reject) => {
var headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
this.http.post(Rest.serviceUrl+"/config/heartbeat",
this.prepareDeviceInfo(deviceInfo, false),
{ headers: headers })
.subscribe((response:Response) => {
resolve(response.json());
},(error:Response) => {
switch (error.status) {
case 401:
reject(ERROR_CODE_UNAUTHORIZED);
break;
case 404:
reject(ERROR_CODE_NOT_FOUND);
break;
default:
reject(ERROR_CODE_SERVER_ERROR);
break;
}
});
});
}
}
\ No newline at end of file
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"declaration": true,
"experimentalDecorators": true,
"lib": ["dom", "es2015"],
"noImplicitAny": false,
"outDir": "./dist/",
"target": "es5"
},
"exclude": [
"node_modules",
"spec"
]
}
\ No newline at end of file