@travetto/runtime 8.0.0-alpha.9 → 8.0.1

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/queue.ts CHANGED
@@ -2,7 +2,6 @@
2
2
  * An asynchronous queue
3
3
  */
4
4
  export class AsyncQueue<X> implements AsyncIterator<X>, AsyncIterable<X> {
5
-
6
5
  #buffer: X[] = [];
7
6
  #done = false;
8
7
  #ready = Promise.withResolvers<void>();
@@ -59,4 +58,4 @@ export class AsyncQueue<X> implements AsyncIterator<X>, AsyncIterable<X> {
59
58
  this.#ready.reject(error);
60
59
  return { value: undefined, done: this.#done };
61
60
  }
62
- }
61
+ }
package/src/resources.ts CHANGED
@@ -25,4 +25,4 @@ class $RuntimeResources extends FileLoader {
25
25
  }
26
26
 
27
27
  /** Runtime resources */
28
- export const RuntimeResources = new $RuntimeResources();
28
+ export const RuntimeResources = new $RuntimeResources();
package/src/shutdown.ts CHANGED
@@ -1,17 +1,21 @@
1
1
  import type { ChildProcess } from 'node:child_process';
2
2
 
3
3
  import { Env } from './env.ts';
4
- import { Util } from './util.ts';
5
4
  import { TimeUtil } from './time.ts';
5
+ import { Util } from './util.ts';
6
6
 
7
- const MAPPING = [['restart', 200], ['error', 1], ['quit', 0]] as const;
8
- export type ShutdownReason = typeof MAPPING[number][0];
7
+ const MAPPING = [
8
+ ['restart', 200],
9
+ ['error', 1],
10
+ ['quit', 0]
11
+ ] as const;
12
+ export type ShutdownReason = (typeof MAPPING)[number][0];
9
13
 
10
14
  const REASON_TO_CODE = new Map<ShutdownReason, number>(MAPPING);
11
15
  const CODE_TO_REASON = new Map<number, ShutdownReason>(MAPPING.map(([k, v]) => [v, k]));
12
16
 
13
17
  type Handler = (event: Event) => unknown;
14
- type ShutdownEvent = { reason?: ShutdownReason, mode?: 'exit' | 'interrupt' };
18
+ type ShutdownEvent = { reason?: ShutdownReason; mode?: 'exit' | 'interrupt' };
15
19
 
16
20
  const isShutdownEvent = (event: unknown): event is ShutdownEvent =>
17
21
  typeof event === 'object' && event !== null && 'type' in event && event.type === 'shutdown';
@@ -33,14 +37,20 @@ export class ShutdownManager {
33
37
  static #controller = new AbortController();
34
38
 
35
39
  static {
36
- this.#controller.signal.addEventListener = (_: 'abort', listener: Handler): void => { this.#registered.add(listener); };
37
- this.#controller.signal.removeEventListener = (_: 'abort', listener: Handler): void => { this.#registered.delete(listener); };
40
+ this.#controller.signal.addEventListener = (_: 'abort', listener: Handler): void => {
41
+ this.#registered.add(listener);
42
+ };
43
+ this.#controller.signal.removeEventListener = (_: 'abort', listener: Handler): void => {
44
+ this.#registered.delete(listener);
45
+ };
38
46
  try {
39
47
  process
40
- .on('message', event => { isShutdownEvent(event) && this.shutdown(event); })
48
+ .on('message', event => {
49
+ isShutdownEvent(event) && this.shutdown(event);
50
+ })
41
51
  .on('SIGINT', () => this.shutdown({ mode: 'interrupt' }))
42
52
  .on('SIGTERM', () => this.shutdown());
43
- } catch { }
53
+ } catch {}
44
54
  }
45
55
 
46
56
  static get signal(): AbortSignal {
@@ -60,7 +70,7 @@ export class ShutdownManager {
60
70
 
61
71
  /** Trigger a watch signal signal to a subprocess */
62
72
  static async shutdownChild(subprocess: ChildProcess, config?: ShutdownEvent): Promise<void> {
63
- subprocess?.send!({ type: 'shutdown', ...config });
73
+ subprocess?.send?.({ type: 'shutdown', ...config });
64
74
  }
65
75
 
66
76
  /**
@@ -87,10 +97,7 @@ export class ShutdownManager {
87
97
  this.#controller.abort('Shutdown started');
88
98
  console.debug('Shutdown started', context);
89
99
 
90
- const winner = await Promise.race([
91
- Util.nonBlockingTimeout(timeout).then(() => this),
92
- Promise.all([...this.#registered].map(wrapped))
93
- ]);
100
+ const winner = await Promise.race([Util.nonBlockingTimeout(timeout).then(() => this), Promise.all([...this.#registered].map(wrapped))]);
94
101
 
95
102
  if (winner !== this) {
96
103
  console.debug('Shutdown completed', context);
@@ -102,4 +109,4 @@ export class ShutdownManager {
102
109
  process.exit();
103
110
  }
104
111
  }
105
- }
112
+ }
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
@@ -1,38 +1,39 @@
1
1
  import { type ManifestModuleRole } from '@travetto/manifest';
2
+
2
3
  import { type TimeSpan } from './time.ts';
3
4
  type Role = Exclude<ManifestModuleRole, 'compile'>;
4
5
 
5
6
  declare module '@travetto/runtime' {
6
7
  interface EnvData {
7
- /**
8
+ /**
8
9
  * The node environment we are running in
9
10
  * @default development
10
11
  */
11
12
  NODE_ENV: 'development' | 'production';
12
- /**
13
+ /**
13
14
  * Outputs all console.debug messages, defaults to off
14
15
  */
15
16
  DEBUG: boolean | string;
16
- /**
17
+ /**
17
18
  * The role we are running as, allows access to additional files from the manifest during runtime.
18
19
  */
19
20
  TRV_ROLE: Role;
20
- /**
21
+ /**
21
22
  * The folders to use for resource lookup
22
23
  */
23
24
  TRV_RESOURCES: string[];
24
- /**
25
+ /**
25
26
  * Resource path overrides
26
27
  * @private
27
28
  */
28
29
  TRV_RESOURCE_OVERRIDES: Record<string, string>;
29
- /**
30
- * The max time to wait for shutdown to finish after initial SIGINT,
30
+ /**
31
+ * The max time to wait for shutdown to finish after initial SIGINT,
31
32
  * @default 2s
32
33
  */
33
34
  TRV_SHUTDOWN_WAIT: TimeSpan | number;
34
35
  /**
35
- * The desired runtime module
36
+ * The desired runtime module
36
37
  */
37
38
  TRV_MODULE: string;
38
39
  /**
@@ -50,4 +51,4 @@ declare module '@travetto/runtime' {
50
51
  */
51
52
  TRV_DEBUG_BREAK: boolean;
52
53
  }
53
- }
54
+ }
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,35 @@ 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
+ type KeyPathsInner<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
+ ? KeyPathsInner<T[K][number], PrimitiveType, `${K}${SEP}`, SEP>
44
+ : T[K] extends object
45
+ ? KeyPathsInner<T[K], PrimitiveType, `${K}${SEP}`, SEP>
46
+ : never
47
+ : never;
48
+ }[keyof T];
49
+
50
+ export type KeyPaths<T, PrimitiveType = IntrinsicType | IntrinsicType[]> = KeyPathsInner<Required<T>, PrimitiveType>;
51
+
37
52
  export const TypedObject: {
38
53
  keys<T = unknown, K extends keyof T = keyof T & string>(value: T): K[];
39
54
  fromEntries<K extends string | symbol, V>(items: ([K, V] | readonly [K, V])[]): Record<K, V>;
@@ -41,11 +56,9 @@ export const TypedObject: {
41
56
  assign<T extends {}, U extends T>(target: T, ...sources: U[]): U;
42
57
  } & ObjectConstructor = Object;
43
58
 
44
- export const safeAssign = <T extends {}, U extends {}>(target: T, ...sources: U[]): T & U =>
45
- Object.assign(target, ...sources);
59
+ export const safeAssign = <T extends {}, U extends {}>(target: T, ...sources: U[]): T & U => Object.assign(target, ...sources);
46
60
 
47
61
  export function castTo<T>(input: unknown): T {
48
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
49
62
  return input as T;
50
63
  }
51
64
 
@@ -55,16 +68,20 @@ export const asFull = <T>(input: Partial<T>): T => castTo(input);
55
68
  export const asConstructable = <Z = unknown>(input: Class | unknown): { constructor: Class<Z> } => castTo(input);
56
69
 
57
70
  export function classConstruct<T>(cls: Class<T>, args: unknown[] = []): ClassInstance<T> {
58
- const cons: { new(..._args: Any[]): T } = castTo(cls);
71
+ const cons: { new (..._args: Any[]): T } = castTo(cls);
59
72
  return castTo(new cons(...args));
60
73
  }
61
74
 
62
- export const hasFunction = <T>(key: keyof T) => (value: unknown): value is T =>
63
- typeof value === 'object' && value !== null && typeof value[castKey(key)] === 'function';
75
+ export const hasFunction =
76
+ <T>(key: keyof T) =>
77
+ (value: unknown): value is T =>
78
+ typeof value === 'object' && value !== null && typeof value[castKey(key)] === 'function';
64
79
 
65
80
  export const hasToJSON = hasFunction<{ toJSON(): object }>('toJSON');
66
81
 
82
+ // biome-ignore lint/complexity/noUselessTypeConstraint: Unknown behaves slightly differently when being used for an inferred type
67
83
  export function toConcrete<T extends unknown>(): Class<T> {
84
+ // biome-ignore lint/complexity/noArguments: We want to use arguments here
68
85
  return arguments[0];
69
86
  }
70
87
 
@@ -80,4 +97,4 @@ export function getParentClass(cls: Class): Class | undefined {
80
97
  * Get the class from an instance or class
81
98
  */
82
99
  export const getClass = <T = unknown>(value: ClassInstance | Class): Class<T> =>
83
- 'Ⲑid' in value ? castTo(value) : asConstructable<T>(value).constructor;
100
+ 'Ⲑ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,25 +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
96
  // pre-check
95
- if (!await client.isWatching()) { // If we get here, without a watch
97
+ if (!(await client.isWatching())) {
98
+ // If we get here, without a watch
96
99
  throw new RuntimeError('Compile Server is not running');
97
100
  }
98
101
 
99
102
  void this.runWithRetry(async ({ signal }) => {
100
103
  await client.waitForState(['watch-start'], undefined, signal);
101
104
 
102
- if (!await client.isWatching()) { // If we get here, without a watch
105
+ if (!(await client.isWatching())) {
106
+ // If we get here, without a watch
103
107
  return 'error';
104
108
  } else {
105
109
  for await (const event of client.fetchEvents(type, { signal, enforceIteration: true })) {
@@ -111,4 +115,4 @@ export class WatchUtil {
111
115
  }
112
116
  }, options);
113
117
  }
114
- }
118
+ }
package/support/patch.js CHANGED
@@ -1,47 +1,42 @@
1
- import 'temporal-polyfill-lite/global';
2
1
  import fs from 'node:fs/promises';
3
2
 
4
3
  if (process.env.NODE_ENV !== 'production') {
5
4
  process.setSourceMapsEnabled(true); // Ensure source map during compilation/development
6
5
  process.env.NODE_OPTIONS = `${process.env.NODE_OPTIONS ?? ''} --enable-source-maps`; // Ensure it passes to children
7
6
  Error.stackTraceLimit = 50;
8
-
9
- const ogEmitWarning = process.emitWarning;
10
- const exclusions = global.devProcessWarningExclusions = [];
11
- process.emitWarning = (message, category, ...other) => {
12
- if (exclusions.length === 0 || !exclusions.some(filter => filter(message, category))) {
13
- return ogEmitWarning(message, category, ...other);
14
- }
15
- };
16
7
  }
17
8
 
18
- const isError = Error.isError.bind(Error);
19
- Object.defineProperty(Error, 'isError', {
20
- value: (input) => isError(input) || (input instanceof Error)
21
- });
22
-
23
9
  // polyfills
24
-
25
- const [majorVersion, minorVersion] = process.version.replace(/^v/, '').split('.').map(text => parseInt(text, 10));
10
+ if (!globalThis.Temporal) {
11
+ // For anyone that doesn't have it
12
+ void import('temporal-polyfill-lite/global');
13
+ }
26
14
 
27
15
  Map.prototype.getOrInsert ??= function (key, value) {
28
- return (this.has(key) || this.set(key, value), this.get(key));
16
+ if (!this.has(key)) {
17
+ this.set(key, value);
18
+ }
19
+ return this.get(key);
29
20
  };
30
21
 
31
22
  Map.prototype.getOrInsertComputed ??= function (key, compute) {
32
- return (this.has(key) || this.set(key, compute()), this.get(key));
23
+ if (!this.has(key)) {
24
+ this.set(key, compute());
25
+ }
26
+ return this.get(key);
33
27
  };
34
28
 
35
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));
36
31
  if (majorVersion < 25 || (majorVersion === 25 && minorVersion < 7)) {
37
32
  const og = fs.stat;
38
33
  Object.defineProperty(fs, 'stat', {
39
34
  value: (...args) => {
40
35
  const out = og.call(fs, ...args);
41
36
  if (typeof args[1] === 'object' && args[1].throwIfNoEntry === false) {
42
- return out.catch(() => { });
37
+ return out.catch(() => {});
43
38
  }
44
39
  return out;
45
40
  }
46
41
  });
47
- }
42
+ }