@mobiusz/core
v0.7.2-alpha.6
Published
Möb:usz framework's core module.
Downloads
7
Maintainers
Readme
@mobiusz/core
Donate
Description
@mobiusz/core is the very root module that defines the domain for the whole Möb:üsz ecosystem to work with.
@mobiusz/core provides basic types, entities, abstract classes and helpers to be used or extended elsewhere (e.g. in other framework's namespaces: @mobiusz, @vuoz, @pipeline and @mmmap). As other mobiusz modules, @mobiusz/core tends to be agnostic, that is: it can be used in any dependent module as a helper or a frame, even besides the mobiusz framework itself.
The main purpose of these is to propose a common language to make community development and discussion easier.
Targets: node, browser, electron.
Warning
This module is still a work in progress, and API or implementations can change drastically from one version ot another. Use at your own risks!
Install
With yarn (recommended)
yarn add @mobiusz/core
With npm
npm install @mobiusz/core
Usage
Domain
@mobiusz/core provides types, entities and handlers models to be extended and implemented by user's modules.
Some types are only a redefinition of native types.
export type UniqueIdString = string;
export type NameString = string;
export type PropertyName = NameString;
// ...It also exports a basic UseCaseModel entity to be implemented by concrete handlers.
The goal is to strongly encourage separation of concerns and code reuse.
export interface UseCaseModel<T = unknown, S = unknown> {
execute(...args: T[]): S;
dispose?(): void;
}@mobiusz/core proposes a similar common interface for validation and sanitization.
export interface Validator<T = unknown, S = unknown> {
execute(...args: T[]): S;
}
export interface Sanitizer<T = unknown, S = unknown> {
execute(...args: T[]): S;
}As we can see, these interfaces are only a proposal for a basic vocabulary to be used, extended and refactored through the whole Möb:üsz framework.
Example
// We implement a handler for a specific use case.
export class MyHandler implements UseCaseModel<string, Record<string, any>> {
private _anotherInstanceOfSomething: Something | null = null;
constructor () {
this._anotherInstanceOfSomething = new Something();
}
public execute(value: string): Record<string, any> {
const endValue = this._anotherInstanceOfSomething.transform(value)
return { foo: endValue };
}
public dispose(): void {
this._anotherInstanceOfSomething.dispose();
this._anotherInstanceOfSomething = null;
}
}
// Then we 'inject' our handler(s) in a higher level object.
export class MyGreatClass {
constructor (
private _myHandler: MyHandler = new MyHandler(),
private _myOtherHandler: MyOtherHandler = new MyOtherHandler()
) {
// ...
}
public doSomething(value: string): Record<string, any> {
return this._myHandler.execute(value),
}
public doSomethinElse(value: any): void {
this._myOtherHandler_.execute(value),
}
public dispose(): void {
this._myHandler.dispose();
this._myOtherHandler.dipose();
}
}
The end user only has access to MyGreatClass that acts as a façade for exposed functionalities.
const myObject = new MyGreatClass();
const result = myObject.doSomething('bar');
console.log(result); // { foo: 'bar' }Decorators
Following decorators are exposed by @mobiusz/core:
StaticImplements
Allows to implement use cases / ports with static methods.
Usage
// Decorator.
export function StaticImplements<T>() {
return <U extends T>(constructor: U) => {
constructor;
};
}
// Example from @mobiusz/security, that uses the jsonwebtoken package.
@StaticImplements<WebTokenDecodePort>()
export class JwtDecode {
public static async execute(token: Token): Promise<Record<string, any> | null | Error> {
return new Promise((resolve, reject) => {
try {
const decoded = jwt.decode(token);
resolve(decoded);
} catch (err) {
resolve(err);
}
});
}
}
// Where WebTokenDecodePort model is:
export interface WebTokenDecodePort {
execute(token: Token): Promise<Record<string, any>>;
}
// Then, to decode a token.
const decoded = JwtDecode.execute(token)
Errors
@mobiusz/core exposes a DefaultErrorModel entity to be implemented by concrete handlers.
export interface ErrorModel {
name?: NameString;
message?: ErrorMessage;
statusCode?: ErrorStatusCode;
messages?: ErrorMessage[];
stack?: Error['stack'];
}Additionaly, a DefaultErrorabstract class can be extended to create custom errors.
export abstract class DefaultError extends Error implements ErrorModel {
public statusCode: ErrorStatusCode;
public messages: ErrorMessage[] = [];
constructor(message?: ErrorMessage, code?: ErrorStatusCode) {
super(message);
this.name = this.constructor.name;
this.message = message || this.name;
this.messages.push(this.message);
if (code) {
this.statusCode = code;
} else {
if (isClient()) {
// In the browser.
this.statusCode = 400;
} else {
// In node.
this.statusCode = 500;
}
}
}
}Example
export class ImmutablePropertyError extends DefaultError {
constructor(property: MessageString, object?: any) {
if (object) {
super(`Property ${property} on ${object} is immutable.`);
} else {
super(`Property ${property} is immutable.`);
}
}
}@mobiusz/core provides the following standard errors.
ImmutablePropertyErrorInvalidProperyErrorInvalidTypeErrorOnceErrorPrivatePropertyErrorUninplementedError
Implementations
Serialization
Serializer
Serializes an object (array or object) to a string in given encoding.
In the browser it uses window.btoa, in node Buffer.from
const serializer = new Serializer();
const result = serializer.toString('foo', 'utf8', 'base64');Helpers
For its helpers modules, @mobiusz/core uses the Vue 3 composables syntax.
They are used widely through the mobiusz framework.
useTimeHelper:nextTick: Provides a context-awarenextTickmethod.
usePropertyHelper:isInternal(mobiusz specific): Checks if a given property is internal (surrounded by double underscores, e.g.__property__).
useJwtHelper:parseToken: Context-aware parsing of a JSON Web Token.
useArrayHelper:isStringArray: Checks if the provided array is filled with strings.isNumberArray: Checks if the provided array is filled with numbers.sortStringArray: Sorts an array of strings in ascending or descending order.sortNumberArray: Sorts an array of numbers in ascending or descending order.arrayIntersection: Gets the intersection of two arrays (values present in both).arrayDifference: Gets the difference between two arrays (values present in first array and not in second one)arraySymmetric: Gets the symmetric difference between two arrays (values present in first and second array that are not present in the other one).parseOptionsArray: Parses an array that has alternate key / value pairs.
useTypeCheck: If nothing is mentioned, the method is only a syntactic sugar fortypeof foo === typeorinstance instanceof klassisArrayisBooleanisDate: Checks if the given value is an object (isObject) and if it exposes thegetTimemethod.isDefined: Checks if the value is norundefinedneithernull.isFunctionisInstanceOfisNullisNumberisObject: Checks if the value is defined, is an 'object' and NOT an Array.isPromise: Checks if the value is an object (ìsObject) and if it exposes thethenandcatchmethods.isRawObject: Similar totypeof foo === 'object'isStringisSymbolisUndefined
usePrimitiveConvertertoArraytoNumbertoBooleantoIntegertoObjecttoStringtoSet
useFunctionHelperisAsyncisPromisewrapFunctionwrapAsyncFunctiongetCallerFunctionNamegetCallerObjectName
useGlobalHelperisClientisDefaultisCommonJS
useNumberHelperisNaNisFinite,isInfiniteisFloatisOddisEvenisInRangeroundToNearestTen
useObjectHelpergetMethodNamesgetDescriptorsKeyshasPropertyDescriptordeepCloneflatten
useStringHelpertoCamelCasetoPascalCasetoKebabCasesplitAtFirstonlyAlphaonlyAlphaNumericremoveWhitespacesisIntegerStringisNumberString- and all the methods availables in validator.js package.
Example
import { useTypeCheck } from '@mobiusz/core';
const { isString, isObject, isRawObject } = useTypeCheck();
console.log(isString('foo')); // true
console.log(isString(64)); // false
console.log(isObject({ foo: 'bar' })); // true
console.log(isObject(['foo', 'bar'])); // false
console.log(isRawObject({ foo: 'bar' })); // true
console.log(isRawObject(['foo', 'bar'])); // trueTests
Tests are handled with Jest.
yarn test
