@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/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', year: 'years', years: 'years',
6
- M: 'months', month: 'months', months: 'months',
7
- w: 'weeks', week: 'weeks', weeks: 'weeks',
8
- d: 'days', day: 'days', days: 'days',
9
- h: 'hours', hour: 'hours', hours: 'hours',
10
- m: 'minutes', minute: 'minutes', minutes: 'minutes',
11
- s: 'seconds', second: 'seconds', seconds: 'seconds',
12
- ms: 'milliseconds', millisecond: 'milliseconds', milliseconds: 'milliseconds'
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': { unit = 'hours'; value = value * 365 * 24; break; }
54
- case 'months': { value = value * 30 * 24; unit = 'hours'; break; }
55
- case 'weeks': { value = value * 7 * 24; unit = 'hours'; break; }
56
- case 'days': { value = value * 24; unit = 'hours'; break; }
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': return Math.trunc(duration.total('hours') / (365 * 24));
64
- case 'months': return Math.trunc(duration.total('hours') / (30 * 24));
65
- case 'weeks': return Math.trunc(duration.total('hours') / (7 * 24));
66
- default: return Math.trunc(duration.total(resolved));
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 "@travetto/runtime" {
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
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
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]?: (T[P] extends (IntrinsicType | undefined) ? (T[P] | undefined) :
25
- (T[P] extends Any[] ? (DeepPartial<T[P][number]> | null | undefined)[] : DeepPartial<T[P]>));
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 = <T>(key: keyof T) => (value: unknown): value is T =>
63
- typeof value === 'object' && value !== null && typeof value[castKey(key)] === 'function';
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, filename: string, line: number, column: number };
8
+ type StackFrame = { message: string; filename: string; line: number; column: number };
8
9
 
9
- const STACK_POSITION_PATTERN = /[(]\s{0,5}(?<filename>[^()]{1,1000}[.]([cm]?[jt]s))([:](?<line>\d{1,10}))?([:](?<column>\d{1,10}))?\s{0,5}[)]/;
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, positive: boolean }[],
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: (string | T | [value: T, positive: boolean] | [value: T]),
32
+ rule: string | T | [value: T, positive: boolean] | [value: T],
32
33
  convert: (inputRule: string) => T
33
- ): { value: T, positive: boolean } {
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) { // Make valid uuid-v4
48
- // eslint-disable-next-line no-bitwise
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 * mapAsyncIterable<T>(input: AsyncIterable<T>, ...fns: MapFn<unknown, unknown>[]): AsyncIterable<unknown> {
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 || !match.groups) {
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) => (unknown | Promise<unknown>);
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(run: (state: RetryRunState & { signal: AbortSignal }) => Promise<ShutdownReason>, options?: Partial<RetryRunConfig>): Promise<void> {
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': break outer;
63
- case 'error': state.errorIterations += 1; break;
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 = (state.errorIterations >= config.maxRetries) || (Date.now() - state.startTime >= config.maxRetryWindow);
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
- return this.runWithRetry(async ({ signal }) => {
95
- await client.waitForState(['compile-end', 'watch-start'], undefined, signal);
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()) { // If we get here, without a watch
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
+ }
@@ -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
- import { type FunctionMetadataTag } from '../../src/function.ts';
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(state: TransformerState & MetadataInfo,
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, node: ts.ClassDeclaration,
69
- cls: FunctionMetadataTag, methods?: Record<string, FunctionMetadataTag>
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
- node,
90
- node.modifiers,
91
- node.name,
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, TransformerHandler } from '@travetto/transformer';
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, `${final}$Concrete`, [], [], 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
- state.createAccess('Object', 'defineProperty'),
39
- undefined,
40
- [
41
- declaration.name!,
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 (ts.isIdentifier(node.expression) && node.expression.text === 'toConcrete' && node.typeArguments?.length && node.arguments.length === 0) {
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
+ }