@travetto/registry 7.0.0-rc.0 → 7.0.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -54,13 +54,13 @@ class SampleRegistryAdapter implements RegistryAdapter<Group> {
54
54
  this.#class = cls;
55
55
  }
56
56
 
57
- register(...data: Partial<Partial<Group>>[]): Group {
58
- for (const d of data) {
57
+ register(...groups: Partial<Partial<Group>>[]): Group {
58
+ for (const group of groups) {
59
59
  Object.assign(this.#config, {
60
- ...d,
60
+ ...group,
61
61
  children: [
62
62
  ...(this.#config?.children ?? []),
63
- ...(d.children ?? [])
63
+ ...(group.children ?? [])
64
64
  ]
65
65
  });
66
66
  }
@@ -98,7 +98,7 @@ export class SampleRegistryIndex implements RegistryIndex {
98
98
  }
99
99
  ```
100
100
 
101
- The registry index is a [RegistryIndex](https://github.com/travetto/travetto/tree/main/module/registry/src/service/types.ts#L34) that similar to the [Schema](https://github.com/travetto/travetto/tree/main/module/schema#readme "Data type registry for runtime validation, reflection and binding.")'s Schema registry and [Dependency Injection](https://github.com/travetto/travetto/tree/main/module/di#readme "Dependency registration/management and injection support.")'s Dependency registry.
101
+ The registry index is a [RegistryIndex](https://github.com/travetto/travetto/tree/main/module/registry/src/service/types.ts#L36) that similar to the [Schema](https://github.com/travetto/travetto/tree/main/module/schema#readme "Data type registry for runtime validation, reflection and binding.")'s Schema registry and [Dependency Injection](https://github.com/travetto/travetto/tree/main/module/di#readme "Dependency registration/management and injection support.")'s Dependency registry.
102
102
 
103
103
  ### Live Flow
104
104
  At runtime, the registry is designed to listen for changes and to propagate the changes as necessary. In many cases the same file is handled by multiple registries.
@@ -115,12 +115,12 @@ As mentioned in [Manifest](https://github.com/travetto/travetto/tree/main/module
115
115
  const next = new Map<string, Class>(classes.map(cls => [cls.Ⲑid, cls] as const));
116
116
  const sourceFile = RuntimeIndex.getSourceFile(importFile);
117
117
 
118
- let prev = new Map<string, Class>();
118
+ let previous = new Map<string, Class>();
119
119
  if (this.#classes.has(sourceFile)) {
120
- prev = new Map(this.#classes.get(sourceFile)!.entries());
120
+ previous = new Map(this.#classes.get(sourceFile)!.entries());
121
121
  }
122
122
 
123
- const keys = new Set([...Array.from(prev.keys()), ...Array.from(next.keys())]);
123
+ const keys = new Set([...Array.from(previous.keys()), ...Array.from(next.keys())]);
124
124
 
125
125
  if (!this.#classes.has(sourceFile)) {
126
126
  this.#classes.set(sourceFile, new Map());
@@ -129,22 +129,22 @@ As mentioned in [Manifest](https://github.com/travetto/travetto/tree/main/module
129
129
  let changes = 0;
130
130
 
131
131
  // Determine delta based on the various classes (if being added, removed or updated)
132
- for (const k of keys) {
133
- if (!next.has(k)) {
132
+ for (const key of keys) {
133
+ if (!next.has(key)) {
134
134
  changes += 1;
135
- this.emit({ type: 'removing', prev: prev.get(k)! });
136
- this.#classes.get(sourceFile)!.delete(k);
135
+ this.emit({ type: 'removing', previous: previous.get(key)! });
136
+ this.#classes.get(sourceFile)!.delete(key);
137
137
  } else {
138
- this.#classes.get(sourceFile)!.set(k, next.get(k)!);
139
- if (!prev.has(k)) {
138
+ this.#classes.get(sourceFile)!.set(key, next.get(key)!);
139
+ if (!previous.has(key)) {
140
140
  changes += 1;
141
- this.emit({ type: 'added', curr: next.get(k)! });
141
+ this.emit({ type: 'added', current: next.get(key)! });
142
142
  } else {
143
- const prevHash = describeFunction(prev.get(k)!)?.hash;
144
- const nextHash = describeFunction(next.get(k)!)?.hash;
143
+ const prevHash = describeFunction(previous.get(key)!)?.hash;
144
+ const nextHash = describeFunction(next.get(key)!)?.hash;
145
145
  if (prevHash !== nextHash) {
146
146
  changes += 1;
147
- this.emit({ type: 'changed', curr: next.get(k)!, prev: prev.get(k)! });
147
+ this.emit({ type: 'changed', current: next.get(key)!, previous: previous.get(key)! });
148
148
  }
149
149
  }
150
150
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/registry",
3
- "version": "7.0.0-rc.0",
3
+ "version": "7.0.0-rc.2",
4
4
  "description": "Patterns and utilities for handling registration of metadata and functionality for run-time use",
5
5
  "keywords": [
6
6
  "ast-transformations",
@@ -27,11 +27,11 @@
27
27
  "directory": "module/registry"
28
28
  },
29
29
  "dependencies": {
30
- "@travetto/runtime": "^7.0.0-rc.0"
30
+ "@travetto/runtime": "^7.0.0-rc.2"
31
31
  },
32
32
  "peerDependencies": {
33
- "@travetto/cli": "^7.0.0-rc.0",
34
- "@travetto/transformer": "^7.0.0-rc.0"
33
+ "@travetto/cli": "^7.0.0-rc.2",
34
+ "@travetto/transformer": "^7.0.0-rc.2"
35
35
  },
36
36
  "peerDependenciesMeta": {
37
37
  "@travetto/transformer": {
@@ -7,9 +7,9 @@ import { RetargettingProxy } from '../proxy.ts';
7
7
 
8
8
  declare module 'module' {
9
9
  // eslint-disable-next-line @typescript-eslint/naming-convention
10
- function _resolveFilename(req: string, parent: typeof Module): string;
10
+ function _resolveFilename(request: string, parent: typeof Module): string;
11
11
  // eslint-disable-next-line @typescript-eslint/naming-convention
12
- function _load(req: string, parent: typeof Module): unknown;
12
+ function _load(request: string, parent: typeof Module): unknown;
13
13
  }
14
14
 
15
15
  type ModuleLoader = typeof Module['_load'];
@@ -30,22 +30,22 @@ export class DynamicCommonjsLoader {
30
30
  let mod: unknown;
31
31
  try {
32
32
  mod = moduleLoad.apply(null, [request, parent]);
33
- } catch (err: unknown) {
33
+ } catch (error: unknown) {
34
34
  const name = Module._resolveFilename!(request, parent);
35
- if (err instanceof Error && Runtime.dynamic && !name.startsWith('test/')) {
36
- const errMsg = err.message;
37
- console.debug(`Unable to load ${name}: stubbing out with error proxy.`, errMsg);
38
- const e = (): never => { throw new Error(errMsg); };
39
- mod = new Proxy({}, { getOwnPropertyDescriptor: e, get: e, has: e });
35
+ if (error instanceof Error && Runtime.dynamic && !name.startsWith('test/')) {
36
+ const message = error.message;
37
+ console.debug(`Unable to load ${name}: stubbing out with error proxy.`, message);
38
+ const fail = (): never => { throw new Error(message); };
39
+ mod = new Proxy({}, { getOwnPropertyDescriptor: fail, get: fail, has: fail });
40
40
  } else {
41
- throw err;
41
+ throw error;
42
42
  }
43
43
  }
44
44
 
45
45
  const file = Module._resolveFilename!(request, parent);
46
- const src = RuntimeIndex.getEntry(file)?.sourceFile;
46
+ const source = RuntimeIndex.getEntry(file)?.sourceFile;
47
47
  // Only proxy workspace modules
48
- if (src && RuntimeIndex.getModuleFromSource(src)?.workspace) {
48
+ if (source && RuntimeIndex.getModuleFromSource(source)?.workspace) {
49
49
  return proxyModuleLoad ? proxyModuleLoad(file, mod) : mod;
50
50
  } else {
51
51
  return mod;
@@ -3,11 +3,11 @@ import { watchCompiler, WatchEvent, Runtime, RuntimeIndex } from '@travetto/runt
3
3
 
4
4
  const VALID_FILE_TYPES = new Set(['js', 'ts']);
5
5
 
6
- const handle = (err: Error): void => {
7
- if (err && (err.message ?? '').includes('Cannot find module')) { // Handle module reloading
8
- console.error('Cannot find module', { error: err });
6
+ const handle = (error: Error): void => {
7
+ if (error && (error.message ?? '').includes('Cannot find module')) { // Handle module reloading
8
+ console.error('Cannot find module', { error });
9
9
  } else {
10
- throw err;
10
+ throw error;
11
11
  }
12
12
  };
13
13
 
@@ -27,19 +27,19 @@ export class DynamicFileLoader {
27
27
  .on('uncaughtException', handle);
28
28
 
29
29
  // Fire off, and let it run in the bg. Restart on exit
30
- for await (const ev of watchCompiler({ restartOnExit: true })) {
31
- if (ev.file && RuntimeIndex.hasModule(ev.module) && VALID_FILE_TYPES.has(ManifestModuleUtil.getFileType(ev.file))) {
32
- if (ev.action === 'update' || ev.action === 'delete') {
33
- await loader.unload(ev.output);
30
+ for await (const event of watchCompiler({ restartOnExit: true })) {
31
+ if (event.file && RuntimeIndex.hasModule(event.module) && VALID_FILE_TYPES.has(ManifestModuleUtil.getFileType(event.file))) {
32
+ if (event.action === 'update' || event.action === 'delete') {
33
+ await loader.unload(event.output);
34
34
  }
35
- if (ev.action === 'create' || ev.action === 'delete') {
35
+ if (event.action === 'create' || event.action === 'delete') {
36
36
  RuntimeIndex.reinitForModule(Runtime.main.name);
37
37
  }
38
- if (ev.action === 'create' || ev.action === 'update') {
39
- await loader.load(ev.output);
38
+ if (event.action === 'create' || event.action === 'update') {
39
+ await loader.load(event.output);
40
40
  }
41
41
 
42
- yield ev;
42
+ yield event;
43
43
  }
44
44
  }
45
45
  }
package/src/proxy.ts CHANGED
@@ -7,8 +7,8 @@ const AsyncGeneratorFunction = Object.getPrototypeOf(async function* () { });
7
7
  const GeneratorFunction = Object.getPrototypeOf(function* () { });
8
8
  const AsyncFunction = Object.getPrototypeOf(async function () { });
9
9
 
10
- function isFunction(o: unknown): o is Function {
11
- const proto = o && Object.getPrototypeOf(o);
10
+ function isFunction(value: unknown): value is Function {
11
+ const proto = value && Object.getPrototypeOf(value);
12
12
  return proto && (proto === Function.prototype || proto === AsyncFunction || proto === AsyncGeneratorFunction || proto === GeneratorFunction);
13
13
  }
14
14
 
@@ -43,19 +43,19 @@ export class RetargettingHandler<T> implements ProxyHandler<Any> {
43
43
  return classConstruct(castTo(this.target), argArray);
44
44
  }
45
45
 
46
- setPrototypeOf(target: T, v: unknown): boolean {
47
- return Object.setPrototypeOf(this.target, castTo(v));
46
+ setPrototypeOf(target: T, value: unknown): boolean {
47
+ return Object.setPrototypeOf(this.target, castTo(value));
48
48
  }
49
49
 
50
50
  getPrototypeOf(target: T): object | null {
51
51
  return Object.getPrototypeOf(this.target);
52
52
  }
53
53
 
54
- get(target: T, prop: PropertyKey, receiver: unknown): Any {
55
- if (prop === ProxyTargetSymbol) {
54
+ get(target: T, property: PropertyKey, receiver: unknown): Any {
55
+ if (property === ProxyTargetSymbol) {
56
56
  return this.target;
57
57
  }
58
- let result = this.target[castKey<T>(prop)];
58
+ let result = this.target[castKey<T>(property)];
59
59
  if (isFunction(result) && !/^class\s/.test(Function.prototype.toString.call(result))) {
60
60
  // Bind class members to class instance instead of proxy propagating
61
61
  result = result.bind(this.target);
@@ -63,12 +63,12 @@ export class RetargettingHandler<T> implements ProxyHandler<Any> {
63
63
  return result;
64
64
  }
65
65
 
66
- has(target: T, prop: PropertyKey): boolean {
67
- return castTo<object>(this.target).hasOwnProperty(prop);
66
+ has(target: T, property: PropertyKey): boolean {
67
+ return castTo<object>(this.target).hasOwnProperty(property);
68
68
  }
69
69
 
70
- set(target: T, prop: PropertyKey, value: unknown): boolean {
71
- this.target[castKey<T>(prop)] = castTo(value);
70
+ set(target: T, property: PropertyKey, value: unknown): boolean {
71
+ this.target[castKey<T>(property)] = castTo(value);
72
72
  return true;
73
73
  }
74
74
 
@@ -79,12 +79,12 @@ export class RetargettingHandler<T> implements ProxyHandler<Any> {
79
79
  .concat(Object.getOwnPropertySymbols(this.target));
80
80
  }
81
81
 
82
- deleteProperty(target: T, p: PropertyKey): boolean {
83
- return delete this.target[castKey<T>(p)];
82
+ deleteProperty(target: T, property: PropertyKey): boolean {
83
+ return delete this.target[castKey<T>(property)];
84
84
  }
85
85
 
86
- defineProperty(target: T, p: PropertyKey, attributes: PropertyDescriptor): boolean {
87
- Object.defineProperty(this.target, p, attributes);
86
+ defineProperty(target: T, property: PropertyKey, attributes: PropertyDescriptor): boolean {
87
+ Object.defineProperty(this.target, property, attributes);
88
88
  return true;
89
89
  }
90
90
  }
@@ -99,8 +99,8 @@ export class RetargettingProxy<T> {
99
99
  /**
100
100
  * Unwrap proxy
101
101
  */
102
- static unwrap<U>(el: U): U {
103
- return castTo<{ [ProxyTargetSymbol]: U }>(el)?.[ProxyTargetSymbol] ?? el;
102
+ static unwrap<U>(value: U): U {
103
+ return castTo<{ [ProxyTargetSymbol]: U }>(value)?.[ProxyTargetSymbol] ?? value;
104
104
  }
105
105
 
106
106
  #handler: RetargettingHandler<T>;
@@ -4,14 +4,14 @@ import { AppError, castTo, Class, Util } from '@travetto/runtime';
4
4
  import { ClassSource } from '../source/class-source';
5
5
  import { ChangeEvent } from '../types';
6
6
  import { MethodSource } from '../source/method-source';
7
- import { RegistryIndex, RegistryIndexClass } from './types';
7
+ import { RegistryIndex, RegistryIndexClass, EXPIRED_CLASS } from './types';
8
8
 
9
9
  class $Registry {
10
10
 
11
11
  #resolved = false;
12
12
  #initialized?: Promise<unknown>;
13
13
  trace = false;
14
- #uid = Util.uuid();
14
+ #uniqueId = Util.uuid();
15
15
 
16
16
  // Lookups
17
17
  #indexes = new Map<RegistryIndexClass, RegistryIndex>();
@@ -27,6 +27,8 @@ class $Registry {
27
27
  for (const idx of this.#indexOrder) {
28
28
  this.instance(idx).store.remove(cls);
29
29
  }
30
+ // Tag expired classes
31
+ Object.assign(cls, { [EXPIRED_CLASS]: true });
30
32
  }
31
33
  }
32
34
 
@@ -51,22 +53,22 @@ class $Registry {
51
53
  }
52
54
 
53
55
  process(events: ChangeEvent<Class>[]): void {
54
- this.#finalizeItems(events.filter(ev => 'curr' in ev).map(ev => ev.curr));
56
+ this.#finalizeItems(events.filter(event => 'current' in event).map(event => event.current));
55
57
 
56
58
  for (const indexCls of this.#indexOrder) { // Visit every index, in order
57
59
  const inst = this.instance(indexCls);
58
- const matched = events.filter(e => inst.store.has('curr' in e ? e.curr : e.prev!));
60
+ const matched = events.filter(event => inst.store.has('current' in event ? event.current : event.previous!));
59
61
  if (matched.length) {
60
62
  inst.process(matched);
61
63
  }
62
64
  }
63
65
 
64
66
  Util.queueMacroTask().then(() => {
65
- this.#removeItems(events.filter(ev => 'prev' in ev).map(ev => ev.prev!));
67
+ this.#removeItems(events.filter(event => 'previous' in event).map(event => event.previous!));
66
68
  });
67
69
 
68
- for (const e of events) {
69
- this.#emitter.emit('event', e);
70
+ for (const event of events) {
71
+ this.#emitter.emit('event', event);
70
72
  }
71
73
  }
72
74
 
@@ -78,12 +80,12 @@ class $Registry {
78
80
  this.#resolved = false;
79
81
 
80
82
  if (this.trace) {
81
- console.debug('Initializing', { uid: this.#uid });
83
+ console.debug('Initializing', { uniqueId: this.#uniqueId });
82
84
  }
83
85
 
84
86
  const added = await this.#classSource.init();
85
- this.process(added.map(cls => ({ type: 'added', curr: cls })));
86
- this.#classSource.on(e => this.process([e]));
87
+ this.process(added.map(cls => ({ type: 'added', current: cls })));
88
+ this.#classSource.on(event => this.process([event]));
87
89
  } finally {
88
90
  this.#resolved = true;
89
91
  }
@@ -114,7 +116,7 @@ class $Registry {
114
116
  */
115
117
  async init(): Promise<unknown> {
116
118
  if (this.trace && this.#initialized) {
117
- console.trace('Trying to re-initialize', { uid: this.#uid, initialized: !!this.#initialized });
119
+ console.trace('Trying to re-initialize', { uniqueId: this.#uniqueId, initialized: !!this.#initialized });
118
120
  }
119
121
  return this.#initialized ??= this.#init();
120
122
  }
@@ -132,7 +134,7 @@ class $Registry {
132
134
  } else {
133
135
  const inst = this.instance(matches);
134
136
  this.#emitter.on('event', (event) => {
135
- if (inst.store.has('curr' in event ? event.curr : event.prev!)) {
137
+ if (inst.store.has('current' in event ? event.current : event.previous!)) {
136
138
  handler(event);
137
139
  }
138
140
  });
@@ -147,13 +149,13 @@ class $Registry {
147
149
  handler: (event: ChangeEvent<[Class, Function]>) => void,
148
150
  matches?: RegistryIndexClass,
149
151
  ): void {
150
- const src = this.#methodSource ??= new MethodSource(this.#classSource);
152
+ const emitter = this.#methodSource ??= new MethodSource(this.#classSource);
151
153
  if (!matches) {
152
- src.on(handler);
154
+ emitter.on(handler);
153
155
  } else {
154
156
  const inst = this.instance(matches);
155
- src.on((event) => {
156
- if (inst.store.has('curr' in event ? event.curr[0] : event.prev[0])) {
157
+ emitter.on((event) => {
158
+ if (inst.store.has('current' in event ? event.current[0] : event.previous[0])) {
157
159
  handler(event);
158
160
  }
159
161
  });
@@ -1,6 +1,22 @@
1
- import { AppError, castTo, Class, getParentClass } from '@travetto/runtime';
1
+ import { Any, AppError, castTo, Class, getParentClass, Runtime } from '@travetto/runtime';
2
2
 
3
- import { RegistrationMethods, RegistryAdapter } from './types';
3
+ import { EXPIRED_CLASS, RegistrationMethods, RegistryAdapter } from './types';
4
+
5
+ function ExchangeExpired<R = unknown>() {
6
+ return function (
7
+ target: Any,
8
+ propertyKey: string,
9
+ descriptor: TypedPropertyDescriptor<(this: RegistryIndexStore, cls: Class) => R>
10
+ ): void {
11
+ if (Runtime.dynamic) {
12
+ const original = descriptor.value!;
13
+ descriptor.value = function (this: RegistryIndexStore, cls: Class): R {
14
+ const resolved = EXPIRED_CLASS in cls ? this.getClassById(cls.Ⲑid) : cls;
15
+ return original.apply(this, [resolved]);
16
+ };
17
+ }
18
+ };
19
+ }
4
20
 
5
21
  /**
6
22
  * Base registry index implementation
@@ -15,16 +31,13 @@ export class RegistryIndexStore<A extends RegistryAdapter<{}> = RegistryAdapter<
15
31
 
16
32
  constructor(adapterCls: new (cls: Class) => A) {
17
33
  this.#adapterCls = adapterCls;
34
+ this.getClassById = this.getClassById.bind(this);
18
35
  }
19
36
 
20
37
  getClasses(): Class[] {
21
38
  return Array.from(this.#adapters.keys());
22
39
  }
23
40
 
24
- has(cls: Class): boolean {
25
- return this.#adapters.has(cls);
26
- }
27
-
28
41
  getClassById(id: string): Class {
29
42
  return this.#idToCls.get(id)!;
30
43
  }
@@ -38,6 +51,17 @@ export class RegistryIndexStore<A extends RegistryAdapter<{}> = RegistryAdapter<
38
51
  this.#finalized.set(cls, true);
39
52
  }
40
53
 
54
+ remove(cls: Class): void {
55
+ this.#adapters.delete(cls);
56
+ this.#finalized.delete(cls);
57
+ }
58
+
59
+ @ExchangeExpired()
60
+ has(cls: Class): boolean {
61
+ return this.#adapters.has(cls);
62
+ }
63
+
64
+ @ExchangeExpired()
41
65
  adapter(cls: Class): A {
42
66
  if (!this.#adapters.has(cls)!) {
43
67
  const adapter = new this.#adapterCls(cls);
@@ -48,11 +72,7 @@ export class RegistryIndexStore<A extends RegistryAdapter<{}> = RegistryAdapter<
48
72
  return castTo(this.#adapters.get(cls));
49
73
  }
50
74
 
51
- remove(cls: Class): void {
52
- this.#adapters.delete(cls);
53
- this.#finalized.delete(cls);
54
- }
55
-
75
+ @ExchangeExpired()
56
76
  getForRegister(cls: Class, allowFinalized = false): A {
57
77
  if (this.#finalized.get(cls) && !allowFinalized) {
58
78
  throw new AppError(`Class ${cls.Ⲑid} is already finalized`);
@@ -60,6 +80,7 @@ export class RegistryIndexStore<A extends RegistryAdapter<{}> = RegistryAdapter<
60
80
  return this.adapter(cls);
61
81
  }
62
82
 
83
+ @ExchangeExpired()
63
84
  get(cls: Class): Omit<A, RegistrationMethods> {
64
85
  if (!this.has(cls)) {
65
86
  throw new AppError(`Class ${cls.Ⲑid} is not registered for ${this.#adapterCls.Ⲑid}`);
@@ -67,6 +88,7 @@ export class RegistryIndexStore<A extends RegistryAdapter<{}> = RegistryAdapter<
67
88
  return this.adapter(cls);
68
89
  }
69
90
 
91
+ @ExchangeExpired()
70
92
  getOptional(cls: Class): Omit<A, RegistrationMethods> | undefined {
71
93
  if (!this.has(cls)) {
72
94
  return undefined;
@@ -74,6 +96,7 @@ export class RegistryIndexStore<A extends RegistryAdapter<{}> = RegistryAdapter<
74
96
  return this.adapter(cls);
75
97
  }
76
98
 
99
+ @ExchangeExpired()
77
100
  finalized(cls: Class): boolean {
78
101
  return this.#finalized.has(cls);
79
102
  }
@@ -3,6 +3,8 @@ import { ChangeEvent } from '../types';
3
3
 
4
4
  export type RegistrationMethods = `register${string}` | `finalize${string}`;
5
5
 
6
+ export const EXPIRED_CLASS = Symbol();
7
+
6
8
  /**
7
9
  * Interface for registry adapters to implement
8
10
  */
@@ -27,7 +27,7 @@ export class ClassSource implements ChangeSource<Class> {
27
27
  /**
28
28
  * Are we in a mode that should have enhanced debug info
29
29
  */
30
- trace = Env.DEBUG.val?.includes('@travetto/registry');
30
+ trace = Env.DEBUG.value?.includes('@travetto/registry');
31
31
 
32
32
  /**
33
33
  * Flush classes
@@ -35,12 +35,12 @@ export class ClassSource implements ChangeSource<Class> {
35
35
  #flush(): Class[] {
36
36
  const flushed = flushPendingFunctions().filter(isClass);
37
37
  for (const cls of flushed) {
38
- const src = Runtime.getSourceFile(cls);
39
- if (!this.#classes.has(src)) {
40
- this.#classes.set(src, new Map());
38
+ const source = Runtime.getSourceFile(cls);
39
+ if (!this.#classes.has(source)) {
40
+ this.#classes.set(source, new Map());
41
41
  }
42
- this.#classes.get(src)!.set(cls.Ⲑid, cls);
43
- this.emit({ type: 'added', curr: cls });
42
+ this.#classes.get(source)!.set(cls.Ⲑid, cls);
43
+ this.emit({ type: 'added', current: cls });
44
44
  }
45
45
  return flushed;
46
46
  }
@@ -50,7 +50,7 @@ export class ClassSource implements ChangeSource<Class> {
50
50
  if (data) {
51
51
  this.#classes.delete(file);
52
52
  for (const cls of data) {
53
- this.emit({ type: 'removing', prev: cls[1] });
53
+ this.emit({ type: 'removing', previous: cls[1] });
54
54
  }
55
55
  }
56
56
  }
@@ -62,12 +62,12 @@ export class ClassSource implements ChangeSource<Class> {
62
62
  const next = new Map<string, Class>(classes.map(cls => [cls.Ⲑid, cls] as const));
63
63
  const sourceFile = RuntimeIndex.getSourceFile(importFile);
64
64
 
65
- let prev = new Map<string, Class>();
65
+ let previous = new Map<string, Class>();
66
66
  if (this.#classes.has(sourceFile)) {
67
- prev = new Map(this.#classes.get(sourceFile)!.entries());
67
+ previous = new Map(this.#classes.get(sourceFile)!.entries());
68
68
  }
69
69
 
70
- const keys = new Set([...Array.from(prev.keys()), ...Array.from(next.keys())]);
70
+ const keys = new Set([...Array.from(previous.keys()), ...Array.from(next.keys())]);
71
71
 
72
72
  if (!this.#classes.has(sourceFile)) {
73
73
  this.#classes.set(sourceFile, new Map());
@@ -76,22 +76,22 @@ export class ClassSource implements ChangeSource<Class> {
76
76
  let changes = 0;
77
77
 
78
78
  // Determine delta based on the various classes (if being added, removed or updated)
79
- for (const k of keys) {
80
- if (!next.has(k)) {
79
+ for (const key of keys) {
80
+ if (!next.has(key)) {
81
81
  changes += 1;
82
- this.emit({ type: 'removing', prev: prev.get(k)! });
83
- this.#classes.get(sourceFile)!.delete(k);
82
+ this.emit({ type: 'removing', previous: previous.get(key)! });
83
+ this.#classes.get(sourceFile)!.delete(key);
84
84
  } else {
85
- this.#classes.get(sourceFile)!.set(k, next.get(k)!);
86
- if (!prev.has(k)) {
85
+ this.#classes.get(sourceFile)!.set(key, next.get(key)!);
86
+ if (!previous.has(key)) {
87
87
  changes += 1;
88
- this.emit({ type: 'added', curr: next.get(k)! });
88
+ this.emit({ type: 'added', current: next.get(key)! });
89
89
  } else {
90
- const prevHash = describeFunction(prev.get(k)!)?.hash;
91
- const nextHash = describeFunction(next.get(k)!)?.hash;
90
+ const prevHash = describeFunction(previous.get(key)!)?.hash;
91
+ const nextHash = describeFunction(next.get(key)!)?.hash;
92
92
  if (prevHash !== nextHash) {
93
93
  changes += 1;
94
- this.emit({ type: 'changed', curr: next.get(k)!, prev: prev.get(k)! });
94
+ this.emit({ type: 'changed', current: next.get(key)!, previous: previous.get(key)! });
95
95
  }
96
96
  }
97
97
  }
@@ -104,17 +104,17 @@ export class ClassSource implements ChangeSource<Class> {
104
104
  */
105
105
  #handleChanges(classes: Class[] = []): void {
106
106
  const classesByFile = new Map<string, Class[]>();
107
- for (const el of classes) {
108
- const imp = Runtime.getImport(el);
109
- if (!classesByFile.has(imp)) {
110
- classesByFile.set(imp, []);
107
+ for (const cls of classes) {
108
+ const importPath = Runtime.getImport(cls);
109
+ if (!classesByFile.has(importPath)) {
110
+ classesByFile.set(importPath, []);
111
111
  }
112
- classesByFile.get(imp)!.push(el);
112
+ classesByFile.get(importPath)!.push(cls);
113
113
  }
114
114
 
115
- for (const [imp, els] of classesByFile.entries()) {
116
- if (!this.#handleFileChanges(imp, els)) {
117
- this.#emitter.emit('unchanged-import', imp);
115
+ for (const [importPath, items] of classesByFile.entries()) {
116
+ if (!this.#handleFileChanges(importPath, items)) {
117
+ this.#emitter.emit('unchanged-import', importPath);
118
118
  }
119
119
  }
120
120
  }
@@ -122,15 +122,15 @@ export class ClassSource implements ChangeSource<Class> {
122
122
  /**
123
123
  * Emit a change event
124
124
  */
125
- emit(e: ChangeEvent<Class>): void {
125
+ emit(event: ChangeEvent<Class>): void {
126
126
  if (this.trace) {
127
127
  console.debug('Emitting change', {
128
- type: e.type,
129
- curr: (e.type !== 'removing' ? e.curr?.Ⲑid : undefined),
130
- prev: (e.type !== 'added' ? e.prev?.Ⲑid : undefined)
128
+ type: event.type,
129
+ current: (event.type !== 'removing' ? event.current?.Ⲑid : undefined),
130
+ previous: (event.type !== 'added' ? event.previous?.Ⲑid : undefined)
131
131
  });
132
132
  }
133
- this.#emitter.emit('change', e);
133
+ this.#emitter.emit('change', event);
134
134
  }
135
135
 
136
136
  /**
@@ -139,14 +139,14 @@ export class ClassSource implements ChangeSource<Class> {
139
139
  async init(): Promise<Class[]> {
140
140
  if (Runtime.dynamic && !this.#listening) {
141
141
  this.#listening = (async (): Promise<void> => {
142
- for await (const ev of await DynamicFileLoader.listen()) {
143
- if (ev.action === 'delete') {
144
- this.#removeFile(ev.file); // File no longer exists
142
+ for await (const event of await DynamicFileLoader.listen()) {
143
+ if (event.action === 'delete') {
144
+ this.#removeFile(event.file); // File no longer exists
145
145
  } else {
146
146
  this.#handleChanges(flushPendingFunctions().filter(isClass));
147
147
  }
148
148
 
149
- if (ev.action === 'create') {
149
+ if (event.action === 'create') {
150
150
  this.#flush();
151
151
  }
152
152
  }
@@ -155,16 +155,16 @@ export class ClassSource implements ChangeSource<Class> {
155
155
 
156
156
  // Ensure everything is loaded
157
157
  for (const entry of RuntimeIndex.find({
158
- module: (m) => {
159
- const role = Env.TRV_ROLE.val;
158
+ module: (mod) => {
159
+ const role = Env.TRV_ROLE.value;
160
160
  return role !== 'test' && // Skip all modules when in test
161
- m.roles.includes('std') &&
161
+ mod.roles.includes('std') &&
162
162
  (
163
- !Runtime.production || m.prod ||
164
- (role === 'doc' && m.roles.includes(role))
163
+ !Runtime.production || mod.prod ||
164
+ (role === 'doc' && mod.roles.includes(role))
165
165
  );
166
166
  },
167
- folder: f => f === 'src' || f === '$index'
167
+ folder: folder => folder === 'src' || folder === '$index'
168
168
  })) {
169
169
  await Runtime.importFrom(entry.import);
170
170
  }
@@ -16,39 +16,43 @@ export class MethodSource implements ChangeSource<[Class, Function]> {
16
16
  * Define parent change source, generally will be the class source
17
17
  */
18
18
  constructor(classSource: ChangeSource<Class>) {
19
- classSource.on(e => this.onClassEvent(e));
19
+ classSource.on(event => this.onClassEvent(event));
20
20
  }
21
21
 
22
22
  async init(): Promise<void> { }
23
23
 
24
- emit(ev: ChangeEvent<[Class, Function]>): void {
25
- this.#emitter.emit('change', ev);
24
+ emit(event: ChangeEvent<[Class, Function]>): void {
25
+ this.#emitter.emit('change', event);
26
26
  }
27
27
 
28
28
  /**
29
29
  * On a class being emitted, check methods
30
30
  */
31
- onClassEvent(e: ChangeEvent<Class>): void {
32
- const next = (e.type !== 'removing' ? describeFunction(e.curr!)?.methods : null) ?? {};
33
- const prev = (e.type !== 'added' ? describeFunction(e.prev!)?.methods : null) ?? {};
31
+ onClassEvent(event: ChangeEvent<Class>): void {
32
+ const next = (event.type !== 'removing' ? describeFunction(event.current!)?.methods : null) ?? {};
33
+ const previous = (event.type !== 'added' ? describeFunction(event.previous!)?.methods : null) ?? {};
34
34
 
35
35
  /**
36
36
  * Go through each method, comparing hashes. To see added/removed and changed
37
37
  */
38
- for (const k of Object.keys(next)) {
39
- if ((!prev[k] || !('prev' in e)) && e.type !== 'removing') {
40
- this.emit({ type: 'added', curr: [e.curr!, e.curr!.prototype[k]] });
41
- } else if (next[k].hash !== prev[k].hash && e.type === 'changed') {
42
- // FIXME: Why is e.prev undefined sometimes?
43
- this.emit({ type: 'changed', curr: [e.curr, e.curr.prototype[k]], prev: [e.prev, e.prev.prototype[k]] });
38
+ for (const key of Object.keys(next)) {
39
+ if ((!previous[key] || !('previous' in event)) && event.type !== 'removing') {
40
+ this.emit({ type: 'added', current: [event.current!, event.current!.prototype[key]] });
41
+ } else if (next[key].hash !== previous[key].hash && event.type === 'changed') {
42
+ // FIXME: Why is event.previous undefined sometimes?
43
+ this.emit({
44
+ type: 'changed',
45
+ current: [event.current, event.current.prototype[key]],
46
+ previous: [event.previous, event.previous.prototype[key]]
47
+ });
44
48
  } else {
45
49
  // Method Unchanged
46
50
  }
47
51
  }
48
52
 
49
- for (const k of Object.keys(prev)) {
50
- if (!next[k] && e.type !== 'added') {
51
- this.emit({ type: 'removing', prev: [e.prev, e.prev.prototype[k]] });
53
+ for (const key of Object.keys(previous)) {
54
+ if (!next[key] && event.type !== 'added') {
55
+ this.emit({ type: 'removing', previous: [event.previous, event.previous.prototype[key]] });
52
56
  }
53
57
  }
54
58
  }
package/src/types.ts CHANGED
@@ -2,14 +2,14 @@
2
2
  * A change event
3
3
  */
4
4
  export type ChangeEvent<T> =
5
- { type: 'changed', prev: T, curr: T } |
6
- { type: 'added', curr: T } |
7
- { type: 'removing', prev: T };
5
+ { type: 'changed', previous: T, current: T } |
6
+ { type: 'added', current: T } |
7
+ { type: 'removing', previous: T };
8
8
 
9
9
  /**
10
10
  * Change handler
11
11
  */
12
- export type ChangeHandler<T> = (e: ChangeEvent<T>) => unknown;
12
+ export type ChangeHandler<T> = (event: ChangeEvent<T>) => unknown;
13
13
 
14
14
  /**
15
15
  * Change source