Skip to content

wentout/mnemonica

Repository files navigation

mnemonica

Abstract technique that aids information retention: Instance Inheritance System

... allows us to make inherited descriptions of mappings of transformations from predecessor structured data types to the successors, as if it was math f(x)=>y ... and we will use this keyword as a persistent data structure where we will apply that transformations

concept


shortcuts

  • ?. : state : mad science
  • ?. : type : asynchronous monad descriptor => this
  • ?. : prod ready : we wonder about
  • ?. : example : git clone && npm run example

Coverage Status NPM GitHub package.json version GitHub last commit NPM


Table of Contents


Overview

Mnemonica helps create ordered sequences of data transformations using prototype chain inheritance. It combines Object Instances with Inheritance through the Prototype Chain, enabling you to create new instances inherited from existing ones.

Think of it as a mathematical function f(x) => y where this is your persistent data structure and transformations are applied sequentially.

"O Great Mnemosyne! Please! Save us from Oblivion..."

— from the source, where memory persists

Key Features:

  • Factory of Constructors with Prototype Chain Inheritance
  • Instance-level inheritance (not just class-level)
  • Async constructor support with chainable awaits
  • Type-safe data flow definition
  • Comprehensive hook system for lifecycle events

Related Reading:


Installation

npm install mnemonica

Requirements: Node.js >=18 <24


Quick Start

CommonJS

const { define } = require('mnemonica');

// Define a type
const UserType = define('UserType', function (data) {
  Object.assign(this, data);
});

// Create an instance
const user = new UserType({ name: 'John', email: 'john@example.com' });

// Define a subtype
const AdminType = UserType.define('AdminType', function () {
  this.role = 'admin';
});

// Create nested instance (inherits from user)
const admin = new user.AdminType();
console.log(admin.name); // 'John' (inherited)
console.log(admin.role); // 'admin' (own property)

ESM

import { define, lookup } from 'mnemonica/module';

Core Concepts

Factory of Constructors

Define types using constructors, factory functions, or classes:

// Using a constructor function
const SomeType = define('SomeType', function (opts) {
  Object.assign(this, opts);
});

// Using a factory function
const AnotherType = define(() => {
  const AnotherTypeConstructor = function (opts) {
    Object.assign(this, opts);
  };
  AnotherTypeConstructor.prototype.description = 'SomeType Constructor';
  return AnotherTypeConstructor;
});

// Using a class
const ClassType = define(() => {
  class MyClass {
    constructor(opts) {
      Object.assign(this, opts);
    }
  }
  return MyClass;
});

Nested Type Definition

// Define nested types
SomeType.define('SubType', function (opts) {
  this.other = opts.other;
}, {
  description: 'SomeSubType Constructor'
});

// Or using assignment
SomeType.SubType = function (opts) {
  this.other = opts.other;
};
SomeType.SubType.prototype = {
  description: 'SomeSubType Constructor'
};

Instance Creation and Inheritance

const someInstance = new SomeType({
  some: 'arguments',
  data: 'necessary'
});

const subInstance = new someInstance.SubType({
  other: 'data needed'
});

// All properties are inherited
console.log(subInstance.some);   // 'arguments' (inherited)
console.log(subInstance.other);  // 'data needed' (own)

The .extract() Method

Extract all inherited properties into a flat object:

const extracted = subInstance.extract();
// Result: { data, description, other, some }

// Or use the standalone utility
const { utils: { extract } } = require('mnemonica');
const extracted2 = extract(subInstance);

TypeScript Support

The define function has full TypeScript support with comprehensive type definitions:

import { define, apply, call, bind } from 'mnemonica';

interface UserData {
  email: string;
  password: string;
}

const UserType = define('UserType', function (this: UserData, data: UserData) {
  Object.assign(this, data);
});

// Nested constructors work with apply/call/bind for type inference
const user = new UserType({ email: 'test@test.com', password: 'secret' });

For complex nested types, use apply, call, or bind for better type inference:

const SomeSubType = SomeType.define('SomeSubType', function (...args: string[]) {
  // ...
});

const someInstance = new SomeType();
const subInstance = call(someInstance, SomeSubType, 'arg1', 'arg2');

Exported Type Definitions

The following types are available for advanced TypeScript usage:

import {
  // Core constructor types
  IDEF,                          // Base constructor function type: { new(): T } | { (this: T, ...args): void }
  ConstructorFunction,           // Constructor with prototype
  Constructor,                   // Generic constructor type
  
  // Instance types
  MnemonicaInstance,             // Instance methods interface (extract, pick, parent, fork, etc.)
  Props,                         // Internal instance properties (__type__, __args__, __parent__, etc.)
  SiblingAccessor,               // Sibling type accessor type
  
  // Type definition types
  TypeClass,                     // Base type constructor returned by define()
  IDefinitorInstance,            // Definitor instance with define/lookup methods and subtypes
  DecoratedClass,                // Type for @decorate decorated classes
  TypeDef,                       // Type definition object structure
  
  // Configuration types
  constructorOptions,            // Type config options (strictChain, blockErrors, etc.)
  hooksTypes,                    // 'preCreation' | 'postCreation' | 'creationError'
  hook,                          // Hook callback type
  hooksOpts,                     // Hook options passed to callbacks
  CollectionDef,                 // Types collection definition
  
  // Utility function types
  ApplyFunction,                 // apply(entity, Ctor, args) => S
  CallFunction,                  // call(entity, Ctor, ...args) => S
  BindFunction,                  // bind(entity, Ctor) => (...args) => S
  
  // createTypesCollection types
  CreateTypesCollectionFunction, // (config?: constructorOptions) => TypesCollection
  TypesCollection,               // Interface returned by createTypesCollection
  
  // Configuration helper types
  HideInstanceMethodsOptions,    // constructorOptions & { exposeInstanceMethods: true }
  IsHidingMethods<Config>,       // Conditional type for exposeInstanceMethods: false detection
  
  // Utility types
  Proto<P, T>,                   // Merges parent P and child T types
  SN,                            // String-Name map for nested constructors
  SubtypesMap,                   // Map<string, TypeClass>
  TypeAbsorber,                  // Main define() function interface with overloads
} from 'mnemonica';

Generic Type Patterns

Define types with proper generic constraints for full type safety:

// Using IDEF with interface definitions
interface UserData {
  email: string;
  password: string;
}

// Type-safe constructor with 'this' context
const UserType = define('UserType', function (this: UserData, data: UserData) {
  Object.assign(this, data);
});

// Type-safe nested types with merged interfaces
interface AdminData {
  role: string;
}

const AdminType = UserType.define('AdminType', function (this: UserData & AdminData, role: string) {
  this.role = role;
  this.email; // string - inherited from UserData
});

Async Constructor Type Patterns

// Async type with proper return type
const AsyncType = define('AsyncType', async function (this: UserData, data: string) {
  await someAsyncOperation();
  return Object.assign(this, { data });
});

// With explicit awaitReturn option (no return required)
const AsyncTypeNoReturn = define('AsyncType', async function () {
  // No return needed
}, { awaitReturn: false });

API Reference

Core Functions

define(typeName, constructHandler, config?)

Defines a new type constructor. Returns a TypeClass.

const MyType = define('MyType', function (data) {
  Object.assign(this, data);
}, {
  strictChain: true,
  blockErrors: true
});

Parameters:

  • typeName (string): Name of the type (optional if using factory function)
  • constructHandler (Function): Constructor function
  • config (object, optional): Configuration options

lookup(typeNestedPath)

Looks up a type by its nested path.

const { lookup } = require('mnemonica');
const SomeType = lookup('SomeType');
const SomeNestedType = lookup('SomeType.SomeNestedType');

lookupTyped(typeNestedPath)

Type-safe lookup function for use with tactica-generated type definitions. Requires TypeRegistry augmentation from tactica.

import { lookupTyped } from 'mnemonica';

// Type-safe lookup - returns properly typed constructor
const UserType = lookupTyped('UserType');
const user = new UserType({ name: 'John' }); // Full type safety!

// Works with nested types too
const SubType = lookupTyped('Parent.SubType');

To enable type safety, generate types with tactica:

npx tactica

Then include the generated types in your project. See Usage with @mnemonica/tactica for details.

apply(entity, Constructor, args?)

Applies a constructor to an entity with an array of arguments.

const { apply } = require('mnemonica');
const subInstance = apply(parentInstance, SubType, ['arg1', 'arg2']);

call(entity, Constructor, ...args)

Calls a constructor on an entity with spread arguments.

const { call } = require('mnemonica');
const subInstance = call(parentInstance, SubType, 'arg1', 'arg2');

bind(entity, Constructor)

Binds a constructor to an entity, returning a function.

const { bind } = require('mnemonica');
const createSub = bind(parentInstance, SubType);
const subInstance = createSub('arg1', 'arg2');

decorate(target?, config?)

TypeScript decorator for class-based definitions.

Usage Patterns:

import { decorate } from 'mnemonica';

// 1. Basic decoration
@decorate()
class MyClass {
  field: number = 123;
}

// 2. With configuration
@decorate({ strictChain: false, blockErrors: true })
class ConfiguredClass {
  field: number = 123;
}

// 3. Nested decoration (define as subtype)
@decorate()
class ParentClass {
  parentField: string = 'parent';
}

@decorate(ParentClass)
class ChildClass {
  childField: string = 'child';
}

// Create parent instance, then child from it
const parent = new ParentClass();
const child = new parent.ChildClass();

// 4. Parent with configuration
@decorate(ParentClass, { strictChain: false })
class ConfiguredChildClass {
  field: number = 123;
}

// 5. Using decorated class as decorator (advanced)
// After a class is decorated with @decorate(), it can be used
// as a decorator for nested types
@decorate()
class BaseDecorator {
  baseField: number = 100;
}

// Use BaseDecorator as a decorator
// @ts-ignore - TypeScript limitation with callable class types
@BaseDecorator()
class ExtendedClass {
  extField: number = 200;
}

Note: When using decorated classes as decorators (pattern 5), TypeScript may require @ts-ignore due to type checking limitations with callable class types.

registerHook(Constructor, hookType, callback)

Registers a hook for a specific constructor.

const { registerHook } = require('mnemonica');

registerHook(MyType, 'preCreation', (hookData) => {
  console.log('Creating:', hookData.TypeName);
});

Type Reference

For advanced TypeScript usage, the following types are exported from mnemonica:

Type Description Usage
IDEF<T> Base constructor function type define('Name', fn: IDEF<MyType>)
MnemonicaInstance Instance methods interface instance.extract(), instance.pick()
TypeClass Base type constructor const MyType: TypeClass = define(...)
DecoratedClass<T> Decorated class type @decorate() class MyClass {}
IDefinitorInstance<N, S> Constructor with subtypes Returned by define() with .define() method
ConstructorFunction<T> Constructor with prototype Generic constructor function signature
constructorOptions Configuration options { strictChain: true, blockErrors: true }
hooksTypes Hook type literals 'preCreation' | 'postCreation' | 'creationError'
hook Hook callback type (opts: hooksOpts) => void
hooksOpts Hook options object Passed to hook callbacks
TypeDef Type definition structure instance.__type__ structure
CollectionDef Types collection instance.__collection__ structure
ApplyFunction apply() function type apply<E, T, S>(entity, Ctor, args) => S
CallFunction call() function type call<E, T, S>(entity, Ctor, ...args) => S
BindFunction bind() function type bind<E, T, S>(entity, Ctor) => (...args) => S

These types enable complete type safety when defining and using mnemonica types in TypeScript projects.


Type Management

defaultTypes

The default types collection. All types defined with the top-level define() are stored here.

const { defaultTypes } = require('mnemonica');
const MyType = defaultTypes.MyType;

createTypesCollection(config?)

Creates a new isolated types collection.

const { createTypesCollection } = require('mnemonica');
const myCollection = createTypesCollection();
const MyType = myCollection.define('MyType', function () {});

TypesCollection Interface:

createTypesCollection() returns a TypesCollection object with the following interface:

interface TypesCollection {
  // Define a new type in this collection
  define: TypeAbsorber;
  
  // Look up a type by its nested path (e.g., 'TypeName.SubType')
  lookup: (path: string) => TypeClass | undefined;
  
  // Register a hook for all types in this collection
  registerHook(hookType: hooksTypes, callback: hook): void;
  
  // Invoke hooks manually (advanced usage)
  invokeHook(hookType: hooksTypes, opts: hooksOpts): void;
  
  // Register a flow checker that runs before hooks
  registerFlowChecker(callback: () => unknown): void;
  
  // Map of all types defined in this collection
  subtypes: Map<string, TypeClass>;
  
  // Registered hooks for this collection
  hooks: Record<string, hook[]>;
}

Example with full configuration:

const { createTypesCollection } = require('mnemonica');

// Create isolated collection with custom config
const myCollection = createTypesCollection({
  strictChain: false,
  blockErrors: false,
  exposeInstanceMethods: false  // Hide instance methods for cleaner API
});

// Define types in isolation
const MyType = myCollection.define('MyType', function (data) {
  Object.assign(this, data);
});

// Collection-level hooks
myCollection.registerHook('preCreation', (opts) => {
  console.log('Creating in myCollection:', opts.TypeName);
});

// Look up types within the collection
const FoundType = myCollection.lookup('MyType');

getProps(instance) / setProps(instance, values)

Get or set internal properties of an instance.

const { getProps, setProps } = require('mnemonica');

const props = getProps(instance);
console.log(props.__type__, props.__args__);

// Set properties
setProps(instance, { __timestamp__: Date.now() });

Instance Methods

All mnemonica instances have the following methods:

Note: You can disable instance methods by setting exposeInstanceMethods: false in the type configuration. When disabled, these methods are still accessible via getProps(instance).__self__ or the standalone utils export.

.extract()

Extracts all inherited properties into a single flat object.

const extracted = instance.extract();

.pick(...keys) / .pick([keys])

Picks specific properties from the instance and its inheritance chain.

const picked = instance.pick('email', 'password');
// or
const picked = instance.pick(['email', 'password']);

.parent(constructorName?)

Gets the parent instance. If constructorName is provided, walks up the chain.

const immediateParent = instance.parent();
const specificParent = instance.parent('UserType');

.clone

Property that returns a cloned instance (same parent, same args).

const cloned = instance.clone;
// Note: For async constructors, use: await instance.clone

.fork(...args)

Creates a forked instance from the same parent with optional new arguments.

const forked = instance.fork();           // same args
const forkedWithNewArgs = instance.fork('new', 'args');
// Note: For async constructors, use: await instance.fork(...)

.fork.call(thisArg, ...args) / .fork.apply(thisArg, args)

Forks with a different this context (useful for Directed Acyclic Graphs).

const dagInstance = instanceA.fork.call(instanceB, 'args');

.exception(error, ...args)

Creates an exception instance from the current instance.

const error = someInstance.exception(new Error('Something went wrong'));
throw error;

.sibling(typeName) / .sibling.TypeName

Access sibling types from the same collection.

const siblingType = instance.sibling('OtherType');
const sibling = instance.sibling.OtherType;

Instance Properties (via getProps)

All instances have non-enumerable internal properties:

Property Type Description
.__args__ unknown[] Arguments used for instance creation
.__type__ TypeDef Type definition object
.__parent__ object Parent instance reference
.__subtypes__ Map<string, object> Map of available subtypes
.__collection__ CollectionDef Types collection where type was defined
.__stack__ string Stack trace (if submitStack: true in config)
.__creator__ TypeDef Instance creator reference
.__timestamp__ number Creation timestamp (ms since epoch)
.__self__ object Self reference to the instance (useful when exposeInstanceMethods: false)

Utilities

Access via utils export:

const { utils } = require('mnemonica');

utils.extract(instance)

Standalone extract function.

utils.pick(instance, ...keys)

Standalone pick function.

utils.parent(instance, constructorName?)

Standalone parent function.

utils.parse(instance)

Parses an instance structure, returning:

  • name: constructor name
  • props: extracted properties
  • self: the instance itself
  • proto: prototype object
  • joint: prototype properties
  • parent: parent prototype
const { utils: { parse } } = require('mnemonica');
const parsed = parse(instance);

utils.merge(A, B, ...args)

Merges two instances using fork semantics.

const merged = utils.merge(instanceA, instanceB, 'args');
// Note: For async constructors, use: await utils.merge(...)

utils.toJSON(instance)

Serializes an instance to JSON.

const json = utils.toJSON(instance);

utils.collectConstructors(instance, flat?)

Collects all constructors in the instance's prototype chain.

const constructors = utils.collectConstructors(instance, true);

Hooks

Hook Types

  • 'preCreation' - Called before instance creation
  • 'postCreation' - Called after instance creation
  • 'creationError' - Called when instance creation throws an error

type.registerHook(hookType, callback)

Register a hook on a specific type.

MyType.registerHook('preCreation', (hookData) => {
  console.log('Creating:', hookData.TypeName);
});

collection.registerHook(hookType, callback)

Register a hook on a types collection.

defaultTypes.registerHook('postCreation', (hookData) => {
  console.log('Created:', hookData.inheritedInstance.constructor.name);
});

collection.registerFlowChecker(callback)

Register a flow checker that runs before hooks.

defaultTypes.registerFlowChecker((opts) => {
  console.log('Flow check:', opts.TypeName);
});

Hook Data Structure

interface HookData {
  TypeName: string;              // Constructor name
  type: TypeDef;                 // The type being constructed
  args: unknown[];               // Arguments passed to constructor
  existentInstance: object;      // Parent instance
  inheritedInstance: object;     // New instance (postCreation only)
  throwModificationError(error: Error): void;  // Throw error from hook
}
MyType.registerHook('postCreation', (hookData) => {
  // Throw custom error from hook
  hookData.throwModificationError(new Error('Custom hook error'));
});

Note: In preCreation hooks, existentInstance refers to the parent; in postCreation hooks, it refers to the instance used for inheritance.


Error Handling

Error Types

All mnemonica errors extend BASE_MNEMONICA_ERROR:

const { errors } = require('mnemonica');

// Available error types:
errors.BASE_MNEMONICA_ERROR
errors.WRONG_TYPE_DEFINITION
errors.WRONG_INSTANCE_INVOCATION
errors.WRONG_MODIFICATION_PATTERN
errors.ALREADY_DECLARED
errors.TYPENAME_MUST_BE_A_STRING
errors.HANDLER_MUST_BE_A_FUNCTION
errors.WRONG_ARGUMENTS_USED
errors.WRONG_HOOK_TYPE
errors.MISSING_HOOK_CALLBACK
errors.MISSING_CALLBACK_ARGUMENT
errors.FLOW_CHECKER_REDEFINITION
errors.OPTIONS_ERROR
errors.WRONG_STACK_CLEANER

Exception Instances

When creating exceptions using instance.exception():

const error = instance.exception(new Error('Original error'));

// Properties:
error.originalError    // The original error
error.exceptionReason  // { methodName, ... }
error.BaseStack        // Base stack trace
error.parse()          // Parse the exception structure
error.extract()        // Extract properties from the exception

Stack Cleaning

const { defineStackCleaner } = require('mnemonica');

// Add regex patterns to clean stack traces
defineStackCleaner(/node_modules\/some-package/);

Symbols & Constants

const {
  SymbolParentType,              // Parent type symbol
  SymbolConstructorName,         // Constructor name symbol
  SymbolDefaultTypesCollection,  // Default collection symbol
  SymbolConfig,                  // Config symbol
  MNEMONICA,                     // Library name
  MNEMOSYNE                      // Collection identifier
} = require('mnemonica');

Configuration Options

Pass options as the third argument to define():

define('SomeType', function () {}, {
  strictChain: true,        // Only allow sub-instances from current type
  blockErrors: true,        // Disallow construction if error in prototype chain
  submitStack: false,       // Collect stack trace as __stack__ property
  awaitReturn: true,        // Ensure await new Constructor() returns value
  ModificationConstructor: fn,  // Custom modification constructor
  asClass: false,           // Force class mode (auto-detected by default)
  exposeInstanceMethods: true   // Expose instance methods (default: true for backward compatibility)
});

Configuration Option Details

Option Type Default Description
strictChain boolean true If true, only direct subtypes can be instantiated. If false, allows using subtypes from parent chains.
blockErrors boolean true If true, prevents construction when errors exist in the prototype chain.
submitStack boolean false If true, collects stack trace and stores as __stack__ property on instances.
awaitReturn boolean true For async constructors, ensures await new Constructor() returns the instance.
asClass boolean auto Force class mode detection. Usually auto-detected from constructor syntax.
exposeInstanceMethods boolean true Expose instance methods on the instance. Set to false to hide from TypeScript types. See details below.
ModificationConstructor Function - Custom constructor function for internal instance modification.

exposeInstanceMethods Option

Controls whether instance methods (extract(), pick(), parent(), clone, fork(), exception(), sibling()) are exposed on the instance type.

Value Behavior
true (default) All instance methods are available directly on instances
false Methods are hidden from TypeScript types but still accessible via prototype chain

Use Case: Set to false when you want a cleaner public API and don't want internal mnemonica methods cluttering autocomplete/IntelliSense.

import { define, getProps, utils } from 'mnemonica';

// With exposeInstanceMethods: false
const CleanType = define('CleanType', function (data) {
  Object.assign(this, data);
}, { exposeInstanceMethods: false });

const instance = new CleanType({ value: 42 });

// Methods not available directly on instance (TypeScript error)
// instance.extract();  // Error!

// But still accessible via getProps
const props = getProps(instance);
props.__self__.extract();  // Works!

// Or using utils
utils.extract(instance);  // Works!

Override Default Config for Collection

import { defaultTypes, SymbolConfig } from 'mnemonica';

defaultTypes[SymbolConfig].blockErrors = false;

Usage with TypeØmatica

TypeØmatica is a companion library that provides strict runtime type checking using JavaScript Proxies. It enforces types at runtime exactly as TypeScript expects at compile time.

import { BaseClass } from 'typeomatica';
import { decorate } from 'mnemonica';

@decorate()
class User extends BaseClass {
  name: string = 'default';
  age: number = 0;
}

const user = new User();
user.name = 'John';     // ✓ Works - string to string
user.age = 25;          // ✓ Works - number to number

// @ts-ignore
user.age = '25';        // ✗ TypeError: Type Mismatch at runtime!

For complete documentation including integration patterns, error handling, and advanced usage, see TypeØmatica.md.


AI Agent Usage Guide

This section helps AI agents understand and work with mnemonica programmatically.

1. Type Introspection

Use utils.parse(instance) to understand instance structure:

const { utils: { parse } } = require('mnemonica');

const parsed = parse(instance);
// Returns: { name, props, self, proto, joint, parent, constructor }

2. Safe Property Access

Always use getProps() instead of direct property access:

const { getProps } = require('mnemonica');

const props = getProps(instance);
// props.__type__, props.__args__, props.__parent__, props.__subtypes__, etc.

3. Type Discovery

const { defaultTypes } = require('mnemonica');

// List all types in default collection
const typeNames = [...defaultTypes.subtypes.keys()];

// List subtypes of a specific type
const myType = defaultTypes.MyType;
const subTypeNames = [...myType.subtypes.keys()];

// Check if a type exists
const hasType = defaultTypes.lookup('MyType') !== undefined;

4. Instance Traversal

const { getProps } = require('mnemonica');

// Walk up the inheritance chain
function traverseChain(instance) {
  const chain = [];
  let current = instance;
  
  while (current) {
    const props = getProps(current);
    if (!props) break;
    
    chain.push({
      typeName: props.__type__.TypeName,
      timestamp: props.__timestamp__,
      args: props.__args__
    });
    
    current = props.__parent__;
  }
  
  return chain;
}

5. Safe Construction Patterns

const { lookup } = require('mnemonica');

// Always check if type exists before construction
const MyType = lookup('MyType');
if (MyType) {
  const instance = new MyType(data);
}

// For nested construction with proper error handling
try {
  const subInstance = new instance.SubType(data);
} catch (error) {
  // Handle WRONG_MODIFICATION_PATTERN if SubType not defined
  console.error('Subtype not available:', error.message);
}

6. Analyzing Type Structure

const { getProps } = require('mnemonica');

function analyzeType(typeConstructor) {
  return {
    name: typeConstructor.TypeName,
    isSubType: typeConstructor.isSubType,
    subTypesCount: typeConstructor.subtypes?.size || 0,
    hasHooks: Object.keys(typeConstructor.hooks || {}).length > 0,
    config: typeConstructor.config
  };
}

7. Working with Collections

const { createTypesCollection, defaultTypes } = require('mnemonica');

// Create isolated collection for testing
const testCollection = createTypesCollection({
  strictChain: false,
  blockErrors: false
});

// Define types in isolation
const TestType = testCollection.define('TestType', function () {});

// Register collection-level hooks
testCollection.registerHook('preCreation', (data) => {
  console.log('Creating in test collection:', data.TypeName);
});

Examples

Asynchronous Constructors

const AsyncType = define('AsyncType', async function (data) {
  await someAsyncOperation();
  return Object.assign(this, { data });
});

// Usage
const asyncInstance = await new AsyncType('tada');

// Nested async types
const NestedAsync = AsyncType.define('NestedAsync', async function (data) {
  return Object.assign(this, { nestedData: data });
});

const nested = await new asyncInstance.NestedAsync('nested');

Async Chain with Single Await

async (req, res) => {
  const result = await new UserTypeConstructor({
      email: req.body.email,
      password: req.body.password
    })
    .UserEntityValidate('valid sign')
    .WithoutPassword()
    .AsyncPushToStorage()
    .AsyncGetStorageResponse()
    .SyncValidateStorageData()
    .AsyncReplyToRequest(res);
};

Using call with Existing Objects

// Combine with process, window, document, etc.
const usingProcessAsProto = Singletoned.call(process, {
  some: 'arguments'
});

// With React
import ReactDOM from "react-dom";
const ReactDOOMed = define("ReactDOOMed", function() {});
const usingReactAsProto = ReactDOOMed.call(ReactDOM);

Directed Acyclic Graphs (DAG)

// Fork from different parent
const dagInstance = instanceA.fork.call(instanceB, 'args');

// Or use merge utility
const { utils: { merge } } = require('mnemonica');
const merged = merge(instanceA, instanceB, 'args');

Epilogue

So, now you can craft as many types as you wish, combine them, re-define them and spend much more time playing with them:

  • test : instances & arguments
  • track : moments of creation
  • check : if the order of creation is OK
  • validate : everything, 4 example use sort of TS in runtime
  • and even .parse them using mnemonica.utils.parse

Good Luck!


License

MIT

Copyright (c) 2019 https://github.com/wentout

About

abstract technique that aids information retention : instance inheritance system

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors