@travetto/runtime 5.0.0-rc.3 → 5.0.0-rc.4

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 CHANGED
@@ -61,12 +61,14 @@ class $Runtime {
61
61
  /** Resolve resource paths */
62
62
  resourcePaths(paths: string[] = []): string[];
63
63
  /** Get source for function */
64
- getSource(fn: Function): string;
64
+ getSourceFile(fn: Function): string;
65
+ /** Get import for function */
66
+ getImport(fn: Function): string;
65
67
  }
66
68
  ```
67
69
 
68
70
  ## Environment Support
69
- The functionality we support for testing and retrieving environment information for known environment variables. They can be accessed directly on the [Env](https://github.com/travetto/travetto/tree/main/module/runtime/src/env.ts#L109) object, and will return a scoped [EnvProp](https://github.com/travetto/travetto/tree/main/module/runtime/src/env.ts#L4), that is compatible with the property definition. E.g. only showing boolean related fields when the underlying flag supports `true` or `false`
71
+ The functionality we support for testing and retrieving environment information for known environment variables. They can be accessed directly on the [Env](https://github.com/travetto/travetto/tree/main/module/runtime/src/env.ts#L108) object, and will return a scoped [EnvProp](https://github.com/travetto/travetto/tree/main/module/runtime/src/env.ts#L4), that is compatible with the property definition. E.g. only showing boolean related fields when the underlying flag supports `true` or `false`
70
72
 
71
73
  **Code: Base Known Environment Flags**
72
74
  ```typescript
@@ -118,7 +120,12 @@ interface TravettoEnv {
118
120
  /**
119
121
  * trvc log level
120
122
  */
121
- TRV_BUILD: 'none' | 'info' | 'debug' | 'error' | 'warn'
123
+ TRV_BUILD: 'none' | 'info' | 'debug' | 'error' | 'warn',
124
+ /**
125
+ * Should break on first line of a method when using the @DebugBreak decorator
126
+ * @default false
127
+ */
128
+ TRV_DEBUG_BREAK: boolean;
122
129
  }
123
130
  ```
124
131
 
@@ -245,7 +252,7 @@ The primary access patterns for resources, is to directly request a file, and to
245
252
 
246
253
  The [FileLoader](https://github.com/travetto/travetto/tree/main/module/runtime/src/file-loader.ts#L11) allows for accessing information about the resources, and subsequently reading the file as text/binary or to access the resource as a `Readable` stream. If a file is not found, it will throw an [AppError](https://github.com/travetto/travetto/tree/main/module/runtime/src/error.ts#L13) with a category of 'notfound'.
247
254
 
248
- The [FileLoader](https://github.com/travetto/travetto/tree/main/module/runtime/src/file-loader.ts#L11) also supports tying itself to [Env](https://github.com/travetto/travetto/tree/main/module/runtime/src/env.ts#L109)'s `TRV_RESOURCES` information on where to attempt to find a requested resource.
255
+ The [FileLoader](https://github.com/travetto/travetto/tree/main/module/runtime/src/file-loader.ts#L11) also supports tying itself to [Env](https://github.com/travetto/travetto/tree/main/module/runtime/src/env.ts#L108)'s `TRV_RESOURCES` information on where to attempt to find a requested resource.
249
256
 
250
257
  ## Common Utilities
251
258
  Common utilities used throughout the framework. Currently [Util](https://github.com/travetto/travetto/tree/main/module/runtime/src/util.ts#L17) includes:
package/__index__.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  /// <reference path="./src/global.d.ts" />
3
3
  export * from './src/console';
4
4
  export * from './src/context';
5
+ export * from './src/debug';
5
6
  export * from './src/error';
6
7
  export * from './src/exec';
7
8
  export * from './src/env';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/runtime",
3
- "version": "5.0.0-rc.3",
3
+ "version": "5.0.0-rc.4",
4
4
  "description": "Runtime for travetto applications.",
5
5
  "keywords": [
6
6
  "console-manager",
@@ -24,14 +24,17 @@
24
24
  "url": "https://github.com/travetto/travetto.git",
25
25
  "directory": "module/runtime"
26
26
  },
27
+ "engines": {
28
+ "node": ">=22.0.0"
29
+ },
27
30
  "dependencies": {
28
31
  "@travetto/manifest": "^5.0.0-rc.2",
29
32
  "@types/debug": "^4.1.12",
30
- "@types/node": "^20.14.10",
33
+ "@types/node": "^22.1.0",
31
34
  "debug": "^4.3.5"
32
35
  },
33
36
  "peerDependencies": {
34
- "@travetto/transformer": "^5.0.0-rc.2"
37
+ "@travetto/transformer": "^5.0.0-rc.3"
35
38
  },
36
39
  "peerDependenciesMeta": {
37
40
  "@travetto/transformer": {
package/src/context.ts CHANGED
@@ -93,8 +93,13 @@ class $Runtime {
93
93
  }
94
94
 
95
95
  /** Get source for function */
96
- getSource(fn: Function): string {
97
- return this.#idx.getFromImport(describeFunction(fn).import)?.sourceFile!;
96
+ getSourceFile(fn: Function): string {
97
+ return this.#idx.getFromImport(this.getImport(fn))?.sourceFile!;
98
+ }
99
+
100
+ /** Get import for function */
101
+ getImport(fn: Function): string {
102
+ return describeFunction(fn).import;
98
103
  }
99
104
  }
100
105
 
package/src/debug.ts ADDED
@@ -0,0 +1,18 @@
1
+ import { Env } from './env';
2
+ import { ClassInstance } from './types';
3
+
4
+ /**
5
+ * The `@DebugBreak` indicates that a function inserts an optional debugger keyword to stop on entry
6
+ * @augments `@travetto/runtime:DebugBreak`
7
+ */
8
+ export function DebugBreak(): MethodDecorator {
9
+ return (inst: ClassInstance, prop: string | symbol, descriptor: PropertyDescriptor) => descriptor;
10
+
11
+ }
12
+
13
+ /**
14
+ * Determine if we should invoke the debugger
15
+ */
16
+ export function tryDebugger(): boolean {
17
+ return Env.TRV_DEBUG_BREAK.isTrue;
18
+ }
package/src/function.ts CHANGED
@@ -1,14 +1,19 @@
1
- export type FunctionMetadataTag = { hash: number, lines: [number, number] };
1
+ export type FunctionMetadataTag = { hash: number, lines: [start: number, end: number, bodyStart?: number] };
2
2
  export type FunctionMetadata = FunctionMetadataTag & {
3
3
  id: string;
4
4
  import: string;
5
+ module: string;
6
+ modulePath: string;
5
7
  methods?: Record<string, FunctionMetadataTag>;
6
8
  synthetic?: boolean;
9
+ class?: boolean;
7
10
  abstract?: boolean;
8
11
  };
9
12
 
10
13
  const METADATA = Symbol.for('@travetto/runtime:function-metadata');
11
14
 
15
+ const pending = new Set<Function>([]);
16
+
12
17
  /**
13
18
  * Initialize the meta data for a function/class
14
19
  * @param fn Class
@@ -20,16 +25,28 @@ const METADATA = Symbol.for('@travetto/runtime:function-metadata');
20
25
  * @param `synthetic` Is this code generated at build time
21
26
  * @private
22
27
  */
23
- export function register(
24
- fn: Function, module: [string, string], tag: FunctionMetadataTag,
28
+ export function registerFunction(
29
+ fn: Function, [pkg, pth]: [string, string], tag: FunctionMetadataTag,
25
30
  methods?: Record<string, FunctionMetadataTag>, abstract?: boolean, synthetic?: boolean
26
31
  ): void {
27
- let id = module.join(':');
28
- if (fn.name) {
29
- id = `${id}○${fn.name}`;
30
- }
31
- const value = { id, import: module.join('/'), ...tag, methods, abstract, synthetic };
32
- Object.defineProperties(fn, { Ⲑid: { value: id }, [METADATA]: { value } });
32
+ const metadata = {
33
+ id: fn.name ? `${pkg}:${pth}○${fn.name}` : `${pkg}:${pth}`,
34
+ import: `${pkg}/${pth}`,
35
+ module: pkg,
36
+ modulePath: pth,
37
+ ...tag, methods, abstract, synthetic, class: abstract !== undefined
38
+ };
39
+ pending.add(fn);
40
+ Object.defineProperties(fn, { Ⲑid: { value: metadata.id }, [METADATA]: { value: metadata } });
41
+ }
42
+
43
+ /**
44
+ * Flush all pending function registers
45
+ */
46
+ export function flushPendingFunctions(): Function[] {
47
+ const fns = [...pending];
48
+ pending.clear();
49
+ return fns;
33
50
  }
34
51
 
35
52
  /**
package/src/trv.d.ts CHANGED
@@ -54,6 +54,11 @@ declare global {
54
54
  /**
55
55
  * trvc log level
56
56
  */
57
- TRV_BUILD: 'none' | 'info' | 'debug' | 'error' | 'warn'
57
+ TRV_BUILD: 'none' | 'info' | 'debug' | 'error' | 'warn',
58
+ /**
59
+ * Should break on first line of a method when using the @DebugBreak decorator
60
+ * @default false
61
+ */
62
+ TRV_DEBUG_BREAK: boolean;
58
63
  }
59
64
  }
package/src/types.ts CHANGED
@@ -5,8 +5,19 @@ export type ClassInstance<T = any> = T & {
5
5
  constructor: ConcreteClass<T> & { Ⲑid: string };
6
6
  };
7
7
 
8
+ export type AnyMap = {
9
+ [key: string]: any
10
+ };
11
+
12
+ export type Primitive = number | bigint | boolean | string | Date;
13
+
14
+ export type DeepPartial<T> = {
15
+ [P in keyof T]?: (T[P] extends (Primitive | undefined) ? (T[P] | undefined) :
16
+ (T[P] extends any[] ? (DeepPartial<T[P][number]> | null | undefined)[] : DeepPartial<T[P]>));
17
+ };
18
+
8
19
  export const TypedObject: {
9
20
  keys<T = unknown, K extends keyof T = keyof T>(o: T): K[];
10
21
  fromEntries<K extends string | symbol, V>(items: ([K, V] | readonly [K, V])[]): Record<K, V>;
11
22
  entries<K extends Record<symbol | string, unknown>>(record: K): [keyof K, K[keyof K]][];
12
- } & ObjectConstructor = Object;
23
+ } & ObjectConstructor = Object;
@@ -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
+ }
@@ -15,6 +15,7 @@ const methods = Symbol.for(`${RUNTIME_MOD}:methods`);
15
15
  const cls = Symbol.for(`${RUNTIME_MOD}:class`);
16
16
  const fn = Symbol.for(`${RUNTIME_MOD}:function`);
17
17
  const registerImport = Symbol.for(`${RUNTIME_MOD}:registerImport`);
18
+ const registerFn = 'registerFunction';
18
19
 
19
20
  interface MetadataInfo {
20
21
  [registerImport]?: Import;
@@ -32,6 +33,12 @@ export class RegisterTransformer {
32
33
  const hash = SystemUtil.naiveHash(node.getText());
33
34
  try {
34
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
+ }
35
42
  return { hash, lines: range };
36
43
  } catch (err) {
37
44
  return { hash, lines: [0, 0] };
@@ -80,7 +87,7 @@ export class RegisterTransformer {
80
87
  const name = node.name?.escapedText.toString() ?? '';
81
88
 
82
89
  const meta = state.factory.createCallExpression(
83
- state.createAccess(state[registerImport].ident, 'register'),
90
+ state.createAccess(state[registerImport].ident, registerFn),
84
91
  [],
85
92
  [
86
93
  state.createIdentifier(name),
@@ -122,7 +129,7 @@ export class RegisterTransformer {
122
129
  state[registerImport] ??= state.importFile(REGISTER_IMPORT);
123
130
  const tag = this.#tag(state, node);
124
131
  const meta = state.factory.createCallExpression(
125
- state.createAccess(state[registerImport].ident, 'register'),
132
+ state.createAccess(state[registerImport].ident, registerFn),
126
133
  [],
127
134
  [
128
135
  state.createIdentifier(node.name),