@mobiusz/core
TypeScript icon, indicating that this package has built-in type declarations

0.7.2-alpha.6 • Public • Published

@mobiusz/core

lerna made

Donate

paypal

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.

  • 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.

List of helpers
  • useTimeHelper:
    • nextTick: Provides a context-aware nextTick 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 for typeof foo === type or instance instanceof klass
    • isArray
    • isBoolean
    • isDate: Checks if the given value is an object (isObject) and if it exposes the getTime method.
    • isDefined: Checks if the value is nor undefined neither null.
    • 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 the then and catch methods.
    • isRawObject: Similar to typeof 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

Contributors

Author

Benoît Lahoz

License

GPL-3.0+

Package Sidebar

Install

npm i @mobiusz/core

Weekly Downloads

16

Version

0.7.2-alpha.6

License

GPL-3.0+

Unpacked Size

410 kB

Total Files

66

Last publish

Collaborators

  • benoitlahoz