@travetto/runtime 8.0.0-alpha.2 → 8.0.0-alpha.20
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 -21
- package/__index__.ts +6 -5
- package/package.json +9 -6
- package/src/binary-metadata.ts +33 -19
- package/src/binary.ts +18 -10
- package/src/codec.ts +25 -7
- package/src/console.ts +20 -12
- package/src/context.ts +26 -17
- package/src/debug.ts +1 -2
- package/src/env.ts +42 -22
- package/src/error.ts +4 -15
- package/src/exec.ts +41 -27
- package/src/file-loader.ts +4 -5
- package/src/function.ts +14 -6
- package/src/global.d.ts +20 -0
- package/src/json.ts +63 -48
- package/src/manifest-index.ts +1 -1
- package/src/queue.ts +1 -2
- package/src/resources.ts +1 -1
- package/src/shutdown.ts +21 -14
- package/src/time.ts +54 -19
- package/src/trv.d.ts +1 -1
- package/src/types.ts +30 -15
- package/src/util.ts +20 -22
- package/src/watch.ts +27 -18
- package/support/patch.js +42 -0
- package/support/transformer/metadata.ts +15 -28
- package/support/transformer.concrete-type.ts +19 -21
- package/support/transformer.console-log.ts +13 -19
- package/support/transformer.debug-method.ts +13 -9
- package/support/transformer.dynamic-import.ts +1 -2
- package/support/transformer.function-metadata.ts +6 -4
- package/support/transformer.rewrite-path-import.ts +9 -12
- package/support/polyfill.js +0 -9
package/src/time.ts
CHANGED
|
@@ -2,16 +2,32 @@ import { RuntimeError } from './error.ts';
|
|
|
2
2
|
import { castTo } from './types.ts';
|
|
3
3
|
|
|
4
4
|
const TIME_UNIT_TO_TEMPORAL_UNIT = {
|
|
5
|
-
y: 'years',
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
y: 'years',
|
|
6
|
+
year: 'years',
|
|
7
|
+
years: 'years',
|
|
8
|
+
M: 'months',
|
|
9
|
+
month: 'months',
|
|
10
|
+
months: 'months',
|
|
11
|
+
w: 'weeks',
|
|
12
|
+
week: 'weeks',
|
|
13
|
+
weeks: 'weeks',
|
|
14
|
+
d: 'days',
|
|
15
|
+
day: 'days',
|
|
16
|
+
days: 'days',
|
|
17
|
+
h: 'hours',
|
|
18
|
+
hour: 'hours',
|
|
19
|
+
hours: 'hours',
|
|
20
|
+
m: 'minutes',
|
|
21
|
+
minute: 'minutes',
|
|
22
|
+
minutes: 'minutes',
|
|
23
|
+
s: 'seconds',
|
|
24
|
+
second: 'seconds',
|
|
25
|
+
seconds: 'seconds',
|
|
26
|
+
ms: 'milliseconds',
|
|
27
|
+
millisecond: 'milliseconds',
|
|
28
|
+
milliseconds: 'milliseconds'
|
|
13
29
|
} as const;
|
|
14
|
-
type TemporalUnit = typeof TIME_UNIT_TO_TEMPORAL_UNIT[keyof typeof TIME_UNIT_TO_TEMPORAL_UNIT];
|
|
30
|
+
type TemporalUnit = (typeof TIME_UNIT_TO_TEMPORAL_UNIT)[keyof typeof TIME_UNIT_TO_TEMPORAL_UNIT];
|
|
15
31
|
|
|
16
32
|
export type TimeSpan = `${number}${keyof typeof TIME_UNIT_TO_TEMPORAL_UNIT}`;
|
|
17
33
|
export type TimeUnit = keyof typeof TIME_UNIT_TO_TEMPORAL_UNIT;
|
|
@@ -19,7 +35,6 @@ export type TimeUnit = keyof typeof TIME_UNIT_TO_TEMPORAL_UNIT;
|
|
|
19
35
|
const TIME_PATTERN = /^(?<amount>-?[0-9]+)(?<unit>(?:year|month|week|day|hour|minute|second|millisecond)s?|y|M|w|d|h|m|s|ms)$/;
|
|
20
36
|
|
|
21
37
|
export class TimeUtil {
|
|
22
|
-
|
|
23
38
|
/**
|
|
24
39
|
* Test to see if a string is valid for relative time
|
|
25
40
|
*/
|
|
@@ -50,20 +65,40 @@ export class TimeUtil {
|
|
|
50
65
|
}
|
|
51
66
|
|
|
52
67
|
switch (unit) {
|
|
53
|
-
case 'years': {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
68
|
+
case 'years': {
|
|
69
|
+
unit = 'hours';
|
|
70
|
+
value = value * 365 * 24;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
case 'months': {
|
|
74
|
+
value = value * 30 * 24;
|
|
75
|
+
unit = 'hours';
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
case 'weeks': {
|
|
79
|
+
value = value * 7 * 24;
|
|
80
|
+
unit = 'hours';
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
case 'days': {
|
|
84
|
+
value = value * 24;
|
|
85
|
+
unit = 'hours';
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
57
88
|
}
|
|
58
89
|
|
|
59
90
|
const duration = Temporal.Duration.from({ [unit]: value });
|
|
60
91
|
if (outputUnit) {
|
|
61
92
|
const resolved = TIME_UNIT_TO_TEMPORAL_UNIT[outputUnit];
|
|
62
93
|
switch (resolved) {
|
|
63
|
-
case 'years':
|
|
64
|
-
|
|
65
|
-
case '
|
|
66
|
-
|
|
94
|
+
case 'years':
|
|
95
|
+
return Math.trunc(duration.total('hours') / (365 * 24));
|
|
96
|
+
case 'months':
|
|
97
|
+
return Math.trunc(duration.total('hours') / (30 * 24));
|
|
98
|
+
case 'weeks':
|
|
99
|
+
return Math.trunc(duration.total('hours') / (7 * 24));
|
|
100
|
+
default:
|
|
101
|
+
return Math.trunc(duration.total(resolved));
|
|
67
102
|
}
|
|
68
103
|
} else {
|
|
69
104
|
return duration;
|
|
@@ -94,4 +129,4 @@ export class TimeUtil {
|
|
|
94
129
|
return `${toFixed(seconds)}s`;
|
|
95
130
|
}
|
|
96
131
|
}
|
|
97
|
-
}
|
|
132
|
+
}
|
package/src/trv.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type ManifestModuleRole } from '@travetto/manifest';
|
|
|
2
2
|
import { type TimeSpan } from './time.ts';
|
|
3
3
|
type Role = Exclude<ManifestModuleRole, 'compile'>;
|
|
4
4
|
|
|
5
|
-
declare module
|
|
5
|
+
declare module '@travetto/runtime' {
|
|
6
6
|
interface EnvData {
|
|
7
7
|
/**
|
|
8
8
|
* The node environment we are running in
|
package/src/types.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Readable } from 'node:stream';
|
|
2
2
|
|
|
3
|
-
//
|
|
3
|
+
// biome-ignore lint/suspicious/noExplicitAny: This is the any reference we use explicitly
|
|
4
4
|
export type Any = any;
|
|
5
5
|
|
|
6
6
|
export type AnyMap = { [key: string]: Any };
|
|
@@ -12,7 +12,6 @@ export type TypedFunction<R = Any, V = unknown> = (this: V, ...args: Any[]) => R
|
|
|
12
12
|
export type MethodDescriptor<V = Any, R = Any> = TypedPropertyDescriptor<TypedFunction<R, V>>;
|
|
13
13
|
export type AsyncMethodDescriptor<V = Any, R = Any> = TypedPropertyDescriptor<TypedFunction<Promise<R>, V>>;
|
|
14
14
|
export type AsyncIterableMethodDescriptor<V = Any, R = Any> = TypedPropertyDescriptor<TypedFunction<AsyncIterable<R>, V>>;
|
|
15
|
-
export type ClassTDecorator<T extends Class = Class> = (target: T) => T | void;
|
|
16
15
|
|
|
17
16
|
export type NumericPrimitive = number | bigint;
|
|
18
17
|
export type Primitive = NumericPrimitive | boolean | string;
|
|
@@ -21,19 +20,33 @@ export type NumericLikeIntrinsic = Date | NumericPrimitive;
|
|
|
21
20
|
export type IntrinsicType = Primitive | Date | ArrayBuffer | Uint8Array | Uint16Array | Uint32Array | Readable | Buffer | Blob | File;
|
|
22
21
|
|
|
23
22
|
export type DeepPartial<T> = {
|
|
24
|
-
[P in keyof T]?:
|
|
25
|
-
|
|
23
|
+
[P in keyof T]?: T[P] extends IntrinsicType | undefined
|
|
24
|
+
? T[P] | undefined
|
|
25
|
+
: T[P] extends Any[]
|
|
26
|
+
? (DeepPartial<T[P][number]> | null | undefined)[]
|
|
27
|
+
: DeepPartial<T[P]>;
|
|
26
28
|
};
|
|
27
29
|
|
|
28
30
|
export type ValidFields<T, I> = {
|
|
29
|
-
[K in keyof T]:
|
|
30
|
-
(T[K] extends (Primitive | I | undefined) ? K :
|
|
31
|
-
(T[K] extends (Function | undefined) ? never :
|
|
32
|
-
K))
|
|
31
|
+
[K in keyof T]: T[K] extends Primitive | I | undefined ? K : T[K] extends Function | undefined ? never : K;
|
|
33
32
|
}[keyof T];
|
|
34
33
|
|
|
35
34
|
export type RetainIntrinsicFields<T> = Pick<T, ValidFields<T, IntrinsicType>>;
|
|
36
35
|
|
|
36
|
+
export type KeyPaths<T, PrimitiveType = IntrinsicType | IntrinsicType[], PREFIX extends string = '', SEP extends string = '.'> = {
|
|
37
|
+
[K in keyof T]: K extends string
|
|
38
|
+
? T[K] extends IntrinsicType[] | IntrinsicType | undefined
|
|
39
|
+
? T[K] extends PrimitiveType
|
|
40
|
+
? `${PREFIX}${K}`
|
|
41
|
+
: never
|
|
42
|
+
: T[K] extends Any[]
|
|
43
|
+
? KeyPaths<T[K][number], PrimitiveType, `${K}${SEP}`, SEP>
|
|
44
|
+
: T[K] extends object
|
|
45
|
+
? KeyPaths<T[K], PrimitiveType, `${K}${SEP}`, SEP>
|
|
46
|
+
: never
|
|
47
|
+
: never;
|
|
48
|
+
}[keyof T];
|
|
49
|
+
|
|
37
50
|
export const TypedObject: {
|
|
38
51
|
keys<T = unknown, K extends keyof T = keyof T & string>(value: T): K[];
|
|
39
52
|
fromEntries<K extends string | symbol, V>(items: ([K, V] | readonly [K, V])[]): Record<K, V>;
|
|
@@ -41,11 +54,9 @@ export const TypedObject: {
|
|
|
41
54
|
assign<T extends {}, U extends T>(target: T, ...sources: U[]): U;
|
|
42
55
|
} & ObjectConstructor = Object;
|
|
43
56
|
|
|
44
|
-
export const safeAssign = <T extends {}, U extends {}>(target: T, ...sources: U[]): T & U =>
|
|
45
|
-
Object.assign(target, ...sources);
|
|
57
|
+
export const safeAssign = <T extends {}, U extends {}>(target: T, ...sources: U[]): T & U => Object.assign(target, ...sources);
|
|
46
58
|
|
|
47
59
|
export function castTo<T>(input: unknown): T {
|
|
48
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
49
60
|
return input as T;
|
|
50
61
|
}
|
|
51
62
|
|
|
@@ -55,16 +66,20 @@ export const asFull = <T>(input: Partial<T>): T => castTo(input);
|
|
|
55
66
|
export const asConstructable = <Z = unknown>(input: Class | unknown): { constructor: Class<Z> } => castTo(input);
|
|
56
67
|
|
|
57
68
|
export function classConstruct<T>(cls: Class<T>, args: unknown[] = []): ClassInstance<T> {
|
|
58
|
-
const cons: { new(..._args: Any[]): T } = castTo(cls);
|
|
69
|
+
const cons: { new (..._args: Any[]): T } = castTo(cls);
|
|
59
70
|
return castTo(new cons(...args));
|
|
60
71
|
}
|
|
61
72
|
|
|
62
|
-
export const hasFunction =
|
|
63
|
-
|
|
73
|
+
export const hasFunction =
|
|
74
|
+
<T>(key: keyof T) =>
|
|
75
|
+
(value: unknown): value is T =>
|
|
76
|
+
typeof value === 'object' && value !== null && typeof value[castKey(key)] === 'function';
|
|
64
77
|
|
|
65
78
|
export const hasToJSON = hasFunction<{ toJSON(): object }>('toJSON');
|
|
66
79
|
|
|
80
|
+
// biome-ignore lint/complexity/noUselessTypeConstraint: Unknown behaves slightly differently when being used for an inferred type
|
|
67
81
|
export function toConcrete<T extends unknown>(): Class<T> {
|
|
82
|
+
// biome-ignore lint/complexity/noArguments: We want to use arguments here
|
|
68
83
|
return arguments[0];
|
|
69
84
|
}
|
|
70
85
|
|
|
@@ -80,4 +95,4 @@ export function getParentClass(cls: Class): Class | undefined {
|
|
|
80
95
|
* Get the class from an instance or class
|
|
81
96
|
*/
|
|
82
97
|
export const getClass = <T = unknown>(value: ClassInstance | Class): Class<T> =>
|
|
83
|
-
'Ⲑid' in value ? castTo(value) : asConstructable<T>(value).constructor;
|
|
98
|
+
'Ⲑid' in value ? castTo(value) : asConstructable<T>(value).constructor;
|
package/src/util.ts
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import timers from 'node:timers/promises';
|
|
2
|
+
|
|
2
3
|
import { path } from '@travetto/manifest';
|
|
3
4
|
|
|
4
5
|
import { castTo } from './types.ts';
|
|
5
6
|
|
|
6
7
|
type MapFn<T, U> = (value: T, i: number) => U | Promise<U>;
|
|
7
|
-
type StackFrame = { message: string
|
|
8
|
+
type StackFrame = { message: string; filename: string; line: number; column: number };
|
|
8
9
|
|
|
9
|
-
const STACK_POSITION_PATTERN =
|
|
10
|
+
const STACK_POSITION_PATTERN =
|
|
11
|
+
/[(]\s{0,5}(?<filename>[^()]{1,1000}[.]([cm]?[jt]s))([:](?<line>\d{1,10}))?([:](?<column>\d{1,10}))?\s{0,5}[)]/;
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* Grab bag of common utilities
|
|
13
15
|
*/
|
|
14
16
|
export class Util {
|
|
15
|
-
|
|
16
17
|
static #match<T, K extends unknown[]>(
|
|
17
|
-
rules: { value: T
|
|
18
|
+
rules: { value: T; positive: boolean }[],
|
|
18
19
|
compare: (rule: T, ...compareInput: K) => boolean,
|
|
19
20
|
unmatchedValue: boolean,
|
|
20
21
|
...input: K
|
|
@@ -28,14 +29,14 @@ export class Util {
|
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
static #allowDenyRuleInput<T>(
|
|
31
|
-
rule:
|
|
32
|
+
rule: string | T | [value: T, positive: boolean] | [value: T],
|
|
32
33
|
convert: (inputRule: string) => T
|
|
33
|
-
): { value: T
|
|
34
|
-
return typeof rule === 'string'
|
|
35
|
-
{ value: convert(rule.replace(/^!/, '')), positive: !rule.startsWith('!') }
|
|
36
|
-
Array.isArray(rule)
|
|
37
|
-
{ value: rule[0], positive: rule[1] ?? true }
|
|
38
|
-
{ value: rule, positive: true };
|
|
34
|
+
): { value: T; positive: boolean } {
|
|
35
|
+
return typeof rule === 'string'
|
|
36
|
+
? { value: convert(rule.replace(/^!/, '')), positive: !rule.startsWith('!') }
|
|
37
|
+
: Array.isArray(rule)
|
|
38
|
+
? { value: rule[0], positive: rule[1] ?? true }
|
|
39
|
+
: { value: rule, positive: true };
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
/**
|
|
@@ -44,10 +45,9 @@ export class Util {
|
|
|
44
45
|
*/
|
|
45
46
|
static uuid(length: number = 32): string {
|
|
46
47
|
const bytes = crypto.getRandomValues(new Uint8Array(Math.ceil(length / 2)));
|
|
47
|
-
if (length === 32) {
|
|
48
|
-
//
|
|
48
|
+
if (length === 32) {
|
|
49
|
+
// Make valid uuid-v4
|
|
49
50
|
bytes[6] = (bytes[6] & 0x0f) | 0x40;
|
|
50
|
-
// eslint-disable-next-line no-bitwise
|
|
51
51
|
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
|
52
52
|
}
|
|
53
53
|
return bytes.toHex().substring(0, length);
|
|
@@ -59,7 +59,7 @@ export class Util {
|
|
|
59
59
|
static mapAsyncIterable<T, U, V, W>(source: AsyncIterable<T>, fn1: MapFn<T, U>, fn2: MapFn<U, V>, fn3: MapFn<V, W>): AsyncIterable<W>;
|
|
60
60
|
static mapAsyncIterable<T, U, V>(source: AsyncIterable<T>, fn1: MapFn<T, U>, fn2: MapFn<U, V>): AsyncIterable<V>;
|
|
61
61
|
static mapAsyncIterable<T, U>(source: AsyncIterable<T>, fn: MapFn<T, U>): AsyncIterable<U>;
|
|
62
|
-
static async *
|
|
62
|
+
static async *mapAsyncIterable<T>(input: AsyncIterable<T>, ...fns: MapFn<unknown, unknown>[]): AsyncIterable<unknown> {
|
|
63
63
|
let idx = -1;
|
|
64
64
|
for await (const item of input) {
|
|
65
65
|
if (item !== undefined) {
|
|
@@ -77,14 +77,14 @@ export class Util {
|
|
|
77
77
|
* Non-blocking timeout
|
|
78
78
|
*/
|
|
79
79
|
static nonBlockingTimeout(time: number): Promise<void> {
|
|
80
|
-
return timers.setTimeout(time, undefined, { ref: false }).catch(() => {
|
|
80
|
+
return timers.setTimeout(time, undefined, { ref: false }).catch(() => {});
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
84
|
* Blocking timeout
|
|
85
85
|
*/
|
|
86
86
|
static blockingTimeout(time: number): Promise<void> {
|
|
87
|
-
return timers.setTimeout(time, undefined, { ref: true }).catch(() => {
|
|
87
|
+
return timers.setTimeout(time, undefined, { ref: true }).catch(() => {});
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
/**
|
|
@@ -104,16 +104,14 @@ export class Util {
|
|
|
104
104
|
compare: (rule: T, ...compareInput: K) => boolean,
|
|
105
105
|
cacheKey?: (...keyInput: K) => string
|
|
106
106
|
): (...input: K) => boolean {
|
|
107
|
-
|
|
108
|
-
const rawRules = (Array.isArray(rules) ? rules : rules.split(/,/g).map(rule => rule.trim()));
|
|
107
|
+
const rawRules = Array.isArray(rules) ? rules : rules.split(/,/g).map(rule => rule.trim());
|
|
109
108
|
const convertedRules = rawRules.map(rule => this.#allowDenyRuleInput(rule, convert));
|
|
110
109
|
const unmatchedValue = !convertedRules.some(rule => rule.positive);
|
|
111
110
|
|
|
112
111
|
if (convertedRules.length) {
|
|
113
112
|
if (cacheKey) {
|
|
114
113
|
const cache: Record<string, boolean> = {};
|
|
115
|
-
return (...input: K) =>
|
|
116
|
-
cache[cacheKey(...input)] ??= this.#match(convertedRules, compare, unmatchedValue, ...input);
|
|
114
|
+
return (...input: K) => (cache[cacheKey(...input)] ??= this.#match(convertedRules, compare, unmatchedValue, ...input));
|
|
117
115
|
} else {
|
|
118
116
|
return (...input: K) => this.#match(convertedRules, compare, unmatchedValue, ...input);
|
|
119
117
|
}
|
|
@@ -133,7 +131,7 @@ export class Util {
|
|
|
133
131
|
.split('\n')
|
|
134
132
|
.map(frameText => {
|
|
135
133
|
const match = STACK_POSITION_PATTERN.exec(frameText);
|
|
136
|
-
if (!match
|
|
134
|
+
if (!match?.groups) {
|
|
137
135
|
return undefined;
|
|
138
136
|
}
|
|
139
137
|
const { filename, line, column } = match.groups;
|
package/src/watch.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { CompilerEventPayload, CompilerEventType } from '@travetto/compiler';
|
|
2
2
|
|
|
3
3
|
import { RuntimeError } from './error.ts';
|
|
4
|
-
import { Util } from './util.ts';
|
|
5
4
|
import { RuntimeIndex } from './manifest-index.ts';
|
|
6
5
|
import { ShutdownManager, type ShutdownReason } from './shutdown.ts';
|
|
7
6
|
import { castTo } from './types.ts';
|
|
7
|
+
import { Util } from './util.ts';
|
|
8
8
|
|
|
9
9
|
type RetryRunState = {
|
|
10
10
|
iteration: number;
|
|
@@ -17,25 +17,25 @@ type RetryRunConfig = {
|
|
|
17
17
|
maxRetries: number;
|
|
18
18
|
maxRetryWindow: number;
|
|
19
19
|
signal?: AbortSignal;
|
|
20
|
-
onRetry: (state: RetryRunState, config: RetryRunConfig) =>
|
|
20
|
+
onRetry: (state: RetryRunState, config: RetryRunConfig) => unknown | Promise<unknown>;
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Utilities for watching resources
|
|
25
25
|
*/
|
|
26
26
|
export class WatchUtil {
|
|
27
|
-
|
|
28
27
|
/** Compute the delay before restarting */
|
|
29
28
|
static computeRestartDelay(state: RetryRunState, config: RetryRunConfig): number {
|
|
30
|
-
return state.result === 'error'
|
|
31
|
-
? config.maxRetryWindow / (config.maxRetries + 1)
|
|
32
|
-
: 10;
|
|
29
|
+
return state.result === 'error' ? config.maxRetryWindow / (config.maxRetries + 1) : 10;
|
|
33
30
|
}
|
|
34
31
|
|
|
35
32
|
/**
|
|
36
33
|
* Run with restart capability
|
|
37
34
|
*/
|
|
38
|
-
static async runWithRetry(
|
|
35
|
+
static async runWithRetry(
|
|
36
|
+
run: (state: RetryRunState & { signal: AbortSignal }) => Promise<ShutdownReason>,
|
|
37
|
+
options?: Partial<RetryRunConfig>
|
|
38
|
+
): Promise<void> {
|
|
39
39
|
let retryExhausted = false;
|
|
40
40
|
|
|
41
41
|
const state: RetryRunState = {
|
|
@@ -48,10 +48,9 @@ export class WatchUtil {
|
|
|
48
48
|
maxRetryWindow: 10 * 1000,
|
|
49
49
|
maxRetries: 10,
|
|
50
50
|
onRetry: () => Util.nonBlockingTimeout(this.computeRestartDelay(state, config)),
|
|
51
|
-
...options
|
|
51
|
+
...options
|
|
52
52
|
};
|
|
53
53
|
|
|
54
|
-
|
|
55
54
|
outer: while (!ShutdownManager.signal.aborted && !retryExhausted) {
|
|
56
55
|
if (state.iteration > 0) {
|
|
57
56
|
await config.onRetry(state, config);
|
|
@@ -59,15 +58,18 @@ export class WatchUtil {
|
|
|
59
58
|
|
|
60
59
|
state.result = await run({ ...state, signal: ShutdownManager.signal }).catch(() => 'error' as const);
|
|
61
60
|
switch (state.result) {
|
|
62
|
-
case 'quit':
|
|
63
|
-
|
|
61
|
+
case 'quit':
|
|
62
|
+
break outer;
|
|
63
|
+
case 'error':
|
|
64
|
+
state.errorIterations += 1;
|
|
65
|
+
break;
|
|
64
66
|
case 'restart': {
|
|
65
67
|
state.startTime = Date.now();
|
|
66
68
|
state.errorIterations = 0;
|
|
67
69
|
}
|
|
68
70
|
}
|
|
69
71
|
|
|
70
|
-
retryExhausted =
|
|
72
|
+
retryExhausted = state.errorIterations >= config.maxRetries || Date.now() - state.startTime >= config.maxRetryWindow;
|
|
71
73
|
state.iteration += 1;
|
|
72
74
|
}
|
|
73
75
|
|
|
@@ -81,20 +83,27 @@ export class WatchUtil {
|
|
|
81
83
|
type: K,
|
|
82
84
|
onChange: (input: T) => unknown,
|
|
83
85
|
filter?: (input: T) => boolean,
|
|
84
|
-
options?: Partial<RetryRunConfig
|
|
86
|
+
options?: Partial<RetryRunConfig>
|
|
85
87
|
): Promise<void> {
|
|
86
88
|
const { CompilerClient } = await import('@travetto/compiler/src/server/client.ts');
|
|
87
89
|
const client = new CompilerClient(RuntimeIndex.manifest, {
|
|
88
90
|
debug: (...args: unknown[]): void => console.debug(...args),
|
|
89
91
|
info: (...args: unknown[]): void => console.info(...args),
|
|
90
92
|
warn: (...args: unknown[]): void => console.warn(...args),
|
|
91
|
-
error: (...args: unknown[]): void => console.error(...args)
|
|
93
|
+
error: (...args: unknown[]): void => console.error(...args)
|
|
92
94
|
});
|
|
93
95
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
+
// pre-check
|
|
97
|
+
if (!(await client.isWatching())) {
|
|
98
|
+
// If we get here, without a watch
|
|
99
|
+
throw new RuntimeError('Compile Server is not running');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
void this.runWithRetry(async ({ signal }) => {
|
|
103
|
+
await client.waitForState(['watch-start'], undefined, signal);
|
|
96
104
|
|
|
97
|
-
if (!await client.isWatching()) {
|
|
105
|
+
if (!(await client.isWatching())) {
|
|
106
|
+
// If we get here, without a watch
|
|
98
107
|
return 'error';
|
|
99
108
|
} else {
|
|
100
109
|
for await (const event of client.fetchEvents(type, { signal, enforceIteration: true })) {
|
|
@@ -106,4 +115,4 @@ export class WatchUtil {
|
|
|
106
115
|
}
|
|
107
116
|
}, options);
|
|
108
117
|
}
|
|
109
|
-
}
|
|
118
|
+
}
|
package/support/patch.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
|
|
3
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
4
|
+
process.setSourceMapsEnabled(true); // Ensure source map during compilation/development
|
|
5
|
+
process.env.NODE_OPTIONS = `${process.env.NODE_OPTIONS ?? ''} --enable-source-maps`; // Ensure it passes to children
|
|
6
|
+
Error.stackTraceLimit = 50;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// polyfills
|
|
10
|
+
if (!globalThis.Temporal) {
|
|
11
|
+
// For anyone that doesn't have it
|
|
12
|
+
void import('temporal-polyfill-lite/global');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
Map.prototype.getOrInsert ??= function (key, value) {
|
|
16
|
+
if (!this.has(key)) {
|
|
17
|
+
this.set(key, value);
|
|
18
|
+
}
|
|
19
|
+
return this.get(key);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
Map.prototype.getOrInsertComputed ??= function (key, compute) {
|
|
23
|
+
if (!this.has(key)) {
|
|
24
|
+
this.set(key, compute());
|
|
25
|
+
}
|
|
26
|
+
return this.get(key);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// Allow for the throwIfNoEntry if on a version of node that is less than 25.7
|
|
30
|
+
const [majorVersion, minorVersion] = process.version.match(/\d+/g).map(text => parseInt(text, 10));
|
|
31
|
+
if (majorVersion < 25 || (majorVersion === 25 && minorVersion < 7)) {
|
|
32
|
+
const og = fs.stat;
|
|
33
|
+
Object.defineProperty(fs, 'stat', {
|
|
34
|
+
value: (...args) => {
|
|
35
|
+
const out = og.call(fs, ...args);
|
|
36
|
+
if (typeof args[1] === 'object' && args[1].throwIfNoEntry === false) {
|
|
37
|
+
return out.catch(() => {});
|
|
38
|
+
}
|
|
39
|
+
return out;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
|
|
3
3
|
import { CoreUtil, type Import, SystemUtil, type TransformerState } from '@travetto/transformer';
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
import type { FunctionMetadataTag } from '../../src/function.ts';
|
|
5
6
|
|
|
6
7
|
const RegisterImportSymbol = Symbol();
|
|
7
8
|
|
|
@@ -13,7 +14,6 @@ interface MetadataInfo {
|
|
|
13
14
|
* Utils for registering function/class metadata at compile time
|
|
14
15
|
*/
|
|
15
16
|
export class MetadataRegistrationUtil {
|
|
16
|
-
|
|
17
17
|
static REGISTER_IMPORT = '@travetto/runtime/src/function.ts';
|
|
18
18
|
static REGISTER_FN = 'registerFunction';
|
|
19
19
|
|
|
@@ -41,7 +41,8 @@ export class MetadataRegistrationUtil {
|
|
|
41
41
|
/**
|
|
42
42
|
* Register metadata on a function
|
|
43
43
|
*/
|
|
44
|
-
static registerFunction(
|
|
44
|
+
static registerFunction(
|
|
45
|
+
state: TransformerState & MetadataInfo,
|
|
45
46
|
node: ts.FunctionDeclaration | ts.FunctionExpression,
|
|
46
47
|
source?: ts.FunctionDeclaration | ts.FunctionExpression | ts.InterfaceDeclaration | ts.TypeAliasDeclaration
|
|
47
48
|
): void {
|
|
@@ -52,11 +53,7 @@ export class MetadataRegistrationUtil {
|
|
|
52
53
|
const metadata = state.factory.createCallExpression(
|
|
53
54
|
state.createAccess(state[RegisterImportSymbol].identifier, this.REGISTER_FN),
|
|
54
55
|
[],
|
|
55
|
-
[
|
|
56
|
-
state.createIdentifier(node.name!.text),
|
|
57
|
-
state.getModuleIdentifier(),
|
|
58
|
-
state.fromLiteral(tag),
|
|
59
|
-
]
|
|
56
|
+
[state.createIdentifier(node.name!.text), state.getModuleIdentifier(), state.fromLiteral(tag)]
|
|
60
57
|
);
|
|
61
58
|
state.addStatements([state.factory.createExpressionStatement(metadata)]);
|
|
62
59
|
}
|
|
@@ -65,10 +62,11 @@ export class MetadataRegistrationUtil {
|
|
|
65
62
|
* Register metadata on a class
|
|
66
63
|
*/
|
|
67
64
|
static registerClass(
|
|
68
|
-
state: TransformerState & MetadataInfo,
|
|
69
|
-
|
|
65
|
+
state: TransformerState & MetadataInfo,
|
|
66
|
+
node: ts.ClassDeclaration,
|
|
67
|
+
cls: FunctionMetadataTag,
|
|
68
|
+
methods?: Record<string, FunctionMetadataTag>
|
|
70
69
|
): ts.ClassDeclaration {
|
|
71
|
-
|
|
72
70
|
state[RegisterImportSymbol] ??= state.importFile(this.REGISTER_IMPORT);
|
|
73
71
|
|
|
74
72
|
const name = node.name?.escapedText.toString() ?? '';
|
|
@@ -81,24 +79,13 @@ export class MetadataRegistrationUtil {
|
|
|
81
79
|
state.getModuleIdentifier(),
|
|
82
80
|
state.fromLiteral(cls),
|
|
83
81
|
state.extendObjectLiteral(methods ?? {}),
|
|
84
|
-
state.fromLiteral(CoreUtil.isAbstract(node))
|
|
82
|
+
state.fromLiteral(CoreUtil.isAbstract(node))
|
|
85
83
|
]
|
|
86
84
|
);
|
|
87
85
|
|
|
88
|
-
return state.factory.updateClassDeclaration(
|
|
89
|
-
|
|
90
|
-
node.
|
|
91
|
-
|
|
92
|
-
node.typeParameters,
|
|
93
|
-
node.heritageClauses,
|
|
94
|
-
[
|
|
95
|
-
state.factory.createClassStaticBlockDeclaration(
|
|
96
|
-
state.factory.createBlock([
|
|
97
|
-
state.factory.createExpressionStatement(metadata)
|
|
98
|
-
])
|
|
99
|
-
),
|
|
100
|
-
...node.members
|
|
101
|
-
]
|
|
102
|
-
);
|
|
86
|
+
return state.factory.updateClassDeclaration(node, node.modifiers, node.name, node.typeParameters, node.heritageClauses, [
|
|
87
|
+
state.factory.createClassStaticBlockDeclaration(state.factory.createBlock([state.factory.createExpressionStatement(metadata)])),
|
|
88
|
+
...node.members
|
|
89
|
+
]);
|
|
103
90
|
}
|
|
104
|
-
}
|
|
91
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
|
|
3
|
-
import { type TransformerState
|
|
3
|
+
import { TransformerHandler, type TransformerState } from '@travetto/transformer';
|
|
4
4
|
|
|
5
5
|
import { MetadataRegistrationUtil } from './transformer/metadata.ts';
|
|
6
6
|
|
|
@@ -10,7 +10,6 @@ const SRC = '@travetto/runtime/src/types.ts';
|
|
|
10
10
|
* Providing support for concrete types
|
|
11
11
|
*/
|
|
12
12
|
export class ConcreteTransformer {
|
|
13
|
-
|
|
14
13
|
static {
|
|
15
14
|
TransformerHandler(this, this.onInterface, 'before', 'interface');
|
|
16
15
|
TransformerHandler(this, this.onTypeAlias, 'before', 'type');
|
|
@@ -25,24 +24,23 @@ export class ConcreteTransformer {
|
|
|
25
24
|
const final = typeof name === 'string' ? name : name.getText();
|
|
26
25
|
|
|
27
26
|
const declaration = state.factory.createFunctionDeclaration(
|
|
28
|
-
// eslint-disable-next-line no-bitwise
|
|
29
27
|
state.factory.createModifiersFromModifierFlags(ts.ModifierFlags.Export | ts.ModifierFlags.Const),
|
|
30
|
-
undefined,
|
|
28
|
+
undefined,
|
|
29
|
+
`${final}$Concrete`,
|
|
30
|
+
[],
|
|
31
|
+
[],
|
|
32
|
+
undefined,
|
|
31
33
|
state.factory.createBlock([])
|
|
32
34
|
);
|
|
33
35
|
|
|
34
36
|
state.addStatements([
|
|
35
37
|
declaration,
|
|
36
38
|
state.factory.createExpressionStatement(
|
|
37
|
-
state.factory.createCallExpression(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
state.fromLiteral('name'),
|
|
43
|
-
state.fromLiteral({ value: final })
|
|
44
|
-
]
|
|
45
|
-
)
|
|
39
|
+
state.factory.createCallExpression(state.createAccess('Object', 'defineProperty'), undefined, [
|
|
40
|
+
declaration.name!,
|
|
41
|
+
state.fromLiteral('name'),
|
|
42
|
+
state.fromLiteral({ value: final })
|
|
43
|
+
])
|
|
46
44
|
)
|
|
47
45
|
]);
|
|
48
46
|
|
|
@@ -72,19 +70,19 @@ export class ConcreteTransformer {
|
|
|
72
70
|
}
|
|
73
71
|
|
|
74
72
|
static onToConcreteCall(state: TransformerState, node: ts.CallExpression): typeof node {
|
|
75
|
-
if (
|
|
73
|
+
if (
|
|
74
|
+
ts.isIdentifier(node.expression) &&
|
|
75
|
+
node.expression.text === 'toConcrete' &&
|
|
76
|
+
node.typeArguments?.length &&
|
|
77
|
+
node.arguments.length === 0
|
|
78
|
+
) {
|
|
76
79
|
const type = state.resolveType(node.expression);
|
|
77
80
|
if ('importName' in type && type.importName === SRC) {
|
|
78
81
|
const [target] = node.typeArguments;
|
|
79
|
-
return state.factory.updateCallExpression(
|
|
80
|
-
node,
|
|
81
|
-
node.expression,
|
|
82
|
-
node.typeArguments,
|
|
83
|
-
[state.getConcreteType(target)]
|
|
84
|
-
);
|
|
82
|
+
return state.factory.updateCallExpression(node, node.expression, node.typeArguments, [state.getConcreteType(target)]);
|
|
85
83
|
}
|
|
86
84
|
}
|
|
87
85
|
|
|
88
86
|
return node;
|
|
89
87
|
}
|
|
90
|
-
}
|
|
88
|
+
}
|