mnemonica 0.9.99777 → 0.9.99779
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.
- package/README.md +704 -545
- package/build/api/errors/exceptionConstructor.d.ts +1 -1
- package/build/api/errors/exceptionConstructor.js +1 -1
- package/build/api/errors/index.js +1 -1
- package/build/api/errors/throwModificationError.d.ts +20 -1
- package/build/api/errors/throwModificationError.js +1 -1
- package/build/api/index.d.ts +2 -2
- package/build/api/types/InstanceCreator.d.ts +26 -5
- package/build/api/types/InstanceCreator.js +1 -1
- package/build/api/types/InstanceModificator.js +1 -1
- package/build/api/types/Mnemosyne.d.ts +23 -7
- package/build/api/types/Mnemosyne.js +1 -1
- package/build/api/types/Props.d.ts +4 -40
- package/build/api/types/Props.js +1 -1
- package/build/api/types/TypeProxy.d.ts +22 -2
- package/build/api/types/TypeProxy.js +21 -11
- package/build/api/types/compileNewModificatorFunctionBody.d.ts +1 -1
- package/build/api/types/compileNewModificatorFunctionBody.js +1 -1
- package/build/api/types/index.d.ts +3 -2
- package/build/api/types/index.js +12 -7
- package/build/api/utils/index.d.ts +3 -3
- package/build/api/utils/index.js +13 -5
- package/build/constants/index.d.ts +1 -1
- package/build/constants/index.js +1 -1
- package/build/descriptors/errors/index.d.ts +2 -1
- package/build/descriptors/errors/index.js +3 -3
- package/build/descriptors/index.d.ts +3 -3
- package/build/descriptors/index.js +5 -2
- package/build/descriptors/types/index.d.ts +2 -2
- package/build/descriptors/types/index.js +7 -6
- package/build/index.d.ts +15 -16
- package/build/index.js +47 -27
- package/build/types/index.d.ts +141 -29
- package/build/types/index.js +1 -1
- package/build/utils/collectConstructors.js +1 -1
- package/build/utils/extract.d.ts +2 -2
- package/build/utils/extract.js +1 -1
- package/build/utils/index.d.ts +1 -1
- package/build/utils/index.js +9 -7
- package/build/utils/merge.d.ts +1 -1
- package/build/utils/merge.js +4 -3
- package/build/utils/parent.d.ts +1 -1
- package/build/utils/parent.js +1 -1
- package/build/utils/parse.d.ts +12 -1
- package/build/utils/parse.js +12 -7
- package/build/utils/pick.d.ts +2 -2
- package/build/utils/pick.js +3 -2
- package/build/utils/toJSON.js +1 -1
- package/package.json +22 -21
package/README.md
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
# mnemonica
|
|
2
|
-
|
|
1
|
+
# mnemonica
|
|
2
|
+
|
|
3
|
+
**Abstract technique that aids information retention: Instance Inheritance System**
|
|
3
4
|
|
|
4
5
|
... 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
|
|
5
6
|
|
|
@@ -10,823 +11,981 @@ abstract technique that aids information retention : instance inheritance system
|
|
|
10
11
|
|
|
11
12
|
# shortcuts
|
|
12
13
|
|
|
14
|
+
* ?. : state : **mad science**
|
|
13
15
|
* ?. : type : **asynchronous monad descriptor** => this
|
|
14
16
|
* ?. : prod ready : **we wonder about**
|
|
15
17
|
* ?. : example : **git clone && npm run example**
|
|
16
18
|
|
|
17
19
|
---
|
|
18
|
-
|
|
19
20
|
[](https://coveralls.io/github/wentout/mnemonica?branch=master)
|
|
20
|
-
|
|
21
21
|

|
|
22
22
|

|
|
23
23
|

|
|
24
|
-
|
|
25
24
|
[](https://www.npmjs.com/package/mnemonica)
|
|
26
25
|
|
|
27
26
|
---
|
|
28
27
|
|
|
28
|
+
## Table of Contents
|
|
29
|
+
|
|
30
|
+
- [Overview](#overview)
|
|
31
|
+
- [Installation](#installation)
|
|
32
|
+
- [Quick Start](#quick-start)
|
|
33
|
+
- [Core Concepts](#core-concepts)
|
|
34
|
+
- [TypeScript Support](#typescript-support)
|
|
35
|
+
- [API Reference](#api-reference)
|
|
36
|
+
- [Core Functions](#core-functions)
|
|
37
|
+
- [Type Reference](#type-reference)
|
|
38
|
+
- [Type Management](#type-management)
|
|
39
|
+
- [Instance Methods](#instance-methods)
|
|
40
|
+
- [Utilities](#utilities)
|
|
41
|
+
- [Hooks](#hooks)
|
|
42
|
+
- [Error Handling](#error-handling)
|
|
43
|
+
- [Symbols & Constants](#symbols--constants)
|
|
44
|
+
- [Configuration Options](#configuration-options)
|
|
45
|
+
- [AI Agent Usage Guide](#ai-agent-usage-guide)
|
|
46
|
+
- [Examples](#examples)
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Overview
|
|
29
51
|
|
|
30
|
-
|
|
52
|
+
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.
|
|
31
53
|
|
|
32
|
-
|
|
54
|
+
Think of it as a mathematical function `f(x) => y` where `this` is your persistent data structure and transformations are applied sequentially.
|
|
33
55
|
|
|
34
|
-
*
|
|
35
|
-
|
|
36
|
-
* [Dead Simple type checker for JavaScript](https://dev.to/wentout/dead-simple-type-checker-for-javascript-4l40)
|
|
56
|
+
> *"O Great Mnemosyne! Please! Save us from Oblivion..."*
|
|
57
|
+
> — from the source, where memory persists
|
|
37
58
|
|
|
59
|
+

|
|
60
|
+
|
|
61
|
+
**Key Features:**
|
|
62
|
+
- Factory of Constructors with Prototype Chain Inheritance
|
|
63
|
+
- Instance-level inheritance (not just class-level)
|
|
64
|
+
- Async constructor support with chainable awaits
|
|
65
|
+
- Type-safe data flow definition
|
|
66
|
+
- Comprehensive hook system for lifecycle events
|
|
38
67
|
|
|
39
|
-
|
|
68
|
+
**Related Reading:**
|
|
69
|
+
- [Inheritance in JavaScript: Factory of Constructors with Prototype Chain](https://github.com/mythographica/stash/blob/master/inheritance.md)
|
|
70
|
+
- [Architecture of Prototype Inheritance in JavaScript](https://dev.to/wentout/architecture-of-prototype-inheritance-in-javascript-ce6)
|
|
71
|
+
- [Dead Simple type checker for JavaScript](https://dev.to/wentout/dead-simple-type-checker-for-javascript-4l40)
|
|
40
72
|
|
|
41
|
-
|
|
73
|
+
---
|
|
42
74
|
|
|
43
|
-
|
|
75
|
+
## Installation
|
|
44
76
|
|
|
77
|
+
```bash
|
|
78
|
+
npm install mnemonica
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Requirements:** Node.js >=16 <24
|
|
82
|
+
|
|
83
|
+
---
|
|
45
84
|
|
|
46
|
-
##
|
|
85
|
+
## Quick Start
|
|
47
86
|
|
|
48
|
-
|
|
87
|
+
### CommonJS
|
|
49
88
|
|
|
50
89
|
```js
|
|
51
90
|
const { define } = require('mnemonica');
|
|
52
91
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
92
|
+
// Define a type
|
|
93
|
+
const UserType = define('UserType', function (data) {
|
|
94
|
+
Object.assign(this, data);
|
|
95
|
+
});
|
|
56
96
|
|
|
57
|
-
//
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
97
|
+
// Create an instance
|
|
98
|
+
const user = new UserType({ name: 'John', email: 'john@example.com' });
|
|
99
|
+
|
|
100
|
+
// Define a subtype
|
|
101
|
+
const AdminType = UserType.define('AdminType', function () {
|
|
102
|
+
this.role = 'admin';
|
|
103
|
+
});
|
|
61
104
|
|
|
105
|
+
// Create nested instance (inherits from user)
|
|
106
|
+
const admin = new user.AdminType();
|
|
107
|
+
console.log(admin.name); // 'John' (inherited)
|
|
108
|
+
console.log(admin.role); // 'admin' (own property)
|
|
62
109
|
```
|
|
63
110
|
|
|
64
|
-
|
|
111
|
+
### ESM
|
|
65
112
|
|
|
66
113
|
```js
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const SomeTypeConstructor = function (opts) {
|
|
70
|
-
// as this is absolutely the same behaviour
|
|
71
|
-
// we described upper
|
|
72
|
-
// in TypeModificationProcedure
|
|
73
|
-
// we allowed to do the following
|
|
74
|
-
// for shortening this example lines
|
|
75
|
-
Object.assign(this, opts);
|
|
76
|
-
};
|
|
77
|
-
// prototype definition is NOT obligatory
|
|
78
|
-
SomeTypeConstructor.prototype
|
|
79
|
-
.description = 'SomeType Constructor';
|
|
114
|
+
import { define, lookup } from 'mnemonica/module';
|
|
115
|
+
```
|
|
80
116
|
|
|
81
|
-
|
|
82
|
-
};
|
|
117
|
+
---
|
|
83
118
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
// just to show the example
|
|
96
|
-
// of how it works
|
|
97
|
-
const {
|
|
98
|
-
some,
|
|
99
|
-
data,
|
|
100
|
-
// we will re-define
|
|
101
|
-
// "inside" property later
|
|
102
|
-
// using nested sub-type
|
|
103
|
-
inside
|
|
104
|
-
} = opts;
|
|
105
|
-
this.some = some;
|
|
106
|
-
this.data = data;
|
|
107
|
-
this.inside = inside;
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
return SomeTypeConstructor;
|
|
111
|
-
};
|
|
119
|
+
## Core Concepts
|
|
120
|
+
|
|
121
|
+
### Factory of Constructors
|
|
122
|
+
|
|
123
|
+
Define types using constructors, factory functions, or classes:
|
|
124
|
+
|
|
125
|
+
```js
|
|
126
|
+
// Using a constructor function
|
|
127
|
+
const SomeType = define('SomeType', function (opts) {
|
|
128
|
+
Object.assign(this, opts);
|
|
129
|
+
});
|
|
112
130
|
|
|
113
|
-
|
|
131
|
+
// Using a factory function
|
|
132
|
+
const AnotherType = define(() => {
|
|
133
|
+
const AnotherTypeConstructor = function (opts) {
|
|
134
|
+
Object.assign(this, opts);
|
|
135
|
+
};
|
|
136
|
+
AnotherTypeConstructor.prototype.description = 'SomeType Constructor';
|
|
137
|
+
return AnotherTypeConstructor;
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// Using a class
|
|
141
|
+
const ClassType = define(() => {
|
|
142
|
+
class MyClass {
|
|
143
|
+
constructor(opts) {
|
|
144
|
+
Object.assign(this, opts);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return MyClass;
|
|
148
|
+
});
|
|
114
149
|
```
|
|
115
150
|
|
|
116
|
-
|
|
151
|
+
### Nested Type Definition
|
|
117
152
|
|
|
118
153
|
```js
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
inside // again
|
|
123
|
-
} = opts;
|
|
124
|
-
this.other = other;
|
|
125
|
-
// here we will re-define
|
|
126
|
-
// our previously defined property
|
|
127
|
-
// with the new value
|
|
128
|
-
this.inside = inside;
|
|
154
|
+
// Define nested types
|
|
155
|
+
SomeType.define('SubType', function (opts) {
|
|
156
|
+
this.other = opts.other;
|
|
129
157
|
}, {
|
|
130
|
-
|
|
158
|
+
description: 'SomeSubType Constructor'
|
|
131
159
|
});
|
|
132
160
|
|
|
133
|
-
//
|
|
134
|
-
SomeType.
|
|
135
|
-
|
|
136
|
-
other,
|
|
137
|
-
inside // again
|
|
138
|
-
} = opts;
|
|
139
|
-
this.other = other;
|
|
140
|
-
// here we will re-define
|
|
141
|
-
// our previously defined property
|
|
142
|
-
// with the new value
|
|
143
|
-
this.inside = inside;
|
|
161
|
+
// Or using assignment
|
|
162
|
+
SomeType.SubType = function (opts) {
|
|
163
|
+
this.other = opts.other;
|
|
144
164
|
};
|
|
145
|
-
SomeType.
|
|
146
|
-
|
|
165
|
+
SomeType.SubType.prototype = {
|
|
166
|
+
description: 'SomeSubType Constructor'
|
|
147
167
|
};
|
|
148
168
|
```
|
|
149
169
|
|
|
150
|
-
|
|
170
|
+
### Instance Creation and Inheritance
|
|
151
171
|
|
|
152
172
|
```js
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
173
|
+
const someInstance = new SomeType({
|
|
174
|
+
some: 'arguments',
|
|
175
|
+
data: 'necessary'
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const subInstance = new someInstance.SubType({
|
|
179
|
+
other: 'data needed'
|
|
180
|
+
});
|
|
158
181
|
|
|
159
|
-
|
|
182
|
+
// All properties are inherited
|
|
183
|
+
console.log(subInstance.some); // 'arguments' (inherited)
|
|
184
|
+
console.log(subInstance.other); // 'data needed' (own)
|
|
185
|
+
```
|
|
160
186
|
|
|
161
|
-
|
|
187
|
+
### The `.extract()` Method
|
|
162
188
|
|
|
163
|
-
|
|
189
|
+
Extract all inherited properties into a flat object:
|
|
164
190
|
|
|
165
191
|
```js
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
});
|
|
192
|
+
const extracted = subInstance.extract();
|
|
193
|
+
// Result: { data, description, other, some }
|
|
194
|
+
|
|
195
|
+
// Or use the standalone utility
|
|
196
|
+
const { utils: { extract } } = require('mnemonica');
|
|
197
|
+
const extracted2 = extract(subInstance);
|
|
171
198
|
```
|
|
172
199
|
|
|
173
|
-
|
|
200
|
+
---
|
|
174
201
|
|
|
175
|
-
|
|
202
|
+
## TypeScript Support
|
|
176
203
|
|
|
177
|
-
|
|
178
|
-
// someTypeInstance is an instance
|
|
179
|
-
// we did before, through the referenced
|
|
180
|
-
// SomeType constructor we made using
|
|
181
|
-
// define at the first step
|
|
182
|
-
// of this fabulous adventure
|
|
183
|
-
someTypeInstance
|
|
184
|
-
// we defined SomeSubType
|
|
185
|
-
// as a nested constructor
|
|
186
|
-
// so we have to use it
|
|
187
|
-
// utilising instance
|
|
188
|
-
// crafted from it's parent
|
|
189
|
-
.SomeSubType({
|
|
190
|
-
other : 'data needed',
|
|
191
|
-
// and this is -re-definition
|
|
192
|
-
// of "inside" property
|
|
193
|
-
// as we promised before
|
|
194
|
-
inside : ' of ... etc ...'
|
|
195
|
-
});
|
|
204
|
+
The `define` function has full TypeScript support with comprehensive type definitions:
|
|
196
205
|
|
|
197
|
-
```
|
|
206
|
+
```typescript
|
|
207
|
+
import { define, apply, call, bind } from 'mnemonica';
|
|
198
208
|
|
|
199
|
-
|
|
209
|
+
interface UserData {
|
|
210
|
+
email: string;
|
|
211
|
+
password: string;
|
|
212
|
+
}
|
|
200
213
|
|
|
214
|
+
const UserType = define('UserType', function (this: UserData, data: UserData) {
|
|
215
|
+
Object.assign(this, data);
|
|
216
|
+
});
|
|
201
217
|
|
|
202
|
-
|
|
218
|
+
// Nested constructors work with apply/call/bind for type inference
|
|
219
|
+
const user = new UserType({ email: 'test@test.com', password: 'secret' });
|
|
220
|
+
```
|
|
203
221
|
|
|
204
|
-
|
|
222
|
+
For complex nested types, use `apply`, `call`, or `bind` for better type inference:
|
|
205
223
|
|
|
206
|
-
|
|
224
|
+
```typescript
|
|
225
|
+
const SomeSubType = SomeType.define('SomeSubType', function (...args: string[]) {
|
|
226
|
+
// ...
|
|
227
|
+
});
|
|
207
228
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
229
|
+
const someInstance = new SomeType();
|
|
230
|
+
const subInstance = call(someInstance, SomeSubType, 'arg1', 'arg2');
|
|
231
|
+
```
|
|
211
232
|
|
|
212
|
-
|
|
233
|
+
### Exported Type Definitions
|
|
213
234
|
|
|
214
|
-
|
|
215
|
-
inside : ' of ... etc ...'
|
|
235
|
+
The following types are available for advanced TypeScript usage:
|
|
216
236
|
|
|
237
|
+
```typescript
|
|
238
|
+
import {
|
|
239
|
+
// Core constructor types
|
|
240
|
+
IDEF, // Base constructor function type: { new(): T } | { (this: T, ...args): void }
|
|
241
|
+
ConstructorFunction, // Constructor with prototype
|
|
242
|
+
Constructor, // Generic constructor type
|
|
243
|
+
|
|
244
|
+
// Instance types
|
|
245
|
+
MnemonicaInstance, // Instance methods interface (extract, pick, parent, fork, etc.)
|
|
246
|
+
Props, // Internal instance properties (__type__, __args__, __parent__, etc.)
|
|
247
|
+
SiblingAccessor, // Sibling type accessor type
|
|
248
|
+
|
|
249
|
+
// Type definition types
|
|
250
|
+
TypeClass, // Base type constructor returned by define()
|
|
251
|
+
IDefinitorInstance, // Definitor instance with define/lookup methods and subtypes
|
|
252
|
+
DecoratedClass, // Type for @decorate decorated classes
|
|
253
|
+
TypeDef, // Type definition object structure
|
|
254
|
+
|
|
255
|
+
// Configuration types
|
|
256
|
+
constructorOptions, // Type config options (strictChain, blockErrors, etc.)
|
|
257
|
+
hooksTypes, // 'preCreation' | 'postCreation' | 'creationError'
|
|
258
|
+
hook, // Hook callback type
|
|
259
|
+
hooksOpts, // Hook options passed to callbacks
|
|
260
|
+
CollectionDef, // Types collection definition
|
|
261
|
+
|
|
262
|
+
// Utility function types
|
|
263
|
+
ApplyFunction, // apply(entity, Ctor, args) => S
|
|
264
|
+
CallFunction, // call(entity, Ctor, ...args) => S
|
|
265
|
+
BindFunction, // bind(entity, Ctor) => (...args) => S
|
|
266
|
+
} from 'mnemonica';
|
|
217
267
|
```
|
|
218
268
|
|
|
219
|
-
|
|
269
|
+
### Generic Type Patterns
|
|
220
270
|
|
|
221
|
-
|
|
271
|
+
Define types with proper generic constraints for full type safety:
|
|
222
272
|
|
|
223
|
-
|
|
273
|
+
```typescript
|
|
274
|
+
// Using IDEF with interface definitions
|
|
275
|
+
interface UserData {
|
|
276
|
+
email: string;
|
|
277
|
+
password: string;
|
|
278
|
+
}
|
|
224
279
|
|
|
225
|
-
|
|
280
|
+
// Type-safe constructor with 'this' context
|
|
281
|
+
const UserType = define('UserType', function (this: UserData, data: UserData) {
|
|
282
|
+
Object.assign(this, data);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// Type-safe nested types with merged interfaces
|
|
286
|
+
interface AdminData {
|
|
287
|
+
role: string;
|
|
288
|
+
}
|
|
226
289
|
|
|
227
|
-
const
|
|
290
|
+
const AdminType = UserType.define('AdminType', function (this: UserData & AdminData, role: string) {
|
|
291
|
+
this.role = role;
|
|
292
|
+
this.email; // string - inherited from UserData
|
|
293
|
+
});
|
|
294
|
+
```
|
|
228
295
|
|
|
229
|
-
|
|
296
|
+
### Async Constructor Type Patterns
|
|
230
297
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
298
|
+
```typescript
|
|
299
|
+
// Async type with proper return type
|
|
300
|
+
const AsyncType = define('AsyncType', async function (this: UserData, data: string) {
|
|
301
|
+
await someAsyncOperation();
|
|
302
|
+
return Object.assign(this, { data });
|
|
303
|
+
});
|
|
236
304
|
|
|
305
|
+
// With explicit awaitReturn option (no return required)
|
|
306
|
+
const AsyncTypeNoReturn = define('AsyncType', async function () {
|
|
307
|
+
// No return needed
|
|
308
|
+
}, { awaitReturn: false });
|
|
237
309
|
```
|
|
238
310
|
|
|
239
|
-
|
|
311
|
+
---
|
|
240
312
|
|
|
241
|
-
|
|
242
|
-
const { extract } = require('mnemonica').utils;
|
|
243
|
-
const extracted = extract(someSubTypeInstance);
|
|
313
|
+
## API Reference
|
|
244
314
|
|
|
245
|
-
|
|
246
|
-
description : "SomeSubType Constructor"
|
|
247
|
-
inside : " of ... etc ..."
|
|
248
|
-
other : "data needed"
|
|
249
|
-
some : "arguments"
|
|
315
|
+
### Core Functions
|
|
250
316
|
|
|
251
|
-
|
|
317
|
+
#### `define(typeName, constructHandler, config?)`
|
|
252
318
|
|
|
253
|
-
|
|
254
|
-
description : "SomeType Constructor"
|
|
255
|
-
inside : "of SomeType definition"
|
|
256
|
-
some : "arguments"
|
|
319
|
+
Defines a new type constructor. Returns a TypeClass.
|
|
257
320
|
|
|
321
|
+
```js
|
|
322
|
+
const MyType = define('MyType', function (data) {
|
|
323
|
+
Object.assign(this, data);
|
|
324
|
+
}, {
|
|
325
|
+
strictChain: true,
|
|
326
|
+
blockErrors: true
|
|
327
|
+
});
|
|
258
328
|
```
|
|
259
329
|
|
|
260
|
-
|
|
330
|
+
**Parameters:**
|
|
331
|
+
- `typeName` (string): Name of the type (optional if using factory function)
|
|
332
|
+
- `constructHandler` (Function): Constructor function
|
|
333
|
+
- `config` (object, optional): Configuration options
|
|
261
334
|
|
|
262
|
-
|
|
335
|
+
#### `lookup(typeNestedPath)`
|
|
263
336
|
|
|
264
|
-
|
|
337
|
+
Looks up a type by its nested path.
|
|
265
338
|
|
|
266
339
|
```js
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
console.log(someSubTypeInstance instanceof SomeSubType); // true
|
|
271
|
-
// who there can care... but, yes, it is again: true
|
|
272
|
-
console.log(someSubTypeInstance instanceof someTypeInstance);
|
|
273
|
-
|
|
340
|
+
const { lookup } = require('mnemonica');
|
|
341
|
+
const SomeType = lookup('SomeType');
|
|
342
|
+
const SomeNestedType = lookup('SomeType.SomeNestedType');
|
|
274
343
|
```
|
|
275
344
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
## How do we use defined "mnemonicas"
|
|
345
|
+
#### `apply(entity, Constructor, args?)`
|
|
279
346
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
Let's create Constructor for this sort of data.
|
|
347
|
+
Applies a constructor to an entity with an array of arguments.
|
|
283
348
|
|
|
284
349
|
```js
|
|
285
|
-
const
|
|
286
|
-
|
|
287
|
-
FactoryOfRequestHandlerCostructor);
|
|
350
|
+
const { apply } = require('mnemonica');
|
|
351
|
+
const subInstance = apply(parentInstance, SubType, ['arg1', 'arg2']);
|
|
288
352
|
```
|
|
289
353
|
|
|
290
|
-
|
|
354
|
+
#### `call(entity, Constructor, ...args)`
|
|
355
|
+
|
|
356
|
+
Calls a constructor on an entity with spread arguments.
|
|
291
357
|
|
|
292
358
|
```js
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
RequestDataTypeModificator(req.body);
|
|
296
|
-
};
|
|
359
|
+
const { call } = require('mnemonica');
|
|
360
|
+
const subInstance = call(parentInstance, SubType, 'arg1', 'arg2');
|
|
297
361
|
```
|
|
298
362
|
|
|
299
|
-
|
|
363
|
+
#### `bind(entity, Constructor)`
|
|
364
|
+
|
|
365
|
+
Binds a constructor to an entity, returning a function.
|
|
300
366
|
|
|
301
367
|
```js
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
define('GoneToTheDataBase',
|
|
306
|
-
DataBaseRequestHandlerCostructor);
|
|
368
|
+
const { bind } = require('mnemonica');
|
|
369
|
+
const createSub = bind(parentInstance, SubType);
|
|
370
|
+
const subInstance = createSub('arg1', 'arg2');
|
|
307
371
|
```
|
|
308
372
|
|
|
309
|
-
|
|
373
|
+
#### `decorate(target?, config?)`
|
|
310
374
|
|
|
311
|
-
|
|
375
|
+
TypeScript decorator for class-based definitions.
|
|
312
376
|
|
|
313
|
-
```
|
|
314
|
-
|
|
377
|
+
```typescript
|
|
378
|
+
import { decorate } from 'mnemonica';
|
|
315
379
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
TypeName : TypeModificatorConstructor.name,
|
|
321
|
-
|
|
322
|
-
// 1. [ array ]
|
|
323
|
-
// ...args of TypeModificator
|
|
324
|
-
// for instance creation
|
|
325
|
-
argumentsOfTypeModificator,
|
|
326
|
-
|
|
327
|
-
// 2. { object }
|
|
328
|
-
// instance we will craft from
|
|
329
|
-
// using our TypeModificator
|
|
330
|
-
instanceUsedForInheritance
|
|
331
|
-
|
|
332
|
-
} = hookData;
|
|
333
|
-
// some necessary pre-investigations
|
|
334
|
-
};
|
|
380
|
+
@decorate()
|
|
381
|
+
class MyClass {
|
|
382
|
+
field: number = 123;
|
|
383
|
+
}
|
|
335
384
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
const postCreationCallback = (hookData) => {
|
|
343
|
-
const {
|
|
344
|
-
// { string }
|
|
345
|
-
TypeName : TypeModificatorConstructor.name,
|
|
346
|
-
|
|
347
|
-
// 1. [ array ]
|
|
348
|
-
argumentsOfTypeModificator,
|
|
349
|
-
|
|
350
|
-
// 2. { object }
|
|
351
|
-
instanceUsedForInheritance,
|
|
352
|
-
|
|
353
|
-
// 3. { object }
|
|
354
|
-
// instance we just crafted
|
|
355
|
-
// from instanceUsedForInheritance
|
|
356
|
-
// using our TypeModificator
|
|
357
|
-
// with argumentsOfTypeModificator
|
|
358
|
-
// and ... inheritedInstance
|
|
359
|
-
// .constructor.name is
|
|
360
|
-
// TypeName
|
|
361
|
-
inheritedInstance
|
|
362
|
-
|
|
363
|
-
} = hookData;
|
|
364
|
-
// some necessary post-investigations
|
|
365
|
-
};
|
|
385
|
+
// With configuration
|
|
386
|
+
@decorate({ strictChain: false })
|
|
387
|
+
class ConfiguredClass {
|
|
388
|
+
// ...
|
|
389
|
+
}
|
|
366
390
|
|
|
367
|
-
//
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
391
|
+
// Nested decoration
|
|
392
|
+
@decorate()
|
|
393
|
+
class ParentClass {}
|
|
394
|
+
|
|
395
|
+
@decorate(ParentClass)
|
|
396
|
+
class ChildClass {}
|
|
372
397
|
```
|
|
373
398
|
|
|
374
|
-
|
|
399
|
+
#### `registerHook(Constructor, hookType, callback)`
|
|
375
400
|
|
|
376
|
-
|
|
401
|
+
Registers a hook for a specific constructor.
|
|
377
402
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
'preCreation', // ...
|
|
381
|
-
|
|
382
|
-
GoneToTheDataBase
|
|
383
|
-
.registerHook(
|
|
384
|
-
'postCreation', // ...
|
|
385
|
-
|
|
403
|
+
```js
|
|
404
|
+
const { registerHook } = require('mnemonica');
|
|
386
405
|
|
|
406
|
+
registerHook(MyType, 'preCreation', (hookData) => {
|
|
407
|
+
console.log('Creating:', hookData.TypeName);
|
|
408
|
+
});
|
|
387
409
|
```
|
|
388
410
|
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
### Type Reference
|
|
414
|
+
|
|
415
|
+
For advanced TypeScript usage, the following types are exported from `mnemonica`:
|
|
416
|
+
|
|
417
|
+
| Type | Description | Usage |
|
|
418
|
+
|------|-------------|-------|
|
|
419
|
+
| `IDEF<T>` | Base constructor function type | `define('Name', fn: IDEF<MyType>)` |
|
|
420
|
+
| `MnemonicaInstance` | Instance methods interface | `instance.extract()`, `instance.pick()` |
|
|
421
|
+
| `TypeClass` | Base type constructor | `const MyType: TypeClass = define(...)` |
|
|
422
|
+
| `DecoratedClass<T>` | Decorated class type | `@decorate() class MyClass {}` |
|
|
423
|
+
| `IDefinitorInstance<N, S>` | Constructor with subtypes | Returned by `define()` with `.define()` method |
|
|
424
|
+
| `ConstructorFunction<T>` | Constructor with prototype | Generic constructor function signature |
|
|
425
|
+
| `constructorOptions` | Configuration options | `{ strictChain: true, blockErrors: true }` |
|
|
426
|
+
| `hooksTypes` | Hook type literals | `'preCreation' \| 'postCreation' \| 'creationError'` |
|
|
427
|
+
| `hook` | Hook callback type | `(opts: hooksOpts) => void` |
|
|
428
|
+
| `hooksOpts` | Hook options object | Passed to hook callbacks |
|
|
429
|
+
| `TypeDef` | Type definition structure | `instance.__type__` structure |
|
|
430
|
+
| `CollectionDef` | Types collection | `instance.__collection__` structure |
|
|
431
|
+
| `ApplyFunction` | apply() function type | `apply<E, T, S>(entity, Ctor, args) => S` |
|
|
432
|
+
| `CallFunction` | call() function type | `call<E, T, S>(entity, Ctor, ...args) => S` |
|
|
433
|
+
| `BindFunction` | bind() function type | `bind<E, T, S>(entity, Ctor) => (...args) => S` |
|
|
434
|
+
|
|
435
|
+
These types enable complete type safety when defining and using mnemonica types in TypeScript projects.
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
### Type Management
|
|
389
440
|
|
|
390
|
-
|
|
441
|
+
#### `defaultTypes`
|
|
391
442
|
|
|
443
|
+
The default types collection. All types defined with the top-level `define()` are stored here.
|
|
392
444
|
|
|
393
445
|
```js
|
|
394
|
-
const {
|
|
395
|
-
|
|
396
|
-
|
|
446
|
+
const { defaultTypes } = require('mnemonica');
|
|
447
|
+
const MyType = defaultTypes.MyType;
|
|
448
|
+
```
|
|
397
449
|
|
|
398
|
-
|
|
399
|
-
.registerHook(
|
|
400
|
-
'preCreation', preCreationTypesCollectionCallback);
|
|
401
|
-
|
|
402
|
-
defaultTypes
|
|
403
|
-
.registerHook(
|
|
404
|
-
'postCreation', postCreationTypesCollectionCallback);
|
|
450
|
+
#### `createTypesCollection(config?)`
|
|
405
451
|
|
|
452
|
+
Creates a new isolated types collection.
|
|
406
453
|
|
|
454
|
+
```js
|
|
455
|
+
const { createTypesCollection } = require('mnemonica');
|
|
456
|
+
const myCollection = createTypesCollection();
|
|
457
|
+
const MyType = myCollection.define('MyType', function () {});
|
|
407
458
|
```
|
|
408
459
|
|
|
409
|
-
|
|
460
|
+
#### `getProps(instance)` / `setProps(instance, values)`
|
|
461
|
+
|
|
462
|
+
Get or set internal properties of an instance.
|
|
410
463
|
|
|
411
464
|
```js
|
|
465
|
+
const { getProps, setProps } = require('mnemonica');
|
|
412
466
|
|
|
413
|
-
|
|
414
|
-
|
|
467
|
+
const props = getProps(instance);
|
|
468
|
+
console.log(props.__type__, props.__args__);
|
|
415
469
|
|
|
416
|
-
//
|
|
417
|
-
|
|
470
|
+
// Set properties
|
|
471
|
+
setProps(instance, { __timestamp__: Date.now() });
|
|
472
|
+
```
|
|
418
473
|
|
|
419
|
-
|
|
474
|
+
---
|
|
420
475
|
|
|
421
|
-
|
|
422
|
-
type.invokeHook('postCreation', // ...
|
|
476
|
+
### Instance Methods
|
|
423
477
|
|
|
424
|
-
|
|
425
|
-
typecollection.invokeHook('postCreation', // ...
|
|
478
|
+
All mnemonica instances have the following methods:
|
|
426
479
|
|
|
480
|
+
#### `.extract()`
|
|
427
481
|
|
|
482
|
+
Extracts all inherited properties into a single flat object.
|
|
483
|
+
|
|
484
|
+
```js
|
|
485
|
+
const extracted = instance.extract();
|
|
428
486
|
```
|
|
429
487
|
|
|
430
|
-
|
|
488
|
+
#### `.pick(...keys)` / `.pick([keys])`
|
|
431
489
|
|
|
432
|
-
|
|
490
|
+
Picks specific properties from the instance and its inheritance chain.
|
|
433
491
|
|
|
434
492
|
```js
|
|
435
|
-
const
|
|
436
|
-
|
|
437
|
-
|
|
493
|
+
const picked = instance.pick('email', 'password');
|
|
494
|
+
// or
|
|
495
|
+
const picked = instance.pick(['email', 'password']);
|
|
496
|
+
```
|
|
438
497
|
|
|
439
|
-
|
|
440
|
-
|
|
498
|
+
#### `.parent(constructorName?)`
|
|
499
|
+
|
|
500
|
+
Gets the parent instance. If `constructorName` is provided, walks up the chain.
|
|
441
501
|
|
|
502
|
+
```js
|
|
503
|
+
const immediateParent = instance.parent();
|
|
504
|
+
const specificParent = instance.parent('UserType');
|
|
442
505
|
```
|
|
443
506
|
|
|
444
|
-
|
|
507
|
+
#### `.clone`
|
|
508
|
+
|
|
509
|
+
Property that returns a cloned instance (same parent, same args).
|
|
445
510
|
|
|
446
511
|
```js
|
|
512
|
+
const cloned = instance.clone;
|
|
513
|
+
// Note: For async constructors, use: await instance.clone
|
|
514
|
+
```
|
|
447
515
|
|
|
448
|
-
|
|
449
|
-
// operators
|
|
450
|
-
});
|
|
516
|
+
#### `.fork(...args)`
|
|
451
517
|
|
|
452
|
-
|
|
453
|
-
// if you have reference
|
|
454
|
-
SomeExistentType.define('SomeExistentNestedType.NewType', function () {
|
|
455
|
-
// operators
|
|
456
|
-
});
|
|
518
|
+
Creates a forked instance from the same parent with optional new arguments.
|
|
457
519
|
|
|
458
|
-
|
|
520
|
+
```js
|
|
521
|
+
const forked = instance.fork(); // same args
|
|
522
|
+
const forkedWithNewArgs = instance.fork('new', 'args');
|
|
523
|
+
// Note: For async constructors, use: await instance.fork(...)
|
|
524
|
+
```
|
|
459
525
|
|
|
460
|
-
|
|
461
|
-
// name of "NewType" is here
|
|
462
|
-
// nested inside of delcaration
|
|
463
|
-
return class NewType {
|
|
464
|
-
constructor (str) {
|
|
465
|
-
// operators
|
|
466
|
-
}
|
|
467
|
-
};
|
|
468
|
-
});
|
|
526
|
+
#### `.fork.call(thisArg, ...args)` / `.fork.apply(thisArg, args)`
|
|
469
527
|
|
|
528
|
+
Forks with a different `this` context (useful for Directed Acyclic Graphs).
|
|
529
|
+
|
|
530
|
+
```js
|
|
531
|
+
const dagInstance = instanceA.fork.call(instanceB, 'args');
|
|
470
532
|
```
|
|
471
533
|
|
|
472
|
-
|
|
534
|
+
#### `.exception(error, ...args)`
|
|
473
535
|
|
|
474
|
-
|
|
536
|
+
Creates an exception instance from the current instance.
|
|
475
537
|
|
|
476
538
|
```js
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
.OverMore
|
|
480
|
-
// ...
|
|
481
|
-
// ...
|
|
482
|
-
.InitialType
|
|
539
|
+
const error = someInstance.exception(new Error('Something went wrong'));
|
|
540
|
+
throw error;
|
|
483
541
|
```
|
|
484
542
|
|
|
485
|
-
|
|
543
|
+
#### `.sibling(typeName)` / `.sibling.TypeName`
|
|
544
|
+
|
|
545
|
+
Access sibling types from the same collection.
|
|
486
546
|
|
|
487
547
|
```js
|
|
548
|
+
const siblingType = instance.sibling('OtherType');
|
|
549
|
+
const sibling = instance.sibling.OtherType;
|
|
550
|
+
```
|
|
488
551
|
|
|
489
|
-
|
|
490
|
-
// simply equal to getProps(instance).__parent__
|
|
491
|
-
const parent = instance.parent();
|
|
552
|
+
---
|
|
492
553
|
|
|
493
|
-
|
|
494
|
-
const parent = instance
|
|
495
|
-
.parent( 'DeepParentName' );
|
|
554
|
+
### Instance Properties (via `getProps`)
|
|
496
555
|
|
|
497
|
-
|
|
556
|
+
All instances have non-enumerable internal properties:
|
|
498
557
|
|
|
558
|
+
| Property | Type | Description |
|
|
559
|
+
|----------|------|-------------|
|
|
560
|
+
| `.__args__` | `unknown[]` | Arguments used for instance creation |
|
|
561
|
+
| `.__type__` | `TypeDef` | Type definition object |
|
|
562
|
+
| `.__parent__` | `object` | Parent instance reference |
|
|
563
|
+
| `.__subtypes__` | `Map<string, object>` | Map of available subtypes |
|
|
564
|
+
| `.__collection__` | `CollectionDef` | Types collection where type was defined |
|
|
565
|
+
| `.__stack__` | `string` | Stack trace (if `submitStack: true` in config) |
|
|
566
|
+
| `.__creator__` | `TypeDef` | Instance creator reference |
|
|
567
|
+
| `.__timestamp__` | `number` | Creation timestamp (ms since epoch) |
|
|
568
|
+
| `.__self__` | `object` | Self reference to the instance |
|
|
499
569
|
|
|
500
|
-
|
|
501
|
-
You can combine existing TypeConstructor with any instance, even with Singletones:
|
|
570
|
+
---
|
|
502
571
|
|
|
503
|
-
|
|
504
|
-
const usingProcessAsProto = Singletoned.call(process, {
|
|
505
|
-
some : 'arguments',
|
|
506
|
-
data : 'necessary',
|
|
507
|
-
inside : 'for definition'
|
|
508
|
-
});
|
|
509
|
-
console.log(typeof instanceUsingProcessSingletone.on) // function
|
|
510
|
-
```
|
|
572
|
+
### Utilities
|
|
511
573
|
|
|
512
|
-
|
|
574
|
+
Access via `utils` export:
|
|
513
575
|
|
|
514
576
|
```js
|
|
577
|
+
const { utils } = require('mnemonica');
|
|
578
|
+
```
|
|
515
579
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
const usingJQueryAsProto = JQueried.call(jQuery);
|
|
580
|
+
#### `utils.extract(instance)`
|
|
581
|
+
Standalone extract function.
|
|
519
582
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
import { define } from "mnemonica";
|
|
523
|
-
const ReactDOOMed = define("ReactDOOMed", function() {});
|
|
524
|
-
const usingReactAsProto = ReactDOOMed.call(ReactDOM);
|
|
583
|
+
#### `utils.pick(instance, ...keys)`
|
|
584
|
+
Standalone pick function.
|
|
525
585
|
|
|
526
|
-
|
|
527
|
-
|
|
586
|
+
#### `utils.parent(instance, constructorName?)`
|
|
587
|
+
Standalone parent function.
|
|
528
588
|
|
|
589
|
+
#### `utils.parse(instance)`
|
|
590
|
+
Parses an instance structure, returning:
|
|
591
|
+
- `name`: constructor name
|
|
592
|
+
- `props`: extracted properties
|
|
593
|
+
- `self`: the instance itself
|
|
594
|
+
- `proto`: prototype object
|
|
595
|
+
- `joint`: prototype properties
|
|
596
|
+
- `parent`: parent prototype
|
|
597
|
+
|
|
598
|
+
```js
|
|
599
|
+
const { utils: { parse } } = require('mnemonica');
|
|
600
|
+
const parsed = parse(instance);
|
|
529
601
|
```
|
|
530
602
|
|
|
603
|
+
#### `utils.merge(A, B, ...args)`
|
|
604
|
+
Merges two instances using fork semantics.
|
|
531
605
|
|
|
532
|
-
|
|
606
|
+
```js
|
|
607
|
+
const merged = utils.merge(instanceA, instanceB, 'args');
|
|
608
|
+
// Note: For async constructors, use: await utils.merge(...)
|
|
609
|
+
```
|
|
533
610
|
|
|
534
|
-
|
|
611
|
+
#### `utils.toJSON(instance)`
|
|
612
|
+
Serializes an instance to JSON.
|
|
535
613
|
|
|
536
614
|
```js
|
|
537
|
-
const
|
|
538
|
-
|
|
539
|
-
});
|
|
615
|
+
const json = utils.toJSON(instance);
|
|
616
|
+
```
|
|
540
617
|
|
|
618
|
+
#### `utils.collectConstructors(instance, flat?)`
|
|
619
|
+
Collects all constructors in the instance's prototype chain.
|
|
541
620
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
});
|
|
621
|
+
```js
|
|
622
|
+
const constructors = utils.collectConstructors(instance, true);
|
|
623
|
+
```
|
|
546
624
|
|
|
547
|
-
|
|
625
|
+
---
|
|
548
626
|
|
|
549
|
-
|
|
550
|
-
someInstance, SomeSubType, ...args);
|
|
627
|
+
### Hooks
|
|
551
628
|
|
|
552
|
-
|
|
553
|
-
const someSubInstance = apply(
|
|
554
|
-
someInstance, SomeSubType, args);
|
|
629
|
+
#### Hook Types
|
|
555
630
|
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
631
|
+
- `'preCreation'` - Called before instance creation
|
|
632
|
+
- `'postCreation'` - Called after instance creation
|
|
633
|
+
- `'creationError'` - Called when instance creation throws an error
|
|
559
634
|
|
|
560
|
-
|
|
635
|
+
#### `type.registerHook(hookType, callback)`
|
|
561
636
|
|
|
637
|
+
Register a hook on a specific type.
|
|
638
|
+
|
|
639
|
+
```js
|
|
640
|
+
MyType.registerHook('preCreation', (hookData) => {
|
|
641
|
+
console.log('Creating:', hookData.TypeName);
|
|
642
|
+
});
|
|
562
643
|
```
|
|
563
644
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
645
|
+
#### `collection.registerHook(hookType, callback)`
|
|
646
|
+
|
|
647
|
+
Register a hook on a types collection.
|
|
567
648
|
|
|
568
649
|
```js
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
data
|
|
572
|
-
});
|
|
650
|
+
defaultTypes.registerHook('postCreation', (hookData) => {
|
|
651
|
+
console.log('Created:', hookData.inheritedInstance.constructor.name);
|
|
573
652
|
});
|
|
653
|
+
```
|
|
574
654
|
|
|
575
|
-
|
|
576
|
-
const asyncConstructedInstance = await new AsyncType('tada');
|
|
577
|
-
console.log(asyncConstructedInstance) // { data: "tada" }
|
|
578
|
-
console.log(asyncConstructedInstance instanceof AsyncType) // true
|
|
579
|
-
};
|
|
655
|
+
#### `collection.registerFlowChecker(callback)`
|
|
580
656
|
|
|
581
|
-
|
|
657
|
+
Register a flow checker that runs before hooks.
|
|
658
|
+
|
|
659
|
+
```js
|
|
660
|
+
defaultTypes.registerFlowChecker((opts) => {
|
|
661
|
+
console.log('Flow check:', opts.TypeName);
|
|
662
|
+
});
|
|
582
663
|
```
|
|
583
664
|
|
|
584
|
-
|
|
665
|
+
#### Hook Data Structure
|
|
666
|
+
|
|
667
|
+
```typescript
|
|
668
|
+
interface HookData {
|
|
669
|
+
TypeName: string; // Constructor name
|
|
670
|
+
type: TypeDef; // The type being constructed
|
|
671
|
+
args: unknown[]; // Arguments passed to constructor
|
|
672
|
+
existentInstance: object; // Parent instance
|
|
673
|
+
inheritedInstance: object; // New instance (postCreation only)
|
|
674
|
+
throwModificationError(error: Error): void; // Throw error from hook
|
|
675
|
+
}
|
|
676
|
+
```
|
|
585
677
|
|
|
586
678
|
```js
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
}, {
|
|
593
|
-
description: 'async of nested'
|
|
594
|
-
});
|
|
679
|
+
MyType.registerHook('postCreation', (hookData) => {
|
|
680
|
+
// Throw custom error from hook
|
|
681
|
+
hookData.throwModificationError(new Error('Custom hook error'));
|
|
682
|
+
});
|
|
683
|
+
```
|
|
595
684
|
|
|
596
|
-
|
|
597
|
-
asyncConstructedInstance.NestedAsyncType('boom');
|
|
685
|
+
**Note:** In preCreation hooks, `existentInstance` refers to the parent; in postCreation hooks, it refers to the instance used for inheritance.
|
|
598
686
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
```
|
|
687
|
+
---
|
|
688
|
+
|
|
689
|
+
### Error Handling
|
|
603
690
|
|
|
604
|
-
|
|
691
|
+
#### Error Types
|
|
692
|
+
|
|
693
|
+
All mnemonica errors extend `BASE_MNEMONICA_ERROR`:
|
|
605
694
|
|
|
606
695
|
```js
|
|
607
|
-
const
|
|
608
|
-
|
|
609
|
-
//
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
696
|
+
const { errors } = require('mnemonica');
|
|
697
|
+
|
|
698
|
+
// Available error types:
|
|
699
|
+
errors.BASE_MNEMONICA_ERROR
|
|
700
|
+
errors.WRONG_TYPE_DEFINITION
|
|
701
|
+
errors.WRONG_INSTANCE_INVOCATION
|
|
702
|
+
errors.WRONG_MODIFICATION_PATTERN
|
|
703
|
+
errors.ALREADY_DECLARED
|
|
704
|
+
errors.TYPENAME_MUST_BE_A_STRING
|
|
705
|
+
errors.HANDLER_MUST_BE_A_FUNCTION
|
|
706
|
+
errors.WRONG_ARGUMENTS_USED
|
|
707
|
+
errors.WRONG_HOOK_TYPE
|
|
708
|
+
errors.MISSING_HOOK_CALLBACK
|
|
709
|
+
errors.MISSING_CALLBACK_ARGUMENT
|
|
710
|
+
errors.FLOW_CHECKER_REDEFINITION
|
|
711
|
+
errors.OPTIONS_ERROR
|
|
712
|
+
errors.WRONG_STACK_CLEANER
|
|
614
713
|
```
|
|
615
714
|
|
|
616
|
-
|
|
715
|
+
#### Exception Instances
|
|
617
716
|
|
|
618
|
-
|
|
717
|
+
When creating exceptions using `instance.exception()`:
|
|
619
718
|
|
|
620
719
|
```js
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
new UserTypeConstructor({
|
|
630
|
-
email,
|
|
631
|
-
password
|
|
632
|
-
})
|
|
633
|
-
.UserEntityValidate('valid sign') // sync
|
|
634
|
-
.WithoutPassword() // sync, rid of password
|
|
635
|
-
|
|
636
|
-
const storagePushResult =
|
|
637
|
-
await user.AsyncPushToStorage();
|
|
638
|
-
const storageGetResult =
|
|
639
|
-
await storagePushResult.AsyncGetStorageResponse();
|
|
640
|
-
const storageValidateResult =
|
|
641
|
-
storagePushResult.SyncValidateStorageData()
|
|
642
|
-
const requestRplyResult =
|
|
643
|
-
await StorageValidateResult.AsyncReplyToRequest(res);
|
|
644
|
-
return requestRplyResult;
|
|
645
|
-
};
|
|
720
|
+
const error = instance.exception(new Error('Original error'));
|
|
721
|
+
|
|
722
|
+
// Properties:
|
|
723
|
+
error.originalError // The original error
|
|
724
|
+
error.exceptionReason // { methodName, ... }
|
|
725
|
+
error.BaseStack // Base stack trace
|
|
726
|
+
error.parse() // Parse the exception structure
|
|
727
|
+
error.extract() // Extract properties from the exception
|
|
646
728
|
```
|
|
647
729
|
|
|
648
|
-
|
|
730
|
+
#### Stack Cleaning
|
|
649
731
|
|
|
650
732
|
```js
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
password // : 'some password'
|
|
656
|
-
} = req.body
|
|
657
|
-
|
|
658
|
-
const user =
|
|
659
|
-
await (
|
|
660
|
-
(
|
|
661
|
-
await (
|
|
662
|
-
await (
|
|
663
|
-
new UserTypeConstructor({
|
|
664
|
-
email,
|
|
665
|
-
password
|
|
666
|
-
})
|
|
667
|
-
.UserEntityValidate('valid sign')
|
|
668
|
-
.WithoutPassword()
|
|
669
|
-
).AsyncPushToStorage()
|
|
670
|
-
).AsyncGetStorageResponse()
|
|
671
|
-
).SyncValidateStorageData()
|
|
672
|
-
).AsyncReplyToRequest(res);
|
|
673
|
-
};
|
|
733
|
+
const { defineStackCleaner } = require('mnemonica');
|
|
734
|
+
|
|
735
|
+
// Add regex patterns to clean stack traces
|
|
736
|
+
defineStackCleaner(/node_modules\/some-package/);
|
|
674
737
|
```
|
|
675
738
|
|
|
676
|
-
|
|
739
|
+
---
|
|
677
740
|
|
|
678
|
-
|
|
741
|
+
### Symbols & Constants
|
|
679
742
|
|
|
680
743
|
```js
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
await new UserTypeConstructor({
|
|
690
|
-
email,
|
|
691
|
-
password
|
|
692
|
-
})
|
|
693
|
-
.UserEntityValidate('valid sign')
|
|
694
|
-
.WithoutPassword()
|
|
695
|
-
.AsyncPushToStorage()
|
|
696
|
-
.AsyncGetStorageResponse()
|
|
697
|
-
.SyncValidateStorageData()
|
|
698
|
-
.AsyncReplyToRequest(res);
|
|
699
|
-
};
|
|
744
|
+
const {
|
|
745
|
+
SymbolParentType, // Parent type symbol
|
|
746
|
+
SymbolConstructorName, // Constructor name symbol
|
|
747
|
+
SymbolDefaultTypesCollection, // Default collection symbol
|
|
748
|
+
SymbolConfig, // Config symbol
|
|
749
|
+
MNEMONICA, // Library name
|
|
750
|
+
MNEMOSYNE // Collection identifier
|
|
751
|
+
} = require('mnemonica');
|
|
700
752
|
```
|
|
701
|
-
So now you don't have to care if this constructor is async or sync and where to put brakets and how many of them. It is enough to type constructor name after the dot and pass necessary arguments. That's it.
|
|
702
753
|
|
|
703
|
-
|
|
754
|
+
---
|
|
704
755
|
|
|
705
|
-
|
|
756
|
+
## Configuration Options
|
|
706
757
|
|
|
758
|
+
Pass options as the third argument to `define()`:
|
|
707
759
|
|
|
760
|
+
```js
|
|
761
|
+
define('SomeType', function () {}, {
|
|
762
|
+
strictChain: true, // Only allow sub-instances from current type
|
|
763
|
+
blockErrors: true, // Disallow construction if error in prototype chain
|
|
764
|
+
submitStack: false, // Collect stack trace as __stack__ property
|
|
765
|
+
awaitReturn: true, // Ensure await new Constructor() returns value
|
|
766
|
+
ModificationConstructor: fn, // Custom modification constructor
|
|
767
|
+
asClass: false // Force class mode (auto-detected by default)
|
|
768
|
+
});
|
|
769
|
+
```
|
|
708
770
|
|
|
709
|
-
|
|
771
|
+
### Override Default Config for Collection
|
|
710
772
|
|
|
711
|
-
|
|
773
|
+
```js
|
|
774
|
+
import { defaultTypes, SymbolConfig } from 'mnemonica';
|
|
712
775
|
|
|
713
|
-
|
|
776
|
+
defaultTypes[SymbolConfig].blockErrors = false;
|
|
777
|
+
```
|
|
714
778
|
|
|
715
|
-
|
|
779
|
+
---
|
|
716
780
|
|
|
717
|
-
##
|
|
781
|
+
## AI Agent Usage Guide
|
|
718
782
|
|
|
719
|
-
|
|
783
|
+
This section helps AI agents understand and work with mnemonica programmatically.
|
|
720
784
|
|
|
721
|
-
|
|
722
|
-
The definition of instance type.
|
|
785
|
+
### 1. Type Introspection
|
|
723
786
|
|
|
724
|
-
|
|
725
|
-
If instance is nested, then it is a reference of it's parent.
|
|
787
|
+
Use `utils.parse(instance)` to understand instance structure:
|
|
726
788
|
|
|
727
|
-
|
|
728
|
-
|
|
789
|
+
```js
|
|
790
|
+
const { utils: { parse } } = require('mnemonica');
|
|
729
791
|
|
|
730
|
-
|
|
731
|
-
|
|
792
|
+
const parsed = parse(instance);
|
|
793
|
+
// Returns: { name, props, self, proto, joint, parent, constructor }
|
|
794
|
+
```
|
|
732
795
|
|
|
733
|
-
|
|
734
|
-
|
|
796
|
+
### 2. Safe Property Access
|
|
797
|
+
|
|
798
|
+
Always use `getProps()` instead of direct property access:
|
|
799
|
+
|
|
800
|
+
```js
|
|
801
|
+
const { getProps } = require('mnemonica');
|
|
735
802
|
|
|
736
|
-
|
|
803
|
+
const props = getProps(instance);
|
|
804
|
+
// props.__type__, props.__args__, props.__parent__, props.__subtypes__, etc.
|
|
805
|
+
```
|
|
737
806
|
|
|
807
|
+
### 3. Type Discovery
|
|
738
808
|
|
|
739
|
-
|
|
740
|
-
|
|
809
|
+
```js
|
|
810
|
+
const { defaultTypes } = require('mnemonica');
|
|
741
811
|
|
|
742
|
-
|
|
812
|
+
// List all types in default collection
|
|
813
|
+
const typeNames = [...defaultTypes.subtypes.keys()];
|
|
743
814
|
|
|
815
|
+
// List subtypes of a specific type
|
|
816
|
+
const myType = defaultTypes.MyType;
|
|
817
|
+
const subTypeNames = [...myType.subtypes.keys()];
|
|
744
818
|
|
|
745
|
-
|
|
819
|
+
// Check if a type exists
|
|
820
|
+
const hasType = defaultTypes.lookup('MyType') !== undefined;
|
|
821
|
+
```
|
|
746
822
|
|
|
747
|
-
|
|
748
|
-
## **`instance.fork.apply( thisArg, [args] )`**
|
|
749
|
-
Let assume you nedd [Directed Acyclic Graph](https://en.wikipedia.org/wiki/Directed_acyclic_graph). Then you have to be able to construct it somehow. Starting from `v0.6.1` you can use `fork.call` or `fork.apply` for doing this:
|
|
823
|
+
### 4. Instance Traversal
|
|
750
824
|
|
|
751
825
|
```js
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
826
|
+
const { getProps } = require('mnemonica');
|
|
827
|
+
|
|
828
|
+
// Walk up the inheritance chain
|
|
829
|
+
function traverseChain(instance) {
|
|
830
|
+
const chain = [];
|
|
831
|
+
let current = instance;
|
|
832
|
+
|
|
833
|
+
while (current) {
|
|
834
|
+
const props = getProps(current);
|
|
835
|
+
if (!props) break;
|
|
836
|
+
|
|
837
|
+
chain.push({
|
|
838
|
+
typeName: props.__type__.TypeName,
|
|
839
|
+
timestamp: props.__timestamp__,
|
|
840
|
+
args: props.__args__
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
current = props.__parent__;
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
return chain;
|
|
847
|
+
}
|
|
756
848
|
```
|
|
757
|
-
_Note_: if you are `fork.clone`'ing instance, which has `async Constructor`, you should `await` it;
|
|
758
849
|
|
|
850
|
+
### 5. Safe Construction Patterns
|
|
759
851
|
|
|
760
|
-
|
|
761
|
-
|
|
852
|
+
```js
|
|
853
|
+
const { lookup } = require('mnemonica');
|
|
762
854
|
|
|
763
|
-
|
|
855
|
+
// Always check if type exists before construction
|
|
856
|
+
const MyType = lookup('MyType');
|
|
857
|
+
if (MyType) {
|
|
858
|
+
const instance = new MyType(data);
|
|
859
|
+
}
|
|
764
860
|
|
|
765
|
-
|
|
861
|
+
// For nested construction with proper error handling
|
|
862
|
+
try {
|
|
863
|
+
const subInstance = new instance.SubType(data);
|
|
864
|
+
} catch (error) {
|
|
865
|
+
// Handle WRONG_MODIFICATION_PATTERN if SubType not defined
|
|
866
|
+
console.error('Subtype not available:', error.message);
|
|
867
|
+
}
|
|
868
|
+
```
|
|
766
869
|
|
|
767
|
-
|
|
768
|
-
Starting from v0.6.8 you can try to import ESM using the following scenario:
|
|
870
|
+
### 6. Analyzing Type Structure
|
|
769
871
|
|
|
770
872
|
```js
|
|
771
|
-
|
|
772
|
-
```
|
|
873
|
+
const { getProps } = require('mnemonica');
|
|
773
874
|
|
|
774
|
-
|
|
875
|
+
function analyzeType(typeConstructor) {
|
|
876
|
+
return {
|
|
877
|
+
name: typeConstructor.TypeName,
|
|
878
|
+
isSubType: typeConstructor.isSubType,
|
|
879
|
+
subTypesCount: typeConstructor.subtypes?.size || 0,
|
|
880
|
+
hasHooks: Object.keys(typeConstructor.hooks || {}).length > 0,
|
|
881
|
+
config: typeConstructor.config
|
|
882
|
+
};
|
|
883
|
+
}
|
|
884
|
+
```
|
|
775
885
|
|
|
776
|
-
|
|
886
|
+
### 7. Working with Collections
|
|
777
887
|
|
|
778
888
|
```js
|
|
779
|
-
|
|
889
|
+
const { createTypesCollection, defaultTypes } = require('mnemonica');
|
|
780
890
|
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
891
|
+
// Create isolated collection for testing
|
|
892
|
+
const testCollection = createTypesCollection({
|
|
893
|
+
strictChain: false,
|
|
894
|
+
blockErrors: false
|
|
895
|
+
});
|
|
785
896
|
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
897
|
+
// Define types in isolation
|
|
898
|
+
const TestType = testCollection.define('TestType', function () {});
|
|
899
|
+
|
|
900
|
+
// Register collection-level hooks
|
|
901
|
+
testCollection.registerHook('preCreation', (data) => {
|
|
902
|
+
console.log('Creating in test collection:', data.TypeName);
|
|
903
|
+
});
|
|
904
|
+
```
|
|
905
|
+
|
|
906
|
+
---
|
|
907
|
+
|
|
908
|
+
## Examples
|
|
909
|
+
|
|
910
|
+
### Asynchronous Constructors
|
|
911
|
+
|
|
912
|
+
```js
|
|
913
|
+
const AsyncType = define('AsyncType', async function (data) {
|
|
914
|
+
await someAsyncOperation();
|
|
915
|
+
return Object.assign(this, { data });
|
|
916
|
+
});
|
|
792
917
|
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
// during the process of instance creation
|
|
796
|
-
submitStack: false,
|
|
918
|
+
// Usage
|
|
919
|
+
const asyncInstance = await new AsyncType('tada');
|
|
797
920
|
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
921
|
+
// Nested async types
|
|
922
|
+
const NestedAsync = AsyncType.define('NestedAsync', async function (data) {
|
|
923
|
+
return Object.assign(this, { nestedData: data });
|
|
924
|
+
});
|
|
802
925
|
|
|
803
|
-
|
|
926
|
+
const nested = await new asyncInstance.NestedAsync('nested');
|
|
804
927
|
```
|
|
805
928
|
|
|
806
|
-
|
|
929
|
+
### Async Chain with Single Await
|
|
807
930
|
|
|
808
931
|
```js
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
932
|
+
async (req, res) => {
|
|
933
|
+
const result = await new UserTypeConstructor({
|
|
934
|
+
email: req.body.email,
|
|
935
|
+
password: req.body.password
|
|
936
|
+
})
|
|
937
|
+
.UserEntityValidate('valid sign')
|
|
938
|
+
.WithoutPassword()
|
|
939
|
+
.AsyncPushToStorage()
|
|
940
|
+
.AsyncGetStorageResponse()
|
|
941
|
+
.SyncValidateStorageData()
|
|
942
|
+
.AsyncReplyToRequest(res);
|
|
943
|
+
};
|
|
944
|
+
```
|
|
813
945
|
|
|
814
|
-
|
|
946
|
+
### Using `call` with Existing Objects
|
|
815
947
|
|
|
948
|
+
```js
|
|
949
|
+
// Combine with process, window, document, etc.
|
|
950
|
+
const usingProcessAsProto = Singletoned.call(process, {
|
|
951
|
+
some: 'arguments'
|
|
952
|
+
});
|
|
953
|
+
|
|
954
|
+
// With React
|
|
955
|
+
import ReactDOM from "react-dom";
|
|
956
|
+
const ReactDOOMed = define("ReactDOOMed", function() {});
|
|
957
|
+
const usingReactAsProto = ReactDOOMed.call(ReactDOM);
|
|
816
958
|
```
|
|
817
959
|
|
|
960
|
+
### Directed Acyclic Graphs (DAG)
|
|
961
|
+
|
|
962
|
+
```js
|
|
963
|
+
// Fork from different parent
|
|
964
|
+
const dagInstance = instanceA.fork.call(instanceB, 'args');
|
|
818
965
|
|
|
819
|
-
|
|
966
|
+
// Or use merge utility
|
|
967
|
+
const { utils: { merge } } = require('mnemonica');
|
|
968
|
+
const merged = merge(instanceA, instanceB, 'args');
|
|
969
|
+
```
|
|
970
|
+
|
|
971
|
+
---
|
|
820
972
|
|
|
821
|
-
|
|
973
|
+
## Epilogue
|
|
822
974
|
|
|
975
|
+
So, now you can craft as many types as you wish, combine them, re-define them and spend much more time playing with them:
|
|
823
976
|
|
|
824
977
|
* test : instances & arguments
|
|
825
978
|
* track : moments of creation
|
|
826
979
|
* check : if the order of creation is OK
|
|
827
980
|
* validate : everything, 4 example use sort of TS in runtime
|
|
828
|
-
* and even
|
|
829
|
-
|
|
830
|
-

|
|
981
|
+
* and even `.parse` them using `mnemonica.utils.parse`
|
|
831
982
|
|
|
832
983
|
Good Luck!
|
|
984
|
+
|
|
985
|
+
---
|
|
986
|
+
|
|
987
|
+
## License
|
|
988
|
+
|
|
989
|
+
MIT
|
|
990
|
+
|
|
991
|
+
Copyright (c) 2019 https://github.com/wentout
|