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.
@@ -1,15 +1,15 @@
1
- import * as mobx from 'mobx';
2
- import { Cls, Obj, Arr } from 'dropcap/types';
3
- import { createLog } from 'dropcap/utils';
4
-
5
- declare const _root_: unique symbol;
6
- declare const _parent_: unique symbol;
7
- declare const _attached_: unique symbol;
8
- declare const _disposers_: unique symbol;
9
- declare const _ancestors_: unique symbol;
10
- declare const _pendingAttachHooks_: unique symbol;
11
- type Node<T> = Unit<T> | Obj | Arr;
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
- [_pendingAttachHooks_]?: (() => void)[];
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
- * Gets the root unit of the current unit's tree.
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 self.setTimeout>): number;
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 self.setInterval>): number;
53
+ setInterval(...args: Parameters<typeof setInterval>): NodeJS.Timeout;
57
54
  /**
58
- * Creates an error for an unreachable code path.
55
+ * Create an error for code paths that are logically unreachable.
59
56
  */
60
57
  never(message?: string): Error;
61
58
  /**
62
- * Finds the closest ancestor unit of a given type.
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
- // src/epos-unit.ts
2
- import { createLog, is } from "dropcap/utils";
3
- import "epos";
4
- import { customAlphabet } from "nanoid";
5
- var _root_ = /* @__PURE__ */ Symbol("root");
6
- var _parent_ = /* @__PURE__ */ Symbol("parent");
7
- var _attached_ = /* @__PURE__ */ Symbol("attached");
8
- var _disposers_ = /* @__PURE__ */ Symbol("disposers");
9
- var _ancestors_ = /* @__PURE__ */ Symbol("ancestors");
10
- var _pendingAttachHooks_ = /* @__PURE__ */ Symbol("pendingAttachHooks");
11
- var nanoid = customAlphabet("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 8);
12
- var Unit = class {
13
- constructor(parent) {
14
- this.id = nanoid();
15
- this[_parent_] = parent;
16
- const versioner = getVersioner(this);
17
- const versions = getVersions(versioner);
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
- for (const prototype of getPrototypes(this)) {
51
- const descriptors = Object.getOwnPropertyDescriptors(prototype);
52
- for (const [key, descriptor] of Object.entries(descriptors)) {
53
- if (key === "constructor") continue;
54
- if (this.hasOwnProperty(key)) continue;
55
- if (is.function(descriptor.value) && key.endsWith("View")) {
56
- let Component = epos.component(descriptor.value.bind(this));
57
- Component.displayName = `${this.constructor.name}.${key}`;
58
- Reflect.defineProperty(this, key, {
59
- configurable: true,
60
- get: () => Component,
61
- set: (v) => Component = v
62
- });
63
- } else if (is.function(descriptor.value)) {
64
- let method = descriptor.value.bind(this);
65
- Reflect.defineProperty(this, key, {
66
- configurable: true,
67
- get: () => method,
68
- set: (v) => method = v
69
- });
70
- } else if (descriptor.get) {
71
- const getter = descriptor.get;
72
- const computed = epos.libs.mobx.computed(() => getter.call(this));
73
- Reflect.defineProperty(this, key, {
74
- configurable: true,
75
- get: () => computed.get(),
76
- set: descriptor.set
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
- const attach = Reflect.get(this, "attach");
82
- if (is.function(attach)) {
83
- const unattachedRoot = findUnattachedRoot(this);
84
- if (!unattachedRoot) throw this.never();
85
- ensure(unattachedRoot, _pendingAttachHooks_, () => []);
86
- unattachedRoot[_pendingAttachHooks_].push(() => attach());
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
- if (this[_pendingAttachHooks_]) {
89
- this[_pendingAttachHooks_].forEach((attach2) => attach2());
90
- delete this[_pendingAttachHooks_];
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
- Reflect.defineProperty(this, _attached_, { configurable: true, get: () => true });
93
- }
94
- /**
95
- * Lifecycle method called when the unit is detached from the state tree.
96
- */
97
- [epos.state.DETACH]() {
98
- if (this[_disposers_]) {
99
- this[_disposers_].forEach((disposer) => disposer());
100
- this[_disposers_].clear();
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
- if (this[_ancestors_]) {
103
- this[_ancestors_].clear();
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
- const detach = Reflect.get(this, "detach");
106
- if (is.function(detach)) detach();
107
- }
108
- // ---------------------------------------------------------------------------
109
- // ROOT GETTER
110
- // ---------------------------------------------------------------------------
111
- /**
112
- * Gets the root unit of the current unit's tree.
113
- * The result is cached for subsequent calls.
114
- */
115
- get $() {
116
- ensure(this, _root_, () => findRoot(this));
117
- return this[_root_];
118
- }
119
- // ---------------------------------------------------------------------------
120
- // METHODS
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
- return null;
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
- if (key in object) return;
191
- const value = getInitialValue();
192
- Reflect.defineProperty(object, key, { configurable: true, get: () => value });
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
- const prototype = Reflect.getPrototypeOf(object);
196
- if (!prototype || prototype === Object.prototype) return [];
197
- return [prototype, ...getPrototypes(prototype)];
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
- let root = null;
201
- let cursor = unit;
202
- while (cursor) {
203
- if (cursor instanceof Unit) root = cursor;
204
- cursor = getParent(cursor);
205
- }
206
- return root;
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
- let unattachedRoot = null;
210
- let cursor = unit;
211
- while (cursor) {
212
- if (cursor instanceof Unit && !cursor[_attached_]) unattachedRoot = cursor;
213
- cursor = getParent(cursor);
214
- }
215
- return unattachedRoot;
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
- const parent = Reflect.get(node, _parent_) ?? Reflect.get(node, epos.state.PARENT) ?? null;
219
- return parent;
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
- function getVersions(versioner) {
227
- const numericKeys = Object.keys(versioner).filter((key) => is.numeric(key));
228
- return numericKeys.map(Number).sort((v1, v2) => v1 - v2);
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
@@ -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.17.0",
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": "tsup --config ../../tsup.config.ts --watch",
11
- "build": "tsup --config ../../tsup.config.ts",
12
- "lint": "tsc --noEmit",
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.4.0",
24
- "epos": "^1.32.0",
25
- "nanoid": "^3.3.11"
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
- import type { Arr, Cls, Obj } from 'dropcap/types'
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 _pendingAttachHooks_ = Symbol('pendingAttachHooks')
12
- const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 8)
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 [_pendingAttachHooks_]?: (() => void)[]
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 / DETACH
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
- configurable: true,
61
- get: () => log,
62
- set: v => (log = v),
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
- const stateDescriptor = Reflect.getOwnPropertyDescriptor(this.constructor.prototype, 'state')
67
- if (stateDescriptor && stateDescriptor.get) {
68
- const value = stateDescriptor.get.call(this)
69
- const state = epos.state.local(value, { deep: false })
70
- Reflect.defineProperty(this, 'state', { get: () => state })
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 Component = epos.component(descriptor.value.bind(this))
87
- Component.displayName = `${this.constructor.name}.${key}`
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 hook.
119
- // Do not execute `attach` hooks immediately, but rather queue them on the highest unattached ancestor.
120
- // This way `attach` hooks are called after all versioners have been applied in the entire subtree.
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 unattachedRoot = findUnattachedRoot(this)
124
- if (!unattachedRoot) throw this.never()
125
- ensure(unattachedRoot, _pendingAttachHooks_, () => [])
126
- unattachedRoot[_pendingAttachHooks_].push(() => attach())
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 hooks
130
- if (this[_pendingAttachHooks_]) {
131
- this[_pendingAttachHooks_].forEach(attach => attach())
132
- delete this[_pendingAttachHooks_]
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
- * Gets the root unit of the current unit's tree.
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 self.setTimeout>) {
203
- const id = self.setTimeout(...args)
215
+ setTimeout(...args: Parameters<typeof setTimeout>) {
216
+ const id = setTimeout(...args)
204
217
  ensure(this, _disposers_, () => new Set())
205
- this[_disposers_].add(() => self.clearTimeout(id))
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 self.setInterval>) {
214
- const id = self.setInterval(...args)
225
+ setInterval(...args: Parameters<typeof setInterval>) {
226
+ const id = setInterval(...args)
215
227
  ensure(this, _disposers_, () => new Set())
216
- this[_disposers_].add(() => self.clearInterval(id))
228
+ this[_disposers_].add(() => clearInterval(id))
217
229
  return id
218
230
  }
219
231
 
220
232
  /**
221
- * Creates an error for an unreachable code path.
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.constructor.name}] This should never happen${details}`)
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
- * Finds the closest ancestor unit of a given type.
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
- * Ensures a property exists on an object, initializing it if it doesn't.
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
- * Gets all prototypes of an object up to `Object.prototype`.
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
- * Finds the root `Unit` in the hierarchy for a given unit.
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
- * Finds the highest unattached `Unit` in the hierarchy for a given unit.
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
- * Gets the parent of a node, which can be a `Unit`, an object, or an array.
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
- * Gets the versioner object from a unit's constructor.
330
+ * Create view component for the unit.
319
331
  */
320
- function getVersioner<T>(unit: Unit<T>) {
321
- const versioner: unknown = Reflect.get(unit.constructor, 'versioner')
322
- if (!is.object(versioner)) return {}
323
- return versioner
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
- * Gets a sorted list of numeric version keys from a unit's versioner.
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
  }