@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/README.md +31 -28
- package/__index__.ts +6 -5
- package/package.json +18 -15
- package/src/binary-metadata.ts +33 -19
- package/src/binary.ts +18 -10
- package/src/codec.ts +25 -7
- package/src/console.ts +20 -12
- package/src/context.ts +18 -15
- package/src/debug.ts +1 -2
- package/src/env.ts +40 -20
- package/src/error.ts +4 -15
- package/src/exec.ts +41 -27
- package/src/file-loader.ts +2 -3
- package/src/function.ts +14 -6
- package/src/global.d.ts +22 -14
- package/src/json.ts +42 -22
- package/src/manifest-index.ts +1 -1
- package/src/queue.ts +1 -2
- package/src/resources.ts +1 -1
- package/src/shutdown.ts +21 -14
- package/src/time.ts +54 -19
- package/src/trv.d.ts +10 -9
- package/src/types.ts +32 -15
- package/src/util.ts +20 -22
- package/src/watch.ts +21 -17
- package/support/patch.js +15 -20
- package/support/transformer/metadata.ts +15 -28
- package/support/transformer.concrete-type.ts +19 -21
- package/support/transformer.console-log.ts +13 -19
- package/support/transformer.debug-method.ts +13 -9
- package/support/transformer.dynamic-import.ts +1 -2
- package/support/transformer.function-metadata.ts +6 -4
- package/support/transformer.rewrite-path-import.ts +9 -12
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ npm install @travetto/runtime
|
|
|
13
13
|
yarn add @travetto/runtime
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
Runtime is the foundation of all [Travetto](https://travetto.dev) applications.
|
|
16
|
+
Runtime is the foundation of all [Travetto](https://travetto.dev) applications. It is intended to be a minimal application set, as well as support for commonly shared functionality. It has support for the following key areas:
|
|
17
17
|
* Runtime Context
|
|
18
18
|
* Environment Support
|
|
19
19
|
* Standard Error Support
|
|
@@ -29,7 +29,7 @@ Runtime is the foundation of all [Travetto](https://travetto.dev) applications.
|
|
|
29
29
|
* Path behavior
|
|
30
30
|
|
|
31
31
|
## Runtime Context
|
|
32
|
-
While running any code within the framework, there are common patterns/goals for interacting with the underlying code repository.
|
|
32
|
+
While running any code within the framework, there are common patterns/goals for interacting with the underlying code repository. These include:
|
|
33
33
|
* Determining attributes of the running environment (e.g., name, debug information, production flags)
|
|
34
34
|
* Resolving paths within the workspace (e.g. standard, tooling, resourcing, modules)
|
|
35
35
|
|
|
@@ -75,43 +75,43 @@ class $Runtime {
|
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
### Class and Function Metadata
|
|
78
|
-
For the framework to work properly, metadata needs to be collected about files, classes and functions to uniquely identify them, with support for detecting changes during live reloads.
|
|
78
|
+
For the framework to work properly, metadata needs to be collected about files, classes and functions to uniquely identify them, with support for detecting changes during live reloads. To achieve this, every `class` is decorated with metadata, including methods, line numbers, and ultimately a unique id stored at `Ⲑid`.
|
|
79
79
|
|
|
80
80
|
## Environment Support
|
|
81
|
-
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#
|
|
81
|
+
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#L134) object, and will return a scoped [EnvProp](https://github.com/travetto/travetto/tree/main/module/runtime/src/env.ts#L8), that is compatible with the property definition. E.g. only showing boolean related fields when the underlying flag supports `true` or `false`
|
|
82
82
|
|
|
83
83
|
**Code: Base Known Environment Flags**
|
|
84
84
|
```typescript
|
|
85
85
|
interface EnvData {
|
|
86
|
-
/**
|
|
86
|
+
/**
|
|
87
87
|
* The node environment we are running in
|
|
88
88
|
* @default development
|
|
89
89
|
*/
|
|
90
90
|
NODE_ENV: 'development' | 'production';
|
|
91
|
-
/**
|
|
91
|
+
/**
|
|
92
92
|
* Outputs all console.debug messages, defaults to off
|
|
93
93
|
*/
|
|
94
94
|
DEBUG: boolean | string;
|
|
95
|
-
/**
|
|
95
|
+
/**
|
|
96
96
|
* The role we are running as, allows access to additional files from the manifest during runtime.
|
|
97
97
|
*/
|
|
98
98
|
TRV_ROLE: Role;
|
|
99
|
-
/**
|
|
99
|
+
/**
|
|
100
100
|
* The folders to use for resource lookup
|
|
101
101
|
*/
|
|
102
102
|
TRV_RESOURCES: string[];
|
|
103
|
-
/**
|
|
103
|
+
/**
|
|
104
104
|
* Resource path overrides
|
|
105
105
|
* @private
|
|
106
106
|
*/
|
|
107
107
|
TRV_RESOURCE_OVERRIDES: Record<string, string>;
|
|
108
|
-
/**
|
|
109
|
-
* The max time to wait for shutdown to finish after initial SIGINT,
|
|
108
|
+
/**
|
|
109
|
+
* The max time to wait for shutdown to finish after initial SIGINT,
|
|
110
110
|
* @default 2s
|
|
111
111
|
*/
|
|
112
112
|
TRV_SHUTDOWN_WAIT: TimeSpan | number;
|
|
113
113
|
/**
|
|
114
|
-
* The desired runtime module
|
|
114
|
+
* The desired runtime module
|
|
115
115
|
*/
|
|
116
116
|
TRV_MODULE: string;
|
|
117
117
|
/**
|
|
@@ -138,7 +138,9 @@ For a given [EnvProp](https://github.com/travetto/travetto/tree/main/module/runt
|
|
|
138
138
|
```typescript
|
|
139
139
|
export class EnvProp<T> {
|
|
140
140
|
readonly key: string;
|
|
141
|
-
constructor(key: string)
|
|
141
|
+
constructor(key: string);
|
|
142
|
+
/** Set value according to type */
|
|
143
|
+
set(value: T | undefined | null): void;
|
|
142
144
|
/** Remove value */
|
|
143
145
|
clear(): void;
|
|
144
146
|
/** Export value */
|
|
@@ -165,9 +167,9 @@ export class EnvProp<T> {
|
|
|
165
167
|
```
|
|
166
168
|
|
|
167
169
|
## Standard Error Support
|
|
168
|
-
While the framework is 100 % compatible with standard `Error` instances, there are cases in which additional functionality is desired. Within the framework we use [RuntimeError](https://github.com/travetto/travetto/tree/main/module/runtime/src/error.ts#
|
|
170
|
+
While the framework is 100 % compatible with standard `Error` instances, there are cases in which additional functionality is desired. Within the framework we use [RuntimeError](https://github.com/travetto/travetto/tree/main/module/runtime/src/error.ts#L10) (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 [Web API](https://github.com/travetto/travetto/tree/main/module/web#readme "Declarative support for creating Web Applications") module and HTTP status codes).
|
|
169
171
|
|
|
170
|
-
The [RuntimeError](https://github.com/travetto/travetto/tree/main/module/runtime/src/error.ts#
|
|
172
|
+
The [RuntimeError](https://github.com/travetto/travetto/tree/main/module/runtime/src/error.ts#L10) takes in a message, and an optional payload and / or error classification. The currently supported error classifications are:
|
|
171
173
|
* `general` - General purpose errors
|
|
172
174
|
* `system` - Synonym for `general`
|
|
173
175
|
* `data` - Data format, content, etc are incorrect. Generally correlated to bad input.
|
|
@@ -190,7 +192,7 @@ The supported operations are:
|
|
|
190
192
|
**Note**: All other console methods are excluded, specifically `trace`, `inspect`, `dir`, `time`/`timeEnd`
|
|
191
193
|
|
|
192
194
|
### How Logging is Instrumented
|
|
193
|
-
All of the logging instrumentation occurs at transpilation time.
|
|
195
|
+
All of the logging instrumentation occurs at transpilation time. All `console.*` methods are replaced with a call to a globally defined variable that delegates to the [ConsoleManager](https://github.com/travetto/travetto/tree/main/module/runtime/src/console.ts#L44). This module, hooks into the [ConsoleManager](https://github.com/travetto/travetto/tree/main/module/runtime/src/console.ts#L44) and receives all logging events from all files compiled by the [Travetto](https://travetto.dev).
|
|
194
196
|
|
|
195
197
|
A sample of the instrumentation would be:
|
|
196
198
|
|
|
@@ -227,7 +229,7 @@ export function work() {
|
|
|
227
229
|
```
|
|
228
230
|
|
|
229
231
|
#### Filtering Debug
|
|
230
|
-
The `debug` messages can be filtered using the patterns from the [debug](https://www.npmjs.com/package/debug).
|
|
232
|
+
The `debug` messages can be filtered using the patterns from the [debug](https://www.npmjs.com/package/debug). You can specify wild cards to only `DEBUG` specific modules, folders or files. You can specify multiple, and you can also add negations to exclude specific packages.
|
|
231
233
|
|
|
232
234
|
**Terminal: Sample environment flags**
|
|
233
235
|
```bash
|
|
@@ -251,9 +253,9 @@ $ DEBUG=express:*,@travetto/web npx trv run web
|
|
|
251
253
|
## Resource Access
|
|
252
254
|
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.
|
|
253
255
|
|
|
254
|
-
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.
|
|
256
|
+
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 [RuntimeError](https://github.com/travetto/travetto/tree/main/module/runtime/src/error.ts#L10) with a category of 'notfound'.
|
|
255
257
|
|
|
256
|
-
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#
|
|
258
|
+
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#L134)'s `TRV_RESOURCES` information on where to attempt to find a requested resource.
|
|
257
259
|
|
|
258
260
|
## Encoding and Decoding Utilities
|
|
259
261
|
The [CodecUtil](https://github.com/travetto/travetto/tree/main/module/runtime/src/codec.ts#L15) class provides a variety of static methods for encoding and decoding data. When working with JSON data, it also provide security checks to prevent prototype pollution. The utility supports the following formats:
|
|
@@ -265,12 +267,12 @@ The [CodecUtil](https://github.com/travetto/travetto/tree/main/module/runtime/sr
|
|
|
265
267
|
* New Line Delimited UTF8
|
|
266
268
|
|
|
267
269
|
## Common Utilities
|
|
268
|
-
Common utilities used throughout the framework. Currently [Util](https://github.com/travetto/travetto/tree/main/module/runtime/src/util.ts#
|
|
270
|
+
Common utilities used throughout the framework. Currently [Util](https://github.com/travetto/travetto/tree/main/module/runtime/src/util.ts#L16) includes:
|
|
269
271
|
* `uuid(len: number)` generates a simple uuid for use within the application.
|
|
270
|
-
* `allowDenyMatcher(rules[])` builds a matching function that leverages the rules as an allow/deny list, where order of the rules matters.
|
|
272
|
+
* `allowDenyMatcher(rules[])` builds a matching function that leverages the rules as an allow/deny list, where order of the rules matters. Negative rules are prefixed by '!'.
|
|
271
273
|
* `hash(text: string, size?: number)` produces a full sha512 hash.
|
|
272
|
-
* `resolvablePromise()` produces a `Promise` instance with the `resolve` and `reject` methods attached to the instance.
|
|
273
|
-
* `bufferedFileWrite(file:string, content: string)` will write the file, using a temporary buffer file to ensure that the entire file is written before being moved to the final location.
|
|
274
|
+
* `resolvablePromise()` produces a `Promise` instance with the `resolve` and `reject` methods attached to the instance. This is extremely useful for integrating promises into async iterations, or any other situation in which the promise creation and the execution flow don't always match up.
|
|
275
|
+
* `bufferedFileWrite(file:string, content: string)` will write the file, using a temporary buffer file to ensure that the entire file is written before being moved to the final location. This helps minimize file watch noise when writing files.
|
|
274
276
|
|
|
275
277
|
**Code: Sample makeTemplate Usage**
|
|
276
278
|
```typescript
|
|
@@ -281,10 +283,10 @@ tpl`{{age:20}} {{name: 'bob'}}</>;
|
|
|
281
283
|
```
|
|
282
284
|
|
|
283
285
|
## Binary Utilities
|
|
284
|
-
The [BinaryUtil](https://github.com/travetto/travetto/tree/main/module/runtime/src/binary.ts#
|
|
286
|
+
The [BinaryUtil](https://github.com/travetto/travetto/tree/main/module/runtime/src/binary.ts#L68) 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
287
|
|
|
286
288
|
## JSON Utilities
|
|
287
|
-
The [JSONUtil](https://github.com/travetto/travetto/tree/main/module/runtime/src/json.ts#
|
|
289
|
+
The [JSONUtil](https://github.com/travetto/travetto/tree/main/module/runtime/src/json.ts#L39) 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
290
|
* `fromUTF8(input, config?)` - Parse JSON from a UTF-8 string
|
|
289
291
|
* `toUTF8(value, config?)` - Serialize a value to JSON string
|
|
290
292
|
* `toUTF8Pretty(value)` - Serialize with pretty formatting (2-space indent)
|
|
@@ -299,7 +301,7 @@ The [JSONUtil](https://github.com/travetto/travetto/tree/main/module/runtime/src
|
|
|
299
301
|
The `TRANSMIT_REVIVER` automatically restores `Date` objects and `BigInt` values during deserialization, making it ideal for transmitting complex data structures across network boundaries.
|
|
300
302
|
|
|
301
303
|
## Time Utilities
|
|
302
|
-
[TimeUtil](https://github.com/travetto/travetto/tree/main/module/runtime/src/time.ts#
|
|
304
|
+
[TimeUtil](https://github.com/travetto/travetto/tree/main/module/runtime/src/time.ts#L37) contains general helper methods, created to assist with time-based inputs via environment variables, command line interfaces, and other string-heavy based input.
|
|
303
305
|
|
|
304
306
|
**Code: Time Utilities**
|
|
305
307
|
```typescript
|
|
@@ -324,13 +326,14 @@ export class TimeUtil {
|
|
|
324
326
|
```
|
|
325
327
|
|
|
326
328
|
## Process Execution
|
|
327
|
-
[ExecUtil](https://github.com/travetto/travetto/tree/main/module/runtime/src/exec.ts#L41) exposes `getResult` as a means to wrap [child_process](https://nodejs.org/api/child_process.html)'s process object.
|
|
329
|
+
[ExecUtil](https://github.com/travetto/travetto/tree/main/module/runtime/src/exec.ts#L41) exposes `getResult` as a means to wrap [child_process](https://nodejs.org/api/child_process.html)'s process object. This wrapper allows for a promise-based resolution of the subprocess with the ability to capture the stderr/stdout.
|
|
328
330
|
|
|
329
331
|
A simple example would be:
|
|
330
332
|
|
|
331
333
|
**Code: Running a directory listing via ls**
|
|
332
334
|
```typescript
|
|
333
335
|
import { spawn } from 'node:child_process';
|
|
336
|
+
|
|
334
337
|
import { ExecUtil } from '@travetto/runtime';
|
|
335
338
|
|
|
336
339
|
export async function executeListing() {
|
|
@@ -357,4 +360,4 @@ export function registerShutdownHandler() {
|
|
|
357
360
|
```
|
|
358
361
|
|
|
359
362
|
## Path Behavior
|
|
360
|
-
To ensure consistency in path usage throughout the framework, imports pointing at `node:path` and `path` are rewritten at compile time.
|
|
363
|
+
To ensure consistency in path usage throughout the framework, imports pointing at `node:path` and `path` are rewritten at compile time. These imports are pointing towards [Manifest](https://github.com/travetto/travetto/tree/main/module/manifest#readme "Support for project indexing, manifesting, along with file watching")'s `path` implementation. This allows for seamless import/usage patterns with the reliability needed for cross platform support.
|
package/__index__.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
1
|
+
import type {} from './src/global.d.ts';
|
|
2
|
+
import type {} from './src/trv.d.ts';
|
|
3
|
+
|
|
3
4
|
export * from './src/binary.ts';
|
|
4
5
|
export * from './src/binary-metadata.ts';
|
|
6
|
+
export * from './src/codec.ts';
|
|
5
7
|
export * from './src/console.ts';
|
|
6
8
|
export * from './src/context.ts';
|
|
7
9
|
export * from './src/debug.ts';
|
|
10
|
+
export * from './src/env.ts';
|
|
8
11
|
export * from './src/error.ts';
|
|
9
12
|
export * from './src/exec.ts';
|
|
10
|
-
export * from './src/codec.ts';
|
|
11
|
-
export * from './src/env.ts';
|
|
12
13
|
export * from './src/file-loader.ts';
|
|
13
14
|
export * from './src/function.ts';
|
|
14
15
|
export * from './src/json.ts';
|
|
@@ -18,5 +19,5 @@ export * from './src/resources.ts';
|
|
|
18
19
|
export * from './src/shutdown.ts';
|
|
19
20
|
export * from './src/time.ts';
|
|
20
21
|
export * from './src/types.ts';
|
|
21
|
-
export * from './src/watch.ts';
|
|
22
22
|
export * from './src/util.ts';
|
|
23
|
+
export * from './src/watch.ts';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@travetto/runtime",
|
|
3
|
-
"version": "8.0.
|
|
4
|
-
"
|
|
3
|
+
"version": "8.0.1",
|
|
4
|
+
"private": false,
|
|
5
5
|
"description": "Runtime for travetto applications.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"console-manager",
|
|
@@ -12,38 +12,41 @@
|
|
|
12
12
|
"homepage": "https://travetto.io",
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"author": {
|
|
15
|
-
"
|
|
16
|
-
"
|
|
15
|
+
"name": "Travetto Framework",
|
|
16
|
+
"email": "travetto.framework@gmail.com"
|
|
17
|
+
},
|
|
18
|
+
"repository": {
|
|
19
|
+
"url": "git+https://github.com/travetto/travetto.git",
|
|
20
|
+
"directory": "module/runtime"
|
|
17
21
|
},
|
|
18
22
|
"files": [
|
|
19
23
|
"__index__.ts",
|
|
20
24
|
"src",
|
|
21
25
|
"support"
|
|
22
26
|
],
|
|
27
|
+
"type": "module",
|
|
23
28
|
"main": "__index__.ts",
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"directory": "module/runtime"
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
27
31
|
},
|
|
28
32
|
"dependencies": {
|
|
29
|
-
"@travetto/manifest": "^8.0.
|
|
33
|
+
"@travetto/manifest": "^8.0.1",
|
|
30
34
|
"@types/debug": "^4.1.13",
|
|
31
|
-
"debug": "^4.4.3"
|
|
32
|
-
"temporal-polyfill-lite": "^0.3.2"
|
|
35
|
+
"debug": "^4.4.3"
|
|
33
36
|
},
|
|
34
37
|
"peerDependencies": {
|
|
35
|
-
"@travetto/transformer": "^8.0.
|
|
38
|
+
"@travetto/transformer": "^8.0.1",
|
|
39
|
+
"temporal-polyfill-lite": "^0.4.3"
|
|
36
40
|
},
|
|
37
41
|
"peerDependenciesMeta": {
|
|
38
42
|
"@travetto/transformer": {
|
|
39
43
|
"optional": true
|
|
44
|
+
},
|
|
45
|
+
"temporal-polyfill-lite": {
|
|
46
|
+
"optional": true
|
|
40
47
|
}
|
|
41
48
|
},
|
|
42
49
|
"travetto": {
|
|
43
50
|
"displayName": "Runtime"
|
|
44
|
-
},
|
|
45
|
-
"private": false,
|
|
46
|
-
"publishConfig": {
|
|
47
|
-
"access": "public"
|
|
48
51
|
}
|
|
49
52
|
}
|
package/src/binary-metadata.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import crypto from 'node:crypto';
|
|
2
|
+
import { createReadStream, ReadStream } from 'node:fs';
|
|
2
3
|
import fs from 'node:fs/promises';
|
|
3
4
|
import path from 'node:path';
|
|
4
|
-
import { createReadStream, ReadStream } from 'node:fs';
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import { RuntimeError } from './error.ts';
|
|
6
|
+
import { type BinaryArray, type BinaryContainer, type BinaryStream, type BinaryType, BinaryUtil } from './binary.ts';
|
|
8
7
|
import { CodecUtil } from './codec.ts';
|
|
8
|
+
import { RuntimeError } from './error.ts';
|
|
9
9
|
|
|
10
|
-
type BlobInput = BinaryType | (() =>
|
|
10
|
+
type BlobInput = BinaryType | (() => BinaryType | Promise<BinaryType>);
|
|
11
11
|
|
|
12
12
|
/** Range of bytes, inclusive */
|
|
13
|
-
export type ByteRange = { start: number
|
|
13
|
+
export type ByteRange = { start: number; end?: number };
|
|
14
14
|
|
|
15
15
|
export interface BinaryMetadata {
|
|
16
16
|
/** Size of binary data */
|
|
@@ -45,7 +45,7 @@ export class BinaryMetadataUtil {
|
|
|
45
45
|
/** Set metadata for a binary type */
|
|
46
46
|
static write(input: BinaryType, metadata: BinaryMetadata): BinaryMetadata {
|
|
47
47
|
const withMeta: BinaryType & { [BinaryMetaSymbol]?: BinaryMetadata } = input;
|
|
48
|
-
return withMeta[BinaryMetaSymbol] = metadata;
|
|
48
|
+
return (withMeta[BinaryMetaSymbol] = metadata);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
/** Read metadata for a binary type, if available */
|
|
@@ -75,15 +75,13 @@ export class BinaryMetadataUtil {
|
|
|
75
75
|
hash.update(BinaryUtil.binaryArrayToUint8Array(input));
|
|
76
76
|
return hash.digest(outputEncoding).substring(0, length);
|
|
77
77
|
} else {
|
|
78
|
-
return BinaryUtil.pipeline(input, hash).then(() =>
|
|
79
|
-
hash.digest(outputEncoding).substring(0, length)
|
|
80
|
-
);
|
|
78
|
+
return BinaryUtil.pipeline(input, hash).then(() => hash.digest(outputEncoding).substring(0, length));
|
|
81
79
|
}
|
|
82
80
|
}
|
|
83
81
|
|
|
84
82
|
/** Compute the length of the binary data to be returned */
|
|
85
83
|
static readLength(metadata: BinaryMetadata): number | undefined {
|
|
86
|
-
return metadata.range ?
|
|
84
|
+
return metadata.range ? metadata.range.end - metadata.range.start + 1 : metadata.size;
|
|
87
85
|
}
|
|
88
86
|
|
|
89
87
|
/** Compute metadata for a given binary input */
|
|
@@ -119,13 +117,25 @@ export class BinaryMetadataUtil {
|
|
|
119
117
|
* Rewrite a blob to support metadata, and provide a dynamic input source
|
|
120
118
|
*/
|
|
121
119
|
static defineBlob<T extends Blob>(target: T, input: BlobInput, metadata: BinaryMetadata = {}): typeof target {
|
|
122
|
-
const inputFn = async (): Promise<BinaryType> => typeof input === 'function' ? await input() : input;
|
|
120
|
+
const inputFn = async (): Promise<BinaryType> => (typeof input === 'function' ? await input() : input);
|
|
123
121
|
this.write(target, metadata);
|
|
124
122
|
|
|
125
123
|
Object.defineProperties(target, {
|
|
126
|
-
size: {
|
|
127
|
-
|
|
128
|
-
|
|
124
|
+
size: {
|
|
125
|
+
get() {
|
|
126
|
+
return BinaryMetadataUtil.readLength(metadata);
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
type: {
|
|
130
|
+
get() {
|
|
131
|
+
return metadata.contentType;
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
name: {
|
|
135
|
+
get() {
|
|
136
|
+
return metadata.filename;
|
|
137
|
+
}
|
|
138
|
+
},
|
|
129
139
|
arrayBuffer: { value: () => inputFn().then(BinaryUtil.toArrayBuffer) },
|
|
130
140
|
stream: { value: () => BinaryUtil.toReadableStream(BinaryUtil.toSynchronous(input)) },
|
|
131
141
|
bytes: { value: () => inputFn().then(BinaryUtil.toBuffer) },
|
|
@@ -133,11 +143,15 @@ export class BinaryMetadataUtil {
|
|
|
133
143
|
slice: {
|
|
134
144
|
value: (start?: number, end?: number, _contentType?: string) => {
|
|
135
145
|
const result = target instanceof File ? new File([], '') : new Blob([]);
|
|
136
|
-
return BinaryMetadataUtil.defineBlob(
|
|
137
|
-
|
|
146
|
+
return BinaryMetadataUtil.defineBlob(
|
|
147
|
+
result,
|
|
148
|
+
() =>
|
|
149
|
+
inputFn()
|
|
150
|
+
.then(BinaryUtil.toBinaryArray)
|
|
151
|
+
.then(data => BinaryUtil.sliceByteArray(data, start, end)),
|
|
138
152
|
{
|
|
139
153
|
...metadata,
|
|
140
|
-
range: { start: start ?? 0, end: end ?? metadata.size! - 1 }
|
|
154
|
+
range: { start: start ?? 0, end: end ?? metadata.size! - 1 }
|
|
141
155
|
}
|
|
142
156
|
);
|
|
143
157
|
}
|
|
@@ -163,7 +177,7 @@ export class BinaryMetadataUtil {
|
|
|
163
177
|
const size = metadata.size;
|
|
164
178
|
|
|
165
179
|
// End is inclusive
|
|
166
|
-
const [start, end] = [range.start, Math.min(range.end ??
|
|
180
|
+
const [start, end] = [range.start, Math.min(range.end ?? size - 1, size - 1)];
|
|
167
181
|
|
|
168
182
|
if (Number.isNaN(start) || Number.isNaN(end) || !Number.isFinite(start) || start >= size || start < 0 || start > end) {
|
|
169
183
|
throw new RuntimeError('Invalid position, out of range', { category: 'data', details: { start, end, size } });
|
|
@@ -171,4 +185,4 @@ export class BinaryMetadataUtil {
|
|
|
171
185
|
|
|
172
186
|
return { start, end };
|
|
173
187
|
}
|
|
174
|
-
}
|
|
188
|
+
}
|
package/src/binary.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { PassThrough, Readable, type Writable } from 'node:stream';
|
|
2
|
+
import consumers from 'node:stream/consumers';
|
|
2
3
|
import { pipeline } from 'node:stream/promises';
|
|
3
4
|
import { ReadableStream } from 'node:stream/web';
|
|
4
|
-
import
|
|
5
|
-
import { isArrayBuffer, isPromise, isTypedArray, isUint16Array, isUint32Array, isUint8Array, isUint8ClampedArray } from 'node:util/types';
|
|
5
|
+
import { isArrayBuffer, isPromise, isTypedArray, isUint8Array, isUint8ClampedArray, isUint16Array, isUint32Array } from 'node:util/types';
|
|
6
6
|
|
|
7
7
|
import { castTo, hasFunction, toConcrete } from './types.ts';
|
|
8
8
|
|
|
@@ -28,8 +28,16 @@ export type BinaryContainer = Blob | File;
|
|
|
28
28
|
export type BinaryType = BinaryArray | BinaryStream | BinaryContainer;
|
|
29
29
|
|
|
30
30
|
const BINARY_CONSTRUCTOR_SET = new Set<unknown>([
|
|
31
|
-
Readable,
|
|
32
|
-
|
|
31
|
+
Readable,
|
|
32
|
+
Buffer,
|
|
33
|
+
Blob,
|
|
34
|
+
ReadableStream,
|
|
35
|
+
ArrayBuffer,
|
|
36
|
+
Uint8Array,
|
|
37
|
+
Uint16Array,
|
|
38
|
+
Uint32Array,
|
|
39
|
+
Uint8ClampedArray,
|
|
40
|
+
File
|
|
33
41
|
]);
|
|
34
42
|
|
|
35
43
|
let BINARY_REFS: Set<unknown> | undefined;
|
|
@@ -40,7 +48,7 @@ const isBinaryTypeReference = (value: unknown): boolean =>
|
|
|
40
48
|
toConcrete<BinaryType>(),
|
|
41
49
|
toConcrete<BinaryStream>(),
|
|
42
50
|
toConcrete<BinaryArray>(),
|
|
43
|
-
toConcrete<BinaryContainer>()
|
|
51
|
+
toConcrete<BinaryContainer>()
|
|
44
52
|
])).has(value);
|
|
45
53
|
|
|
46
54
|
const isReadable = hasFunction<Readable>('pipe');
|
|
@@ -51,13 +59,13 @@ const isBinaryArray = (value: unknown): value is BinaryArray =>
|
|
|
51
59
|
isUint8Array(value) || isArrayBuffer(value) || isUint16Array(value) || isUint32Array(value) || isUint8ClampedArray(value);
|
|
52
60
|
const isBinaryStream = (value: unknown): value is BinaryStream => isReadable(value) || isReadableStream(value) || isAsyncIterable(value);
|
|
53
61
|
const isBinaryContainer = (value: unknown): value is BinaryContainer => value instanceof Blob;
|
|
54
|
-
const isBinaryType = (value: unknown): value is BinaryType =>
|
|
62
|
+
const isBinaryType = (value: unknown): value is BinaryType =>
|
|
63
|
+
!!value && (isBinaryArray(value) || isBinaryStream(value) || isBinaryContainer(value));
|
|
55
64
|
|
|
56
65
|
/**
|
|
57
66
|
* Common functions for dealing with binary data/streams
|
|
58
67
|
*/
|
|
59
68
|
export class BinaryUtil {
|
|
60
|
-
|
|
61
69
|
/** Is the input a byte array */
|
|
62
70
|
static isBinaryArray = isBinaryArray;
|
|
63
71
|
/** Is the input a byte stream */
|
|
@@ -180,8 +188,8 @@ export class BinaryUtil {
|
|
|
180
188
|
/**
|
|
181
189
|
* Convert an inbound binary type or factory into a synchronous binary type
|
|
182
190
|
*/
|
|
183
|
-
static toSynchronous(input: BinaryType | (() =>
|
|
184
|
-
const value =
|
|
191
|
+
static toSynchronous(input: BinaryType | (() => BinaryType | Promise<BinaryType>)): BinaryType {
|
|
192
|
+
const value = typeof input === 'function' ? input() : input;
|
|
185
193
|
if (isPromise(value)) {
|
|
186
194
|
const stream = new PassThrough();
|
|
187
195
|
value.then(result => BinaryUtil.pipeline(result, stream)).catch(error => stream.destroy(error));
|
|
@@ -190,4 +198,4 @@ export class BinaryUtil {
|
|
|
190
198
|
return value;
|
|
191
199
|
}
|
|
192
200
|
}
|
|
193
|
-
}
|
|
201
|
+
}
|
package/src/codec.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createInterface } from 'node:readline/promises';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { type BinaryArray, type BinaryType, BinaryUtil } from './binary.ts';
|
|
4
4
|
import { RuntimeError } from './error.ts';
|
|
5
|
-
import {
|
|
5
|
+
import { type Any, castTo } from './types.ts';
|
|
6
6
|
|
|
7
7
|
type TextInput = string | BinaryArray;
|
|
8
8
|
|
|
@@ -13,7 +13,6 @@ const UTF8_ENCODER = new TextEncoder();
|
|
|
13
13
|
* Utilities for encoding and decoding common formats
|
|
14
14
|
*/
|
|
15
15
|
export class CodecUtil {
|
|
16
|
-
|
|
17
16
|
/** Generate buffer from hex string */
|
|
18
17
|
static fromHexString(value: string): BinaryArray {
|
|
19
18
|
try {
|
|
@@ -85,7 +84,10 @@ export class CodecUtil {
|
|
|
85
84
|
/** Consume lines */
|
|
86
85
|
static async readLines(stream: BinaryType, handler: (input: string) => unknown | Promise<unknown>): Promise<void> {
|
|
87
86
|
for await (const item of createInterface(BinaryUtil.toReadable(stream))) {
|
|
88
|
-
await handler(item);
|
|
87
|
+
const result = await handler(item);
|
|
88
|
+
if (result === false) {
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
89
91
|
}
|
|
90
92
|
}
|
|
91
93
|
|
|
@@ -99,7 +101,23 @@ export class CodecUtil {
|
|
|
99
101
|
if (!encoding) {
|
|
100
102
|
return this.readUtf8Chunk(chunk);
|
|
101
103
|
}
|
|
102
|
-
return BinaryUtil.isBinaryArray(chunk)
|
|
103
|
-
|
|
104
|
+
return BinaryUtil.isBinaryArray(chunk)
|
|
105
|
+
? chunk
|
|
106
|
+
: Buffer.from(typeof chunk === 'string' ? chunk : `${chunk}`, castTo(encoding ?? 'utf8'));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
static readFirstLine(data: string): string;
|
|
110
|
+
static readFirstLine(data: string | undefined, defaultValue: string): string;
|
|
111
|
+
static readFirstLine(data: string | undefined, defaultValue: string = ''): string {
|
|
112
|
+
if (typeof data === 'undefined') {
|
|
113
|
+
return defaultValue;
|
|
114
|
+
} else {
|
|
115
|
+
const end = data.indexOf('\n');
|
|
116
|
+
if (end === -1) {
|
|
117
|
+
return data.trim();
|
|
118
|
+
} else {
|
|
119
|
+
return data.substring(0, end).trim();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
104
122
|
}
|
|
105
|
-
}
|
|
123
|
+
}
|
package/src/console.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import util from 'node:util';
|
|
2
|
+
|
|
2
3
|
import debug from 'debug';
|
|
3
4
|
|
|
4
5
|
import { RuntimeIndex } from './manifest-index.ts';
|
|
@@ -21,7 +22,7 @@ export interface ConsoleEvent {
|
|
|
21
22
|
scope?: string;
|
|
22
23
|
/** Arguments passed to the console call*/
|
|
23
24
|
args: unknown[];
|
|
24
|
-
}
|
|
25
|
+
}
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
28
|
* @concrete
|
|
@@ -41,7 +42,6 @@ const DEBUG_HANDLE = { formatArgs: debug.formatArgs, log: debug.log };
|
|
|
41
42
|
* @alias ConsoleManager
|
|
42
43
|
*/
|
|
43
44
|
class $ConsoleManager implements ConsoleListener {
|
|
44
|
-
|
|
45
45
|
/**
|
|
46
46
|
* The current listener
|
|
47
47
|
*/
|
|
@@ -84,10 +84,15 @@ class $ConsoleManager implements ConsoleListener {
|
|
|
84
84
|
args.unshift(this.namespace);
|
|
85
85
|
args.push(debug.humanize(this.diff));
|
|
86
86
|
};
|
|
87
|
-
debug.log = (modulePath, ...args: string[]): void =>
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
debug.log = (modulePath, ...args: string[]): void =>
|
|
88
|
+
this.log({
|
|
89
|
+
level: 'debug',
|
|
90
|
+
module: '@npm:debug',
|
|
91
|
+
modulePath,
|
|
92
|
+
args: [util.format(...args)],
|
|
93
|
+
line: 0,
|
|
94
|
+
timestamp: new Date()
|
|
95
|
+
});
|
|
91
96
|
} else {
|
|
92
97
|
debug.formatArgs = DEBUG_HANDLE.formatArgs;
|
|
93
98
|
debug.log = DEBUG_HANDLE.log;
|
|
@@ -118,10 +123,9 @@ class $ConsoleManager implements ConsoleListener {
|
|
|
118
123
|
modulePath: event.modulePath ?? event.import?.[1]
|
|
119
124
|
};
|
|
120
125
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
return this.#listener.log(result);
|
|
126
|
+
const filter = this.#filters[result.level];
|
|
127
|
+
if (!filter || filter(result)) {
|
|
128
|
+
this.#listener.log(result);
|
|
125
129
|
}
|
|
126
130
|
}
|
|
127
131
|
|
|
@@ -140,5 +144,9 @@ class $ConsoleManager implements ConsoleListener {
|
|
|
140
144
|
}
|
|
141
145
|
}
|
|
142
146
|
|
|
143
|
-
export const ConsoleManager = new $ConsoleManager({
|
|
144
|
-
|
|
147
|
+
export const ConsoleManager = new $ConsoleManager({
|
|
148
|
+
log(event): void {
|
|
149
|
+
console;
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
export const log = ConsoleManager.log.bind(ConsoleManager);
|