@travetto/runtime 5.0.0-rc.10
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/LICENSE +21 -0
- package/README.md +356 -0
- package/__index__.ts +19 -0
- package/package.json +51 -0
- package/src/binary.ts +108 -0
- package/src/console.ts +137 -0
- package/src/context.ts +122 -0
- package/src/debug.ts +18 -0
- package/src/env.ts +109 -0
- package/src/error.ts +66 -0
- package/src/exec.ts +156 -0
- package/src/file-loader.ts +59 -0
- package/src/function.ts +61 -0
- package/src/global.d.ts +20 -0
- package/src/manifest-index.ts +4 -0
- package/src/queue.ts +64 -0
- package/src/resources.ts +28 -0
- package/src/shutdown.ts +65 -0
- package/src/time.ts +100 -0
- package/src/trv.d.ts +64 -0
- package/src/types.ts +73 -0
- package/src/util.ts +134 -0
- package/src/watch.ts +38 -0
- package/support/transformer.console-log.ts +112 -0
- package/support/transformer.debug-method.ts +41 -0
- package/support/transformer.function-metadata.ts +144 -0
- package/support/transformer.rewrite-path-import.ts +39 -0
- package/support/transformer.type-helpers.ts +25 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
TransformerState, OnCall, LiteralUtil,
|
|
5
|
+
OnClass, AfterClass, OnMethod, AfterMethod, AfterFunction, OnFunction
|
|
6
|
+
} from '@travetto/transformer';
|
|
7
|
+
|
|
8
|
+
const CONSOLE_IMPORT = '@travetto/runtime/src/console';
|
|
9
|
+
const MANIFEST_MOD = '@travetto/manifest';
|
|
10
|
+
|
|
11
|
+
type CustomState = TransformerState & {
|
|
12
|
+
scope: { type: 'method' | 'class' | 'function', name: string }[];
|
|
13
|
+
imported?: ts.Identifier;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const VALID_LEVELS: Record<string, string> = {
|
|
17
|
+
log: 'info',
|
|
18
|
+
info: 'info',
|
|
19
|
+
debug: 'debug',
|
|
20
|
+
warn: 'warn',
|
|
21
|
+
error: 'error'
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Logging support with code-location aware messages.
|
|
26
|
+
*/
|
|
27
|
+
export class ConsoleLogTransformer {
|
|
28
|
+
|
|
29
|
+
static initState(state: CustomState): void {
|
|
30
|
+
state.scope = state.scope ?? [];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@OnClass()
|
|
34
|
+
static startClassForLog(state: CustomState, node: ts.ClassDeclaration): typeof node {
|
|
35
|
+
this.initState(state);
|
|
36
|
+
state.scope.push({ type: 'class', name: node.name?.text ?? 'unknown' });
|
|
37
|
+
return node;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@AfterClass()
|
|
41
|
+
static leaveClassForLog(state: CustomState, node: ts.ClassDeclaration): typeof node {
|
|
42
|
+
state.scope.pop();
|
|
43
|
+
return node;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@OnMethod()
|
|
47
|
+
static startMethodForLog(state: CustomState, node: ts.MethodDeclaration): typeof node {
|
|
48
|
+
this.initState(state);
|
|
49
|
+
let name = 'unknown';
|
|
50
|
+
if (ts.isIdentifier(node.name) || ts.isPrivateIdentifier(node.name)) {
|
|
51
|
+
name = node.name?.text ?? name;
|
|
52
|
+
}
|
|
53
|
+
state.scope.push({ type: 'method', name });
|
|
54
|
+
return node;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@AfterMethod()
|
|
58
|
+
static leaveMethodForLog(state: CustomState, node: ts.MethodDeclaration): typeof node {
|
|
59
|
+
state.scope.pop();
|
|
60
|
+
return node;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@OnFunction()
|
|
64
|
+
static startFunctionForLog(state: CustomState, node: ts.FunctionDeclaration | ts.FunctionExpression): typeof node {
|
|
65
|
+
this.initState(state);
|
|
66
|
+
state.scope.push({ type: 'function', name: node.name?.text ?? 'unknown' });
|
|
67
|
+
return node;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@AfterFunction()
|
|
71
|
+
static leaveFunctionForLog(state: CustomState, node: ts.FunctionDeclaration | ts.FunctionExpression): typeof node {
|
|
72
|
+
state.scope.pop();
|
|
73
|
+
return node;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@OnCall()
|
|
77
|
+
static onLogCall(state: CustomState, node: ts.CallExpression): typeof node | ts.Identifier {
|
|
78
|
+
if (!ts.isPropertyAccessExpression(node.expression) || state.importName.startsWith(MANIFEST_MOD)) {
|
|
79
|
+
return node;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const chain = node.expression;
|
|
83
|
+
const name = chain.name;
|
|
84
|
+
const prop = chain.expression;
|
|
85
|
+
|
|
86
|
+
if (!ts.isIdentifier(prop) || prop.escapedText !== 'console' || !ts.isIdentifier(name)) {
|
|
87
|
+
return node;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const level = name.escapedText!;
|
|
91
|
+
|
|
92
|
+
if (VALID_LEVELS[level]) {
|
|
93
|
+
const ident = state.imported ??= state.importFile(CONSOLE_IMPORT, 'ᚕ_c').ident;
|
|
94
|
+
return state.factory.updateCallExpression(
|
|
95
|
+
node,
|
|
96
|
+
state.createAccess(ident, 'log'),
|
|
97
|
+
node.typeArguments,
|
|
98
|
+
[
|
|
99
|
+
LiteralUtil.fromLiteral(state.factory, {
|
|
100
|
+
level: state.factory.createStringLiteral(VALID_LEVELS[level]),
|
|
101
|
+
import: state.getModuleIdentifier(),
|
|
102
|
+
line: state.source.getLineAndCharacterOfPosition(node.getStart(state.source)).line + 1,
|
|
103
|
+
scope: state.scope?.map(x => x.name).join(':'),
|
|
104
|
+
args: node.arguments.slice(0)
|
|
105
|
+
}),
|
|
106
|
+
]
|
|
107
|
+
);
|
|
108
|
+
} else {
|
|
109
|
+
return node;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
|
|
3
|
+
import { TransformerState, OnMethod, CoreUtil } from '@travetto/transformer';
|
|
4
|
+
|
|
5
|
+
const DebugⲐ = Symbol.for('@travetto/runtime:debug');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Debug transformation state
|
|
9
|
+
*/
|
|
10
|
+
interface DebugState {
|
|
11
|
+
[DebugⲐ]?: ts.Expression;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Add debugger-optional statement to methods that should be debuggable
|
|
16
|
+
*/
|
|
17
|
+
export class DebugEntryTransformer {
|
|
18
|
+
|
|
19
|
+
@OnMethod('DebugBreak')
|
|
20
|
+
static debugOnEntry(state: TransformerState & DebugState, node: ts.MethodDeclaration): ts.MethodDeclaration {
|
|
21
|
+
if (!state[DebugⲐ]) {
|
|
22
|
+
const imp = state.importFile('@travetto/runtime/src/debug').ident;
|
|
23
|
+
state[DebugⲐ] = CoreUtil.createAccess(state.factory, imp, 'tryDebugger');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return state.factory.updateMethodDeclaration(node,
|
|
27
|
+
node.modifiers,
|
|
28
|
+
node.asteriskToken,
|
|
29
|
+
node.name,
|
|
30
|
+
node.questionToken,
|
|
31
|
+
node.typeParameters,
|
|
32
|
+
node.parameters,
|
|
33
|
+
node.type,
|
|
34
|
+
node.body ? state.factory.updateBlock(node.body, [
|
|
35
|
+
state.factory.createIfStatement(state[DebugⲐ]!,
|
|
36
|
+
state.factory.createExpressionStatement(state.factory.createIdentifier('debugger'))),
|
|
37
|
+
...node.body.statements
|
|
38
|
+
]) : node.body
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
TransformerState, OnMethod, OnClass, AfterClass,
|
|
5
|
+
CoreUtil, SystemUtil, Import, OnFunction
|
|
6
|
+
} from '@travetto/transformer';
|
|
7
|
+
|
|
8
|
+
import type { FunctionMetadataTag } from '../src/function';
|
|
9
|
+
|
|
10
|
+
const RUNTIME_MOD = '@travetto/runtime';
|
|
11
|
+
const RUNTIME_MOD_SRC = `${RUNTIME_MOD}/src`;
|
|
12
|
+
const REGISTER_IMPORT = `${RUNTIME_MOD_SRC}/function`;
|
|
13
|
+
|
|
14
|
+
const methods = Symbol.for(`${RUNTIME_MOD}:methods`);
|
|
15
|
+
const cls = Symbol.for(`${RUNTIME_MOD}:class`);
|
|
16
|
+
const fn = Symbol.for(`${RUNTIME_MOD}:function`);
|
|
17
|
+
const registerImport = Symbol.for(`${RUNTIME_MOD}:registerImport`);
|
|
18
|
+
const registerFn = 'registerFunction';
|
|
19
|
+
|
|
20
|
+
interface MetadataInfo {
|
|
21
|
+
[registerImport]?: Import;
|
|
22
|
+
[methods]?: Record<string, FunctionMetadataTag>;
|
|
23
|
+
[cls]?: FunctionMetadataTag;
|
|
24
|
+
[fn]?: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Providing metadata for classes
|
|
29
|
+
*/
|
|
30
|
+
export class RegisterTransformer {
|
|
31
|
+
|
|
32
|
+
static #tag(state: TransformerState, node: ts.Node): FunctionMetadataTag {
|
|
33
|
+
const hash = SystemUtil.naiveHash(node.getText());
|
|
34
|
+
try {
|
|
35
|
+
const range = CoreUtil.getRangeOf(state.source, node) ?? [0, 0];
|
|
36
|
+
if (ts.isMethodDeclaration(node) || ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node)) {
|
|
37
|
+
const bodyStart = CoreUtil.getRangeOf(state.source, node?.body?.statements[0])?.[0];
|
|
38
|
+
if (bodyStart) {
|
|
39
|
+
range.push(bodyStart);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return { hash, lines: range };
|
|
43
|
+
} catch {
|
|
44
|
+
return { hash, lines: [0, 0] };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static #valid({ importName: imp }: TransformerState): boolean {
|
|
49
|
+
return !imp.startsWith(REGISTER_IMPORT);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Hash each class
|
|
54
|
+
*/
|
|
55
|
+
@OnClass()
|
|
56
|
+
static collectClassMetadata(state: TransformerState & MetadataInfo, node: ts.ClassDeclaration): ts.ClassDeclaration {
|
|
57
|
+
if (!this.#valid(state)) {
|
|
58
|
+
return node; // Exclude self
|
|
59
|
+
}
|
|
60
|
+
state[cls] = this.#tag(state, node);
|
|
61
|
+
return node;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Hash each method
|
|
66
|
+
*/
|
|
67
|
+
@OnMethod()
|
|
68
|
+
static collectMethodMetadata(state: TransformerState & MetadataInfo, node: ts.MethodDeclaration): ts.MethodDeclaration {
|
|
69
|
+
if (state[cls] && ts.isIdentifier(node.name) && !CoreUtil.isAbstract(node) && ts.isClassDeclaration(node.parent)) {
|
|
70
|
+
state[methods] ??= {};
|
|
71
|
+
state[methods]![node.name.escapedText.toString()] = this.#tag(state, node);
|
|
72
|
+
}
|
|
73
|
+
return node;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* After visiting each class, register all the collected metadata
|
|
78
|
+
*/
|
|
79
|
+
@AfterClass()
|
|
80
|
+
static registerClassMetadata(state: TransformerState & MetadataInfo, node: ts.ClassDeclaration): ts.ClassDeclaration {
|
|
81
|
+
if (!state[cls]) {
|
|
82
|
+
return node;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
state[registerImport] ??= state.importFile(REGISTER_IMPORT);
|
|
86
|
+
|
|
87
|
+
const name = node.name?.escapedText.toString() ?? '';
|
|
88
|
+
|
|
89
|
+
const meta = state.factory.createCallExpression(
|
|
90
|
+
state.createAccess(state[registerImport].ident, registerFn),
|
|
91
|
+
[],
|
|
92
|
+
[
|
|
93
|
+
state.createIdentifier(name),
|
|
94
|
+
state.getModuleIdentifier(),
|
|
95
|
+
state.fromLiteral(state[cls]),
|
|
96
|
+
state.extendObjectLiteral(state[methods] || {}),
|
|
97
|
+
state.fromLiteral(CoreUtil.isAbstract(node)),
|
|
98
|
+
state.fromLiteral(name.endsWith(TransformerState.SYNTHETIC_EXT))
|
|
99
|
+
]
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
state[methods] = {};
|
|
103
|
+
delete state[cls];
|
|
104
|
+
|
|
105
|
+
return state.factory.updateClassDeclaration(
|
|
106
|
+
node,
|
|
107
|
+
node.modifiers,
|
|
108
|
+
node.name,
|
|
109
|
+
node.typeParameters,
|
|
110
|
+
node.heritageClauses,
|
|
111
|
+
[
|
|
112
|
+
state.createStaticField('Ⲑinit', meta),
|
|
113
|
+
...node.members
|
|
114
|
+
]
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Give proper functions a file name
|
|
120
|
+
*/
|
|
121
|
+
@OnFunction()
|
|
122
|
+
static registerFunctionMetadata(state: TransformerState & MetadataInfo, node: ts.FunctionDeclaration | ts.FunctionExpression): typeof node {
|
|
123
|
+
if (!this.#valid(state)) {
|
|
124
|
+
return node;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (ts.isFunctionDeclaration(node) && node.name && node.parent && ts.isSourceFile(node.parent)) {
|
|
128
|
+
// If we have a class like function
|
|
129
|
+
state[registerImport] ??= state.importFile(REGISTER_IMPORT);
|
|
130
|
+
const tag = this.#tag(state, node);
|
|
131
|
+
const meta = state.factory.createCallExpression(
|
|
132
|
+
state.createAccess(state[registerImport].ident, registerFn),
|
|
133
|
+
[],
|
|
134
|
+
[
|
|
135
|
+
state.createIdentifier(node.name),
|
|
136
|
+
state.getModuleIdentifier(),
|
|
137
|
+
state.fromLiteral(tag),
|
|
138
|
+
]
|
|
139
|
+
);
|
|
140
|
+
state.addStatements([state.factory.createExpressionStatement(meta)]);
|
|
141
|
+
}
|
|
142
|
+
return node;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
|
|
3
|
+
import { TransformerState, OnCall } from '@travetto/transformer';
|
|
4
|
+
|
|
5
|
+
const SRC = '@travetto/runtime/src/types.ts';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Allows for removal of type helpers at compile time
|
|
9
|
+
*/
|
|
10
|
+
export class TypeHelpersTransformer {
|
|
11
|
+
@OnCall()
|
|
12
|
+
static onTypeHelper(state: TransformerState, node: ts.CallExpression): ts.Node {
|
|
13
|
+
if (
|
|
14
|
+
ts.isIdentifier(node.expression) &&
|
|
15
|
+
node.arguments.length === 1 &&
|
|
16
|
+
/as(Class|Constructable|Full)|cast(To|Key)/.test(node.expression.escapedText.toString())
|
|
17
|
+
) {
|
|
18
|
+
const type = state.resolveType(node.expression);
|
|
19
|
+
if (type.key === 'unknown' && 'importName' in type && type.importName === SRC) {
|
|
20
|
+
// return node.arguments[0];
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return node;
|
|
24
|
+
}
|
|
25
|
+
}
|