@travetto/runtime 5.0.10 → 5.0.12
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 +3 -3
- package/package.json +4 -4
- package/src/binary.ts +1 -1
- package/src/error.ts +32 -22
- package/src/file-loader.ts +1 -1
- package/src/types.ts +2 -0
- package/src/util.ts +6 -4
package/README.md
CHANGED
|
@@ -164,9 +164,9 @@ export class EnvProp<T> {
|
|
|
164
164
|
```
|
|
165
165
|
|
|
166
166
|
## Standard Error Support
|
|
167
|
-
While the framework is 100 % compatible with standard `Error` instances, there are cases in which additional functionality is desired. Within the framework we use [AppError](https://github.com/travetto/travetto/tree/main/module/runtime/src/error.ts#
|
|
167
|
+
While the framework is 100 % compatible with standard `Error` instances, there are cases in which additional functionality is desired. Within the framework we use [AppError](https://github.com/travetto/travetto/tree/main/module/runtime/src/error.ts#L26) (or its derivatives) to represent framework errors. This class is available for use in your own projects. Some of the additional benefits of using this class is enhanced error reporting, as well as better integration with other modules (e.g. the [RESTful API](https://github.com/travetto/travetto/tree/main/module/rest#readme "Declarative api for RESTful APIs with support for the dependency injection module.") module and HTTP status codes).
|
|
168
168
|
|
|
169
|
-
The [AppError](https://github.com/travetto/travetto/tree/main/module/runtime/src/error.ts#
|
|
169
|
+
The [AppError](https://github.com/travetto/travetto/tree/main/module/runtime/src/error.ts#L26) takes in a message, and an optional payload and / or error classification. The currently supported error classifications are:
|
|
170
170
|
* `general` - General purpose errors
|
|
171
171
|
* `system` - Synonym for `general`
|
|
172
172
|
* `data` - Data format, content, etc are incorrect. Generally correlated to bad input.
|
|
@@ -254,7 +254,7 @@ $ DEBUG=express:*,@travetto/rest npx trv run rest
|
|
|
254
254
|
## Resource Access
|
|
255
255
|
The primary access patterns for resources, is to directly request a file, and to resolve that file either via file-system look up or leveraging the [Manifest](https://github.com/travetto/travetto/tree/main/module/manifest#readme "Support for project indexing, manifesting, along with file watching")'s data for what resources were found at manifesting time.
|
|
256
256
|
|
|
257
|
-
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#
|
|
257
|
+
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#L26) with a category of 'notfound'.
|
|
258
258
|
|
|
259
259
|
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#L111)'s `TRV_RESOURCES` information on where to attempt to find a requested resource.
|
|
260
260
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/runtime",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.12",
|
|
4
4
|
"description": "Runtime for travetto applications.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"console-manager",
|
|
@@ -28,13 +28,13 @@
|
|
|
28
28
|
"node": ">=22.0.0"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@travetto/manifest": "^5.0.
|
|
31
|
+
"@travetto/manifest": "^5.0.9",
|
|
32
32
|
"@types/debug": "^4.1.12",
|
|
33
|
-
"@types/node": "^22.7.
|
|
33
|
+
"@types/node": "^22.7.9",
|
|
34
34
|
"debug": "^4.3.7"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"@travetto/transformer": "^5.0.
|
|
37
|
+
"@travetto/transformer": "^5.0.10"
|
|
38
38
|
},
|
|
39
39
|
"peerDependenciesMeta": {
|
|
40
40
|
"@travetto/transformer": {
|
package/src/binary.ts
CHANGED
|
@@ -108,7 +108,7 @@ export class BinaryUtil {
|
|
|
108
108
|
transform(chunk, encoding, callback): void {
|
|
109
109
|
read += (Buffer.isBuffer(chunk) || typeof chunk === 'string') ? chunk.length : (chunk instanceof Uint8Array ? chunk.byteLength : 0);
|
|
110
110
|
if (read > maxSize) {
|
|
111
|
-
callback(new AppError('File size exceeded', 'data', { read, size: maxSize }));
|
|
111
|
+
callback(new AppError('File size exceeded', { category: 'data', details: { read, size: maxSize } }));
|
|
112
112
|
} else {
|
|
113
113
|
callback(null, chunk);
|
|
114
114
|
}
|
package/src/error.ts
CHANGED
|
@@ -9,10 +9,21 @@ export type ErrorCategory =
|
|
|
9
9
|
'timeout' |
|
|
10
10
|
'unavailable';
|
|
11
11
|
|
|
12
|
+
export type AppErrorOptions<T> =
|
|
13
|
+
ErrorOptions &
|
|
14
|
+
{
|
|
15
|
+
at?: Date | string | number;
|
|
16
|
+
type?: string;
|
|
17
|
+
category?: ErrorCategory;
|
|
18
|
+
} &
|
|
19
|
+
(T extends undefined ?
|
|
20
|
+
{ details?: T } :
|
|
21
|
+
{ details: T });
|
|
22
|
+
|
|
12
23
|
/**
|
|
13
24
|
* Framework error class, with the aim of being extensible
|
|
14
25
|
*/
|
|
15
|
-
export class AppError<T = unknown> extends Error {
|
|
26
|
+
export class AppError<T = Record<string, unknown> | undefined> extends Error {
|
|
16
27
|
|
|
17
28
|
/** Convert from JSON object */
|
|
18
29
|
static fromJSON(e: unknown): AppError | undefined {
|
|
@@ -20,47 +31,46 @@ export class AppError<T = unknown> extends Error {
|
|
|
20
31
|
('message' in e && typeof e.message === 'string') &&
|
|
21
32
|
('category' in e && typeof e.category === 'string') &&
|
|
22
33
|
('type' in e && typeof e.type === 'string') &&
|
|
23
|
-
('at' in e && typeof e.at === '
|
|
34
|
+
('at' in e && typeof e.at === 'string')
|
|
24
35
|
) {
|
|
25
|
-
|
|
26
|
-
err.at = new Date(e.at);
|
|
27
|
-
err.type = e.type;
|
|
28
|
-
return err;
|
|
36
|
+
return new AppError(e.message, castTo<AppErrorOptions<Record<string, unknown>>>(e));
|
|
29
37
|
}
|
|
30
38
|
}
|
|
31
39
|
|
|
32
40
|
type: string;
|
|
33
|
-
|
|
41
|
+
category: ErrorCategory;
|
|
42
|
+
at: string;
|
|
34
43
|
details: T;
|
|
35
44
|
|
|
36
45
|
/**
|
|
37
46
|
* Build an app error
|
|
38
47
|
*
|
|
39
48
|
* @param message The error message
|
|
40
|
-
* @param category The error category, can be mapped to HTTP statuses
|
|
41
|
-
* @param details Optional error payload
|
|
42
49
|
*/
|
|
43
50
|
constructor(
|
|
44
|
-
message:
|
|
45
|
-
|
|
46
|
-
details?: T
|
|
47
|
-
|
|
51
|
+
...[message, opts]:
|
|
52
|
+
T extends undefined ? ([string] | [string, AppErrorOptions<T>]) : [string, AppErrorOptions<T>]
|
|
48
53
|
) {
|
|
49
|
-
super(message);
|
|
50
|
-
this.type = this.constructor.name;
|
|
51
|
-
this.details = details!;
|
|
54
|
+
super(message, opts?.cause ? { cause: opts.cause } : undefined);
|
|
55
|
+
this.type = opts?.type ?? this.constructor.name;
|
|
56
|
+
this.details = opts?.details!;
|
|
57
|
+
this.category = opts?.category ?? 'general';
|
|
58
|
+
this.at = new Date(opts?.at ?? Date.now()).toISOString();
|
|
52
59
|
}
|
|
53
60
|
|
|
54
61
|
/**
|
|
55
|
-
*
|
|
62
|
+
* Serializes an error to a basic object
|
|
56
63
|
*/
|
|
57
|
-
toJSON(): { message: string
|
|
58
|
-
|
|
59
|
-
message: this.message,
|
|
64
|
+
toJSON(): AppErrorOptions<T> & { message: string } {
|
|
65
|
+
const res: AppErrorOptions<unknown> = {
|
|
60
66
|
category: this.category,
|
|
67
|
+
...(this.cause ? { cause: `${this.cause}` } : undefined),
|
|
61
68
|
type: this.type,
|
|
62
|
-
at: this.at
|
|
63
|
-
details:
|
|
69
|
+
at: this.at,
|
|
70
|
+
...(this.details ? { details: this.details } : undefined!),
|
|
64
71
|
};
|
|
72
|
+
|
|
73
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
74
|
+
return { message: this.message, ...res as AppErrorOptions<T> };
|
|
65
75
|
}
|
|
66
76
|
}
|
package/src/file-loader.ts
CHANGED
|
@@ -34,7 +34,7 @@ export class FileLoader {
|
|
|
34
34
|
return resolved;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
-
throw new AppError(`Unable to find: ${relativePath}, searched=${this.searchPaths.join(',')}`, 'notfound');
|
|
37
|
+
throw new AppError(`Unable to find: ${relativePath}, searched=${this.searchPaths.join(',')}`, { category: 'notfound' });
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/**
|
package/src/types.ts
CHANGED
|
@@ -49,6 +49,8 @@ export function classConstruct<T>(cls: Class<T>, args: unknown[] = []): ClassIns
|
|
|
49
49
|
export const hasFunction = <T>(key: keyof T) => (o: unknown): o is T =>
|
|
50
50
|
typeof o === 'object' && o !== null && typeof o[castKey(key)] === 'function';
|
|
51
51
|
|
|
52
|
+
export const hasToJSON = hasFunction<{ toJSON(): object }>('toJSON');
|
|
53
|
+
|
|
52
54
|
/**
|
|
53
55
|
* Range of bytes, inclusive
|
|
54
56
|
*/
|
package/src/util.ts
CHANGED
|
@@ -47,10 +47,12 @@ export class Util {
|
|
|
47
47
|
*/
|
|
48
48
|
static uuid(len: number = 32): string {
|
|
49
49
|
const bytes = crypto.randomBytes(Math.ceil(len / 2));
|
|
50
|
-
//
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
if (len === 32) { // Make valid uuid-v4
|
|
51
|
+
// eslint-disable-next-line no-bitwise
|
|
52
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x40;
|
|
53
|
+
// eslint-disable-next-line no-bitwise
|
|
54
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
|
55
|
+
}
|
|
54
56
|
return bytes.toString('hex').substring(0, len);
|
|
55
57
|
}
|
|
56
58
|
|