@travetto/manifest 5.0.0-rc.0 → 5.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 +5 -30
- package/__index__.ts +1 -2
- package/package.json +1 -1
- package/src/manifest-index.ts +39 -19
- package/src/types/common.ts +1 -10
- package/src/global.d.ts +0 -3
- package/src/runtime.ts +0 -155
- package/support/transformer.function-metadata.ts +0 -142
- package/support/transformer.rewrite-path-import.ts +0 -39
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ During the compilation process, it is helpful to know how the output content dif
|
|
|
35
35
|
## Class and Function Metadata
|
|
36
36
|
For the framework to work properly, metadata needs to be collected about files, classes and functions to uniquely identify them, with support for detecting changes during live reloads. To achieve this, every `class` is decorated with an additional field of `Ⲑid`. `Ⲑid` represents a computed id that is tied to the file/class combination.
|
|
37
37
|
|
|
38
|
-
`Ⲑid` is used heavily throughout the framework for determining which classes are owned by the framework, and being able to lookup
|
|
38
|
+
`Ⲑid` is used heavily throughout the framework for determining which classes are owned by the framework, and being able to lookup associated data by the id.
|
|
39
39
|
|
|
40
40
|
**Code: Test Class**
|
|
41
41
|
```typescript
|
|
@@ -50,11 +50,11 @@ export class TestClass {
|
|
|
50
50
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
51
|
exports.TestClass = void 0;
|
|
52
52
|
const tslib_1 = require("tslib");
|
|
53
|
-
const Ⲑ_runtime_1 = tslib_1.__importStar(require("@travetto/manifest/src/runtime.js"));
|
|
54
53
|
const Ⲑ_decorator_1 = tslib_1.__importStar(require("@travetto/registry/src/decorator.js"));
|
|
55
|
-
|
|
54
|
+
const Ⲑ_function_1 = tslib_1.__importStar(require("@travetto/runtime/src/function.js"));
|
|
55
|
+
var ᚕm = ["@travetto/manifest", "doc/test-class"];
|
|
56
56
|
let TestClass = class TestClass {
|
|
57
|
-
static Ⲑinit = Ⲑ
|
|
57
|
+
static Ⲑinit = Ⲑ_function_1.register(TestClass, ᚕm, { hash: 197152026, lines: [1, 3] }, { doStuff: { hash: 51337554, lines: [2, 2] } }, false, false);
|
|
58
58
|
async doStuff() { }
|
|
59
59
|
};
|
|
60
60
|
exports.TestClass = TestClass;
|
|
@@ -63,21 +63,6 @@ exports.TestClass = TestClass = tslib_1.__decorate([
|
|
|
63
63
|
], TestClass);
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
-
**Terminal: Index Lookup at Runtime**
|
|
67
|
-
```bash
|
|
68
|
-
$ trv main ./doc/lookup.ts
|
|
69
|
-
|
|
70
|
-
{
|
|
71
|
-
id: '@travetto/manifest:doc/test-class○TestClass',
|
|
72
|
-
source: './doc/test-class.ts',
|
|
73
|
-
hash: 197152026,
|
|
74
|
-
lines: [ 1, 3 ],
|
|
75
|
-
methods: { doStuff: { hash: 51337554, lines: [ 2, 2 ] } },
|
|
76
|
-
abstract: false,
|
|
77
|
-
synthetic: false
|
|
78
|
-
}
|
|
79
|
-
```
|
|
80
|
-
|
|
81
66
|
## Module Indexing
|
|
82
67
|
Once the manifest is created, the application runtime can now read this manifest, which allows for influencing runtime behavior. The most common patterns include:
|
|
83
68
|
* Loading all source files
|
|
@@ -91,8 +76,6 @@ Once the manifest is created, the application runtime can now read this manifest
|
|
|
91
76
|
## Path Normalization
|
|
92
77
|
By default, all paths within the framework are assumed to be in a POSIX style, and all input paths are converted to the POSIX style. This works appropriately within a Unix and a Windows environment. This module offers up [path](https://github.com/travetto/travetto/tree/main/module/manifest/src/path.ts#L9) as an equivalent to [Node](https://nodejs.org)'s [http](https://nodejs.org/api/path.html) library. This allows for consistent behavior across all file-interactions.
|
|
93
78
|
|
|
94
|
-
Imports pointing at $`node:path` and $`path` are rewritten at compile time to point to the implementation provided by the module. This allows for seamless import/usage patterns with the reliability needed for cross platform support.
|
|
95
|
-
|
|
96
79
|
## Anatomy of a Manifest
|
|
97
80
|
|
|
98
81
|
**Code: Manifest for @travetto/manifest**
|
|
@@ -140,7 +123,6 @@ Imports pointing at $`node:path` and $`path` are rewritten at compile time to po
|
|
|
140
123
|
],
|
|
141
124
|
"doc": [
|
|
142
125
|
[ "DOC.tsx", "ts", 1868155200000, "doc" ],
|
|
143
|
-
[ "doc/lookup.ts", "ts", 1868155200000, "doc" ],
|
|
144
126
|
[ "doc/test-class.ts", "ts", 1868155200000, "doc" ]
|
|
145
127
|
],
|
|
146
128
|
"$index": [
|
|
@@ -150,26 +132,19 @@ Imports pointing at $`node:path` and $`path` are rewritten at compile time to po
|
|
|
150
132
|
[ "package.json", "package-json", 1868155200000 ]
|
|
151
133
|
],
|
|
152
134
|
"test": [
|
|
153
|
-
[ "test/path.ts", "ts", 1868155200000, "test" ]
|
|
154
|
-
[ "test/runtime.ts", "ts", 1868155200000, "test" ]
|
|
135
|
+
[ "test/path.ts", "ts", 1868155200000, "test" ]
|
|
155
136
|
],
|
|
156
137
|
"test/fixtures": [
|
|
157
138
|
[ "test/fixtures/simple.ts", "fixture", 1868155200000, "test" ]
|
|
158
139
|
],
|
|
159
|
-
"$transformer": [
|
|
160
|
-
[ "support/transformer.function-metadata.ts", "ts", 1868155200000, "compile" ],
|
|
161
|
-
[ "support/transformer.rewrite-path-import.ts", "ts", 1868155200000, "compile" ]
|
|
162
|
-
],
|
|
163
140
|
"src": [
|
|
164
141
|
[ "src/delta.ts", "ts", 1868155200000 ],
|
|
165
142
|
[ "src/dependencies.ts", "ts", 1868155200000 ],
|
|
166
143
|
[ "src/file.ts", "ts", 1868155200000 ],
|
|
167
|
-
[ "src/global.d.ts", "typings", 1868155200000 ],
|
|
168
144
|
[ "src/manifest-index.ts", "ts", 1868155200000 ],
|
|
169
145
|
[ "src/module.ts", "ts", 1868155200000 ],
|
|
170
146
|
[ "src/package.ts", "ts", 1868155200000 ],
|
|
171
147
|
[ "src/path.ts", "ts", 1868155200000 ],
|
|
172
|
-
[ "src/runtime.ts", "ts", 1868155200000 ],
|
|
173
148
|
[ "src/util.ts", "ts", 1868155200000 ],
|
|
174
149
|
[ "src/types/common.ts", "ts", 1868155200000 ],
|
|
175
150
|
[ "src/types/context.ts", "ts", 1868155200000 ],
|
package/__index__.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
/// <reference path="
|
|
1
|
+
/// <reference path="../runtime/src/global.d.ts" />
|
|
2
2
|
|
|
3
3
|
export * from './src/module';
|
|
4
4
|
export * from './src/delta';
|
|
5
5
|
export * from './src/manifest-index';
|
|
6
|
-
export * from './src/runtime';
|
|
7
6
|
export * from './src/package';
|
|
8
7
|
export * from './src/util';
|
|
9
8
|
export * from './src/file';
|
package/package.json
CHANGED
package/src/manifest-index.ts
CHANGED
|
@@ -22,13 +22,12 @@ export class ManifestIndex {
|
|
|
22
22
|
#manifest: ManifestRoot;
|
|
23
23
|
#modules: IndexedModule[];
|
|
24
24
|
#modulesByName: Record<string, IndexedModule> = {};
|
|
25
|
-
#modulesByFolder: Record<string, IndexedModule> = {};
|
|
26
25
|
#outputRoot: string;
|
|
27
26
|
#outputToEntry = new Map<string, IndexedFile>();
|
|
28
27
|
#sourceToEntry = new Map<string, IndexedFile>();
|
|
29
28
|
#importToEntry = new Map<string, IndexedFile>();
|
|
30
29
|
|
|
31
|
-
constructor(manifest: string) {
|
|
30
|
+
constructor(manifest: string = process.env.TRV_MANIFEST!) {
|
|
32
31
|
this.init(manifest);
|
|
33
32
|
}
|
|
34
33
|
|
|
@@ -50,6 +49,14 @@ export class ManifestIndex {
|
|
|
50
49
|
this.#index();
|
|
51
50
|
}
|
|
52
51
|
|
|
52
|
+
/**
|
|
53
|
+
* **WARNING**: This is a destructive operation, and should only be called before loading any code
|
|
54
|
+
* @private
|
|
55
|
+
*/
|
|
56
|
+
reinitForModule(module: string): void {
|
|
57
|
+
this.init(`${this.outputRoot}/node_modules/${module}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
53
60
|
#moduleFiles(m: ManifestModule, files: ManifestModuleFile[]): IndexedFile[] {
|
|
54
61
|
return files.map(([f, type, ts, role = 'std']) => {
|
|
55
62
|
const isSource = type === 'ts' || type === 'js';
|
|
@@ -98,7 +105,6 @@ export class ManifestIndex {
|
|
|
98
105
|
}
|
|
99
106
|
}
|
|
100
107
|
this.#modulesByName = Object.fromEntries(this.#modules.map(x => [x.name, x]));
|
|
101
|
-
this.#modulesByFolder = Object.fromEntries(this.#modules.map(x => [x.sourceFolder, x]));
|
|
102
108
|
|
|
103
109
|
// Store child information
|
|
104
110
|
for (const mod of this.#modules) {
|
|
@@ -162,13 +168,6 @@ export class ManifestIndex {
|
|
|
162
168
|
return this.#modulesByName[name];
|
|
163
169
|
}
|
|
164
170
|
|
|
165
|
-
/**
|
|
166
|
-
* Get module by folder
|
|
167
|
-
*/
|
|
168
|
-
getModuleByFolder(folder: string): IndexedModule | undefined {
|
|
169
|
-
return this.#modulesByFolder[folder];
|
|
170
|
-
}
|
|
171
|
-
|
|
172
171
|
/**
|
|
173
172
|
* Resolve import
|
|
174
173
|
*/
|
|
@@ -203,15 +202,6 @@ export class ManifestIndex {
|
|
|
203
202
|
return name ? this.getModule(name) : undefined;
|
|
204
203
|
}
|
|
205
204
|
|
|
206
|
-
/**
|
|
207
|
-
* Get module from import name
|
|
208
|
-
* @param importName
|
|
209
|
-
*/
|
|
210
|
-
getModuleFromImport(importName: string): IndexedModule | undefined {
|
|
211
|
-
const name = this.getFromImport(importName)?.module;
|
|
212
|
-
return name ? this.getModule(name) : undefined;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
205
|
/**
|
|
216
206
|
* Build module list from an expression list (e.g. `@travetto/rest,-@travetto/log)
|
|
217
207
|
*/
|
|
@@ -266,4 +256,34 @@ export class ManifestIndex {
|
|
|
266
256
|
);
|
|
267
257
|
return lookup(file.replace(`${base}/`, '').split('/'));
|
|
268
258
|
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Get manifest module by name
|
|
262
|
+
*/
|
|
263
|
+
getManifestModule(mod: string): ManifestModule {
|
|
264
|
+
return this.manifest.modules[mod];
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Get manifest modules
|
|
269
|
+
*/
|
|
270
|
+
getManifestModules(): ManifestModule[] {
|
|
271
|
+
return Object.values(this.manifest.modules);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Get main module for manifest
|
|
276
|
+
*/
|
|
277
|
+
get mainModule(): IndexedModule {
|
|
278
|
+
return this.getModule(this.manifest.main.name)!;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Get source file from import location
|
|
283
|
+
* @param importFile
|
|
284
|
+
*/
|
|
285
|
+
getSourceFile(importFile: string | [string, string]): string {
|
|
286
|
+
importFile = Array.isArray(importFile) ? importFile.join('/') : importFile;
|
|
287
|
+
return this.getFromImport(importFile)?.sourceFile ?? importFile;
|
|
288
|
+
}
|
|
269
289
|
}
|
package/src/types/common.ts
CHANGED
|
@@ -8,13 +8,4 @@ export type ManifestModuleFolderType =
|
|
|
8
8
|
'test/fixtures' | 'support/fixtures' | 'support/resources' |
|
|
9
9
|
'$other' | '$transformer';
|
|
10
10
|
|
|
11
|
-
export type ManifestModuleRole = 'std' | 'test' | 'doc' | 'compile' | 'build';
|
|
12
|
-
|
|
13
|
-
export type FunctionMetadataTag = { hash: number, lines: [number, number] };
|
|
14
|
-
export type FunctionMetadata = FunctionMetadataTag & {
|
|
15
|
-
id: string;
|
|
16
|
-
source: string;
|
|
17
|
-
methods?: Record<string, FunctionMetadataTag>;
|
|
18
|
-
synthetic?: boolean;
|
|
19
|
-
abstract?: boolean;
|
|
20
|
-
};
|
|
11
|
+
export type ManifestModuleRole = 'std' | 'test' | 'doc' | 'compile' | 'build';
|
package/src/global.d.ts
DELETED
package/src/runtime.ts
DELETED
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import { path } from './path';
|
|
2
|
-
import { ManifestIndex } from './manifest-index';
|
|
3
|
-
|
|
4
|
-
import type { FunctionMetadata, FunctionMetadataTag } from './types/common';
|
|
5
|
-
import type { IndexedModule, ManifestModule } from './types/manifest';
|
|
6
|
-
import type { ManifestContext } from './types/context';
|
|
7
|
-
|
|
8
|
-
const METADATA = Symbol.for('@travetto/manifest:metadata');
|
|
9
|
-
type Metadated = { [METADATA]: FunctionMetadata };
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Extended manifest index geared for application execution
|
|
13
|
-
*/
|
|
14
|
-
class $RuntimeIndex extends ManifestIndex {
|
|
15
|
-
|
|
16
|
-
#metadata = new Map<string, FunctionMetadata>();
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* **WARNING**: This is a destructive operation, and should only be called before loading any code
|
|
20
|
-
* @private
|
|
21
|
-
*/
|
|
22
|
-
reinitForModule(module: string): void {
|
|
23
|
-
this.init(`${this.outputRoot}/node_modules/${module}`);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Get internal id from file name and optionally, class name
|
|
28
|
-
*/
|
|
29
|
-
getId(filename: string, clsName?: string): string {
|
|
30
|
-
filename = path.toPosix(filename);
|
|
31
|
-
const id = this.getEntry(filename)?.id ?? filename;
|
|
32
|
-
return clsName ? `${id}○${clsName}` : id;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Get main module for manifest
|
|
37
|
-
*/
|
|
38
|
-
get mainModule(): IndexedModule {
|
|
39
|
-
return this.getModule(this.manifest.main.name)!;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Get source file from import location
|
|
44
|
-
* @param outputFile
|
|
45
|
-
*/
|
|
46
|
-
getSourceFile(importFile: string): string {
|
|
47
|
-
return this.getFromImport(importFile)?.sourceFile ?? importFile;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Initialize the meta data for a function/class
|
|
52
|
-
* @param cls Class
|
|
53
|
-
* @param `file` Filename
|
|
54
|
-
* @param `hash` Hash of class contents
|
|
55
|
-
* @param `line` Line number in source
|
|
56
|
-
* @param `methods` Methods and their hashes
|
|
57
|
-
* @param `abstract` Is the class abstract
|
|
58
|
-
* @param `synthetic` Is this code generated at build time
|
|
59
|
-
*/
|
|
60
|
-
registerFunction(
|
|
61
|
-
cls: Function, fileOrImport: string, tag: FunctionMetadataTag,
|
|
62
|
-
methods?: Record<string, FunctionMetadataTag>, abstract?: boolean, synthetic?: boolean
|
|
63
|
-
): boolean {
|
|
64
|
-
const source = this.getSourceFile(fileOrImport);
|
|
65
|
-
const id = this.getId(source, cls.name);
|
|
66
|
-
Object.defineProperty(cls, 'Ⲑid', { value: id });
|
|
67
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
68
|
-
(cls as unknown as Metadated)[METADATA] = { id, source, ...tag, methods, abstract, synthetic };
|
|
69
|
-
this.#metadata.set(id, { id, source, ...tag, methods, abstract, synthetic });
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Retrieve function metadata by function, or function id
|
|
75
|
-
*/
|
|
76
|
-
getFunctionMetadataFromClass(cls: Function | undefined): FunctionMetadata | undefined {
|
|
77
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
78
|
-
return (cls as unknown as Metadated)?.[METADATA];
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Retrieve function metadata by function, or function id
|
|
83
|
-
*/
|
|
84
|
-
getFunctionMetadata(clsId: string | Function): FunctionMetadata | undefined {
|
|
85
|
-
const id = clsId === undefined ? '' : typeof clsId === 'string' ? clsId : clsId.Ⲑid;
|
|
86
|
-
return this.#metadata.get(id);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Resolve module path to folder, with support for main module and monorepo support
|
|
91
|
-
*/
|
|
92
|
-
resolveModulePath(modulePath: string): string {
|
|
93
|
-
const main = this.manifest.main.name;
|
|
94
|
-
const workspace = this.manifest.workspace.path;
|
|
95
|
-
const [base, sub] = modulePath
|
|
96
|
-
.replace(/^(@@?)(#|$)/g, (_, v, r) => `${v === '@' ? main : workspace}${r}`)
|
|
97
|
-
.split('#');
|
|
98
|
-
return path.resolve(this.hasModule(base) ? this.getModule(base)!.sourcePath : base, sub ?? '.');
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Get manifest module by name
|
|
103
|
-
*/
|
|
104
|
-
getManifestModule(mod: string): ManifestModule {
|
|
105
|
-
return this.manifest.modules[mod];
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Get manifest modules
|
|
110
|
-
*/
|
|
111
|
-
getManifestModules(): ManifestModule[] {
|
|
112
|
-
return Object.values(this.manifest.modules);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export const RuntimeIndex = new $RuntimeIndex(process.env.TRV_MANIFEST!);
|
|
117
|
-
|
|
118
|
-
const build = <T extends object, K extends keyof ManifestContext>(inp: T, props: K[]): T & Pick<ManifestContext, K> => {
|
|
119
|
-
for (const prop of props) {
|
|
120
|
-
Object.defineProperty(inp, prop, { configurable: false, get: () => RuntimeIndex.manifest[prop] });
|
|
121
|
-
}
|
|
122
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
123
|
-
return inp as T & ManifestContext;
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
export const RuntimeContext = build({
|
|
127
|
-
/**
|
|
128
|
-
* Produce a workspace relative path
|
|
129
|
-
* @param rel The relative path
|
|
130
|
-
*/
|
|
131
|
-
workspaceRelative(...rel: string[]): string {
|
|
132
|
-
return path.resolve(RuntimeIndex.manifest.workspace.path, ...rel);
|
|
133
|
-
},
|
|
134
|
-
/**
|
|
135
|
-
* Strip off the workspace path from a file
|
|
136
|
-
* @param full A full path
|
|
137
|
-
*/
|
|
138
|
-
stripWorkspacePath(full: string): string {
|
|
139
|
-
return full === RuntimeIndex.manifest.workspace.path ? '' : full.replace(`${RuntimeIndex.manifest.workspace.path}/`, '');
|
|
140
|
-
},
|
|
141
|
-
/**
|
|
142
|
-
* Produce a workspace path for tooling, with '@' being replaced by node_module/name folder
|
|
143
|
-
* @param rel The relative path
|
|
144
|
-
*/
|
|
145
|
-
toolPath(...rel: string[]): string {
|
|
146
|
-
rel = rel.flatMap(x => x === '@' ? ['node_modules', RuntimeIndex.manifest.main.name] : [x]);
|
|
147
|
-
return path.resolve(RuntimeIndex.manifest.workspace.path, RuntimeIndex.manifest.build.toolFolder, ...rel);
|
|
148
|
-
},
|
|
149
|
-
/**
|
|
150
|
-
* Are we running from a mono-root?
|
|
151
|
-
*/
|
|
152
|
-
get monoRoot(): boolean {
|
|
153
|
-
return !!RuntimeIndex.manifest.workspace.mono && !RuntimeIndex.manifest.main.folder;
|
|
154
|
-
}
|
|
155
|
-
}, ['main', 'workspace']);
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import ts from 'typescript';
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
TransformerState, OnMethod, OnClass, AfterClass,
|
|
5
|
-
AfterFunction, CoreUtil, SystemUtil, Import
|
|
6
|
-
} from '@travetto/transformer';
|
|
7
|
-
|
|
8
|
-
import type { FunctionMetadataTag } from '../src/types/common';
|
|
9
|
-
|
|
10
|
-
const MANIFEST_MOD = '@travetto/manifest';
|
|
11
|
-
const MANIFEST_MOD_SRC = `${MANIFEST_MOD}/src`;
|
|
12
|
-
const MANIFEST_IDX = `${MANIFEST_MOD}/__index__`;
|
|
13
|
-
|
|
14
|
-
const RUNTIME_IDX_IMPORT = `${MANIFEST_MOD_SRC}/runtime`;
|
|
15
|
-
const RUNTIME_IDX_CLS = 'RuntimeIndex';
|
|
16
|
-
|
|
17
|
-
const methods = Symbol.for(`${MANIFEST_MOD}:methods`);
|
|
18
|
-
const cls = Symbol.for(`${MANIFEST_MOD}:class`);
|
|
19
|
-
const fn = Symbol.for(`${MANIFEST_MOD}:function`);
|
|
20
|
-
const runtimeIdx = Symbol.for(`${MANIFEST_MOD}:runtimeIndex`);
|
|
21
|
-
|
|
22
|
-
interface MetadataInfo {
|
|
23
|
-
[runtimeIdx]?: Import;
|
|
24
|
-
[methods]?: Record<string, FunctionMetadataTag>;
|
|
25
|
-
[cls]?: FunctionMetadataTag;
|
|
26
|
-
[fn]?: number;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Providing metadata for classes
|
|
31
|
-
*/
|
|
32
|
-
export class RegisterTransformer {
|
|
33
|
-
|
|
34
|
-
static #tag(state: TransformerState, node: ts.Node): FunctionMetadataTag {
|
|
35
|
-
const hash = SystemUtil.naiveHash(node.getText());
|
|
36
|
-
try {
|
|
37
|
-
const range = CoreUtil.getRangeOf(state.source, node) ?? [0, 0];
|
|
38
|
-
return { hash, lines: range };
|
|
39
|
-
} catch (err) {
|
|
40
|
-
return { hash, lines: [0, 0] };
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
static #valid({ importName: imp }: TransformerState): boolean {
|
|
45
|
-
return !imp.startsWith(MANIFEST_MOD_SRC) && imp !== MANIFEST_IDX;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Hash each class
|
|
50
|
-
*/
|
|
51
|
-
@OnClass()
|
|
52
|
-
static collectClassMetadata(state: TransformerState & MetadataInfo, node: ts.ClassDeclaration): ts.ClassDeclaration {
|
|
53
|
-
if (!this.#valid(state)) {
|
|
54
|
-
return node; // Exclude self
|
|
55
|
-
}
|
|
56
|
-
state[cls] = this.#tag(state, node);
|
|
57
|
-
return node;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Hash each method
|
|
62
|
-
*/
|
|
63
|
-
@OnMethod()
|
|
64
|
-
static collectMethodMetadata(state: TransformerState & MetadataInfo, node: ts.MethodDeclaration): ts.MethodDeclaration {
|
|
65
|
-
if (state[cls] && ts.isIdentifier(node.name) && !CoreUtil.isAbstract(node) && ts.isClassDeclaration(node.parent)) {
|
|
66
|
-
state[methods] ??= {};
|
|
67
|
-
state[methods]![node.name.escapedText.toString()] = this.#tag(state, node);
|
|
68
|
-
}
|
|
69
|
-
return node;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* After visiting each class, register all the collected metadata
|
|
74
|
-
*/
|
|
75
|
-
@AfterClass()
|
|
76
|
-
static registerClassMetadata(state: TransformerState & MetadataInfo, node: ts.ClassDeclaration): ts.ClassDeclaration {
|
|
77
|
-
if (!state[cls]) {
|
|
78
|
-
return node;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
state[runtimeIdx] ??= state.importFile(RUNTIME_IDX_IMPORT);
|
|
82
|
-
const ident = state.createAccess(state[runtimeIdx].ident, RUNTIME_IDX_CLS);
|
|
83
|
-
|
|
84
|
-
const name = node.name?.escapedText.toString() ?? '';
|
|
85
|
-
|
|
86
|
-
const meta = state.factory.createCallExpression(
|
|
87
|
-
state.createAccess(ident, 'registerFunction'),
|
|
88
|
-
[],
|
|
89
|
-
[
|
|
90
|
-
state.createIdentifier(name),
|
|
91
|
-
state.getFilenameIdentifier(),
|
|
92
|
-
state.fromLiteral(state[cls]),
|
|
93
|
-
state.extendObjectLiteral(state[methods] || {}),
|
|
94
|
-
state.fromLiteral(CoreUtil.isAbstract(node)),
|
|
95
|
-
state.fromLiteral(name.endsWith(TransformerState.SYNTHETIC_EXT))
|
|
96
|
-
]
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
state[methods] = {};
|
|
100
|
-
delete state[cls];
|
|
101
|
-
|
|
102
|
-
return state.factory.updateClassDeclaration(
|
|
103
|
-
node,
|
|
104
|
-
node.modifiers,
|
|
105
|
-
node.name,
|
|
106
|
-
node.typeParameters,
|
|
107
|
-
node.heritageClauses,
|
|
108
|
-
[
|
|
109
|
-
state.createStaticField('Ⲑinit', meta),
|
|
110
|
-
...node.members
|
|
111
|
-
]
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Give proper functions a file name
|
|
117
|
-
*/
|
|
118
|
-
@AfterFunction()
|
|
119
|
-
static registerFunctionMetadata(state: TransformerState & MetadataInfo, node: ts.FunctionDeclaration | ts.FunctionExpression): typeof node {
|
|
120
|
-
if (!this.#valid(state)) {
|
|
121
|
-
return node;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
if (ts.isFunctionDeclaration(node) && node.name && node.parent && ts.isSourceFile(node.parent)) {
|
|
125
|
-
// If we have a class like function
|
|
126
|
-
state[runtimeIdx] ??= state.importFile(RUNTIME_IDX_IMPORT);
|
|
127
|
-
const ident = state.createAccess(state[runtimeIdx].ident, RUNTIME_IDX_CLS);
|
|
128
|
-
const tag = this.#tag(state, node);
|
|
129
|
-
const meta = state.factory.createCallExpression(
|
|
130
|
-
state.createAccess(ident, 'registerFunction'),
|
|
131
|
-
[],
|
|
132
|
-
[
|
|
133
|
-
state.createIdentifier(node.name),
|
|
134
|
-
state.getFilenameIdentifier(),
|
|
135
|
-
state.fromLiteral(tag),
|
|
136
|
-
]
|
|
137
|
-
);
|
|
138
|
-
state.addStatements([state.factory.createExpressionStatement(meta)]);
|
|
139
|
-
}
|
|
140
|
-
return node;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import ts from 'typescript';
|
|
2
|
-
|
|
3
|
-
import { TransformerState, OnFile } from '@travetto/transformer';
|
|
4
|
-
|
|
5
|
-
const PATH_REGEX = /^['"](node:)?path['"]$/;
|
|
6
|
-
const PATH_TARGET = '@travetto/manifest/src/path';
|
|
7
|
-
const SKIP_SRC = /^@travetto\/manifest\/(src|support)/;
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Rewriting path imports to use manifest's path
|
|
11
|
-
*/
|
|
12
|
-
export class PathImportTransformer {
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Hash each class
|
|
16
|
-
*/
|
|
17
|
-
@OnFile()
|
|
18
|
-
static rewritePathImport(state: TransformerState, node: ts.SourceFile): ts.SourceFile {
|
|
19
|
-
if (SKIP_SRC.test(state.importName)) {
|
|
20
|
-
return node;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const stmt = node.statements.find((x): x is ts.ImportDeclaration =>
|
|
24
|
-
ts.isImportDeclaration(x) && PATH_REGEX.test(x.moduleSpecifier?.getText() ?? ''));
|
|
25
|
-
if (stmt) {
|
|
26
|
-
const updated = state.factory.updateImportDeclaration(
|
|
27
|
-
stmt,
|
|
28
|
-
stmt.modifiers,
|
|
29
|
-
stmt.importClause,
|
|
30
|
-
state.factory.createStringLiteral(PATH_TARGET),
|
|
31
|
-
stmt.attributes
|
|
32
|
-
);
|
|
33
|
-
return state.factory.updateSourceFile(node, node.statements.map(x =>
|
|
34
|
-
x === stmt ? updated : x
|
|
35
|
-
));
|
|
36
|
-
}
|
|
37
|
-
return node;
|
|
38
|
-
}
|
|
39
|
-
}
|