@travetto/runtime 7.0.0-rc.1 → 7.0.0-rc.3
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 +24 -20
- package/__index__.ts +1 -0
- package/package.json +3 -3
- package/src/binary.ts +14 -14
- package/src/console.ts +15 -15
- package/src/context.ts +18 -22
- package/src/env.ts +30 -30
- package/src/error.ts +15 -15
- package/src/exec.ts +38 -87
- package/src/file-loader.ts +9 -0
- package/src/json.ts +74 -0
- package/src/queue.ts +2 -2
- package/src/resources.ts +3 -3
- package/src/shutdown.ts +4 -4
- package/src/time.ts +11 -11
- package/src/trv.d.ts +0 -4
- package/src/types.ts +13 -12
- package/src/util.ts +25 -101
- package/src/watch.ts +63 -15
- package/support/transformer/metadata.ts +5 -5
- package/support/transformer.concrete-type.ts +4 -4
- package/support/transformer.console-log.ts +5 -5
- package/support/transformer.debug-method.ts +1 -1
- package/support/transformer.function-metadata.ts +2 -2
- package/support/transformer.rewrite-path-import.ts +11 -9
package/src/watch.ts
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
|
+
import { ManifestModuleUtil, type ChangeEventType, type ManifestModuleFileType } from '@travetto/manifest';
|
|
2
|
+
|
|
1
3
|
import { RuntimeIndex } from './manifest-index.ts';
|
|
2
|
-
import { ExecUtil } from './exec.ts';
|
|
3
4
|
import { ShutdownManager } from './shutdown.ts';
|
|
4
5
|
import { Util } from './util.ts';
|
|
6
|
+
import { AppError } from './error.ts';
|
|
7
|
+
|
|
8
|
+
type WatchEvent = { file: string, action: ChangeEventType, output: string, module: string, import: string, time: number };
|
|
5
9
|
|
|
6
|
-
|
|
10
|
+
type WatchCompilerOptions = {
|
|
11
|
+
/**
|
|
12
|
+
* Restart the watch loop on compiler exit
|
|
13
|
+
*/
|
|
14
|
+
restartOnCompilerExit?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Run on restart
|
|
17
|
+
*/
|
|
18
|
+
onRestart?: () => void;
|
|
19
|
+
};
|
|
7
20
|
|
|
8
|
-
export async function* watchCompiler(
|
|
21
|
+
export async function* watchCompiler(config?: WatchCompilerOptions): AsyncIterable<WatchEvent> {
|
|
9
22
|
// Load at runtime
|
|
10
23
|
const { CompilerClient } = await import('@travetto/compiler/support/server/client.ts');
|
|
11
24
|
|
|
@@ -16,24 +29,59 @@ export async function* watchCompiler(cfg?: { restartOnExit?: boolean, signal?: A
|
|
|
16
29
|
info(message, ...args): void { console.error('info', message, ...args); },
|
|
17
30
|
});
|
|
18
31
|
|
|
19
|
-
const
|
|
20
|
-
const remove = ShutdownManager.onGracefulShutdown(async () =>
|
|
32
|
+
const controller = new AbortController();
|
|
33
|
+
const remove = ShutdownManager.onGracefulShutdown(async () => controller.abort());
|
|
34
|
+
|
|
35
|
+
const maxIterations = 10;
|
|
36
|
+
const maxWindow = 10 * 1000;
|
|
37
|
+
const iterations: number[] = [];
|
|
38
|
+
let iterationsExhausted = false;
|
|
21
39
|
|
|
22
|
-
|
|
40
|
+
while (
|
|
41
|
+
!controller.signal.aborted &&
|
|
42
|
+
!iterationsExhausted &&
|
|
43
|
+
(config?.restartOnCompilerExit || iterations.length === 0)
|
|
44
|
+
) {
|
|
45
|
+
if (iterations.length) { // Wait on next iteration
|
|
46
|
+
await Util.nonBlockingTimeout(10);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
await client.waitForState(['compile-end', 'watch-start'], undefined, controller.signal);
|
|
23
50
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
51
|
+
if (!await client.isWatching()) { // If we get here, without a watch
|
|
52
|
+
throw new AppError('Compiler is not running');
|
|
53
|
+
} else {
|
|
54
|
+
if (iterations.length) {
|
|
55
|
+
config?.onRestart?.();
|
|
56
|
+
}
|
|
57
|
+
yield* client.fetchEvents('change', { signal: controller.signal, enforceIteration: true });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
iterations.push(Date.now());
|
|
61
|
+
if (iterations.length >= maxIterations) {
|
|
62
|
+
iterationsExhausted = (Date.now() - iterations[0]) > maxWindow;
|
|
63
|
+
iterations.shift();
|
|
27
64
|
}
|
|
28
|
-
} else {
|
|
29
|
-
yield* client.fetchEvents('change', { signal: ctrl.signal, enforceIteration: true });
|
|
30
65
|
}
|
|
31
66
|
|
|
32
67
|
remove();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function listenForSourceChanges(onChange: () => void, debounceDelay = 10): void {
|
|
71
|
+
let timeout: ReturnType<typeof setTimeout> | undefined;
|
|
72
|
+
|
|
73
|
+
const validFileTypes = new Set<ManifestModuleFileType>(['ts', 'js', 'package-json', 'typings']);
|
|
33
74
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
process.exit(ExecUtil.RESTART_EXIT_CODE);
|
|
75
|
+
function send(): void {
|
|
76
|
+
clearTimeout(timeout);
|
|
77
|
+
timeout = setTimeout(onChange, debounceDelay);
|
|
38
78
|
}
|
|
79
|
+
|
|
80
|
+
(async function (): Promise<void> {
|
|
81
|
+
for await (const item of watchCompiler({ restartOnCompilerExit: true, onRestart: send })) {
|
|
82
|
+
if (validFileTypes.has(ManifestModuleUtil.getFileType(item.file)) && RuntimeIndex.findModuleForArbitraryFile(item.file)) {
|
|
83
|
+
send();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
})();
|
|
39
87
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import ts from 'typescript';
|
|
2
2
|
|
|
3
3
|
import { FunctionMetadataTag } from '@travetto/runtime';
|
|
4
4
|
import { CoreUtil, Import, SystemUtil, TransformerState } from '@travetto/transformer';
|
|
@@ -43,14 +43,14 @@ export class MetadataRegistrationUtil {
|
|
|
43
43
|
*/
|
|
44
44
|
static registerFunction(state: TransformerState & MetadataInfo,
|
|
45
45
|
node: ts.FunctionDeclaration | ts.FunctionExpression,
|
|
46
|
-
|
|
46
|
+
source?: ts.FunctionDeclaration | ts.FunctionExpression | ts.InterfaceDeclaration | ts.TypeAliasDeclaration
|
|
47
47
|
): void {
|
|
48
48
|
// If we have a class like function
|
|
49
49
|
state[RegisterImportSymbol] ??= state.importFile(this.REGISTER_IMPORT);
|
|
50
50
|
|
|
51
|
-
const tag = this.tag(state,
|
|
51
|
+
const tag = this.tag(state, source ?? node);
|
|
52
52
|
const meta = state.factory.createCallExpression(
|
|
53
|
-
state.createAccess(state[RegisterImportSymbol].
|
|
53
|
+
state.createAccess(state[RegisterImportSymbol].identifier, this.REGISTER_FN),
|
|
54
54
|
[],
|
|
55
55
|
[
|
|
56
56
|
state.createIdentifier(node.name!.text),
|
|
@@ -74,7 +74,7 @@ export class MetadataRegistrationUtil {
|
|
|
74
74
|
const name = node.name?.escapedText.toString() ?? '';
|
|
75
75
|
|
|
76
76
|
const meta = state.factory.createCallExpression(
|
|
77
|
-
state.createAccess(state[RegisterImportSymbol].
|
|
77
|
+
state.createAccess(state[RegisterImportSymbol].identifier, this.REGISTER_FN),
|
|
78
78
|
[],
|
|
79
79
|
[
|
|
80
80
|
state.createIdentifier(name),
|
|
@@ -18,7 +18,7 @@ export class ConcreteTransformer {
|
|
|
18
18
|
static #createConcreteFunction(state: TransformerState, name: string | ts.Identifier): ts.FunctionDeclaration {
|
|
19
19
|
const final = typeof name === 'string' ? name : name.getText();
|
|
20
20
|
|
|
21
|
-
const
|
|
21
|
+
const declaration = state.factory.createFunctionDeclaration(
|
|
22
22
|
// eslint-disable-next-line no-bitwise
|
|
23
23
|
state.factory.createModifiersFromModifierFlags(ts.ModifierFlags.Export | ts.ModifierFlags.Const),
|
|
24
24
|
undefined, `${final}$Concrete`, [], [], undefined,
|
|
@@ -26,13 +26,13 @@ export class ConcreteTransformer {
|
|
|
26
26
|
);
|
|
27
27
|
|
|
28
28
|
state.addStatements([
|
|
29
|
-
|
|
29
|
+
declaration,
|
|
30
30
|
state.factory.createExpressionStatement(
|
|
31
31
|
state.factory.createCallExpression(
|
|
32
32
|
state.createAccess('Object', 'defineProperty'),
|
|
33
33
|
undefined,
|
|
34
34
|
[
|
|
35
|
-
|
|
35
|
+
declaration.name!,
|
|
36
36
|
state.fromLiteral('name'),
|
|
37
37
|
state.fromLiteral({ value: final })
|
|
38
38
|
]
|
|
@@ -40,7 +40,7 @@ export class ConcreteTransformer {
|
|
|
40
40
|
)
|
|
41
41
|
]);
|
|
42
42
|
|
|
43
|
-
return
|
|
43
|
+
return declaration;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
/**
|
|
@@ -83,26 +83,26 @@ export class ConsoleLogTransformer {
|
|
|
83
83
|
|
|
84
84
|
const chain = node.expression;
|
|
85
85
|
const name = chain.name;
|
|
86
|
-
const
|
|
86
|
+
const expr = chain.expression;
|
|
87
87
|
|
|
88
|
-
if (!ts.isIdentifier(
|
|
88
|
+
if (!ts.isIdentifier(expr) || expr.escapedText !== 'console' || !ts.isIdentifier(name)) {
|
|
89
89
|
return node;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
const level = name.escapedText!;
|
|
93
93
|
|
|
94
94
|
if (VALID_LEVELS[level]) {
|
|
95
|
-
const
|
|
95
|
+
const identifier = state.imported ??= state.importFile(CONSOLE_IMPORT).identifier;
|
|
96
96
|
return state.factory.updateCallExpression(
|
|
97
97
|
node,
|
|
98
|
-
state.createAccess(
|
|
98
|
+
state.createAccess(identifier, 'log'),
|
|
99
99
|
node.typeArguments,
|
|
100
100
|
[
|
|
101
101
|
LiteralUtil.fromLiteral(state.factory, {
|
|
102
102
|
level: state.factory.createStringLiteral(VALID_LEVELS[level]),
|
|
103
103
|
import: state.getModuleIdentifier(),
|
|
104
104
|
line: state.source.getLineAndCharacterOfPosition(node.getStart(state.source)).line + 1,
|
|
105
|
-
scope: state.scope?.map(
|
|
105
|
+
scope: state.scope?.map(part => part.name).join(':'),
|
|
106
106
|
args: node.arguments.slice(0)
|
|
107
107
|
}),
|
|
108
108
|
]
|
|
@@ -19,7 +19,7 @@ export class DebugEntryTransformer {
|
|
|
19
19
|
@OnMethod('DebugBreak')
|
|
20
20
|
static debugOnEntry(state: TransformerState & DebugState, node: ts.MethodDeclaration): ts.MethodDeclaration {
|
|
21
21
|
if (!state[DebugSymbol]) {
|
|
22
|
-
const imp = state.importFile('@travetto/runtime/src/debug.ts').
|
|
22
|
+
const imp = state.importFile('@travetto/runtime/src/debug.ts').identifier;
|
|
23
23
|
state[DebugSymbol] = CoreUtil.createAccess(state.factory, imp, 'tryDebugger');
|
|
24
24
|
}
|
|
25
25
|
|
|
@@ -52,9 +52,9 @@ export class RegisterTransformer {
|
|
|
52
52
|
return node;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
const { [MethodsSymbol]:
|
|
55
|
+
const { [MethodsSymbol]: method, [ClassSymbol]: cls } = state;
|
|
56
56
|
delete state[ClassSymbol];
|
|
57
|
-
return MetadataRegistrationUtil.registerClass(state, node,
|
|
57
|
+
return MetadataRegistrationUtil.registerClass(state, node, cls!, method);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
/**
|
|
@@ -5,6 +5,9 @@ import { TransformerState, OnFile } from '@travetto/transformer';
|
|
|
5
5
|
const PATH_REGEX = /^['"](node:)?path['"]$/;
|
|
6
6
|
const PATH_IMPORT = '@travetto/manifest/src/path.ts';
|
|
7
7
|
|
|
8
|
+
const isImport = (node: ts.Node): node is ts.ImportDeclaration =>
|
|
9
|
+
ts.isImportDeclaration(node) && PATH_REGEX.test(node.moduleSpecifier?.getText() ?? '');
|
|
10
|
+
|
|
8
11
|
/**
|
|
9
12
|
* Rewriting path imports to use manifest's path
|
|
10
13
|
*/
|
|
@@ -15,18 +18,17 @@ export class PathImportTransformer {
|
|
|
15
18
|
*/
|
|
16
19
|
@OnFile()
|
|
17
20
|
static rewritePathImport(state: TransformerState, node: ts.SourceFile): ts.SourceFile {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
if (stmt) {
|
|
21
|
+
const statement = node.statements.find(isImport);
|
|
22
|
+
if (statement) {
|
|
21
23
|
const updated = state.factory.updateImportDeclaration(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
statement,
|
|
25
|
+
statement.modifiers,
|
|
26
|
+
statement.importClause,
|
|
25
27
|
state.factory.createStringLiteral(PATH_IMPORT),
|
|
26
|
-
|
|
28
|
+
statement.attributes
|
|
27
29
|
);
|
|
28
|
-
return state.factory.updateSourceFile(node, node.statements.map(
|
|
29
|
-
|
|
30
|
+
return state.factory.updateSourceFile(node, node.statements.map(item =>
|
|
31
|
+
item === statement ? updated : item
|
|
30
32
|
));
|
|
31
33
|
}
|
|
32
34
|
return node;
|