@mobiusz/core
v0.7.2-alpha.6
Published
Möb:usz framework's core module.
Downloads
8
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 DefaultError
abstract 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.
ImmutablePropertyError
InvalidProperyError
InvalidTypeError
OnceError
PrivatePropertyError
UninplementedError
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-awarenextTick
method.
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 === type
orinstance instanceof klass
isArray
isBoolean
isDate
: Checks if the given value is an object (isObject
) and if it exposes thegetTime
method.isDefined
: Checks if the value is norundefined
neithernull
.isFunction
isInstanceOf
isNull
isNumber
isObject
: 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 thethen
andcatch
methods.isRawObject
: Similar totypeof foo === 'object'
isString
isSymbol
isUndefined
usePrimitiveConverter
toArray
toNumber
toBoolean
toInteger
toObject
toString
toSet
useFunctionHelper
isAsync
isPromise
wrapFunction
wrapAsyncFunction
getCallerFunctionName
getCallerObjectName
useGlobalHelper
isClient
isDefault
isCommonJS
useNumberHelper
isNaN
isFinite
,isInfinite
isFloat
isOdd
isEven
isInRange
roundToNearestTen
useObjectHelper
getMethodNames
getDescriptorsKeys
hasPropertyDescriptor
deepClone
flatten
useStringHelper
toCamelCase
toPascalCase
toKebabCase
splitAtFirst
onlyAlpha
onlyAlphaNumeric
removeWhitespaces
isIntegerString
isNumberString
- 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'])); // true
Tests
Tests are handled with Jest.
yarn test