@travetto/runtime 8.0.0-alpha.1 → 8.0.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/package.json +5 -5
- package/src/context.ts +9 -3
- package/src/env.ts +2 -2
- package/src/file-loader.ts +2 -2
- package/src/global.d.ts +12 -0
- package/src/json.ts +33 -38
- package/src/trv.d.ts +1 -1
- package/src/watch.ts +7 -2
- package/support/patch.js +47 -0
- package/support/polyfill.js +0 -9
package/README.md
CHANGED
|
@@ -70,7 +70,7 @@ class $Runtime {
|
|
|
70
70
|
/** Import from a given path */
|
|
71
71
|
async importFrom<T = unknown>(location?: string): Promise<T>;
|
|
72
72
|
/** Get an install command for a given npm module */
|
|
73
|
-
getInstallCommand(pkg: string, production
|
|
73
|
+
getInstallCommand(pkg: string, production?: boolean): string;
|
|
74
74
|
}
|
|
75
75
|
```
|
|
76
76
|
|
|
@@ -284,7 +284,7 @@ tpl`{{age:20}} {{name: 'bob'}}</>;
|
|
|
284
284
|
The [BinaryUtil](https://github.com/travetto/travetto/tree/main/module/runtime/src/binary.ts#L59) class provides a unified interface for working with binary data across different formats, especially bridging the gap between Node.js specific types (`Buffer`, `Stream`) and Web Standard types (`Blob`, `ArrayBuffer`). The framework leverages this to allow for seamless handling of binary data, regardless of the source.
|
|
285
285
|
|
|
286
286
|
## JSON Utilities
|
|
287
|
-
The [JSONUtil](https://github.com/travetto/travetto/tree/main/module/runtime/src/json.ts#
|
|
287
|
+
The [JSONUtil](https://github.com/travetto/travetto/tree/main/module/runtime/src/json.ts#L33) class provides a comprehensive set of utilities for working with JSON data, including serialization, deserialization, encoding, and deep cloning capabilities. The utility handles special types like `Date`, `BigInt`, and `Error` objects seamlessly. Key features include:
|
|
288
288
|
* `fromUTF8(input, config?)` - Parse JSON from a UTF-8 string
|
|
289
289
|
* `toUTF8(value, config?)` - Serialize a value to JSON string
|
|
290
290
|
* `toUTF8Pretty(value)` - Serialize with pretty formatting (2-space indent)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/runtime",
|
|
3
|
-
"version": "8.0.0-alpha.
|
|
3
|
+
"version": "8.0.0-alpha.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Runtime for travetto applications.",
|
|
6
6
|
"keywords": [
|
|
@@ -26,13 +26,13 @@
|
|
|
26
26
|
"directory": "module/runtime"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@travetto/manifest": "^8.0.0-alpha.
|
|
30
|
-
"@types/debug": "^4.1.
|
|
29
|
+
"@travetto/manifest": "^8.0.0-alpha.4",
|
|
30
|
+
"@types/debug": "^4.1.13",
|
|
31
31
|
"debug": "^4.4.3",
|
|
32
|
-
"temporal-polyfill-lite": "^0.
|
|
32
|
+
"temporal-polyfill-lite": "^0.3.3"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"@travetto/transformer": "^8.0.0-alpha.
|
|
35
|
+
"@travetto/transformer": "^8.0.0-alpha.5"
|
|
36
36
|
},
|
|
37
37
|
"peerDependenciesMeta": {
|
|
38
38
|
"@travetto/transformer": {
|
package/src/context.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { type ManifestIndex, type ManifestContext, ManifestModuleUtil } from '@t
|
|
|
6
6
|
import { Env } from './env.ts';
|
|
7
7
|
import { RuntimeIndex } from './manifest-index.ts';
|
|
8
8
|
import { describeFunction } from './function.ts';
|
|
9
|
-
import type { Role } from './trv';
|
|
9
|
+
import type { Role } from './trv.ts';
|
|
10
10
|
import { JSONUtil } from './json.ts';
|
|
11
11
|
|
|
12
12
|
/** Constrained version of {@type ManifestContext} */
|
|
@@ -111,7 +111,7 @@ class $Runtime {
|
|
|
111
111
|
/** Import from a given path */
|
|
112
112
|
async importFrom<T = unknown>(location?: string): Promise<T> {
|
|
113
113
|
const file = path.resolve(this.#idx.mainModule.sourcePath, location!);
|
|
114
|
-
if (await fs.stat(file
|
|
114
|
+
if (await fs.stat(file, { throwIfNoEntry: false })) {
|
|
115
115
|
location = this.#idx.getFromSource(file)?.import;
|
|
116
116
|
}
|
|
117
117
|
|
|
@@ -138,7 +138,13 @@ class $Runtime {
|
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
/** Get an install command for a given npm module */
|
|
141
|
-
getInstallCommand(pkg: string, production
|
|
141
|
+
getInstallCommand(pkg: string, production?: boolean): string {
|
|
142
|
+
if (production === undefined) {
|
|
143
|
+
const module = RuntimeIndex.getModule(pkg);
|
|
144
|
+
if (module !== undefined) {
|
|
145
|
+
production = module.production;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
142
148
|
switch (this.workspace.manager) {
|
|
143
149
|
case 'npm': return `npm install ${production ? '' : '--save-dev '}${pkg}`;
|
|
144
150
|
case 'yarn': return `yarn add ${production ? '' : '--dev '}${pkg}`;
|
package/src/env.ts
CHANGED
|
@@ -90,7 +90,7 @@ export class EnvProp<T> {
|
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
type
|
|
93
|
+
type EnvDataCombinedType = {
|
|
94
94
|
[K in keyof EnvData]: Pick<EnvProp<EnvData[K]>, 'key' | 'export' | 'value' | 'set' | 'clear' | 'isSet' |
|
|
95
95
|
(EnvData[K] extends unknown[] ? 'list' | 'add' : never) |
|
|
96
96
|
(Extract<EnvData[K], object> extends never ? never : 'object') |
|
|
@@ -99,7 +99,7 @@ type AllType = {
|
|
|
99
99
|
>
|
|
100
100
|
};
|
|
101
101
|
|
|
102
|
-
function delegate<T extends object>(base: T):
|
|
102
|
+
function delegate<T extends object>(base: T): EnvDataCombinedType & T {
|
|
103
103
|
return new Proxy(castTo(base), {
|
|
104
104
|
get(target, property): unknown {
|
|
105
105
|
return typeof property !== 'string' ? undefined :
|
package/src/file-loader.ts
CHANGED
|
@@ -30,7 +30,7 @@ export class FileLoader {
|
|
|
30
30
|
async resolve(relativePath: string): Promise<string> {
|
|
31
31
|
for (const sub of this.searchPaths) {
|
|
32
32
|
const resolved = path.join(sub, relativePath);
|
|
33
|
-
if (await fs.stat(resolved
|
|
33
|
+
if (await fs.stat(resolved, { throwIfNoEntry: false })) {
|
|
34
34
|
return resolved;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -41,7 +41,7 @@ export class FileLoader {
|
|
|
41
41
|
* Read a file as utf8 text, after resolving the path
|
|
42
42
|
* @param relativePath The path to read
|
|
43
43
|
*/
|
|
44
|
-
async
|
|
44
|
+
async readUTF8(relativePath: string): Promise<string> {
|
|
45
45
|
const file = await this.resolve(relativePath);
|
|
46
46
|
return fs.readFile(file, 'utf8');
|
|
47
47
|
}
|
package/src/global.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import './types';
|
|
2
2
|
|
|
3
3
|
declare const write: unique symbol;
|
|
4
|
+
|
|
5
|
+
declare global {
|
|
6
|
+
var devProcessWarningExclusions: ((message: string, category: string) => boolean)[] | undefined;
|
|
7
|
+
}
|
|
8
|
+
|
|
4
9
|
declare global {
|
|
5
10
|
// https://github.com/microsoft/TypeScript/issues/59012
|
|
6
11
|
interface WritableStreamDefaultWriter<W = any> {
|
|
@@ -64,4 +69,11 @@ declare module 'stream/web' {
|
|
|
64
69
|
* @concrete node:stream/web#ReadableStream
|
|
65
70
|
*/
|
|
66
71
|
interface ReadableStream { }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Remove once node 26 types are released
|
|
75
|
+
declare module 'node:fs' {
|
|
76
|
+
interface StatOptions {
|
|
77
|
+
throwIfNoEntry?: boolean;
|
|
78
|
+
}
|
|
67
79
|
}
|
package/src/json.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
+
import { AssertionError } from 'node:assert';
|
|
2
|
+
|
|
1
3
|
import type { BinaryArray } from './binary.ts';
|
|
2
4
|
import { CodecUtil } from './codec.ts';
|
|
3
5
|
import { RuntimeError, type RuntimeErrorOptions } from './error.ts';
|
|
4
|
-
import { castTo } from './types.ts';
|
|
6
|
+
import { castTo, type Any } from './types.ts';
|
|
7
|
+
|
|
8
|
+
const VALID_JSON_ERROR_TYPES = ['runtime', 'plain', 'assert'] as const;
|
|
9
|
+
const VALID_JSON_ERROR_TYPE_SET = new Set<unknown>(VALID_JSON_ERROR_TYPES);
|
|
5
10
|
|
|
6
11
|
type JSONTransformer = (this: unknown, key: string, value: unknown) => unknown;
|
|
7
12
|
type JSONOutputConfig = { indent?: number, replacer?: JSONTransformer };
|
|
8
13
|
type JSONInputConfig = { reviver?: JSONTransformer };
|
|
9
14
|
type JSONCloneConfig = JSONOutputConfig & JSONInputConfig;
|
|
10
|
-
type
|
|
11
|
-
type JSONError =
|
|
12
|
-
ErrorShape<'runtime', RuntimeErrorOptions<Record<string, unknown>>> |
|
|
13
|
-
ErrorShape<'plain', { name: string }>;
|
|
15
|
+
type JSONError = { $trv: (typeof VALID_JSON_ERROR_TYPES)[number], name?: string } & Partial<RuntimeErrorOptions<Record<string, unknown>>>;
|
|
14
16
|
|
|
15
17
|
Object.defineProperty(BigInt.prototype, 'toJSON', {
|
|
16
18
|
value() { return `${this}n`; },
|
|
@@ -47,53 +49,46 @@ export class JSONUtil {
|
|
|
47
49
|
|
|
48
50
|
|
|
49
51
|
static isJSONError(value: unknown): value is JSONError {
|
|
50
|
-
return typeof value === 'object' && value !== null && '$trv' in value && (
|
|
51
|
-
value.$trv === 'runtime' || value.$trv === 'plain'
|
|
52
|
-
);
|
|
52
|
+
return typeof value === 'object' && value !== null && '$trv' in value && VALID_JSON_ERROR_TYPE_SET.has(value.$trv);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
/** Convert from JSON object */
|
|
56
|
-
static jsonErrorToError(error: JSONError): Error
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
case 'plain': {
|
|
65
|
-
const result = new Error(error.message);
|
|
66
|
-
result.name = error.name;
|
|
67
|
-
result.stack = error.stack ?? result.stack;
|
|
68
|
-
return result;
|
|
69
|
-
}
|
|
56
|
+
static jsonErrorToError(error: JSONError): Error {
|
|
57
|
+
const { $trv, message, stack, name, ...rest } = error;
|
|
58
|
+
let response: Error;
|
|
59
|
+
switch ($trv) {
|
|
60
|
+
case 'runtime': response = new RuntimeError(message!, castTo<Any>(rest)); break;
|
|
61
|
+
case 'assert': response = new AssertionError({ message, ...rest }); break;
|
|
62
|
+
case 'plain': response = new Error(message!); break;
|
|
70
63
|
}
|
|
64
|
+
response.stack = stack;
|
|
65
|
+
if (name) { response.name = name; }
|
|
66
|
+
return response;
|
|
71
67
|
}
|
|
72
68
|
|
|
73
69
|
/**
|
|
74
70
|
* Serializes an error to a basic object
|
|
75
71
|
*/
|
|
76
|
-
static errorToJSONError(error:
|
|
72
|
+
static errorToJSONError(error: Error, includeStack?: boolean): JSONError | undefined {
|
|
77
73
|
includeStack ??= JSONUtil.includeStackTraces;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
74
|
+
let $trv: JSONError['$trv'];
|
|
75
|
+
switch (true) {
|
|
76
|
+
case error instanceof RuntimeError: $trv = 'runtime'; break;
|
|
77
|
+
case error instanceof AssertionError: $trv = 'assert'; break;
|
|
78
|
+
default: $trv = 'plain'; break;
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
$trv,
|
|
82
|
+
message: error.message,
|
|
83
|
+
...(error.cause ? { cause: `${error.cause}` } : undefined),
|
|
84
|
+
...(includeStack ? { stack: error.stack } : undefined),
|
|
85
|
+
...(error instanceof RuntimeError ? {
|
|
82
86
|
category: error.category,
|
|
83
|
-
...(error.cause ? { cause: `${error.cause}` } : undefined),
|
|
84
87
|
type: error.type,
|
|
85
88
|
at: error.at,
|
|
86
89
|
...(error.details ? { details: error.details } : undefined!),
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
} else {
|
|
90
|
-
return {
|
|
91
|
-
$trv: 'plain',
|
|
92
|
-
message: error.message,
|
|
93
|
-
name: error.name,
|
|
94
|
-
...(includeStack ? { stack: error.stack } : undefined)
|
|
95
|
-
};
|
|
96
|
-
}
|
|
90
|
+
} : {})
|
|
91
|
+
};
|
|
97
92
|
}
|
|
98
93
|
|
|
99
94
|
/** UTF8 string to JSON */
|
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/watch.ts
CHANGED
|
@@ -91,8 +91,13 @@ export class WatchUtil {
|
|
|
91
91
|
error: (...args: unknown[]): void => console.error(...args),
|
|
92
92
|
});
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
// pre-check
|
|
95
|
+
if (!await client.isWatching()) { // If we get here, without a watch
|
|
96
|
+
throw new RuntimeError('Compile Server is not running');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
void this.runWithRetry(async ({ signal }) => {
|
|
100
|
+
await client.waitForState(['watch-start'], undefined, signal);
|
|
96
101
|
|
|
97
102
|
if (!await client.isWatching()) { // If we get here, without a watch
|
|
98
103
|
return 'error';
|
package/support/patch.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import 'temporal-polyfill-lite/global';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
|
|
4
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
5
|
+
process.setSourceMapsEnabled(true); // Ensure source map during compilation/development
|
|
6
|
+
process.env.NODE_OPTIONS = `${process.env.NODE_OPTIONS ?? ''} --enable-source-maps`; // Ensure it passes to children
|
|
7
|
+
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
|
+
}
|
|
17
|
+
|
|
18
|
+
const isError = Error.isError.bind(Error);
|
|
19
|
+
Object.defineProperty(Error, 'isError', {
|
|
20
|
+
value: (input) => isError(input) || (input instanceof Error)
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// polyfills
|
|
24
|
+
|
|
25
|
+
const [majorVersion, minorVersion] = process.version.replace(/^v/, '').split('.').map(text => parseInt(text, 10));
|
|
26
|
+
|
|
27
|
+
Map.prototype.getOrInsert ??= function (key, value) {
|
|
28
|
+
return (this.has(key) || this.set(key, value), this.get(key));
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
Map.prototype.getOrInsertComputed ??= function (key, compute) {
|
|
32
|
+
return (this.has(key) || this.set(key, compute()), this.get(key));
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// Allow for the throwIfNoEntry if on a version of node that is less than 25.7
|
|
36
|
+
if (majorVersion < 25 || (majorVersion === 25 && minorVersion < 7)) {
|
|
37
|
+
const og = fs.stat;
|
|
38
|
+
Object.defineProperty(fs, 'stat', {
|
|
39
|
+
value: (...args) => {
|
|
40
|
+
const out = og.call(fs, ...args);
|
|
41
|
+
if (typeof args[1] === 'object' && args[1].throwIfNoEntry === false) {
|
|
42
|
+
return out.catch(() => { });
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
package/support/polyfill.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import 'temporal-polyfill-lite/global';
|
|
2
|
-
|
|
3
|
-
Map.prototype.getOrInsert ??= function(key, value) {
|
|
4
|
-
return (this.has(key) || this.set(key, value), this.get(key));
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
Map.prototype.getOrInsertComputed ??= function(key, compute) {
|
|
8
|
-
return (this.has(key) || this.set(key, compute()), this.get(key));
|
|
9
|
-
};
|