@travetto/compiler 4.0.7 → 4.0.9
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/package.json +6 -6
- package/src/state.ts +3 -3
- package/src/util.ts +0 -14
- package/src/watch.ts +85 -54
- package/support/server/server.ts +1 -1
- package/support/util.ts +14 -0
- package/tsconfig.trv.json +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/compiler",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.9",
|
|
4
4
|
"description": "The compiler infrastructure for the Travetto framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"compiler",
|
|
@@ -30,13 +30,13 @@
|
|
|
30
30
|
"directory": "module/compiler"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@parcel/watcher": "^2.4.
|
|
34
|
-
"@travetto/manifest": "^4.0.
|
|
35
|
-
"@travetto/transformer": "^4.0.
|
|
36
|
-
"@types/node": "^20.11.
|
|
33
|
+
"@parcel/watcher": "^2.4.1",
|
|
34
|
+
"@travetto/manifest": "^4.0.3",
|
|
35
|
+
"@travetto/transformer": "^4.0.4",
|
|
36
|
+
"@types/node": "^20.11.25"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"@travetto/cli": "^4.0.
|
|
39
|
+
"@travetto/cli": "^4.0.7"
|
|
40
40
|
},
|
|
41
41
|
"peerDependenciesMeta": {
|
|
42
42
|
"@travetto/cli": {
|
package/src/state.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
|
-
import timers from 'node:timers/promises';
|
|
3
2
|
|
|
4
3
|
import { path, ManifestModuleUtil, ManifestModule, ManifestRoot, ManifestIndex } from '@travetto/manifest';
|
|
5
4
|
import { TransformerManager } from '@travetto/transformer';
|
|
@@ -8,6 +7,7 @@ import { TypescriptUtil } from '../support/ts-util';
|
|
|
8
7
|
|
|
9
8
|
import { CompilerUtil } from './util';
|
|
10
9
|
import { CompileEmitError, CompileStateEntry } from './types';
|
|
10
|
+
import { CommonUtil } from '../support/util';
|
|
11
11
|
|
|
12
12
|
function folderMapper(root: string, prefix: string): { dir: string, translate: (val: string) => string } {
|
|
13
13
|
let matched: string = '~~';
|
|
@@ -110,7 +110,7 @@ export class CompilerState implements ts.CompilerHost {
|
|
|
110
110
|
if (force || !this.#program) {
|
|
111
111
|
this.#program = ts.createProgram({ rootNames: this.getAllFiles(), host: this, options: this.#compilerOptions, oldProgram: this.#program });
|
|
112
112
|
this.#transformerManager.init(this.#program.getTypeChecker());
|
|
113
|
-
await
|
|
113
|
+
await CommonUtil.queueMacroTask();
|
|
114
114
|
}
|
|
115
115
|
return this.#program;
|
|
116
116
|
}
|
|
@@ -179,7 +179,7 @@ export class CompilerState implements ts.CompilerHost {
|
|
|
179
179
|
if (!contents || (contents.length === 0 && prevHash)) {
|
|
180
180
|
return false; // Ignore empty file
|
|
181
181
|
}
|
|
182
|
-
const currentHash =
|
|
182
|
+
const currentHash = CommonUtil.naiveHash(contents);
|
|
183
183
|
const changed = prevHash !== currentHash;
|
|
184
184
|
if (changed) {
|
|
185
185
|
this.#sourceHashes.set(inputFile, currentHash);
|
package/src/util.ts
CHANGED
|
@@ -120,18 +120,4 @@ export class CompilerUtil {
|
|
|
120
120
|
}
|
|
121
121
|
return new Error(`Transpiling ${filename.replace(nativeCwd, '.')} failed: \n${errors.join('\n')}`);
|
|
122
122
|
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Naive hashing
|
|
126
|
-
*/
|
|
127
|
-
static naiveHash(text: string): number {
|
|
128
|
-
let hash = 5381;
|
|
129
|
-
|
|
130
|
-
for (let i = 0; i < text.length; i++) {
|
|
131
|
-
// eslint-disable-next-line no-bitwise
|
|
132
|
-
hash = (hash * 33) ^ text.charCodeAt(i);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return Math.abs(hash);
|
|
136
|
-
}
|
|
137
123
|
}
|
package/src/watch.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ManifestModuleFileType, ManifestModuleFolderType, ManifestModuleUtil, ManifestUtil, PackageUtil, RuntimeIndex, path } from '@travetto/manifest';
|
|
2
2
|
|
|
3
3
|
import type { CompileStateEntry } from './types';
|
|
4
4
|
import { CompilerState } from './state';
|
|
@@ -9,6 +9,14 @@ import { AsyncQueue } from '../support/queue';
|
|
|
9
9
|
type WatchAction = 'create' | 'update' | 'delete';
|
|
10
10
|
type WatchEvent = { action: WatchAction, file: string };
|
|
11
11
|
type CompilerWatchEvent = WatchEvent & { entry: CompileStateEntry };
|
|
12
|
+
type FileShape = {
|
|
13
|
+
mod: string;
|
|
14
|
+
folderKey: ManifestModuleFolderType;
|
|
15
|
+
fileType: ManifestModuleFileType;
|
|
16
|
+
moduleFile: string;
|
|
17
|
+
action: WatchAction;
|
|
18
|
+
};
|
|
19
|
+
|
|
12
20
|
|
|
13
21
|
/**
|
|
14
22
|
* Watch support, based on compiler state and manifest details
|
|
@@ -40,8 +48,8 @@ export class CompilerWatcher {
|
|
|
40
48
|
}
|
|
41
49
|
|
|
42
50
|
/** Watch files */
|
|
43
|
-
async * #watchFolder(rootPath: string): AsyncIterable<WatchEvent> {
|
|
44
|
-
const q = new AsyncQueue<WatchEvent>(this.#signal);
|
|
51
|
+
async * #watchFolder(rootPath: string): AsyncIterable<WatchEvent[]> {
|
|
52
|
+
const q = new AsyncQueue<WatchEvent[]>(this.#signal);
|
|
45
53
|
const lib = await import('@parcel/watcher');
|
|
46
54
|
const ignore = this.#getIgnores();
|
|
47
55
|
|
|
@@ -51,9 +59,7 @@ export class CompilerWatcher {
|
|
|
51
59
|
q.throw(err instanceof Error ? err : new Error((err as Error).message));
|
|
52
60
|
return;
|
|
53
61
|
}
|
|
54
|
-
|
|
55
|
-
q.add({ action: ev.type, file: path.toPosix(ev.path) });
|
|
56
|
-
}
|
|
62
|
+
q.add(events.map(ev => ({ action: ev.type, file: path.toPosix(ev.path) })));
|
|
57
63
|
}, { ignore });
|
|
58
64
|
|
|
59
65
|
if (this.#signal.aborted) { // If already aborted, can happen async
|
|
@@ -66,30 +72,49 @@ export class CompilerWatcher {
|
|
|
66
72
|
yield* q;
|
|
67
73
|
}
|
|
68
74
|
|
|
69
|
-
async #rebuildManifestsIfNeeded(
|
|
70
|
-
|
|
75
|
+
async #rebuildManifestsIfNeeded(events: CompilerWatchEvent[]): Promise<void> {
|
|
76
|
+
events = events.filter(x => x.entry.outputFile && x.action !== 'update');
|
|
77
|
+
|
|
78
|
+
if (!events.length) {
|
|
71
79
|
return;
|
|
72
80
|
}
|
|
73
81
|
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
const mods = [...new Set(events.map(v => v.entry.module.name))];
|
|
83
|
+
|
|
84
|
+
const moduleToFiles = new Map(mods.map(m => [m, {
|
|
85
|
+
context: ManifestUtil.getModuleContext(this.#state.manifest, RuntimeIndex.getManifestModule(m)!.sourceFolder),
|
|
86
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
87
|
+
files: [] as FileShape[]
|
|
88
|
+
}] as const));
|
|
89
|
+
|
|
90
|
+
const parents = new Map<string, string[]>(
|
|
91
|
+
mods.map(m => [m, RuntimeIndex.getDependentModules(m, 'parents').map(x => x.name)])
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
const allFiles = events.map(ev => {
|
|
95
|
+
const modRoot = ev.entry.module.sourceFolder || this.#state.manifest.workspace.path;
|
|
96
|
+
const moduleFile = ev.file.includes(modRoot) ? ev.file.split(`${modRoot}/`)[1] : ev.file;
|
|
97
|
+
const folderKey = ManifestModuleUtil.getFolderKey(moduleFile);
|
|
98
|
+
const fileType = ManifestModuleUtil.getFileType(moduleFile);
|
|
99
|
+
return { mod: ev.entry.module.name, action: ev.action, moduleFile, folderKey, fileType };
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
for (const file of allFiles) {
|
|
103
|
+
for (const parent of parents.get(file.mod)!) {
|
|
104
|
+
moduleToFiles.get(parent)!.files.push(file);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
82
107
|
|
|
83
|
-
for (const
|
|
84
|
-
const newManifest = await ManifestUtil.buildManifest(
|
|
85
|
-
|
|
86
|
-
const modFiles = newManifest.modules[mod
|
|
108
|
+
for (const { context, files } of moduleToFiles.values()) {
|
|
109
|
+
const newManifest = await ManifestUtil.buildManifest(context);
|
|
110
|
+
for (const { action, mod, fileType, moduleFile, folderKey } of files) {
|
|
111
|
+
const modFiles = newManifest.modules[mod].files[folderKey] ??= [];
|
|
87
112
|
const idx = modFiles.findIndex(x => x[0] === moduleFile);
|
|
88
113
|
|
|
89
|
-
if (
|
|
114
|
+
if (action === 'create' && idx < 0) {
|
|
90
115
|
modFiles.push([moduleFile, fileType, Date.now()]);
|
|
91
116
|
} else if (idx >= 0) {
|
|
92
|
-
if (
|
|
117
|
+
if (action === 'delete') {
|
|
93
118
|
modFiles.splice(idx, 1);
|
|
94
119
|
} else {
|
|
95
120
|
modFiles[idx] = [moduleFile, fileType, Date.now()];
|
|
@@ -120,45 +145,51 @@ export class CompilerWatcher {
|
|
|
120
145
|
const OUTPUT_PATH = path.resolve(manifest.workspace.path, manifest.build.outputFolder);
|
|
121
146
|
const COMPILER_PATH = path.resolve(manifest.workspace.path, manifest.build.compilerFolder);
|
|
122
147
|
|
|
123
|
-
for await (const
|
|
124
|
-
const { action, file: sourceFile } = ev;
|
|
148
|
+
for await (const events of this.#watchFolder(this.#state.manifest.workspace.path)) {
|
|
125
149
|
|
|
126
|
-
|
|
127
|
-
sourceFile === ROOT_LOCK ||
|
|
128
|
-
sourceFile === ROOT_PKG ||
|
|
129
|
-
(action === 'delete' && (sourceFile === OUTPUT_PATH || sourceFile === COMPILER_PATH))
|
|
130
|
-
) {
|
|
131
|
-
throw new Error('RESET', { cause: `${action}:${sourceFile}` });
|
|
132
|
-
}
|
|
150
|
+
const outEvents: CompilerWatchEvent[] = [];
|
|
133
151
|
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
152
|
+
for (const ev of events) {
|
|
153
|
+
const { action, file: sourceFile } = ev;
|
|
154
|
+
|
|
155
|
+
if (
|
|
156
|
+
sourceFile === ROOT_LOCK ||
|
|
157
|
+
sourceFile === ROOT_PKG ||
|
|
158
|
+
(action === 'delete' && (sourceFile === OUTPUT_PATH || sourceFile === COMPILER_PATH))
|
|
159
|
+
) {
|
|
160
|
+
throw new Error('RESET', { cause: `${action}:${sourceFile}` });
|
|
161
|
+
}
|
|
138
162
|
|
|
139
|
-
|
|
163
|
+
const fileType = ManifestModuleUtil.getFileType(sourceFile);
|
|
164
|
+
if (!CompilerUtil.validFile(fileType)) {
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
140
167
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
168
|
+
let entry = this.#state.getBySource(sourceFile);
|
|
169
|
+
|
|
170
|
+
const mod = entry?.module ?? this.#state.manifestIndex.findModuleForArbitraryFile(sourceFile);
|
|
171
|
+
if (!mod) { // Unknown module
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const modRoot = mod.sourceFolder || this.#state.manifest.workspace.path;
|
|
176
|
+
const moduleFile = sourceFile.includes(modRoot) ? sourceFile.split(`${modRoot}/`)[1] : sourceFile;
|
|
177
|
+
|
|
178
|
+
if (action === 'create') {
|
|
179
|
+
entry = this.#state.registerInput(mod, moduleFile);
|
|
180
|
+
} else if (!entry) {
|
|
181
|
+
continue;
|
|
182
|
+
} else if (action === 'update' && !this.#state.checkIfSourceChanged(entry.inputFile)) {
|
|
183
|
+
continue;
|
|
184
|
+
} else if (action === 'delete') {
|
|
185
|
+
this.#state.removeInput(entry.inputFile);
|
|
186
|
+
}
|
|
145
187
|
|
|
146
|
-
|
|
147
|
-
const moduleFile = sourceFile.includes(modRoot) ? sourceFile.split(`${modRoot}/`)[1] : sourceFile;
|
|
148
|
-
|
|
149
|
-
if (action === 'create') {
|
|
150
|
-
entry = this.#state.registerInput(mod, moduleFile);
|
|
151
|
-
} else if (!entry) {
|
|
152
|
-
continue;
|
|
153
|
-
} else if (action === 'update' && !this.#state.checkIfSourceChanged(entry.inputFile)) {
|
|
154
|
-
continue;
|
|
155
|
-
} else if (action === 'delete') {
|
|
156
|
-
this.#state.removeInput(entry.inputFile);
|
|
188
|
+
outEvents.push({ action, file: entry.sourceFile, entry });
|
|
157
189
|
}
|
|
158
190
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
yield result;
|
|
191
|
+
await this.#rebuildManifestsIfNeeded(outEvents);
|
|
192
|
+
yield* outEvents;
|
|
162
193
|
}
|
|
163
194
|
}
|
|
164
195
|
}
|
package/support/server/server.ts
CHANGED
|
@@ -207,7 +207,7 @@ export class CompilerServer {
|
|
|
207
207
|
CommonUtil.nonBlockingTimeout(2000).then(reject); // Wait 2s max
|
|
208
208
|
this.#server.close(resolve);
|
|
209
209
|
this.#emitEvent({ type: 'state', payload: { state: 'closed' } });
|
|
210
|
-
|
|
210
|
+
CommonUtil.queueMacroTask().then(() => {
|
|
211
211
|
this.#server.closeAllConnections();
|
|
212
212
|
this.#shutdown.abort();
|
|
213
213
|
});
|
package/support/util.ts
CHANGED
|
@@ -58,6 +58,20 @@ export class CommonUtil {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Naive hashing
|
|
63
|
+
*/
|
|
64
|
+
static naiveHash(text: string): number {
|
|
65
|
+
let hash = 5381;
|
|
66
|
+
|
|
67
|
+
for (let i = 0; i < text.length; i++) {
|
|
68
|
+
// eslint-disable-next-line no-bitwise
|
|
69
|
+
hash = (hash * 33) ^ text.charCodeAt(i);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return Math.abs(hash);
|
|
73
|
+
}
|
|
74
|
+
|
|
61
75
|
/**
|
|
62
76
|
* Non-blocking timeout
|
|
63
77
|
*/
|