configurapi 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/configurapi.d.ts +21 -0
  2. package/dist/configurapi.js +33 -0
  3. package/dist/entities/config.d.ts +20 -0
  4. package/dist/entities/config.js +149 -0
  5. package/dist/entities/errorResponse.d.ts +9 -0
  6. package/dist/entities/errorResponse.js +31 -0
  7. package/dist/entities/event.d.ts +22 -0
  8. package/dist/entities/event.js +154 -0
  9. package/dist/entities/identity.d.ts +17 -0
  10. package/dist/entities/identity.js +68 -0
  11. package/dist/entities/policy.d.ts +13 -0
  12. package/dist/entities/policy.js +34 -0
  13. package/dist/entities/policyHandlerLoader.d.ts +11 -0
  14. package/dist/entities/policyHandlerLoader.js +66 -0
  15. package/dist/entities/request.d.ts +14 -0
  16. package/dist/entities/request.js +16 -0
  17. package/dist/entities/response.d.ts +7 -0
  18. package/dist/entities/response.js +14 -0
  19. package/dist/entities/route.d.ts +15 -0
  20. package/dist/entities/route.js +38 -0
  21. package/dist/entities/service.d.ts +20 -0
  22. package/dist/entities/service.js +118 -0
  23. package/dist/interfaces/iClaim.d.ts +6 -0
  24. package/dist/interfaces/iClaim.js +2 -0
  25. package/dist/interfaces/iConfig.d.ts +5 -0
  26. package/dist/interfaces/iConfig.js +2 -0
  27. package/dist/interfaces/iErrorResponse.d.ts +5 -0
  28. package/dist/interfaces/iErrorResponse.js +2 -0
  29. package/dist/interfaces/iEvent.d.ts +16 -0
  30. package/dist/interfaces/iEvent.js +2 -0
  31. package/dist/interfaces/iIdentity.d.ts +11 -0
  32. package/dist/interfaces/iIdentity.js +2 -0
  33. package/dist/interfaces/iPolicy.d.ts +12 -0
  34. package/dist/interfaces/iPolicy.js +2 -0
  35. package/dist/interfaces/iPolicyHandlerLoader.d.ts +7 -0
  36. package/dist/interfaces/iPolicyHandlerLoader.js +2 -0
  37. package/dist/interfaces/iRequest.d.ts +12 -0
  38. package/dist/interfaces/iRequest.js +2 -0
  39. package/dist/interfaces/iResponse.d.ts +5 -0
  40. package/dist/interfaces/iResponse.js +2 -0
  41. package/dist/interfaces/iRoute.d.ts +13 -0
  42. package/dist/interfaces/iRoute.js +2 -0
  43. package/dist/interfaces/iService.d.ts +6 -0
  44. package/dist/interfaces/iService.js +2 -0
  45. package/dist/interfaces/iServiceListener.d.ts +3 -0
  46. package/dist/interfaces/iServiceListener.js +2 -0
  47. package/dist/interfaces/iYamlConfig.d.ts +7 -0
  48. package/dist/interfaces/iYamlConfig.js +2 -0
  49. package/dist/interfaces/logLevel.d.ts +11 -0
  50. package/dist/interfaces/logLevel.js +26 -0
  51. package/dist/interfaces/result.d.ts +4 -0
  52. package/dist/interfaces/result.js +8 -0
  53. package/package.json +1 -1
@@ -0,0 +1,21 @@
1
+ export * from './entities/config';
2
+ export * from './entities/errorResponse';
3
+ export * from './entities/event';
4
+ export * from './entities/identity';
5
+ export * from './entities/policy';
6
+ export * from './entities/policyHandlerLoader';
7
+ export * from './entities/response';
8
+ export * from './entities/route';
9
+ export * from './entities/service';
10
+ export * from './entities/request';
11
+ export * from './interfaces/iClaim';
12
+ export * from './interfaces/iEvent';
13
+ export * from './interfaces/iIdentity';
14
+ export * from './interfaces/iRequest';
15
+ export * from './interfaces/iResponse';
16
+ export * from './interfaces/iService';
17
+ export * from './interfaces/iServiceListener';
18
+ export * from './interfaces/logLevel';
19
+ export * from './interfaces/result';
20
+ export * from './interfaces/iRoute';
21
+ export * from './interfaces/iPolicy';
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
+ for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p);
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ __exportStar(require("./entities/config"), exports);
14
+ __exportStar(require("./entities/errorResponse"), exports);
15
+ __exportStar(require("./entities/event"), exports);
16
+ __exportStar(require("./entities/identity"), exports);
17
+ __exportStar(require("./entities/policy"), exports);
18
+ __exportStar(require("./entities/policyHandlerLoader"), exports);
19
+ __exportStar(require("./entities/response"), exports);
20
+ __exportStar(require("./entities/route"), exports);
21
+ __exportStar(require("./entities/service"), exports);
22
+ __exportStar(require("./entities/request"), exports);
23
+ __exportStar(require("./interfaces/iClaim"), exports);
24
+ __exportStar(require("./interfaces/iEvent"), exports);
25
+ __exportStar(require("./interfaces/iIdentity"), exports);
26
+ __exportStar(require("./interfaces/iRequest"), exports);
27
+ __exportStar(require("./interfaces/iResponse"), exports);
28
+ __exportStar(require("./interfaces/iService"), exports);
29
+ __exportStar(require("./interfaces/iServiceListener"), exports);
30
+ __exportStar(require("./interfaces/logLevel"), exports);
31
+ __exportStar(require("./interfaces/result"), exports);
32
+ __exportStar(require("./interfaces/iRoute"), exports);
33
+ __exportStar(require("./interfaces/iPolicy"), exports);
@@ -0,0 +1,20 @@
1
+ import { IConfig } from '../interfaces/iConfig';
2
+ import { IPolicy } from '../interfaces/iPolicy';
3
+ import { IRoute } from '../interfaces/iRoute';
4
+ import { IYamlApi, IYamlConfig } from '../interfaces/iYamlConfig';
5
+ export declare class Config implements IConfig {
6
+ modules: string[];
7
+ events: Map<String, IRoute>;
8
+ constructor(modules?: string[], events?: Map<String, IRoute>);
9
+ static getPathParentDir(path: any): string;
10
+ static load(path: string): IConfig;
11
+ static parse(content: string, parentDirectory?: string): IConfig;
12
+ static parseImport(document: object, parentDirectory?: string): string[];
13
+ static parseApi(document: Partial<IYamlConfig>): Map<String, IRoute>;
14
+ static parseRoutes(api: IYamlApi): Map<String, IRoute>;
15
+ static parseRoute(route: IRoute, routeIndex: number): IRoute;
16
+ static parsePolicies(route: IRoute, routeName: string): IPolicy[];
17
+ static parsePolicy(policy: IPolicy, routeName: string, policyIndex: number): IPolicy;
18
+ static parsePolicyName(policy: IPolicy): string;
19
+ static parseParameter(policy: IPolicy, policyName: string): any[];
20
+ }
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Config = void 0;
4
+ const fs_1 = require("fs");
5
+ const js_yaml_1 = require("js-yaml");
6
+ const NestedError = require("nested-error-stacks");
7
+ const path_1 = require("path");
8
+ const logLevel_1 = require("../interfaces/logLevel");
9
+ const policy_1 = require("./policy");
10
+ const route_1 = require("./route");
11
+ class Config {
12
+ constructor(modules = [], events = new Map()) {
13
+ this.modules = modules;
14
+ this.events = events;
15
+ }
16
+ static getPathParentDir(path) {
17
+ if (!path_1.isAbsolute(path)) {
18
+ path = path_1.resolve(process.cwd(), path);
19
+ }
20
+ return path_1.parse(path).dir;
21
+ }
22
+ static load(path) {
23
+ let content = "";
24
+ try {
25
+ content = fs_1.readFileSync(path, 'utf8');
26
+ }
27
+ catch (error) {
28
+ throw new NestedError(`Failed to load '${path}'`, error);
29
+ }
30
+ return this.parse(content, this.getPathParentDir(path));
31
+ }
32
+ static parse(content, parentDirectory) {
33
+ let document = js_yaml_1.load(content);
34
+ if (document instanceof Object) {
35
+ return new Config(this.parseImport(document, parentDirectory), this.parseApi(document));
36
+ }
37
+ else {
38
+ throw new Error("The specified config file is not an invalid yaml.");
39
+ }
40
+ }
41
+ static parseImport(document, parentDirectory) {
42
+ let result = [];
43
+ //Check for an optional "import"
44
+ if ('import' in document) {
45
+ if (typeof document['import'][Symbol.iterator] !== 'function') {
46
+ throw new Error(`Could not load 'import.${document['import']}' in the config document`);
47
+ }
48
+ for (let module of document['import']) {
49
+ if (module.startsWith('.')) {
50
+ module = path_1.resolve(parentDirectory, module);
51
+ }
52
+ result.push(module);
53
+ }
54
+ }
55
+ return result;
56
+ }
57
+ static parseApi(document) {
58
+ if ('api' in document) {
59
+ return this.parseRoutes(document.api);
60
+ }
61
+ else {
62
+ throw new Error('Could not find \'api\' in the config document');
63
+ }
64
+ }
65
+ static parseRoutes(api) {
66
+ if ((api instanceof Object) && 'events' in api) {
67
+ let result = new Map();
68
+ if (typeof api.events[Symbol.iterator] !== 'function') {
69
+ throw new Error(`Events could not be empty in the config document.`);
70
+ }
71
+ let routeIndex = 0;
72
+ for (let r of api.events) {
73
+ let route = this.parseRoute(r, routeIndex);
74
+ if (route.enabled) {
75
+ result.set(route.name, route);
76
+ }
77
+ }
78
+ return result;
79
+ }
80
+ else {
81
+ throw new Error('Could not find \'api.events\' in the config document');
82
+ }
83
+ }
84
+ static parseRoute(route, routeIndex) {
85
+ let result = new route_1.Route();
86
+ if (route instanceof Object && 'name' in route) {
87
+ result.name = route.name;
88
+ result.logLevel = logLevel_1.LogLevel[Object.keys(logLevel_1.LogLevel).find(key => key.toLowerCase() === (route.logLevel || logLevel_1.LogLevel.Trace).toLowerCase())];
89
+ if (route.when) {
90
+ if (process.env.NODE_ENV === undefined) {
91
+ result.enabled = false;
92
+ }
93
+ else {
94
+ result.enabled = process.env.NODE_ENV === route.when;
95
+ }
96
+ }
97
+ result.policies = this.parsePolicies(route, result.name);
98
+ return result;
99
+ }
100
+ else {
101
+ throw new Error(`Could not find 'api.events[${routeIndex}].name' in the config document`);
102
+ }
103
+ }
104
+ static parsePolicies(route, routeName) {
105
+ let result = [];
106
+ if (route instanceof Object && 'policies' in route) {
107
+ let policyIndex = 0;
108
+ if (typeof route.policies[Symbol.iterator] !== 'function') {
109
+ throw new Error(`Policies 'api.events[${routeName}].policies' could not be empty in the config document.`);
110
+ }
111
+ for (let policy of route.policies) {
112
+ result.push(this.parsePolicy(policy, routeName, policyIndex));
113
+ }
114
+ return result;
115
+ }
116
+ else {
117
+ throw new Error(`Could not find 'api.events[${routeName}].policies' in the config document`);
118
+ }
119
+ }
120
+ static parsePolicy(policy, routeName, policyIndex) {
121
+ let policyName = this.parsePolicyName(policy);
122
+ if (!policyName) {
123
+ throw new Error(`Could not find 'api.events[${routeName}].policies[${policyIndex}]' in the config document`);
124
+ }
125
+ return new policy_1.Policy({
126
+ name: policyName,
127
+ parameters: this.parseParameter(policy, policyName),
128
+ logLevel: policy.logLevel || logLevel_1.LogLevel.Trace
129
+ });
130
+ }
131
+ static parsePolicyName(policy) {
132
+ if (typeof policy == 'string') {
133
+ return policy;
134
+ }
135
+ for (var key in policy) {
136
+ if (policy.hasOwnProperty(key)) {
137
+ return key;
138
+ }
139
+ return undefined;
140
+ }
141
+ }
142
+ static parseParameter(policy, policyName) {
143
+ if (policy[policyName] instanceof Array) {
144
+ return policy[policyName];
145
+ }
146
+ return policy.parameters || [];
147
+ }
148
+ }
149
+ exports.Config = Config;
@@ -0,0 +1,9 @@
1
+ import { IErrorResponse } from "../interfaces/iErrorResponse";
2
+ import { Response } from "./response";
3
+ export declare class ErrorResponse extends Response implements IErrorResponse {
4
+ error: Error | ErrorResponse | string;
5
+ message: Error | ErrorResponse | any;
6
+ details: string;
7
+ constructor(message: Error | ErrorResponse | any, statusCode?: number, details?: string);
8
+ static isErrorResponse(obj: any): boolean;
9
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ErrorResponse = void 0;
4
+ const response_1 = require("./response");
5
+ class ErrorResponse extends response_1.Response {
6
+ constructor(message, statusCode = 500, details = '') {
7
+ super('', statusCode, { 'Content-Type': 'application/json' });
8
+ this.error = message;
9
+ this.message = message;
10
+ this.details = details;
11
+ if (message instanceof ErrorResponse) {
12
+ let e = message;
13
+ this.message = e.message;
14
+ this.details = e.details;
15
+ this.statusCode = e.statusCode;
16
+ }
17
+ else if (message instanceof Error) {
18
+ this.message = message.message;
19
+ this.details = message.stack;
20
+ }
21
+ else {
22
+ this.message = message;
23
+ this.details = details;
24
+ }
25
+ this.body = { 'statusCode': this.statusCode, 'message': this.message, 'details': this.details };
26
+ }
27
+ static isErrorResponse(obj) {
28
+ return typeof obj === 'object' && 'statusCode' in obj && 'error' in obj && 'message' in obj && 'details' in obj && 'body' in obj;
29
+ }
30
+ }
31
+ exports.ErrorResponse = ErrorResponse;
@@ -0,0 +1,22 @@
1
+ import { IIdentity } from '../configurapi';
2
+ import { IEvent } from '../interfaces/iEvent';
3
+ import { IRequest } from '../interfaces/iRequest';
4
+ import { IResponse } from '../interfaces/iResponse';
5
+ export declare class Event implements IEvent {
6
+ #private;
7
+ id: string;
8
+ params: Record<string, any>;
9
+ name: string;
10
+ request: Partial<IRequest>;
11
+ response: Partial<IResponse>;
12
+ method: string;
13
+ version: string;
14
+ correlationId: string;
15
+ identity: IIdentity;
16
+ payload: string | Record<string, any> | undefined;
17
+ constructor(request?: Partial<IRequest>);
18
+ objectToString(o: any, s: any): string;
19
+ resolve(obj: any): any;
20
+ resolveStr(str: any): any;
21
+ toString(): string;
22
+ }
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, privateMap, value) {
3
+ if (!privateMap.has(receiver)) {
4
+ throw new TypeError("attempted to set private field on non-instance");
5
+ }
6
+ privateMap.set(receiver, value);
7
+ return value;
8
+ };
9
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, privateMap) {
10
+ if (!privateMap.has(receiver)) {
11
+ throw new TypeError("attempted to get private field on non-instance");
12
+ }
13
+ return privateMap.get(receiver);
14
+ };
15
+ var _versionRegExp;
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.Event = void 0;
18
+ const inflection_1 = require("inflection");
19
+ const uuid_1 = require("uuid");
20
+ const response_1 = require("./response");
21
+ class Event {
22
+ constructor(request) {
23
+ _versionRegExp.set(this, void 0);
24
+ this.id = uuid_1.v4();
25
+ if ('query' in request && 'correlationid' in request.query) {
26
+ this.correlationId = request.query['correlationid'].toString();
27
+ }
28
+ else if ('headers' in request && 'correlation-id' in request.headers) {
29
+ this.correlationId = request.headers['correlation-id'];
30
+ }
31
+ else {
32
+ this.correlationId = this.id;
33
+ }
34
+ __classPrivateFieldSet(this, _versionRegExp, new RegExp("^v\\d+(\\.\\d+)*$"));
35
+ this.params = {};
36
+ this.name = request.name || "";
37
+ this.request = request;
38
+ this.response = new response_1.Response();
39
+ this.identity = undefined;
40
+ this.payload = this.request.payload;
41
+ this.method = request.method;
42
+ let segments = request.path.split("/").filter(Boolean);
43
+ if (segments.length === 0)
44
+ return;
45
+ //Extract version, if any.
46
+ if (__classPrivateFieldGet(this, _versionRegExp).test(segments[0])) {
47
+ this.version = segments[0];
48
+ segments = segments.slice(1);
49
+ }
50
+ //Extract resource-resourceId pair.
51
+ for (let i = 0, end = segments.length; i < end; i += 2) {
52
+ let resource;
53
+ let resourceId = '';
54
+ if (i < end) {
55
+ resource = segments[i];
56
+ }
57
+ if (i + 1 < end) {
58
+ resourceId = segments[i + 1];
59
+ }
60
+ if (resource.length === 0)
61
+ break;
62
+ let singularizedResource = inflection_1.singularize(resource);
63
+ //Change 'get' to 'list'
64
+ if (!resourceId && this.method == 'get') {
65
+ this.method = 'list';
66
+ }
67
+ else {
68
+ resource = singularizedResource;
69
+ }
70
+ this.params[singularizedResource] = resourceId;
71
+ this.name += `_${resource}`;
72
+ }
73
+ for (let key in request.query) {
74
+ this.params[key] = request.query[key];
75
+ }
76
+ this.name = this.method + (this.version ? `_${this.version}` : "") + this.name;
77
+ }
78
+ objectToString(o, s) {
79
+ s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
80
+ s = s.replace(/^\./, ''); // strip a leading dot
81
+ var a = s.split('.');
82
+ for (var i = 0, n = a.length; i < n; ++i) {
83
+ var k = a[i];
84
+ if (k in o) {
85
+ o = o[k];
86
+ }
87
+ else {
88
+ return;
89
+ }
90
+ }
91
+ return o;
92
+ }
93
+ resolve(obj) {
94
+ if (typeof obj === 'string') {
95
+ return this.resolveStr(obj);
96
+ }
97
+ else if (typeof obj === 'object') {
98
+ for (let property in obj) {
99
+ obj[property] = this.resolve(obj[property]);
100
+ }
101
+ return obj;
102
+ }
103
+ else {
104
+ return obj;
105
+ }
106
+ }
107
+ resolveStr(str) {
108
+ let regex = /\$\([^\)]*\)/g;
109
+ let matches = str.match(regex);
110
+ if (!matches) {
111
+ return str;
112
+ }
113
+ for (let match of matches) {
114
+ let key = match.substr(2, match.length - 3);
115
+ let value = undefined;
116
+ if (key.startsWith('$env.')) {
117
+ //handle environment variables
118
+ let variableName = key.substr(5);
119
+ value = process.env[variableName];
120
+ }
121
+ else if (key.startsWith('$event.payload.') && this.payload) {
122
+ //handle environment variables
123
+ let path = key.substr(15);
124
+ value = this.objectToString(this.payload, path);
125
+ }
126
+ else if (key === '$event.payload' && this.payload) {
127
+ value = this.payload;
128
+ }
129
+ else if (this.params[key] !== undefined) {
130
+ value = this.params[key];
131
+ }
132
+ else if (key.indexOf('.') !== -1 || key.indexOf('[') !== -1) {
133
+ //handle resolving object using string path such as obj.prop.subprop.list[0]
134
+ let index = key.indexOf('.');
135
+ let objSection = key.substr(0, index);
136
+ let propSection = key.substr(index + 1);
137
+ value = this.params[objSection];
138
+ if (typeof value === 'object') {
139
+ value = this.objectToString(value, propSection);
140
+ }
141
+ }
142
+ if (value === undefined) {
143
+ value = match;
144
+ }
145
+ str = str.replace(match, value);
146
+ }
147
+ return str;
148
+ }
149
+ toString() {
150
+ return `${this.name}(${Object.values(this.params)})`;
151
+ }
152
+ }
153
+ exports.Event = Event;
154
+ _versionRegExp = new WeakMap();
@@ -0,0 +1,17 @@
1
+ import { IClaim } from '../interfaces/iClaim';
2
+ import { IIdentity } from '../interfaces/iIdentity';
3
+ export declare class Identity implements IIdentity {
4
+ private _claims;
5
+ private _claimsTable;
6
+ id: string;
7
+ issuer: string;
8
+ name: string;
9
+ email: string;
10
+ get claims(): Partial<IClaim>[];
11
+ set claims(value: Partial<IClaim>[]);
12
+ getClaimId(type: string, value: string, scope: string): string;
13
+ constructor(identity?: Partial<IIdentity>);
14
+ hasClaim(type: string, valueOrValues: string | string[], scopeOrScopes?: string | string[]): boolean;
15
+ getClaim(type: string, value: string, scope?: string): Partial<IClaim>;
16
+ getClaims(type: string, value: string, scope?: string): IClaim[];
17
+ }
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Identity = void 0;
4
+ class Identity {
5
+ constructor(identity) {
6
+ this._claims = [];
7
+ this._claimsTable = new Map();
8
+ this.id = identity?.id;
9
+ this.claims = identity?.claims || [];
10
+ this.issuer = identity?.issuer;
11
+ this.name = identity?.name;
12
+ this.email = identity?.email;
13
+ }
14
+ get claims() {
15
+ return this._claims;
16
+ }
17
+ set claims(value) {
18
+ this._claims = value;
19
+ this._claimsTable.clear();
20
+ for (let claim of this._claims) {
21
+ let scopes = Array.isArray(claim.scope) ? claim.scope : [claim.scope];
22
+ for (let scope of scopes) {
23
+ this._claimsTable.set(this.getClaimId(claim.type, claim.value, scope), claim);
24
+ }
25
+ }
26
+ }
27
+ getClaimId(type, value, scope) {
28
+ return `${scope || ''}::${type || ''}::${value || ''}`;
29
+ }
30
+ hasClaim(type, valueOrValues, scopeOrScopes) {
31
+ if (!this.claims)
32
+ return false;
33
+ let values = Array.isArray(valueOrValues) ? [...new Set(valueOrValues)] : [valueOrValues];
34
+ let scopes = Array.isArray(scopeOrScopes) ? [...new Set(scopeOrScopes)] : [scopeOrScopes];
35
+ for (let value of values) {
36
+ for (let scope of scopes) {
37
+ if (this._claimsTable.has(this.getClaimId(type, value, scope))) {
38
+ return true;
39
+ }
40
+ }
41
+ }
42
+ return false;
43
+ }
44
+ getClaim(type, value, scope) {
45
+ if (!this._claimsTable.has(this.getClaimId(type, value, scope)))
46
+ return undefined;
47
+ return this._claimsTable.get(this.getClaimId(type, value, scope));
48
+ }
49
+ getClaims(type, value, scope) {
50
+ if (!this.claims)
51
+ return [];
52
+ let result = [];
53
+ let matchingTypeValueClaims = this.claims.filter((c) => c.type === type && c.value === value);
54
+ for (let claim of matchingTypeValueClaims) {
55
+ if (claim.scope === scope) {
56
+ result.push(claim);
57
+ continue;
58
+ }
59
+ //For arrays
60
+ let scopes = Array.isArray(claim.scope) ? claim.scope : [claim.scope];
61
+ if (scopes.includes(scope)) {
62
+ result.push(claim);
63
+ }
64
+ }
65
+ return result;
66
+ }
67
+ }
68
+ exports.Identity = Identity;
@@ -0,0 +1,13 @@
1
+ /// <reference types="node" />
2
+ import { EventEmitter } from 'events';
3
+ import { IEvent, Result } from '../configurapi';
4
+ import { IPolicy } from '../interfaces/iPolicy';
5
+ import { LogLevel } from '../interfaces/logLevel';
6
+ export declare class Policy extends EventEmitter implements IPolicy {
7
+ name: string;
8
+ parameters: any[];
9
+ logLevel: LogLevel;
10
+ handler: Function;
11
+ constructor(policy?: Partial<IPolicy>);
12
+ process(event: IEvent): Promise<Result>;
13
+ }
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Policy = void 0;
4
+ const events_1 = require("events");
5
+ const configurapi_1 = require("../configurapi");
6
+ const logLevel_1 = require("../interfaces/logLevel");
7
+ class Policy extends events_1.EventEmitter {
8
+ constructor(policy) {
9
+ super();
10
+ this.name = policy?.name || "";
11
+ this.parameters = policy?.parameters || [];
12
+ this.logLevel = policy?.logLevel || logLevel_1.LogLevel.Trace;
13
+ this.handler = policy?.handler || undefined;
14
+ }
15
+ async process(event) {
16
+ let state = configurapi_1.Result.Continue;
17
+ let context = {
18
+ 'continue': () => state = configurapi_1.Result.Continue,
19
+ 'complete': () => state = configurapi_1.Result.Completed,
20
+ 'catch': (error) => { throw error; },
21
+ 'emit': (level, message) => this.emit(level, `${event.id} - ${event.correlationId} - ${message}`)
22
+ };
23
+ let handlerParams = this.parameters instanceof Array ? this.parameters.slice(0) : [];
24
+ handlerParams.unshift(event);
25
+ try {
26
+ await this.handler.apply(context, handlerParams);
27
+ return state;
28
+ }
29
+ catch (error) {
30
+ throw error;
31
+ }
32
+ }
33
+ }
34
+ exports.Policy = Policy;
@@ -0,0 +1,11 @@
1
+ import { FunctionType, IPolicyHandlerLoader } from '../interfaces/iPolicyHandlerLoader';
2
+ export declare class PolicyHandlerLoader implements IPolicyHandlerLoader {
3
+ handlers: Map<String, FunctionType>;
4
+ constructor(handlers?: Map<String, FunctionType>);
5
+ get(handlerName: string): Function;
6
+ load(moduleOrFileName: string): void;
7
+ loadCustomHandlers(directory: string): void;
8
+ private resolve;
9
+ loadHandler(obj: any): void;
10
+ private isHandler;
11
+ }
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PolicyHandlerLoader = void 0;
4
+ const fs_1 = require("fs");
5
+ const NestedError = require("nested-error-stacks");
6
+ const path_1 = require("path");
7
+ class PolicyHandlerLoader {
8
+ constructor(handlers = new Map()) {
9
+ this.handlers = handlers;
10
+ }
11
+ get(handlerName) {
12
+ if (this.handlers.has(handlerName)) {
13
+ return this.handlers.get(handlerName);
14
+ }
15
+ else {
16
+ throw new Error(`Handler '${handlerName}' could not be found.`);
17
+ }
18
+ }
19
+ load(moduleOrFileName) {
20
+ let exports = this.resolve(moduleOrFileName);
21
+ if (!exports) {
22
+ throw new Error(`Cannot find '${moduleOrFileName}'.`);
23
+ }
24
+ this.loadHandler(exports);
25
+ }
26
+ loadCustomHandlers(directory) {
27
+ const absoultePath = path_1.resolve(process.cwd(), directory);
28
+ try {
29
+ let paths = fs_1.readdirSync(absoultePath);
30
+ for (const path of paths) {
31
+ let filePath = `${absoultePath}/${path}`;
32
+ let stat = fs_1.lstatSync(filePath);
33
+ if (stat.isFile() && path.match(/\.[jt]s$/i) !== null) {
34
+ this.load(absoultePath + "/" + path.replace(/\.[jt]s$/i, ''));
35
+ }
36
+ }
37
+ }
38
+ catch (error) {
39
+ throw new NestedError(`Could not load '${absoultePath}'`, error);
40
+ }
41
+ }
42
+ resolve(path) {
43
+ try {
44
+ return require(path);
45
+ }
46
+ catch (e) {
47
+ throw new NestedError(`Failed to load ${path}`, e);
48
+ }
49
+ }
50
+ loadHandler(obj) {
51
+ if (typeof obj === "function") {
52
+ this.handlers.set(obj.name, obj);
53
+ }
54
+ else {
55
+ for (let key in obj) {
56
+ if (this.isHandler(obj, key)) {
57
+ this.handlers.set(key, obj[key]);
58
+ }
59
+ }
60
+ }
61
+ }
62
+ isHandler(obj, key) {
63
+ return (typeof obj[key] === "function") && key.match(/handler$/i) !== null;
64
+ }
65
+ }
66
+ exports.PolicyHandlerLoader = PolicyHandlerLoader;
@@ -0,0 +1,14 @@
1
+ /// <reference types="node" />
2
+ import { ParsedUrlQuery } from "querystring";
3
+ import { IRequest } from "../interfaces/iRequest";
4
+ export declare class Request implements IRequest {
5
+ name: string;
6
+ method: string;
7
+ headers: Record<string, string>;
8
+ params: Record<string, string>;
9
+ payload: string | Record<string, any> | undefined;
10
+ query: ParsedUrlQuery | undefined;
11
+ path: string | undefined;
12
+ pathAndQuery: string;
13
+ constructor(method: any);
14
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Request = void 0;
4
+ class Request {
5
+ constructor(method) {
6
+ this.name = undefined;
7
+ this.method = (method || "get").toLowerCase();
8
+ this.headers = {};
9
+ this.params = {};
10
+ this.payload = "";
11
+ this.query = {};
12
+ this.path = "";
13
+ this.pathAndQuery = "";
14
+ }
15
+ }
16
+ exports.Request = Request;
@@ -0,0 +1,7 @@
1
+ import { IResponse } from '../interfaces/iResponse';
2
+ export declare class Response implements IResponse {
3
+ body: any;
4
+ statusCode: number;
5
+ headers: Record<string, string>;
6
+ constructor(body?: any, statusCode?: number, headers?: Record<string, string>);
7
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Response = void 0;
4
+ class Response {
5
+ constructor(body = "", statusCode = 200, headers = {}) {
6
+ this.body = body;
7
+ this.statusCode = statusCode;
8
+ this.headers = headers;
9
+ this.statusCode = statusCode;
10
+ this.body = body;
11
+ this.headers = headers;
12
+ }
13
+ }
14
+ exports.Response = Response;
@@ -0,0 +1,15 @@
1
+ /// <reference types="node" />
2
+ import { EventEmitter } from 'events';
3
+ import { IEvent } from '../interfaces/iEvent';
4
+ import { IPolicy } from '../interfaces/iPolicy';
5
+ import { IRoute } from '../interfaces/iRoute';
6
+ import { LogLevel } from '../interfaces/logLevel';
7
+ export declare class Route extends EventEmitter implements IRoute {
8
+ name: string;
9
+ when: string;
10
+ enabled: boolean;
11
+ policies: IPolicy[];
12
+ logLevel: LogLevel;
13
+ constructor(route?: Partial<IRoute>);
14
+ process(event: IEvent): Promise<void>;
15
+ }
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Route = void 0;
4
+ const events_1 = require("events");
5
+ const logLevel_1 = require("../interfaces/logLevel");
6
+ const result_1 = require("../interfaces/result");
7
+ const perf_hooks_1 = require("perf_hooks");
8
+ class Route extends events_1.EventEmitter {
9
+ constructor(route) {
10
+ super();
11
+ this.name = route?.name || '';
12
+ this.enabled = route?.enabled || true;
13
+ this.policies = route?.policies || [];
14
+ this.logLevel = route?.logLevel;
15
+ this.when = route?.when;
16
+ }
17
+ async process(event) {
18
+ for (let policy of this.policies) {
19
+ let startTime = perf_hooks_1.performance.now();
20
+ try {
21
+ const result = await policy.process(event);
22
+ if (result === result_1.Result.Completed) {
23
+ break;
24
+ }
25
+ }
26
+ catch (error) {
27
+ throw error;
28
+ }
29
+ finally {
30
+ let endTime = perf_hooks_1.performance.now();
31
+ if (logLevel_1.LogLevel.gte(policy.logLevel, logLevel_1.LogLevel.Trace)) {
32
+ this.emit(logLevel_1.LogLevel.Trace, `${event.id} - ${event.correlationId} - Executed ${policy.name} policy [${endTime - startTime}ms]`);
33
+ }
34
+ }
35
+ }
36
+ }
37
+ }
38
+ exports.Route = Route;
@@ -0,0 +1,20 @@
1
+ /// <reference types="node" />
2
+ import { EventEmitter } from 'events';
3
+ import { IConfig } from '../interfaces/iConfig';
4
+ import { IEvent } from '../interfaces/iEvent';
5
+ import { IPolicyHandlerLoader } from '../interfaces/iPolicyHandlerLoader';
6
+ import { IService } from '../interfaces/iService';
7
+ import { LogLevel } from '../interfaces/logLevel';
8
+ export declare class Service extends EventEmitter implements IService {
9
+ private config;
10
+ private loader;
11
+ isReady: boolean;
12
+ onStartPromise: Promise<boolean>;
13
+ constructor(config: IConfig, loader?: IPolicyHandlerLoader);
14
+ configureLogs(svc: EventEmitter & {
15
+ logLevel: LogLevel;
16
+ }): void;
17
+ process(event: IEvent): Promise<void>;
18
+ _handleEvent(eventName: string, event?: IEvent): Promise<boolean>;
19
+ _handleError(event: IEvent, error: object): Promise<void>;
20
+ }
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Service = void 0;
4
+ const events_1 = require("events");
5
+ const fs_1 = require("fs");
6
+ const oneliner = require("one-liner");
7
+ const perf_hooks_1 = require("perf_hooks");
8
+ const logLevel_1 = require("../interfaces/logLevel");
9
+ const errorResponse_1 = require("./errorResponse");
10
+ const policyHandlerLoader_1 = require("./policyHandlerLoader");
11
+ class Service extends events_1.EventEmitter {
12
+ constructor(config, loader = new policyHandlerLoader_1.PolicyHandlerLoader()) {
13
+ super();
14
+ this.config = config;
15
+ this.loader = loader;
16
+ this.isReady = false;
17
+ for (let module of this.config.modules) {
18
+ this.loader.load(module);
19
+ }
20
+ let customHandlerPath = 'handlers';
21
+ if (fs_1.existsSync(customHandlerPath)) {
22
+ this.loader.loadCustomHandlers(customHandlerPath);
23
+ }
24
+ else {
25
+ this.emit(logLevel_1.LogLevel.Trace, `configurapi - - Warning. Custom handlers directory does not exist.`);
26
+ }
27
+ for (let route of this.config.events.values()) {
28
+ for (let policy of route.policies) {
29
+ policy.handler = loader.get(policy.name);
30
+ policy.logLevel = policy.logLevel || route.logLevel;
31
+ this.configureLogs(policy);
32
+ }
33
+ this.configureLogs(route);
34
+ this.emit(logLevel_1.LogLevel.Trace, `configurapi - - Registerd ${route.name} route.`);
35
+ }
36
+ this.onStartPromise = this._handleEvent('on_start');
37
+ }
38
+ configureLogs(svc) {
39
+ for (const level of [logLevel_1.LogLevel.Trace, logLevel_1.LogLevel.Debug, logLevel_1.LogLevel.Error]) {
40
+ if (logLevel_1.LogLevel.gte(svc.logLevel, level))
41
+ svc.on(level, (msg) => this.emit(level, oneliner(msg)));
42
+ }
43
+ }
44
+ async process(event) {
45
+ if (!this.isReady) {
46
+ await this.onStartPromise;
47
+ this.isReady = true;
48
+ }
49
+ let startTime = perf_hooks_1.performance.now();
50
+ try {
51
+ await this._handleEvent('on_before_request', event);
52
+ if (await this._handleEvent(event.name, event) || await this._handleEvent(event.method, event)) {
53
+ //Great
54
+ }
55
+ else if (await this._handleEvent('catchall', event)) {
56
+ //Great
57
+ }
58
+ else {
59
+ throw new errorResponse_1.ErrorResponse('Not Implemented.', 501, `Route for '${event.name}' event could not be found.'`);
60
+ }
61
+ if (event.response && event.response instanceof errorResponse_1.ErrorResponse) {
62
+ throw event.response;
63
+ }
64
+ await this._handleEvent('on_success', event);
65
+ }
66
+ catch (error) {
67
+ await this._handleError(event, error);
68
+ }
69
+ finally {
70
+ try {
71
+ await this._handleEvent('on_after_request', event);
72
+ }
73
+ catch (error) {
74
+ await this._handleError(event, error);
75
+ }
76
+ let endTime = perf_hooks_1.performance.now();
77
+ let route = this.config.events.get(event.name);
78
+ if (route) {
79
+ if (logLevel_1.LogLevel.gte(route.logLevel, logLevel_1.LogLevel.Trace)) {
80
+ this.emit(logLevel_1.LogLevel.Trace, `${event.id} - ${event.correlationId} - Handled ${event.name} [${endTime - startTime}ms]`);
81
+ }
82
+ }
83
+ }
84
+ }
85
+ async _handleEvent(eventName, event) {
86
+ let result = false;
87
+ if (this.config.events.has(eventName)) {
88
+ await this.config.events.get(eventName).process(event);
89
+ result = true;
90
+ }
91
+ return result;
92
+ }
93
+ async _handleError(event, error) {
94
+ if (error instanceof Error) {
95
+ this.emit(logLevel_1.LogLevel.Error, `${event.id} - ${event.correlationId} - Failed to handle ${event.name}: ${error.message}`);
96
+ event.response = new errorResponse_1.ErrorResponse(error, error['statusCode'] || 500);
97
+ }
98
+ else if (error instanceof errorResponse_1.ErrorResponse || errorResponse_1.ErrorResponse.isErrorResponse(error)) {
99
+ this.emit(logLevel_1.LogLevel.Error, `${event.id} - ${event.correlationId} - Failed to handle ${event.name}: ${error.error}`);
100
+ event.response = error;
101
+ }
102
+ else {
103
+ this.emit(logLevel_1.LogLevel.Error, `${event.id} - ${event.correlationId} - Failed to handle ${event.name}: ${error === undefined ? 'undefined' : error.toString()}`);
104
+ event.response = new errorResponse_1.ErrorResponse("Internal Server Error", 500, error.toString());
105
+ }
106
+ if (this.config.events.has('on_error')) {
107
+ try {
108
+ this.emit(logLevel_1.LogLevel.Error, `${event.id} - ${event.correlationId} - Failed to handle ${event.name}: ${error}`);
109
+ await this._handleEvent('on_error', event);
110
+ }
111
+ catch (reason) {
112
+ this.emit(logLevel_1.LogLevel.Error, `${event.id} - ${event.correlationId} - ${reason}`);
113
+ }
114
+ return;
115
+ }
116
+ }
117
+ }
118
+ exports.Service = Service;
@@ -0,0 +1,6 @@
1
+ export interface IClaim {
2
+ type: string;
3
+ value: string;
4
+ scope: string | string[];
5
+ readonly scopes: string[];
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,5 @@
1
+ import { IRoute } from './iRoute';
2
+ export interface IConfig {
3
+ modules: string[];
4
+ events: Map<String, IRoute>;
5
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,5 @@
1
+ import { IResponse } from "./iResponse";
2
+ export interface IErrorResponse extends IResponse {
3
+ message: Error | IResponse | string;
4
+ details: string;
5
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,16 @@
1
+ import { IIdentity } from "./iIdentity";
2
+ import { IRequest } from "./iRequest";
3
+ import { IResponse } from "./iResponse";
4
+ export interface IEvent {
5
+ id: string;
6
+ correlationId: string;
7
+ params: Record<string, any>;
8
+ name: string;
9
+ request: Partial<IRequest>;
10
+ response: Partial<IResponse>;
11
+ method: string;
12
+ version: string;
13
+ identity: IIdentity;
14
+ payload: Record<string, any> | string | undefined;
15
+ resolve(str: string): string;
16
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,11 @@
1
+ import { IClaim } from './iClaim';
2
+ export interface IIdentity {
3
+ id: string;
4
+ issuer: string;
5
+ name: string;
6
+ email: string;
7
+ claims: Partial<IClaim>[];
8
+ hasClaim(type: string, valueOrValues: string | string[], scopeOrScopes?: string | string[]): boolean;
9
+ getClaim(type: string, value: string, scope?: string): Partial<IClaim>;
10
+ getClaims(type: string, value: string, scope?: string): IClaim[];
11
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,12 @@
1
+ /// <reference types="node" />
2
+ import EventEmitter = require("events");
3
+ import { IEvent } from "./iEvent";
4
+ import { LogLevel } from "./logLevel";
5
+ import { Result } from "./result";
6
+ export interface IPolicy extends EventEmitter {
7
+ name: string;
8
+ parameters: any[];
9
+ logLevel: LogLevel;
10
+ handler: Function;
11
+ process(event: IEvent): Promise<Result>;
12
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ export declare type FunctionType = (...args: any[]) => any | Function;
2
+ export interface IPolicyHandlerLoader {
3
+ handlers: Map<String, FunctionType>;
4
+ loadCustomHandlers(handler: string): void;
5
+ load(moduleOrFileName: string): void;
6
+ get(handlerName: string): Function;
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,12 @@
1
+ /// <reference types="node" />
2
+ import { ParsedUrlQuery } from "querystring";
3
+ export interface IRequest {
4
+ name: string;
5
+ method: string;
6
+ headers: Record<string, string>;
7
+ params: Record<string, string>;
8
+ payload: string | Record<string, any> | undefined;
9
+ query: ParsedUrlQuery | undefined;
10
+ path: string | undefined;
11
+ pathAndQuery: string;
12
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,5 @@
1
+ export interface IResponse {
2
+ body: any;
3
+ statusCode: number;
4
+ headers: Record<string, string>;
5
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,13 @@
1
+ /// <reference types="node" />
2
+ import { EventEmitter } from 'events';
3
+ import { IEvent } from './iEvent';
4
+ import { IPolicy } from './iPolicy';
5
+ import { LogLevel } from './logLevel';
6
+ export interface IRoute extends EventEmitter {
7
+ name: string;
8
+ when: string;
9
+ enabled: boolean;
10
+ policies: IPolicy[];
11
+ logLevel: LogLevel;
12
+ process(event: IEvent): Promise<void>;
13
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,6 @@
1
+ import { IEvent } from "./iEvent";
2
+ import { IServiceListener } from "./iServiceListener";
3
+ export interface IService {
4
+ on(type: string, listener: IServiceListener): void;
5
+ process(event: IEvent): Promise<void>;
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ export interface IServiceListener {
2
+ (data: string): void;
3
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ import { IRoute } from "./iRoute";
2
+ export interface IYamlApi {
3
+ events: Set<IRoute>;
4
+ }
5
+ export interface IYamlConfig {
6
+ api: IYamlApi;
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,11 @@
1
+ export declare enum LogLevel {
2
+ Debug = "debug",
3
+ Trace = "trace",
4
+ Info = "info",
5
+ Warn = "warn",
6
+ Error = "error",
7
+ None = "none"
8
+ }
9
+ export declare namespace LogLevel {
10
+ function gte(l1: LogLevel, l2: LogLevel): boolean;
11
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LogLevel = void 0;
4
+ var LogLevel;
5
+ (function (LogLevel) {
6
+ LogLevel["Debug"] = "debug";
7
+ LogLevel["Trace"] = "trace";
8
+ LogLevel["Info"] = "info";
9
+ LogLevel["Warn"] = "warn";
10
+ LogLevel["Error"] = "error";
11
+ LogLevel["None"] = "none";
12
+ })(LogLevel = exports.LogLevel || (exports.LogLevel = {}));
13
+ (function (LogLevel) {
14
+ const LogLevelRank = {
15
+ [LogLevel.Debug]: 100,
16
+ [LogLevel.Trace]: 75,
17
+ [LogLevel.Info]: 25,
18
+ [LogLevel.Warn]: 50,
19
+ [LogLevel.Error]: 10,
20
+ [LogLevel.None]: 1
21
+ };
22
+ function gte(l1, l2) {
23
+ return (LogLevelRank[l1?.toString()] || 0) >= (LogLevelRank[l2?.toString()] || 0);
24
+ }
25
+ LogLevel.gte = gte;
26
+ })(LogLevel = exports.LogLevel || (exports.LogLevel = {}));
@@ -0,0 +1,4 @@
1
+ export declare enum Result {
2
+ Continue = 1,
3
+ Completed = 2
4
+ }
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Result = void 0;
4
+ var Result;
5
+ (function (Result) {
6
+ Result[Result["Continue"] = 1] = "Continue";
7
+ Result[Result["Completed"] = 2] = "Completed";
8
+ })(Result = exports.Result || (exports.Result = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "configurapi",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "A configurable API framework",
5
5
  "main": "dist/configurapi.js",
6
6
  "typings": "dist/configurapi.d.ts",