epos-unit 1.17.0 → 1.19.0
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/dist/epos-unit.d.ts +25 -30
- package/dist/epos-unit.js +293 -219
- package/dist/epos-unit.js.map +1 -1
- package/package.json +7 -7
- package/src/epos-unit.ts +114 -87
package/dist/epos-unit.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
declare const
|
|
6
|
-
declare const
|
|
7
|
-
declare const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
declare class Unit<TRoot = unknown> {
|
|
1
|
+
import { createLog, type Arr, type Cls, type Obj } from 'dropcap/utils';
|
|
2
|
+
export declare const _root_: unique symbol;
|
|
3
|
+
export declare const _parent_: unique symbol;
|
|
4
|
+
export declare const _attached_: unique symbol;
|
|
5
|
+
export declare const _disposers_: unique symbol;
|
|
6
|
+
export declare const _ancestors_: unique symbol;
|
|
7
|
+
export declare const _attachQueue_: unique symbol;
|
|
8
|
+
export type Node<T> = Unit<T> | Obj | Arr;
|
|
9
|
+
export type Versioner<T> = {
|
|
10
|
+
[version: number]: (this: T) => void;
|
|
11
|
+
};
|
|
12
|
+
export declare class Unit<TRoot = unknown> {
|
|
13
13
|
/**
|
|
14
14
|
* Lifecycle method called when the unit is attached to the state tree.
|
|
15
15
|
*/
|
|
@@ -27,42 +27,37 @@ declare class Unit<TRoot = unknown> {
|
|
|
27
27
|
[_attached_]?: boolean;
|
|
28
28
|
[_disposers_]?: Set<() => void>;
|
|
29
29
|
[_ancestors_]?: Map<Cls, unknown>;
|
|
30
|
-
[
|
|
30
|
+
[_attachQueue_]?: (() => void)[];
|
|
31
|
+
static defineVersioner<T extends Unit>(this: Cls<T>, versioner: Versioner<T>): Versioner<T>;
|
|
31
32
|
constructor(parent: Unit<TRoot> | null);
|
|
32
33
|
/**
|
|
33
|
-
*
|
|
34
|
+
* Get the root unit of the current unit's tree.
|
|
34
35
|
* The result is cached for subsequent calls.
|
|
35
36
|
*/
|
|
36
37
|
get $(): TRoot | (undefined & TRoot);
|
|
37
38
|
/**
|
|
38
|
-
* A wrapper around MobX's `autorun` that automatically disposes
|
|
39
|
-
* the reaction when the unit is detached.
|
|
39
|
+
* A wrapper around MobX's `autorun` that automatically disposes the reaction when the unit is detached.
|
|
40
40
|
*/
|
|
41
|
-
autorun(...args: Parameters<typeof epos.libs.mobx.autorun>): mobx.IReactionDisposer;
|
|
41
|
+
autorun(...args: Parameters<typeof epos.libs.mobx.autorun>): import("mobx").IReactionDisposer;
|
|
42
42
|
/**
|
|
43
|
-
* A wrapper around MobX's `reaction` that automatically disposes
|
|
44
|
-
* the reaction when the unit is detached.
|
|
43
|
+
* A wrapper around MobX's `reaction` that automatically disposes the reaction when the unit is detached.
|
|
45
44
|
*/
|
|
46
|
-
reaction(...args: Parameters<typeof epos.libs.mobx.reaction>): mobx.IReactionDisposer;
|
|
45
|
+
reaction(...args: Parameters<typeof epos.libs.mobx.reaction>): import("mobx").IReactionDisposer;
|
|
47
46
|
/**
|
|
48
|
-
* A wrapper around `setTimeout` that automatically clears the timeout
|
|
49
|
-
* when the unit is detached.
|
|
47
|
+
* A wrapper around `setTimeout` that automatically clears the timeout when the unit is detached.
|
|
50
48
|
*/
|
|
51
|
-
setTimeout(...args: Parameters<typeof
|
|
49
|
+
setTimeout(...args: Parameters<typeof setTimeout>): NodeJS.Timeout;
|
|
52
50
|
/**
|
|
53
|
-
* A wrapper around `setInterval` that automatically clears the interval
|
|
54
|
-
* when the unit is detached.
|
|
51
|
+
* A wrapper around `setInterval` that automatically clears the interval when the unit is detached.
|
|
55
52
|
*/
|
|
56
|
-
setInterval(...args: Parameters<typeof
|
|
53
|
+
setInterval(...args: Parameters<typeof setInterval>): NodeJS.Timeout;
|
|
57
54
|
/**
|
|
58
|
-
*
|
|
55
|
+
* Create an error for code paths that are logically unreachable.
|
|
59
56
|
*/
|
|
60
57
|
never(message?: string): Error;
|
|
61
58
|
/**
|
|
62
|
-
*
|
|
59
|
+
* Find the closest ancestor unit of a given type.
|
|
63
60
|
* The result is cached for subsequent calls.
|
|
64
61
|
*/
|
|
65
62
|
closest<T extends Unit>(Ancestor: Cls<T>): T | null;
|
|
66
63
|
}
|
|
67
|
-
|
|
68
|
-
export { type Node, Unit, _ancestors_, _attached_, _disposers_, _parent_, _pendingAttachHooks_, _root_ };
|
package/dist/epos-unit.js
CHANGED
|
@@ -1,239 +1,313 @@
|
|
|
1
|
-
|
|
2
|
-
import { createLog, is } from
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (versions.length > 0) this[":version"] = versions.at(-1);
|
|
19
|
-
}
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
|
-
// ATTACH / DETACH
|
|
22
|
-
// ---------------------------------------------------------------------------
|
|
23
|
-
/**
|
|
24
|
-
* Lifecycle method called when the unit is attached to the state tree.
|
|
25
|
-
*/
|
|
26
|
-
[epos.state.ATTACH]() {
|
|
27
|
-
epos.state.transaction(() => {
|
|
28
|
-
const versioner = getVersioner(this);
|
|
29
|
-
const versions = getVersions(versioner);
|
|
30
|
-
for (const version of versions) {
|
|
31
|
-
if (is.number(this[":version"]) && this[":version"] >= version) continue;
|
|
32
|
-
const versionFn = versioner[version];
|
|
33
|
-
if (!is.function(versionFn)) continue;
|
|
34
|
-
versionFn.call(this, this);
|
|
35
|
-
this[":version"] = version;
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
let log = createLog(this["@"]);
|
|
39
|
-
Reflect.defineProperty(this, "log", {
|
|
40
|
-
configurable: true,
|
|
41
|
-
get: () => log,
|
|
42
|
-
set: (v) => log = v
|
|
43
|
-
});
|
|
44
|
-
const stateDescriptor = Reflect.getOwnPropertyDescriptor(this.constructor.prototype, "state");
|
|
45
|
-
if (stateDescriptor && stateDescriptor.get) {
|
|
46
|
-
const value = stateDescriptor.get.call(this);
|
|
47
|
-
const state = epos.state.local(value, { deep: false });
|
|
48
|
-
Reflect.defineProperty(this, "state", { get: () => state });
|
|
1
|
+
/// <reference types="epos" />
|
|
2
|
+
import { createLog, is } from 'dropcap/utils';
|
|
3
|
+
import { customAlphabet } from 'nanoid';
|
|
4
|
+
export const _root_ = Symbol('root');
|
|
5
|
+
export const _parent_ = Symbol('parent');
|
|
6
|
+
export const _attached_ = Symbol('attached');
|
|
7
|
+
export const _disposers_ = Symbol('disposers');
|
|
8
|
+
export const _ancestors_ = Symbol('ancestors');
|
|
9
|
+
export const _attachQueue_ = Symbol('pendingAttachHooks');
|
|
10
|
+
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz0123456789', 10);
|
|
11
|
+
export class Unit {
|
|
12
|
+
static defineVersioner(versioner) {
|
|
13
|
+
return versioner;
|
|
14
|
+
}
|
|
15
|
+
constructor(parent) {
|
|
16
|
+
this.id = nanoid();
|
|
17
|
+
this[_parent_] = parent;
|
|
49
18
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// ATTACH
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
/**
|
|
23
|
+
* Lifecycle method called when the unit is attached to the state tree.
|
|
24
|
+
*/
|
|
25
|
+
[epos.state.ATTACH]() {
|
|
26
|
+
// Setup logger
|
|
27
|
+
let log = createLog(this['@']);
|
|
28
|
+
Reflect.defineProperty(this, 'log', { configurable: true, get: () => log, set: v => (log = v) });
|
|
29
|
+
// Apply versioner
|
|
30
|
+
void (() => {
|
|
31
|
+
const versioner = Reflect.get(this.constructor, 'versioner');
|
|
32
|
+
if (!is.object(versioner))
|
|
33
|
+
return;
|
|
34
|
+
const asc = (v1, v2) => v1 - v2;
|
|
35
|
+
const versions = Object.keys(versioner).filter(is.numeric).map(Number).sort(asc);
|
|
36
|
+
if (versions.length === 0)
|
|
37
|
+
return;
|
|
38
|
+
epos.state.transaction(() => {
|
|
39
|
+
for (const version of versions) {
|
|
40
|
+
if (is.number(this[':version']) && this[':version'] >= version)
|
|
41
|
+
continue;
|
|
42
|
+
const versionFn = versioner[version];
|
|
43
|
+
if (!is.function(versionFn))
|
|
44
|
+
continue;
|
|
45
|
+
versionFn.call(this);
|
|
46
|
+
this[':version'] = version;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
})();
|
|
50
|
+
// Setup state
|
|
51
|
+
void (() => {
|
|
52
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(this.constructor.prototype, 'state');
|
|
53
|
+
if (!descriptor || !descriptor.get)
|
|
54
|
+
return;
|
|
55
|
+
const value = descriptor.get.call(this);
|
|
56
|
+
if (!is.object(value))
|
|
57
|
+
throw new Error(`'state' getter return an object`);
|
|
58
|
+
const state = epos.state.create(value);
|
|
59
|
+
Reflect.defineProperty(state, epos.state.PARENT, { configurable: true, value: this });
|
|
60
|
+
Reflect.defineProperty(this, 'state', { enumerable: true, get: () => state });
|
|
61
|
+
})();
|
|
62
|
+
// Setup inert
|
|
63
|
+
void (() => {
|
|
64
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(this.constructor.prototype, 'inert');
|
|
65
|
+
if (!descriptor || !descriptor.get)
|
|
66
|
+
return;
|
|
67
|
+
const value = descriptor.get.call(this);
|
|
68
|
+
if (!is.object(value))
|
|
69
|
+
throw new Error(`'inert' getter return an object`);
|
|
70
|
+
Reflect.defineProperty(this, 'inert', { enumerable: true, get: () => value });
|
|
71
|
+
})();
|
|
72
|
+
// Prepare properties for the whole prototype chain:
|
|
73
|
+
// - Create components for methods ending with `View`
|
|
74
|
+
// - Bind all other methods to the unit instance
|
|
75
|
+
// - Turn getters into MobX computed properties
|
|
76
|
+
for (const prototype of getPrototypes(this)) {
|
|
77
|
+
const descriptors = Object.getOwnPropertyDescriptors(prototype);
|
|
78
|
+
for (const [key, descriptor] of Object.entries(descriptors)) {
|
|
79
|
+
// Skip constructor and already defined properties
|
|
80
|
+
if (key === 'constructor')
|
|
81
|
+
continue;
|
|
82
|
+
if (this.hasOwnProperty(key))
|
|
83
|
+
continue;
|
|
84
|
+
// Create components for methods ending with `View`
|
|
85
|
+
if (is.function(descriptor.value) && key.endsWith('View')) {
|
|
86
|
+
let View = createView(this, key, descriptor.value.bind(this));
|
|
87
|
+
Reflect.defineProperty(this, key, { configurable: true, get: () => View, set: v => (View = v) });
|
|
88
|
+
}
|
|
89
|
+
// Bind all other methods to the unit instance
|
|
90
|
+
else if (is.function(descriptor.value)) {
|
|
91
|
+
let method = descriptor.value.bind(this);
|
|
92
|
+
Reflect.defineProperty(this, key, {
|
|
93
|
+
configurable: true,
|
|
94
|
+
get: () => method,
|
|
95
|
+
set: v => (method = v),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
// Turn getters into MobX computed properties
|
|
99
|
+
else if (descriptor.get) {
|
|
100
|
+
const getter = descriptor.get;
|
|
101
|
+
const computed = epos.libs.mobx.computed(() => getter.call(this));
|
|
102
|
+
Reflect.defineProperty(this, key, {
|
|
103
|
+
configurable: true,
|
|
104
|
+
get: () => computed.get(),
|
|
105
|
+
set: descriptor.set,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
78
109
|
}
|
|
79
|
-
|
|
110
|
+
// Queue attach method.
|
|
111
|
+
// Do not execute `attach` methods immediately, but rather queue them on the highest unattached ancestor.
|
|
112
|
+
// This way `attach` methods are called after all versioners have been applied in the entire subtree.
|
|
113
|
+
const attach = Reflect.get(this, 'attach');
|
|
114
|
+
if (is.function(attach)) {
|
|
115
|
+
const head = findUnattachedRoot(this);
|
|
116
|
+
if (!head)
|
|
117
|
+
throw this.never();
|
|
118
|
+
ensure(head, _attachQueue_, () => []);
|
|
119
|
+
head[_attachQueue_].push(() => attach.call(this));
|
|
120
|
+
}
|
|
121
|
+
// Release attach queue
|
|
122
|
+
if (this[_attachQueue_]) {
|
|
123
|
+
this[_attachQueue_].forEach(attach => attach());
|
|
124
|
+
delete this[_attachQueue_];
|
|
125
|
+
}
|
|
126
|
+
// Mark as attached
|
|
127
|
+
Reflect.defineProperty(this, _attached_, { configurable: true, get: () => true });
|
|
80
128
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
129
|
+
// ---------------------------------------------------------------------------
|
|
130
|
+
// DETACH
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
/**
|
|
133
|
+
* Lifecycle method called when the unit is detached from the state tree.
|
|
134
|
+
*/
|
|
135
|
+
[epos.state.DETACH]() {
|
|
136
|
+
// Run and clear disposers
|
|
137
|
+
if (this[_disposers_]) {
|
|
138
|
+
this[_disposers_].forEach(disposer => disposer());
|
|
139
|
+
this[_disposers_].clear();
|
|
140
|
+
}
|
|
141
|
+
// Clear ancestors cache
|
|
142
|
+
if (this[_ancestors_]) {
|
|
143
|
+
this[_ancestors_].clear();
|
|
144
|
+
}
|
|
145
|
+
// Call detach method
|
|
146
|
+
const detach = Reflect.get(this, 'detach');
|
|
147
|
+
if (is.function(detach))
|
|
148
|
+
detach();
|
|
87
149
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
// ROOT GETTER
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
/**
|
|
154
|
+
* Get the root unit of the current unit's tree.
|
|
155
|
+
* The result is cached for subsequent calls.
|
|
156
|
+
*/
|
|
157
|
+
get $() {
|
|
158
|
+
ensure(this, _root_, () => findRoot(this));
|
|
159
|
+
return this[_root_];
|
|
91
160
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
161
|
+
// ---------------------------------------------------------------------------
|
|
162
|
+
// METHODS
|
|
163
|
+
// ---------------------------------------------------------------------------
|
|
164
|
+
/**
|
|
165
|
+
* A wrapper around MobX's `autorun` that automatically disposes the reaction when the unit is detached.
|
|
166
|
+
*/
|
|
167
|
+
autorun(...args) {
|
|
168
|
+
const disposer = epos.libs.mobx.autorun(...args);
|
|
169
|
+
ensure(this, _disposers_, () => new Set());
|
|
170
|
+
this[_disposers_].add(disposer);
|
|
171
|
+
return disposer;
|
|
101
172
|
}
|
|
102
|
-
|
|
103
|
-
|
|
173
|
+
/**
|
|
174
|
+
* A wrapper around MobX's `reaction` that automatically disposes the reaction when the unit is detached.
|
|
175
|
+
*/
|
|
176
|
+
reaction(...args) {
|
|
177
|
+
const disposer = epos.libs.mobx.reaction(...args);
|
|
178
|
+
ensure(this, _disposers_, () => new Set());
|
|
179
|
+
this[_disposers_].add(disposer);
|
|
180
|
+
return disposer;
|
|
104
181
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* A wrapper around MobX's `autorun` that automatically disposes
|
|
124
|
-
* the reaction when the unit is detached.
|
|
125
|
-
*/
|
|
126
|
-
autorun(...args) {
|
|
127
|
-
const disposer = epos.libs.mobx.autorun(...args);
|
|
128
|
-
ensure(this, _disposers_, () => /* @__PURE__ */ new Set());
|
|
129
|
-
this[_disposers_].add(disposer);
|
|
130
|
-
return disposer;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* A wrapper around MobX's `reaction` that automatically disposes
|
|
134
|
-
* the reaction when the unit is detached.
|
|
135
|
-
*/
|
|
136
|
-
reaction(...args) {
|
|
137
|
-
const disposer = epos.libs.mobx.reaction(...args);
|
|
138
|
-
ensure(this, _disposers_, () => /* @__PURE__ */ new Set());
|
|
139
|
-
this[_disposers_].add(disposer);
|
|
140
|
-
return disposer;
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* A wrapper around `setTimeout` that automatically clears the timeout
|
|
144
|
-
* when the unit is detached.
|
|
145
|
-
*/
|
|
146
|
-
setTimeout(...args) {
|
|
147
|
-
const id = self.setTimeout(...args);
|
|
148
|
-
ensure(this, _disposers_, () => /* @__PURE__ */ new Set());
|
|
149
|
-
this[_disposers_].add(() => self.clearTimeout(id));
|
|
150
|
-
return id;
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* A wrapper around `setInterval` that automatically clears the interval
|
|
154
|
-
* when the unit is detached.
|
|
155
|
-
*/
|
|
156
|
-
setInterval(...args) {
|
|
157
|
-
const id = self.setInterval(...args);
|
|
158
|
-
ensure(this, _disposers_, () => /* @__PURE__ */ new Set());
|
|
159
|
-
this[_disposers_].add(() => self.clearInterval(id));
|
|
160
|
-
return id;
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Creates an error for an unreachable code path.
|
|
164
|
-
*/
|
|
165
|
-
never(message = "This should never happen") {
|
|
166
|
-
const details = message ? `: ${message}` : "";
|
|
167
|
-
const error = new Error(`[${this.constructor.name}] This should never happen${details}`);
|
|
168
|
-
Error.captureStackTrace(error, this.never);
|
|
169
|
-
return error;
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Finds the closest ancestor unit of a given type.
|
|
173
|
-
* The result is cached for subsequent calls.
|
|
174
|
-
*/
|
|
175
|
-
closest(Ancestor) {
|
|
176
|
-
ensure(this, _ancestors_, () => /* @__PURE__ */ new Map());
|
|
177
|
-
if (this[_ancestors_].has(Ancestor)) return this[_ancestors_].get(Ancestor);
|
|
178
|
-
let cursor = this;
|
|
179
|
-
while (cursor) {
|
|
180
|
-
if (cursor instanceof Ancestor) {
|
|
181
|
-
this[_ancestors_].set(Ancestor, cursor);
|
|
182
|
-
return cursor;
|
|
183
|
-
}
|
|
184
|
-
cursor = getParent(cursor);
|
|
182
|
+
/**
|
|
183
|
+
* A wrapper around `setTimeout` that automatically clears the timeout when the unit is detached.
|
|
184
|
+
*/
|
|
185
|
+
setTimeout(...args) {
|
|
186
|
+
const id = setTimeout(...args);
|
|
187
|
+
ensure(this, _disposers_, () => new Set());
|
|
188
|
+
this[_disposers_].add(() => clearTimeout(id));
|
|
189
|
+
return id;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* A wrapper around `setInterval` that automatically clears the interval when the unit is detached.
|
|
193
|
+
*/
|
|
194
|
+
setInterval(...args) {
|
|
195
|
+
const id = setInterval(...args);
|
|
196
|
+
ensure(this, _disposers_, () => new Set());
|
|
197
|
+
this[_disposers_].add(() => clearInterval(id));
|
|
198
|
+
return id;
|
|
185
199
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
200
|
+
/**
|
|
201
|
+
* Create an error for code paths that are logically unreachable.
|
|
202
|
+
*/
|
|
203
|
+
never(message = 'This should never happen') {
|
|
204
|
+
const details = message ? `: ${message}` : '';
|
|
205
|
+
const error = new Error(`[${this['@']}] This should never happen${details}`);
|
|
206
|
+
Error.captureStackTrace(error, this.never);
|
|
207
|
+
return error;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Find the closest ancestor unit of a given type.
|
|
211
|
+
* The result is cached for subsequent calls.
|
|
212
|
+
*/
|
|
213
|
+
closest(Ancestor) {
|
|
214
|
+
// Has cached value? -> Return it
|
|
215
|
+
ensure(this, _ancestors_, () => new Map());
|
|
216
|
+
if (this[_ancestors_].has(Ancestor))
|
|
217
|
+
return this[_ancestors_].get(Ancestor);
|
|
218
|
+
// Find the closest ancestor and cache it
|
|
219
|
+
let cursor = this;
|
|
220
|
+
while (cursor) {
|
|
221
|
+
if (cursor instanceof Ancestor) {
|
|
222
|
+
this[_ancestors_].set(Ancestor, cursor);
|
|
223
|
+
return cursor;
|
|
224
|
+
}
|
|
225
|
+
cursor = getParent(cursor);
|
|
226
|
+
}
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// ---------------------------------------------------------------------------
|
|
231
|
+
// HELPERS
|
|
232
|
+
// ---------------------------------------------------------------------------
|
|
233
|
+
/**
|
|
234
|
+
* Ensure a property exists on an object, initialize it if it doesn't.
|
|
235
|
+
*/
|
|
189
236
|
function ensure(object, key, getInitialValue) {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
237
|
+
if (key in object)
|
|
238
|
+
return;
|
|
239
|
+
const value = getInitialValue();
|
|
240
|
+
Reflect.defineProperty(object, key, { configurable: true, get: () => value });
|
|
193
241
|
}
|
|
242
|
+
/**
|
|
243
|
+
* Get all prototypes of an object up to `Object.prototype`.
|
|
244
|
+
*/
|
|
194
245
|
function getPrototypes(object) {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
246
|
+
const prototype = Reflect.getPrototypeOf(object);
|
|
247
|
+
if (!prototype || prototype === Object.prototype)
|
|
248
|
+
return [];
|
|
249
|
+
return [prototype, ...getPrototypes(prototype)];
|
|
198
250
|
}
|
|
251
|
+
/**
|
|
252
|
+
* Find the root `Unit` in the hierarchy for a given unit.
|
|
253
|
+
*/
|
|
199
254
|
function findRoot(unit) {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
255
|
+
let root = null;
|
|
256
|
+
let cursor = unit;
|
|
257
|
+
while (cursor) {
|
|
258
|
+
if (cursor instanceof Unit)
|
|
259
|
+
root = cursor;
|
|
260
|
+
cursor = getParent(cursor);
|
|
261
|
+
}
|
|
262
|
+
return root;
|
|
207
263
|
}
|
|
264
|
+
/**
|
|
265
|
+
* Find the highest unattached `Unit` in the hierarchy for a given unit.
|
|
266
|
+
*/
|
|
208
267
|
function findUnattachedRoot(unit) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
268
|
+
let unattachedRoot = null;
|
|
269
|
+
let cursor = unit;
|
|
270
|
+
while (cursor) {
|
|
271
|
+
if (cursor instanceof Unit && !cursor[_attached_])
|
|
272
|
+
unattachedRoot = cursor;
|
|
273
|
+
cursor = getParent(cursor);
|
|
274
|
+
}
|
|
275
|
+
return unattachedRoot;
|
|
216
276
|
}
|
|
277
|
+
/**
|
|
278
|
+
* Get the parent of a node, which can be a `Unit`, an object, or an array.
|
|
279
|
+
*/
|
|
217
280
|
function getParent(node) {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
}
|
|
221
|
-
function getVersioner(unit) {
|
|
222
|
-
const versioner = Reflect.get(unit.constructor, "versioner");
|
|
223
|
-
if (!is.object(versioner)) return {};
|
|
224
|
-
return versioner;
|
|
281
|
+
const parent = Reflect.get(node, _parent_) ?? Reflect.get(node, epos.state.PARENT) ?? null;
|
|
282
|
+
return parent;
|
|
225
283
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
284
|
+
/**
|
|
285
|
+
* Create view component for the unit.
|
|
286
|
+
*/
|
|
287
|
+
function createView(unit, name, render) {
|
|
288
|
+
const fullName = `${unit['@']}.${name}`;
|
|
289
|
+
const View = epos.component((props) => {
|
|
290
|
+
try {
|
|
291
|
+
return render(props);
|
|
292
|
+
}
|
|
293
|
+
catch (error) {
|
|
294
|
+
unit.log.error(error);
|
|
295
|
+
const message = is.error(error) ? error.message : String(error);
|
|
296
|
+
return epos.libs.reactJsxRuntime.jsx('div', {
|
|
297
|
+
children: `[${fullName}] ${message}`,
|
|
298
|
+
style: {
|
|
299
|
+
width: 'fit-content',
|
|
300
|
+
padding: '4px 6px 4px 4px',
|
|
301
|
+
color: '#f00',
|
|
302
|
+
border: '1px solid #f00',
|
|
303
|
+
background: 'rgba(255, 0, 0, 0.1)',
|
|
304
|
+
fontSize: 12,
|
|
305
|
+
fontWeight: 400,
|
|
306
|
+
},
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
View.displayName = fullName;
|
|
311
|
+
return View;
|
|
229
312
|
}
|
|
230
|
-
export {
|
|
231
|
-
Unit,
|
|
232
|
-
_ancestors_,
|
|
233
|
-
_attached_,
|
|
234
|
-
_disposers_,
|
|
235
|
-
_parent_,
|
|
236
|
-
_pendingAttachHooks_,
|
|
237
|
-
_root_
|
|
238
|
-
};
|
|
239
313
|
//# sourceMappingURL=epos-unit.js.map
|
package/dist/epos-unit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/epos-unit.ts"],"sourcesContent":["import type { Arr, Cls, Obj } from 'dropcap/types'\nimport { createLog, is } from 'dropcap/utils'\nimport 'epos'\nimport { customAlphabet } from 'nanoid'\n\nexport const _root_ = Symbol('root')\nexport const _parent_ = Symbol('parent')\nexport const _attached_ = Symbol('attached')\nexport const _disposers_ = Symbol('disposers')\nexport const _ancestors_ = Symbol('ancestors')\nexport const _pendingAttachHooks_ = Symbol('pendingAttachHooks')\nconst nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 8)\n\nexport type Node<T> = Unit<T> | Obj | Arr\n\nexport class Unit<TRoot = unknown> {\n declare '@': string\n declare id: string\n declare log: ReturnType<typeof createLog>;\n declare [':version']?: number;\n declare [_root_]?: TRoot;\n declare [_parent_]?: Unit<TRoot> | null; // Parent reference for a not-yet-attached units\n declare [_attached_]?: boolean;\n declare [_disposers_]?: Set<() => void>;\n declare [_ancestors_]?: Map<Cls, unknown>;\n declare [_pendingAttachHooks_]?: (() => void)[]\n\n constructor(parent: Unit<TRoot> | null) {\n this.id = nanoid()\n this[_parent_] = parent\n const versioner = getVersioner(this)\n const versions = getVersions(versioner)\n if (versions.length > 0) this[':version'] = versions.at(-1)!\n }\n\n // ---------------------------------------------------------------------------\n // ATTACH / DETACH\n // ---------------------------------------------------------------------------\n\n /**\n * Lifecycle method called when the unit is attached to the state tree.\n */\n [epos.state.ATTACH]() {\n // Apply versioner\n epos.state.transaction(() => {\n const versioner = getVersioner(this)\n const versions = getVersions(versioner)\n for (const version of versions) {\n if (is.number(this[':version']) && this[':version'] >= version) continue\n const versionFn = versioner[version]\n if (!is.function(versionFn)) continue\n versionFn.call(this, this)\n this[':version'] = version\n }\n })\n\n // Setup logger\n let log = createLog(this['@'])\n Reflect.defineProperty(this, 'log', {\n configurable: true,\n get: () => log,\n set: v => (log = v),\n })\n\n // Setup state\n const stateDescriptor = Reflect.getOwnPropertyDescriptor(this.constructor.prototype, 'state')\n if (stateDescriptor && stateDescriptor.get) {\n const value = stateDescriptor.get.call(this)\n const state = epos.state.local(value, { deep: false })\n Reflect.defineProperty(this, 'state', { get: () => state })\n }\n\n // Prepare properties for the whole prototype chain:\n // - Create components for methods ending with `View`\n // - Bind all other methods to the unit instance\n // - Turn getters into MobX computed properties\n for (const prototype of getPrototypes(this)) {\n const descriptors = Object.getOwnPropertyDescriptors(prototype)\n for (const [key, descriptor] of Object.entries(descriptors)) {\n // Skip constructor and already defined properties\n if (key === 'constructor') continue\n if (this.hasOwnProperty(key)) continue\n\n // Create components for methods ending with `View`\n if (is.function(descriptor.value) && key.endsWith('View')) {\n let Component = epos.component(descriptor.value.bind(this))\n Component.displayName = `${this.constructor.name}.${key}`\n Reflect.defineProperty(this, key, {\n configurable: true,\n get: () => Component,\n set: v => (Component = v),\n })\n }\n\n // Bind all other methods to the unit instance\n else if (is.function(descriptor.value)) {\n let method = descriptor.value.bind(this)\n Reflect.defineProperty(this, key, {\n configurable: true,\n get: () => method,\n set: v => (method = v),\n })\n }\n\n // Turn getters into MobX computed properties\n else if (descriptor.get) {\n const getter = descriptor.get\n const computed = epos.libs.mobx.computed(() => getter.call(this))\n Reflect.defineProperty(this, key, {\n configurable: true,\n get: () => computed.get(),\n set: descriptor.set,\n })\n }\n }\n }\n\n // Queue attach hook.\n // Do not execute `attach` hooks immediately, but rather queue them on the highest unattached ancestor.\n // This way `attach` hooks are called after all versioners have been applied in the entire subtree.\n const attach = Reflect.get(this, 'attach')\n if (is.function(attach)) {\n const unattachedRoot = findUnattachedRoot(this)\n if (!unattachedRoot) throw this.never()\n ensure(unattachedRoot, _pendingAttachHooks_, () => [])\n unattachedRoot[_pendingAttachHooks_].push(() => attach())\n }\n\n // Release attach hooks\n if (this[_pendingAttachHooks_]) {\n this[_pendingAttachHooks_].forEach(attach => attach())\n delete this[_pendingAttachHooks_]\n }\n\n // Mark as attached\n Reflect.defineProperty(this, _attached_, { configurable: true, get: () => true })\n }\n\n /**\n * Lifecycle method called when the unit is detached from the state tree.\n */\n [epos.state.DETACH]() {\n // Run and clear disposers\n if (this[_disposers_]) {\n this[_disposers_].forEach(disposer => disposer())\n this[_disposers_].clear()\n }\n\n // Clear ancestors cache\n if (this[_ancestors_]) {\n this[_ancestors_].clear()\n }\n\n // Call detach method\n const detach = Reflect.get(this, 'detach')\n if (is.function(detach)) detach()\n }\n\n // ---------------------------------------------------------------------------\n // ROOT GETTER\n // ---------------------------------------------------------------------------\n\n /**\n * Gets the root unit of the current unit's tree.\n * The result is cached for subsequent calls.\n */\n get $() {\n ensure(this, _root_, () => findRoot(this))\n return this[_root_]\n }\n\n // ---------------------------------------------------------------------------\n // METHODS\n // ---------------------------------------------------------------------------\n\n /**\n * A wrapper around MobX's `autorun` that automatically disposes\n * the reaction when the unit is detached.\n */\n autorun(...args: Parameters<typeof epos.libs.mobx.autorun>) {\n const disposer = epos.libs.mobx.autorun(...args)\n ensure(this, _disposers_, () => new Set())\n this[_disposers_].add(disposer)\n return disposer\n }\n\n /**\n * A wrapper around MobX's `reaction` that automatically disposes\n * the reaction when the unit is detached.\n */\n reaction(...args: Parameters<typeof epos.libs.mobx.reaction>) {\n const disposer = epos.libs.mobx.reaction(...args)\n ensure(this, _disposers_, () => new Set())\n this[_disposers_].add(disposer)\n return disposer\n }\n\n /**\n * A wrapper around `setTimeout` that automatically clears the timeout\n * when the unit is detached.\n */\n setTimeout(...args: Parameters<typeof self.setTimeout>) {\n const id = self.setTimeout(...args)\n ensure(this, _disposers_, () => new Set())\n this[_disposers_].add(() => self.clearTimeout(id))\n return id\n }\n\n /**\n * A wrapper around `setInterval` that automatically clears the interval\n * when the unit is detached.\n */\n setInterval(...args: Parameters<typeof self.setInterval>) {\n const id = self.setInterval(...args)\n ensure(this, _disposers_, () => new Set())\n this[_disposers_].add(() => self.clearInterval(id))\n return id\n }\n\n /**\n * Creates an error for an unreachable code path.\n */\n never(message = 'This should never happen') {\n const details = message ? `: ${message}` : ''\n const error = new Error(`[${this.constructor.name}] This should never happen${details}`)\n Error.captureStackTrace(error, this.never)\n return error\n }\n\n /**\n * Finds the closest ancestor unit of a given type.\n * The result is cached for subsequent calls.\n */\n closest<T extends Unit>(Ancestor: Cls<T>) {\n // Has cached value? -> Return it\n ensure(this, _ancestors_, () => new Map())\n if (this[_ancestors_].has(Ancestor)) return this[_ancestors_].get(Ancestor) as T\n\n // Find the closest ancestor and cache it\n let cursor: Node<TRoot> | null = this\n while (cursor) {\n if (cursor instanceof Ancestor) {\n this[_ancestors_].set(Ancestor, cursor)\n return cursor\n }\n cursor = getParent(cursor)\n }\n\n return null\n }\n}\n\n// ---------------------------------------------------------------------------\n// HELPERS\n// ---------------------------------------------------------------------------\n\n/**\n * Ensures a property exists on an object, initializing it if it doesn't.\n */\nfunction ensure<T extends object, K extends PropertyKey, V>(\n object: T,\n key: K,\n getInitialValue: () => V,\n): asserts object is T & { [key in K]: V } {\n if (key in object) return\n const value = getInitialValue()\n Reflect.defineProperty(object, key, { configurable: true, get: () => value })\n}\n\n/**\n * Gets all prototypes of an object up to `Object.prototype`.\n */\nfunction getPrototypes(object: object): object[] {\n const prototype = Reflect.getPrototypeOf(object)\n if (!prototype || prototype === Object.prototype) return []\n return [prototype, ...getPrototypes(prototype)]\n}\n\n/**\n * Finds the root `Unit` in the hierarchy for a given unit.\n */\nfunction findRoot<T>(unit: Unit<T>) {\n let root: Unit<T> | null = null\n let cursor: Node<T> | null = unit\n\n while (cursor) {\n if (cursor instanceof Unit) root = cursor\n cursor = getParent(cursor)\n }\n\n return root as T\n}\n\n/**\n * Finds the highest unattached `Unit` in the hierarchy for a given unit.\n */\nfunction findUnattachedRoot<T>(unit: Unit<T>) {\n let unattachedRoot: Unit<T> | null = null\n let cursor: Node<T> | null = unit\n\n while (cursor) {\n if (cursor instanceof Unit && !cursor[_attached_]) unattachedRoot = cursor\n cursor = getParent(cursor)\n }\n\n return unattachedRoot\n}\n\n/**\n * Gets the parent of a node, which can be a `Unit`, an object, or an array.\n */\nfunction getParent<T>(node: Node<T>) {\n const parent: Node<T> | null = Reflect.get(node, _parent_) ?? Reflect.get(node, epos.state.PARENT) ?? null\n return parent\n}\n\n/**\n * Gets the versioner object from a unit's constructor.\n */\nfunction getVersioner<T>(unit: Unit<T>) {\n const versioner: unknown = Reflect.get(unit.constructor, 'versioner')\n if (!is.object(versioner)) return {}\n return versioner\n}\n\n/**\n * Gets a sorted list of numeric version keys from a unit's versioner.\n */\nfunction getVersions(versioner: Obj) {\n const numericKeys = Object.keys(versioner).filter(key => is.numeric(key))\n return numericKeys.map(Number).sort((v1, v2) => v1 - v2)\n}\n"],"mappings":"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","names":["attach"]}
|
|
1
|
+
{"version":3,"file":"epos-unit.js","sourceRoot":"","sources":["../src/epos-unit.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "epos-unit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "imkost",
|
|
7
7
|
"description": "",
|
|
8
8
|
"keywords": [],
|
|
9
9
|
"scripts": {
|
|
10
|
-
"dev": "
|
|
11
|
-
"build": "
|
|
12
|
-
"lint": "
|
|
10
|
+
"dev": "rimraf dist && tsgo --watch",
|
|
11
|
+
"build": "rimraf dist && tsgo",
|
|
12
|
+
"lint": "tsgo --noEmit",
|
|
13
13
|
"release": "sh -c 'npm version ${1:-minor} && npm run build && npm publish' --"
|
|
14
14
|
},
|
|
15
15
|
"exports": {
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"src"
|
|
21
21
|
],
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"dropcap": "^1.
|
|
24
|
-
"epos": "^1.
|
|
25
|
-
"nanoid": "^
|
|
23
|
+
"dropcap": "^1.9.0",
|
|
24
|
+
"epos": "^1.38.0",
|
|
25
|
+
"nanoid": "^5.1.6"
|
|
26
26
|
}
|
|
27
27
|
}
|
package/src/epos-unit.ts
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
import { createLog, is } from 'dropcap/utils'
|
|
3
|
-
import 'epos'
|
|
1
|
+
/// <reference types="epos" />
|
|
2
|
+
import { createLog, is, type Arr, type Cls, type Obj } from 'dropcap/utils'
|
|
4
3
|
import { customAlphabet } from 'nanoid'
|
|
4
|
+
import type { FC } from 'react'
|
|
5
5
|
|
|
6
6
|
export const _root_ = Symbol('root')
|
|
7
7
|
export const _parent_ = Symbol('parent')
|
|
8
8
|
export const _attached_ = Symbol('attached')
|
|
9
9
|
export const _disposers_ = Symbol('disposers')
|
|
10
10
|
export const _ancestors_ = Symbol('ancestors')
|
|
11
|
-
export const
|
|
12
|
-
const nanoid = customAlphabet('
|
|
11
|
+
export const _attachQueue_ = Symbol('pendingAttachHooks')
|
|
12
|
+
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz0123456789', 10)
|
|
13
13
|
|
|
14
14
|
export type Node<T> = Unit<T> | Obj | Arr
|
|
15
|
+
export type Versioner<T> = { [version: number]: (this: T) => void }
|
|
15
16
|
|
|
16
17
|
export class Unit<TRoot = unknown> {
|
|
17
18
|
declare '@': string
|
|
@@ -23,52 +24,68 @@ export class Unit<TRoot = unknown> {
|
|
|
23
24
|
declare [_attached_]?: boolean;
|
|
24
25
|
declare [_disposers_]?: Set<() => void>;
|
|
25
26
|
declare [_ancestors_]?: Map<Cls, unknown>;
|
|
26
|
-
declare [
|
|
27
|
+
declare [_attachQueue_]?: (() => void)[]
|
|
28
|
+
|
|
29
|
+
static defineVersioner<T extends Unit>(this: Cls<T>, versioner: Versioner<T>) {
|
|
30
|
+
return versioner
|
|
31
|
+
}
|
|
27
32
|
|
|
28
33
|
constructor(parent: Unit<TRoot> | null) {
|
|
29
34
|
this.id = nanoid()
|
|
30
35
|
this[_parent_] = parent
|
|
31
|
-
const versioner = getVersioner(this)
|
|
32
|
-
const versions = getVersions(versioner)
|
|
33
|
-
if (versions.length > 0) this[':version'] = versions.at(-1)!
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
// ---------------------------------------------------------------------------
|
|
37
|
-
// ATTACH
|
|
39
|
+
// ATTACH
|
|
38
40
|
// ---------------------------------------------------------------------------
|
|
39
41
|
|
|
40
42
|
/**
|
|
41
43
|
* Lifecycle method called when the unit is attached to the state tree.
|
|
42
44
|
*/
|
|
43
45
|
[epos.state.ATTACH]() {
|
|
44
|
-
// Apply versioner
|
|
45
|
-
epos.state.transaction(() => {
|
|
46
|
-
const versioner = getVersioner(this)
|
|
47
|
-
const versions = getVersions(versioner)
|
|
48
|
-
for (const version of versions) {
|
|
49
|
-
if (is.number(this[':version']) && this[':version'] >= version) continue
|
|
50
|
-
const versionFn = versioner[version]
|
|
51
|
-
if (!is.function(versionFn)) continue
|
|
52
|
-
versionFn.call(this, this)
|
|
53
|
-
this[':version'] = version
|
|
54
|
-
}
|
|
55
|
-
})
|
|
56
|
-
|
|
57
46
|
// Setup logger
|
|
58
47
|
let log = createLog(this['@'])
|
|
59
|
-
Reflect.defineProperty(this, 'log', {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
48
|
+
Reflect.defineProperty(this, 'log', { configurable: true, get: () => log, set: v => (log = v) })
|
|
49
|
+
|
|
50
|
+
// Apply versioner
|
|
51
|
+
void (() => {
|
|
52
|
+
const versioner: unknown = Reflect.get(this.constructor, 'versioner')
|
|
53
|
+
if (!is.object(versioner)) return
|
|
54
|
+
|
|
55
|
+
const asc = (v1: number, v2: number) => v1 - v2
|
|
56
|
+
const versions = Object.keys(versioner).filter(is.numeric).map(Number).sort(asc)
|
|
57
|
+
if (versions.length === 0) return
|
|
58
|
+
|
|
59
|
+
epos.state.transaction(() => {
|
|
60
|
+
for (const version of versions) {
|
|
61
|
+
if (is.number(this[':version']) && this[':version'] >= version) continue
|
|
62
|
+
const versionFn = versioner[version]
|
|
63
|
+
if (!is.function(versionFn)) continue
|
|
64
|
+
versionFn.call(this)
|
|
65
|
+
this[':version'] = version
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
})()
|
|
64
69
|
|
|
65
70
|
// Setup state
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
void (() => {
|
|
72
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(this.constructor.prototype, 'state')
|
|
73
|
+
if (!descriptor || !descriptor.get) return
|
|
74
|
+
const value: unknown = descriptor.get.call(this)
|
|
75
|
+
if (!is.object(value)) throw new Error(`'state' getter return an object`)
|
|
76
|
+
const state = epos.state.create(value)
|
|
77
|
+
Reflect.defineProperty(state, epos.state.PARENT, { configurable: true, value: this })
|
|
78
|
+
Reflect.defineProperty(this, 'state', { enumerable: true, get: () => state })
|
|
79
|
+
})()
|
|
80
|
+
|
|
81
|
+
// Setup inert
|
|
82
|
+
void (() => {
|
|
83
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(this.constructor.prototype, 'inert')
|
|
84
|
+
if (!descriptor || !descriptor.get) return
|
|
85
|
+
const value: unknown = descriptor.get.call(this)
|
|
86
|
+
if (!is.object(value)) throw new Error(`'inert' getter return an object`)
|
|
87
|
+
Reflect.defineProperty(this, 'inert', { enumerable: true, get: () => value })
|
|
88
|
+
})()
|
|
72
89
|
|
|
73
90
|
// Prepare properties for the whole prototype chain:
|
|
74
91
|
// - Create components for methods ending with `View`
|
|
@@ -83,13 +100,8 @@ export class Unit<TRoot = unknown> {
|
|
|
83
100
|
|
|
84
101
|
// Create components for methods ending with `View`
|
|
85
102
|
if (is.function(descriptor.value) && key.endsWith('View')) {
|
|
86
|
-
let
|
|
87
|
-
|
|
88
|
-
Reflect.defineProperty(this, key, {
|
|
89
|
-
configurable: true,
|
|
90
|
-
get: () => Component,
|
|
91
|
-
set: v => (Component = v),
|
|
92
|
-
})
|
|
103
|
+
let View = createView(this, key, descriptor.value.bind(this) as FC<unknown>)
|
|
104
|
+
Reflect.defineProperty(this, key, { configurable: true, get: () => View, set: v => (View = v) })
|
|
93
105
|
}
|
|
94
106
|
|
|
95
107
|
// Bind all other methods to the unit instance
|
|
@@ -115,27 +127,31 @@ export class Unit<TRoot = unknown> {
|
|
|
115
127
|
}
|
|
116
128
|
}
|
|
117
129
|
|
|
118
|
-
// Queue attach
|
|
119
|
-
// Do not execute `attach`
|
|
120
|
-
// This way `attach`
|
|
130
|
+
// Queue attach method.
|
|
131
|
+
// Do not execute `attach` methods immediately, but rather queue them on the highest unattached ancestor.
|
|
132
|
+
// This way `attach` methods are called after all versioners have been applied in the entire subtree.
|
|
121
133
|
const attach = Reflect.get(this, 'attach')
|
|
122
134
|
if (is.function(attach)) {
|
|
123
|
-
const
|
|
124
|
-
if (!
|
|
125
|
-
ensure(
|
|
126
|
-
|
|
135
|
+
const head = findUnattachedRoot(this)
|
|
136
|
+
if (!head) throw this.never()
|
|
137
|
+
ensure(head, _attachQueue_, () => [])
|
|
138
|
+
head[_attachQueue_].push(() => attach.call(this))
|
|
127
139
|
}
|
|
128
140
|
|
|
129
|
-
// Release attach
|
|
130
|
-
if (this[
|
|
131
|
-
this[
|
|
132
|
-
delete this[
|
|
141
|
+
// Release attach queue
|
|
142
|
+
if (this[_attachQueue_]) {
|
|
143
|
+
this[_attachQueue_].forEach(attach => attach())
|
|
144
|
+
delete this[_attachQueue_]
|
|
133
145
|
}
|
|
134
146
|
|
|
135
147
|
// Mark as attached
|
|
136
148
|
Reflect.defineProperty(this, _attached_, { configurable: true, get: () => true })
|
|
137
149
|
}
|
|
138
150
|
|
|
151
|
+
// ---------------------------------------------------------------------------
|
|
152
|
+
// DETACH
|
|
153
|
+
// ---------------------------------------------------------------------------
|
|
154
|
+
|
|
139
155
|
/**
|
|
140
156
|
* Lifecycle method called when the unit is detached from the state tree.
|
|
141
157
|
*/
|
|
@@ -161,7 +177,7 @@ export class Unit<TRoot = unknown> {
|
|
|
161
177
|
// ---------------------------------------------------------------------------
|
|
162
178
|
|
|
163
179
|
/**
|
|
164
|
-
*
|
|
180
|
+
* Get the root unit of the current unit's tree.
|
|
165
181
|
* The result is cached for subsequent calls.
|
|
166
182
|
*/
|
|
167
183
|
get $() {
|
|
@@ -174,8 +190,7 @@ export class Unit<TRoot = unknown> {
|
|
|
174
190
|
// ---------------------------------------------------------------------------
|
|
175
191
|
|
|
176
192
|
/**
|
|
177
|
-
* A wrapper around MobX's `autorun` that automatically disposes
|
|
178
|
-
* the reaction when the unit is detached.
|
|
193
|
+
* A wrapper around MobX's `autorun` that automatically disposes the reaction when the unit is detached.
|
|
179
194
|
*/
|
|
180
195
|
autorun(...args: Parameters<typeof epos.libs.mobx.autorun>) {
|
|
181
196
|
const disposer = epos.libs.mobx.autorun(...args)
|
|
@@ -185,8 +200,7 @@ export class Unit<TRoot = unknown> {
|
|
|
185
200
|
}
|
|
186
201
|
|
|
187
202
|
/**
|
|
188
|
-
* A wrapper around MobX's `reaction` that automatically disposes
|
|
189
|
-
* the reaction when the unit is detached.
|
|
203
|
+
* A wrapper around MobX's `reaction` that automatically disposes the reaction when the unit is detached.
|
|
190
204
|
*/
|
|
191
205
|
reaction(...args: Parameters<typeof epos.libs.mobx.reaction>) {
|
|
192
206
|
const disposer = epos.libs.mobx.reaction(...args)
|
|
@@ -196,39 +210,37 @@ export class Unit<TRoot = unknown> {
|
|
|
196
210
|
}
|
|
197
211
|
|
|
198
212
|
/**
|
|
199
|
-
* A wrapper around `setTimeout` that automatically clears the timeout
|
|
200
|
-
* when the unit is detached.
|
|
213
|
+
* A wrapper around `setTimeout` that automatically clears the timeout when the unit is detached.
|
|
201
214
|
*/
|
|
202
|
-
setTimeout(...args: Parameters<typeof
|
|
203
|
-
const id =
|
|
215
|
+
setTimeout(...args: Parameters<typeof setTimeout>) {
|
|
216
|
+
const id = setTimeout(...args)
|
|
204
217
|
ensure(this, _disposers_, () => new Set())
|
|
205
|
-
this[_disposers_].add(() =>
|
|
218
|
+
this[_disposers_].add(() => clearTimeout(id))
|
|
206
219
|
return id
|
|
207
220
|
}
|
|
208
221
|
|
|
209
222
|
/**
|
|
210
|
-
* A wrapper around `setInterval` that automatically clears the interval
|
|
211
|
-
* when the unit is detached.
|
|
223
|
+
* A wrapper around `setInterval` that automatically clears the interval when the unit is detached.
|
|
212
224
|
*/
|
|
213
|
-
setInterval(...args: Parameters<typeof
|
|
214
|
-
const id =
|
|
225
|
+
setInterval(...args: Parameters<typeof setInterval>) {
|
|
226
|
+
const id = setInterval(...args)
|
|
215
227
|
ensure(this, _disposers_, () => new Set())
|
|
216
|
-
this[_disposers_].add(() =>
|
|
228
|
+
this[_disposers_].add(() => clearInterval(id))
|
|
217
229
|
return id
|
|
218
230
|
}
|
|
219
231
|
|
|
220
232
|
/**
|
|
221
|
-
*
|
|
233
|
+
* Create an error for code paths that are logically unreachable.
|
|
222
234
|
*/
|
|
223
235
|
never(message = 'This should never happen') {
|
|
224
236
|
const details = message ? `: ${message}` : ''
|
|
225
|
-
const error = new Error(`[${this
|
|
237
|
+
const error = new Error(`[${this['@']}] This should never happen${details}`)
|
|
226
238
|
Error.captureStackTrace(error, this.never)
|
|
227
239
|
return error
|
|
228
240
|
}
|
|
229
241
|
|
|
230
242
|
/**
|
|
231
|
-
*
|
|
243
|
+
* Find the closest ancestor unit of a given type.
|
|
232
244
|
* The result is cached for subsequent calls.
|
|
233
245
|
*/
|
|
234
246
|
closest<T extends Unit>(Ancestor: Cls<T>) {
|
|
@@ -255,7 +267,7 @@ export class Unit<TRoot = unknown> {
|
|
|
255
267
|
// ---------------------------------------------------------------------------
|
|
256
268
|
|
|
257
269
|
/**
|
|
258
|
-
*
|
|
270
|
+
* Ensure a property exists on an object, initialize it if it doesn't.
|
|
259
271
|
*/
|
|
260
272
|
function ensure<T extends object, K extends PropertyKey, V>(
|
|
261
273
|
object: T,
|
|
@@ -268,7 +280,7 @@ function ensure<T extends object, K extends PropertyKey, V>(
|
|
|
268
280
|
}
|
|
269
281
|
|
|
270
282
|
/**
|
|
271
|
-
*
|
|
283
|
+
* Get all prototypes of an object up to `Object.prototype`.
|
|
272
284
|
*/
|
|
273
285
|
function getPrototypes(object: object): object[] {
|
|
274
286
|
const prototype = Reflect.getPrototypeOf(object)
|
|
@@ -277,7 +289,7 @@ function getPrototypes(object: object): object[] {
|
|
|
277
289
|
}
|
|
278
290
|
|
|
279
291
|
/**
|
|
280
|
-
*
|
|
292
|
+
* Find the root `Unit` in the hierarchy for a given unit.
|
|
281
293
|
*/
|
|
282
294
|
function findRoot<T>(unit: Unit<T>) {
|
|
283
295
|
let root: Unit<T> | null = null
|
|
@@ -292,7 +304,7 @@ function findRoot<T>(unit: Unit<T>) {
|
|
|
292
304
|
}
|
|
293
305
|
|
|
294
306
|
/**
|
|
295
|
-
*
|
|
307
|
+
* Find the highest unattached `Unit` in the hierarchy for a given unit.
|
|
296
308
|
*/
|
|
297
309
|
function findUnattachedRoot<T>(unit: Unit<T>) {
|
|
298
310
|
let unattachedRoot: Unit<T> | null = null
|
|
@@ -307,7 +319,7 @@ function findUnattachedRoot<T>(unit: Unit<T>) {
|
|
|
307
319
|
}
|
|
308
320
|
|
|
309
321
|
/**
|
|
310
|
-
*
|
|
322
|
+
* Get the parent of a node, which can be a `Unit`, an object, or an array.
|
|
311
323
|
*/
|
|
312
324
|
function getParent<T>(node: Node<T>) {
|
|
313
325
|
const parent: Node<T> | null = Reflect.get(node, _parent_) ?? Reflect.get(node, epos.state.PARENT) ?? null
|
|
@@ -315,18 +327,33 @@ function getParent<T>(node: Node<T>) {
|
|
|
315
327
|
}
|
|
316
328
|
|
|
317
329
|
/**
|
|
318
|
-
*
|
|
330
|
+
* Create view component for the unit.
|
|
319
331
|
*/
|
|
320
|
-
function
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
332
|
+
function createView<T>(unit: Unit<T>, name: string, render: FC<unknown>) {
|
|
333
|
+
const fullName = `${unit['@']}.${name}`
|
|
334
|
+
|
|
335
|
+
const View = epos.component((props: unknown) => {
|
|
336
|
+
try {
|
|
337
|
+
return render(props)
|
|
338
|
+
} catch (error) {
|
|
339
|
+
unit.log.error(error)
|
|
340
|
+
const message = is.error(error) ? error.message : String(error)
|
|
341
|
+
return epos.libs.reactJsxRuntime.jsx('div', {
|
|
342
|
+
children: `[${fullName}] ${message}`,
|
|
343
|
+
style: {
|
|
344
|
+
width: 'fit-content',
|
|
345
|
+
padding: '4px 6px 4px 4px',
|
|
346
|
+
color: '#f00',
|
|
347
|
+
border: '1px solid #f00',
|
|
348
|
+
background: 'rgba(255, 0, 0, 0.1)',
|
|
349
|
+
fontSize: 12,
|
|
350
|
+
fontWeight: 400,
|
|
351
|
+
},
|
|
352
|
+
})
|
|
353
|
+
}
|
|
354
|
+
})
|
|
325
355
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
function getVersions(versioner: Obj) {
|
|
330
|
-
const numericKeys = Object.keys(versioner).filter(key => is.numeric(key))
|
|
331
|
-
return numericKeys.map(Number).sort((v1, v2) => v1 - v2)
|
|
356
|
+
View.displayName = fullName
|
|
357
|
+
|
|
358
|
+
return View
|
|
332
359
|
}
|