@travetto/registry 5.0.0-rc.2 → 5.0.0-rc.4
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 +9 -13
- package/package.json +4 -4
- package/src/proxy.ts +2 -2
- package/src/source/class-source.ts +45 -30
- package/src/decorator.ts +0 -43
- package/support/transformer.register.ts +0 -38
package/README.md
CHANGED
|
@@ -82,32 +82,30 @@ As mentioned in [Manifest](https://github.com/travetto/travetto/tree/main/module
|
|
|
82
82
|
**Code: Sample Class Diffing**
|
|
83
83
|
```typescript
|
|
84
84
|
|
|
85
|
-
#handleFileChanges(
|
|
85
|
+
#handleFileChanges(importFile: string, classes: Class[] = []): number {
|
|
86
86
|
const next = new Map<string, Class>(classes.map(cls => [cls.Ⲑid, cls] as const));
|
|
87
87
|
|
|
88
88
|
let prev = new Map<string, Class>();
|
|
89
|
-
if (this.#classes.has(
|
|
90
|
-
prev = new Map(this.#classes.get(
|
|
89
|
+
if (this.#classes.has(importFile)) {
|
|
90
|
+
prev = new Map(this.#classes.get(importFile)!.entries());
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
const keys = new Set([...Array.from(prev.keys()), ...Array.from(next.keys())]);
|
|
94
94
|
|
|
95
|
-
if (!this.#classes.has(
|
|
96
|
-
this.#classes.set(
|
|
95
|
+
if (!this.#classes.has(importFile)) {
|
|
96
|
+
this.#classes.set(importFile, new Map());
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
let changes = 0;
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
* Determine delta based on the various classes (if being added, removed or updated)
|
|
103
|
-
*/
|
|
101
|
+
// Determine delta based on the various classes (if being added, removed or updated)
|
|
104
102
|
for (const k of keys) {
|
|
105
103
|
if (!next.has(k)) {
|
|
106
104
|
changes += 1;
|
|
107
105
|
this.emit({ type: 'removing', prev: prev.get(k)! });
|
|
108
|
-
this.#classes.get(
|
|
106
|
+
this.#classes.get(importFile)!.delete(k);
|
|
109
107
|
} else {
|
|
110
|
-
this.#classes.get(
|
|
108
|
+
this.#classes.get(importFile)!.set(k, next.get(k)!);
|
|
111
109
|
if (!prev.has(k)) {
|
|
112
110
|
changes += 1;
|
|
113
111
|
this.emit({ type: 'added', curr: next.get(k)! });
|
|
@@ -121,8 +119,6 @@ As mentioned in [Manifest](https://github.com/travetto/travetto/tree/main/module
|
|
|
121
119
|
}
|
|
122
120
|
}
|
|
123
121
|
}
|
|
124
|
-
|
|
125
|
-
this.#emitter.emit('unchanged-file', file);
|
|
126
|
-
}
|
|
122
|
+
return changes;
|
|
127
123
|
}
|
|
128
124
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/registry",
|
|
3
|
-
"version": "5.0.0-rc.
|
|
3
|
+
"version": "5.0.0-rc.4",
|
|
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": "^5.0.0-rc.
|
|
30
|
+
"@travetto/runtime": "^5.0.0-rc.4"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
|
-
"@travetto/cli": "^5.0.0-rc.
|
|
34
|
-
"@travetto/transformer": "^5.0.0-rc.
|
|
33
|
+
"@travetto/cli": "^5.0.0-rc.4",
|
|
34
|
+
"@travetto/transformer": "^5.0.0-rc.3"
|
|
35
35
|
},
|
|
36
36
|
"peerDependenciesMeta": {
|
|
37
37
|
"@travetto/transformer": {
|
package/src/proxy.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { ConcreteClass } from '@travetto/runtime';
|
|
2
|
+
|
|
3
3
|
const ProxyTargetⲐ = Symbol.for('@travetto/runtime:proxy-target');
|
|
4
4
|
|
|
5
5
|
const AsyncGeneratorFunction = Object.getPrototypeOf(async function* () { });
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events';
|
|
2
2
|
|
|
3
3
|
import { type FindConfig } from '@travetto/manifest';
|
|
4
|
-
import { Class, Env, Runtime, RuntimeIndex, describeFunction } from '@travetto/runtime';
|
|
4
|
+
import { Class, Env, Runtime, RuntimeIndex, describeFunction, flushPendingFunctions } from '@travetto/runtime';
|
|
5
5
|
|
|
6
6
|
import { DynamicFileLoader } from '../internal/file-loader';
|
|
7
7
|
import { ChangeSource, ChangeEvent, ChangeHandler } from '../types';
|
|
8
|
-
import { PendingRegister } from '../decorator';
|
|
9
8
|
|
|
10
9
|
const moduleFindConfig: FindConfig = {
|
|
11
10
|
module: (m) => {
|
|
@@ -18,6 +17,10 @@ const moduleFindConfig: FindConfig = {
|
|
|
18
17
|
folder: f => f === 'src' || f === '$index'
|
|
19
18
|
};
|
|
20
19
|
|
|
20
|
+
function isClass(cls: Function): cls is Class {
|
|
21
|
+
return !!describeFunction(cls).class;
|
|
22
|
+
}
|
|
23
|
+
|
|
21
24
|
/**
|
|
22
25
|
* A class change source. Meant to be hooked into the
|
|
23
26
|
* compiler as a way to listen to changes via the compiler
|
|
@@ -37,48 +40,43 @@ export class ClassSource implements ChangeSource<Class> {
|
|
|
37
40
|
* Flush classes
|
|
38
41
|
*/
|
|
39
42
|
#flush(): void {
|
|
40
|
-
for (const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
this.#classes.set(file, new Map());
|
|
45
|
-
for (const cls of classes) {
|
|
46
|
-
const src = Runtime.getSource(cls);
|
|
47
|
-
this.#classes.get(src)!.set(cls.Ⲑid, cls);
|
|
48
|
-
this.emit({ type: 'added', curr: cls });
|
|
43
|
+
for (const cls of flushPendingFunctions().filter(isClass)) {
|
|
44
|
+
const src = Runtime.getImport(cls);
|
|
45
|
+
if (!this.#classes.has(src)) {
|
|
46
|
+
this.#classes.set(src, new Map());
|
|
49
47
|
}
|
|
48
|
+
this.#classes.get(src)!.set(cls.Ⲑid, cls);
|
|
49
|
+
this.emit({ type: 'added', curr: cls });
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
|
-
*
|
|
54
|
+
* Process changes for a single file, looking for add/remove/update of classes
|
|
55
55
|
*/
|
|
56
|
-
#handleFileChanges(
|
|
56
|
+
#handleFileChanges(importFile: string, classes: Class[] = []): number {
|
|
57
57
|
const next = new Map<string, Class>(classes.map(cls => [cls.Ⲑid, cls] as const));
|
|
58
58
|
|
|
59
59
|
let prev = new Map<string, Class>();
|
|
60
|
-
if (this.#classes.has(
|
|
61
|
-
prev = new Map(this.#classes.get(
|
|
60
|
+
if (this.#classes.has(importFile)) {
|
|
61
|
+
prev = new Map(this.#classes.get(importFile)!.entries());
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
const keys = new Set([...Array.from(prev.keys()), ...Array.from(next.keys())]);
|
|
65
65
|
|
|
66
|
-
if (!this.#classes.has(
|
|
67
|
-
this.#classes.set(
|
|
66
|
+
if (!this.#classes.has(importFile)) {
|
|
67
|
+
this.#classes.set(importFile, new Map());
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
let changes = 0;
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
* Determine delta based on the various classes (if being added, removed or updated)
|
|
74
|
-
*/
|
|
72
|
+
// Determine delta based on the various classes (if being added, removed or updated)
|
|
75
73
|
for (const k of keys) {
|
|
76
74
|
if (!next.has(k)) {
|
|
77
75
|
changes += 1;
|
|
78
76
|
this.emit({ type: 'removing', prev: prev.get(k)! });
|
|
79
|
-
this.#classes.get(
|
|
77
|
+
this.#classes.get(importFile)!.delete(k);
|
|
80
78
|
} else {
|
|
81
|
-
this.#classes.get(
|
|
79
|
+
this.#classes.get(importFile)!.set(k, next.get(k)!);
|
|
82
80
|
if (!prev.has(k)) {
|
|
83
81
|
changes += 1;
|
|
84
82
|
this.emit({ type: 'added', curr: next.get(k)! });
|
|
@@ -92,8 +90,26 @@ export class ClassSource implements ChangeSource<Class> {
|
|
|
92
90
|
}
|
|
93
91
|
}
|
|
94
92
|
}
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
return changes;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Process all class changes
|
|
98
|
+
*/
|
|
99
|
+
#handleChanges(classes: Class[] = []): void {
|
|
100
|
+
const classesByFile = new Map<string, Class[]>();
|
|
101
|
+
for (const el of classes) {
|
|
102
|
+
const imp = Runtime.getImport(el);
|
|
103
|
+
if (!classesByFile.has(imp)) {
|
|
104
|
+
classesByFile.set(imp, []);
|
|
105
|
+
}
|
|
106
|
+
classesByFile.get(imp)!.push(el);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
for (const [imp, els] of classesByFile.entries()) {
|
|
110
|
+
if (!this.#handleFileChanges(imp, els)) {
|
|
111
|
+
this.#emitter.emit('unchanged-import', imp);
|
|
112
|
+
}
|
|
97
113
|
}
|
|
98
114
|
}
|
|
99
115
|
|
|
@@ -113,9 +129,8 @@ export class ClassSource implements ChangeSource<Class> {
|
|
|
113
129
|
async init(): Promise<void> {
|
|
114
130
|
if (Runtime.dynamic) {
|
|
115
131
|
DynamicFileLoader.onLoadEvent(ev => {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
132
|
+
this.#handleChanges(flushPendingFunctions().filter(isClass));
|
|
133
|
+
|
|
119
134
|
if (ev.action === 'create') {
|
|
120
135
|
this.#flush();
|
|
121
136
|
}
|
|
@@ -140,9 +155,9 @@ export class ClassSource implements ChangeSource<Class> {
|
|
|
140
155
|
}
|
|
141
156
|
|
|
142
157
|
/**
|
|
143
|
-
* Add callback for when a
|
|
158
|
+
* Add callback for when a import is changed, but emits no class changes
|
|
144
159
|
*/
|
|
145
|
-
onNonClassChanges(callback: (
|
|
146
|
-
this.#emitter.on('unchanged-
|
|
160
|
+
onNonClassChanges(callback: (imp: string) => void): void {
|
|
161
|
+
this.#emitter.on('unchanged-import', callback);
|
|
147
162
|
}
|
|
148
163
|
}
|
package/src/decorator.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { Class, Runtime } from '@travetto/runtime';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Register a class as pending
|
|
5
|
-
*/
|
|
6
|
-
class $PendingRegister {
|
|
7
|
-
map = new Map<string, Class[]>();
|
|
8
|
-
ordered: [string, Class[]][] = [];
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Register class as pending
|
|
12
|
-
*/
|
|
13
|
-
add(cls: Class): void {
|
|
14
|
-
const src = Runtime.getSource(cls);
|
|
15
|
-
if (!this.map.has(src)) {
|
|
16
|
-
const sub: Class[] = [];
|
|
17
|
-
this.map.set(src, sub);
|
|
18
|
-
this.ordered.push([src, sub]);
|
|
19
|
-
}
|
|
20
|
-
this.map.get(src)!.push(cls);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Clear pending classes
|
|
25
|
-
*/
|
|
26
|
-
flush(log?: boolean): [string, Class[]][] {
|
|
27
|
-
if (log) {
|
|
28
|
-
console.debug('Pending changes', { changes: this.ordered.map(([, x]) => x.map(y => y.Ⲑid)) });
|
|
29
|
-
}
|
|
30
|
-
const out = this.ordered.slice(0);
|
|
31
|
-
this.map.clear();
|
|
32
|
-
this.ordered = [];
|
|
33
|
-
return out;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export const PendingRegister = new $PendingRegister();
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Decorator to track class as pending
|
|
41
|
-
*/
|
|
42
|
-
export const Register = () =>
|
|
43
|
-
(target: Class): void => PendingRegister.add(target);
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import ts from 'typescript';
|
|
2
|
-
|
|
3
|
-
import { TransformerState, AfterClass, DecoratorUtil } from '@travetto/transformer';
|
|
4
|
-
|
|
5
|
-
const REGISTER_MOD = '@travetto/registry/src/decorator';
|
|
6
|
-
const SKIP_SRC = /^@travetto\/(runtime|manifest)\/(src|support)/;
|
|
7
|
-
const SKIP_FUNCTION = /^@travetto\/registry\/src\/function/;
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Registration of all classes to support the registry
|
|
11
|
-
*/
|
|
12
|
-
export class RegisterTransformer {
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* After visiting each class, register all the collected metadata
|
|
16
|
-
*/
|
|
17
|
-
@AfterClass()
|
|
18
|
-
static registerClass(state: TransformerState, node: ts.ClassDeclaration): ts.ClassDeclaration {
|
|
19
|
-
if (
|
|
20
|
-
state.importName === REGISTER_MOD ||
|
|
21
|
-
SKIP_SRC.test(state.importName) ||
|
|
22
|
-
SKIP_FUNCTION.test(state.importName)
|
|
23
|
-
) { // Cannot process self
|
|
24
|
-
return node;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return state.factory.updateClassDeclaration(
|
|
28
|
-
node,
|
|
29
|
-
DecoratorUtil.spliceDecorators(
|
|
30
|
-
node, undefined, [state.createDecorator(REGISTER_MOD, 'Register')], 0
|
|
31
|
-
),
|
|
32
|
-
node.name,
|
|
33
|
-
node.typeParameters,
|
|
34
|
-
node.heritageClauses,
|
|
35
|
-
node.members
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
}
|