@travetto/runtime 7.1.4 → 8.0.0-alpha.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 +39 -38
- package/__index__.ts +3 -1
- package/package.json +5 -4
- package/src/binary-metadata.ts +174 -0
- package/src/binary.ts +162 -101
- package/src/codec.ts +105 -0
- package/src/console.ts +0 -1
- package/src/context.ts +2 -2
- package/src/error.ts +8 -45
- package/src/exec.ts +13 -22
- package/src/file-loader.ts +18 -19
- package/src/function.ts +16 -20
- package/src/global.d.ts +29 -0
- package/src/json.ts +132 -51
- package/src/queue.ts +5 -5
- package/src/shutdown.ts +1 -1
- package/src/time.ts +62 -76
- package/src/types.ts +10 -40
- package/src/util.ts +32 -4
- package/src/watch.ts +2 -2
- package/support/polyfill.js +9 -0
- package/support/transformer/metadata.ts +4 -4
package/src/codec.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { createInterface } from 'node:readline/promises';
|
|
2
|
+
|
|
3
|
+
import { BinaryUtil, type BinaryArray, type BinaryType } from './binary.ts';
|
|
4
|
+
import { RuntimeError } from './error.ts';
|
|
5
|
+
import { castTo, type Any } from './types.ts';
|
|
6
|
+
|
|
7
|
+
type TextInput = string | BinaryArray;
|
|
8
|
+
|
|
9
|
+
const UTF8_DECODER = new TextDecoder('utf8');
|
|
10
|
+
const UTF8_ENCODER = new TextEncoder();
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Utilities for encoding and decoding common formats
|
|
14
|
+
*/
|
|
15
|
+
export class CodecUtil {
|
|
16
|
+
|
|
17
|
+
/** Generate buffer from hex string */
|
|
18
|
+
static fromHexString(value: string): BinaryArray {
|
|
19
|
+
try {
|
|
20
|
+
return Uint8Array.fromHex(value);
|
|
21
|
+
} catch (err) {
|
|
22
|
+
if (err instanceof SyntaxError) {
|
|
23
|
+
throw new RuntimeError('Invalid hex string', { cause: err });
|
|
24
|
+
}
|
|
25
|
+
throw err;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Convert hex bytes to string */
|
|
30
|
+
static toHexString(value: BinaryArray): string {
|
|
31
|
+
return BinaryUtil.binaryArrayToUint8Array(value).toHex();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Return buffer from base64 string */
|
|
35
|
+
static fromBase64String(value: string): BinaryArray {
|
|
36
|
+
try {
|
|
37
|
+
return Uint8Array.fromBase64(value);
|
|
38
|
+
} catch (err) {
|
|
39
|
+
if (err instanceof SyntaxError) {
|
|
40
|
+
throw new RuntimeError('Invalid base64 string', { cause: err });
|
|
41
|
+
}
|
|
42
|
+
throw err;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Convert value to base64 string */
|
|
47
|
+
static toBase64String(value: BinaryArray): string {
|
|
48
|
+
return BinaryUtil.binaryArrayToUint8Array(value).toBase64();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Return buffer from utf8 string */
|
|
52
|
+
static fromUTF8String(value: string): BinaryArray {
|
|
53
|
+
return UTF8_ENCODER.encode(value);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Return utf8 string from bytes */
|
|
57
|
+
static toUTF8String(value: BinaryArray): string {
|
|
58
|
+
return UTF8_DECODER.decode(BinaryUtil.binaryArrayToUint8Array(value));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Convert utf8 value to base64 value string */
|
|
62
|
+
static utf8ToBase64(value: TextInput): string {
|
|
63
|
+
return this.toBase64String(typeof value === 'string' ? this.fromUTF8String(value) : value);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Convert base64 value to utf8 string */
|
|
67
|
+
static base64ToUTF8(value: TextInput): string {
|
|
68
|
+
const result = this.toUTF8String(typeof value === 'string' ? this.fromBase64String(value) : value);
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Convert url encoded base64 value to utf8 string */
|
|
73
|
+
static urlEncodedBase64ToUTF8(value: TextInput): string {
|
|
74
|
+
const result = this.base64ToUTF8(value);
|
|
75
|
+
return result.startsWith('%') ? decodeURIComponent(result) : result;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Detect encoding of a binary type, if possible */
|
|
79
|
+
static detectEncoding(input: BinaryType): string | undefined {
|
|
80
|
+
if (input && typeof input === 'object' && 'readableEncoding' in input && typeof input.readableEncoding === 'string') {
|
|
81
|
+
return input.readableEncoding;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Consume lines */
|
|
86
|
+
static async readLines(stream: BinaryType, handler: (input: string) => unknown | Promise<unknown>): Promise<void> {
|
|
87
|
+
for await (const item of createInterface(BinaryUtil.toReadable(stream))) {
|
|
88
|
+
await handler(item);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Read chunk as utf8 if not a binary array */
|
|
93
|
+
static readUtf8Chunk(chunk: Any): BinaryArray {
|
|
94
|
+
return BinaryUtil.isBinaryArray(chunk) ? chunk : this.fromUTF8String(typeof chunk === 'string' ? chunk : `${chunk}`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Read chunk, default to toString if type is unknown */
|
|
98
|
+
static readChunk(chunk: Any, encoding?: string | null): BinaryArray {
|
|
99
|
+
if (!encoding) {
|
|
100
|
+
return this.readUtf8Chunk(chunk);
|
|
101
|
+
}
|
|
102
|
+
return BinaryUtil.isBinaryArray(chunk) ? chunk :
|
|
103
|
+
Buffer.from(typeof chunk === 'string' ? chunk : `${chunk}`, castTo(encoding ?? 'utf8'));
|
|
104
|
+
}
|
|
105
|
+
}
|
package/src/console.ts
CHANGED
|
@@ -79,7 +79,6 @@ class $ConsoleManager implements ConsoleListener {
|
|
|
79
79
|
* Enable/disable enhanced debugging
|
|
80
80
|
*/
|
|
81
81
|
enhanceDebug(active: boolean): void {
|
|
82
|
-
Error.stackTraceLimit = active ? 50 : 10;
|
|
83
82
|
if (active) {
|
|
84
83
|
debug.formatArgs = function (args: string[]): void {
|
|
85
84
|
args.unshift(this.namespace);
|
package/src/context.ts
CHANGED
|
@@ -6,8 +6,8 @@ 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 { JSONUtil } from './json.ts';
|
|
10
9
|
import type { Role } from './trv';
|
|
10
|
+
import { JSONUtil } from './json.ts';
|
|
11
11
|
|
|
12
12
|
/** Constrained version of {@type ManifestContext} */
|
|
13
13
|
class $Runtime {
|
|
@@ -119,7 +119,7 @@ class $Runtime {
|
|
|
119
119
|
throw new Error(`Unable to find ${location}, not in the manifest`);
|
|
120
120
|
} else if (location.endsWith('.json')) {
|
|
121
121
|
location = this.#idx.getFromImport(location)?.sourceFile ?? location;
|
|
122
|
-
return fs.readFile(location
|
|
122
|
+
return fs.readFile(location).then(JSONUtil.fromBinaryArray<T>);
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
if (!ManifestModuleUtil.SOURCE_EXT_REGEX.test(location)) {
|
package/src/error.ts
CHANGED
|
@@ -9,70 +9,33 @@ export type ErrorCategory =
|
|
|
9
9
|
'timeout' |
|
|
10
10
|
'unavailable';
|
|
11
11
|
|
|
12
|
-
export type
|
|
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 });
|
|
12
|
+
export type RuntimeErrorOptions<T> = Omit<Partial<RuntimeError>, 'details'> & (T extends undefined ? { details?: T } : { details: T });
|
|
22
13
|
|
|
23
14
|
/**
|
|
24
15
|
* Framework error class, with the aim of being extensible
|
|
25
16
|
*/
|
|
26
|
-
export class
|
|
17
|
+
export class RuntimeError<T = Record<string, unknown> | undefined> extends Error {
|
|
27
18
|
|
|
28
|
-
static defaultCategory
|
|
29
|
-
|
|
30
|
-
/** Convert from JSON object */
|
|
31
|
-
static fromJSON(error: unknown): AppError | undefined {
|
|
32
|
-
if (!!error && typeof error === 'object' &&
|
|
33
|
-
('message' in error && typeof error.message === 'string') &&
|
|
34
|
-
('category' in error && typeof error.category === 'string') &&
|
|
35
|
-
('type' in error && typeof error.type === 'string') &&
|
|
36
|
-
('at' in error && typeof error.at === 'string')
|
|
37
|
-
) {
|
|
38
|
-
return new AppError(error.message, castTo<AppErrorOptions<Record<string, unknown>>>(error));
|
|
39
|
-
}
|
|
40
|
-
}
|
|
19
|
+
static defaultCategory: ErrorCategory = 'general';
|
|
41
20
|
|
|
42
21
|
type: string;
|
|
43
22
|
category: ErrorCategory;
|
|
44
|
-
at:
|
|
23
|
+
at: Date;
|
|
45
24
|
details: T;
|
|
46
25
|
|
|
47
26
|
/**
|
|
48
|
-
* Build
|
|
27
|
+
* Build a runtime error
|
|
49
28
|
*
|
|
50
29
|
* @param message The error message
|
|
51
30
|
*/
|
|
52
31
|
constructor(
|
|
53
32
|
...[message, options]:
|
|
54
|
-
T extends undefined ? ([string] | [string,
|
|
33
|
+
T extends undefined ? ([string] | [string, RuntimeErrorOptions<T>]) : [string, RuntimeErrorOptions<T>]
|
|
55
34
|
) {
|
|
56
35
|
super(message, options?.cause ? { cause: options.cause } : undefined);
|
|
57
36
|
this.type = options?.type ?? this.constructor.name;
|
|
58
37
|
this.details = options?.details!;
|
|
59
|
-
this.category = options?.category ?? castTo<typeof
|
|
60
|
-
this.at = new Date(options?.at ?? Date.now())
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Serializes an error to a basic object
|
|
65
|
-
*/
|
|
66
|
-
toJSON(): AppErrorOptions<T> & { message: string } {
|
|
67
|
-
const options: AppErrorOptions<unknown> = {
|
|
68
|
-
category: this.category,
|
|
69
|
-
...(this.cause ? { cause: `${this.cause}` } : undefined),
|
|
70
|
-
type: this.type,
|
|
71
|
-
at: this.at,
|
|
72
|
-
...(this.details ? { details: this.details } : undefined!),
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
76
|
-
return { message: this.message, ...options as AppErrorOptions<T> };
|
|
38
|
+
this.category = options?.category ?? castTo<typeof RuntimeError>(this.constructor).defaultCategory ?? 'general';
|
|
39
|
+
this.at = new Date(options?.at ?? Date.now());
|
|
77
40
|
}
|
|
78
41
|
}
|
package/src/exec.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { type ChildProcess, spawn, type SpawnOptions } from 'node:child_process';
|
|
2
|
-
import type { Readable } from 'node:stream';
|
|
3
|
-
import { createInterface } from 'node:readline/promises';
|
|
4
2
|
|
|
5
3
|
import { castTo } from './types.ts';
|
|
6
4
|
import { RuntimeIndex } from './manifest-index.ts';
|
|
5
|
+
import { BinaryUtil, type BinaryArray } from './binary.ts';
|
|
6
|
+
import { CodecUtil } from './codec.ts';
|
|
7
7
|
|
|
8
8
|
const ResultSymbol = Symbol();
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Result of an execution
|
|
12
12
|
*/
|
|
13
|
-
export interface ExecutionResult<T extends string |
|
|
13
|
+
export interface ExecutionResult<T extends string | BinaryArray = string | BinaryArray> {
|
|
14
14
|
/**
|
|
15
15
|
* Stdout
|
|
16
16
|
*/
|
|
@@ -50,12 +50,12 @@ export class ExecUtil {
|
|
|
50
50
|
*/
|
|
51
51
|
static getResult(subProcess: ChildProcess): Promise<ExecutionResult<string>>;
|
|
52
52
|
static getResult(subProcess: ChildProcess, options: { catch?: boolean, binary?: false }): Promise<ExecutionResult<string>>;
|
|
53
|
-
static getResult(subProcess: ChildProcess, options: { catch?: boolean, binary: true }): Promise<ExecutionResult<
|
|
54
|
-
static getResult<T extends string |
|
|
53
|
+
static getResult(subProcess: ChildProcess, options: { catch?: boolean, binary: true }): Promise<ExecutionResult<BinaryArray>>;
|
|
54
|
+
static getResult<T extends string | BinaryArray>(subProcess: ChildProcess, options: { catch?: boolean, binary?: boolean } = {}): Promise<ExecutionResult<T>> {
|
|
55
55
|
const typed: ChildProcess & { [ResultSymbol]?: Promise<ExecutionResult> } = subProcess;
|
|
56
56
|
const result = typed[ResultSymbol] ??= new Promise<ExecutionResult>(resolve => {
|
|
57
|
-
const stdout:
|
|
58
|
-
const stderr:
|
|
57
|
+
const stdout: BinaryArray[] = [];
|
|
58
|
+
const stderr: BinaryArray[] = [];
|
|
59
59
|
let done = false;
|
|
60
60
|
const finish = (finalResult: ExecutionBaseResult): void => {
|
|
61
61
|
if (done) {
|
|
@@ -64,13 +64,13 @@ export class ExecUtil {
|
|
|
64
64
|
done = true;
|
|
65
65
|
|
|
66
66
|
const buffers = {
|
|
67
|
-
stdout:
|
|
68
|
-
stderr:
|
|
67
|
+
stdout: BinaryUtil.combineBinaryArrays(stdout),
|
|
68
|
+
stderr: BinaryUtil.combineBinaryArrays(stderr),
|
|
69
69
|
};
|
|
70
70
|
|
|
71
71
|
const final = {
|
|
72
|
-
stdout: options.binary ? buffers.stdout : buffers.stdout.toString('utf8'),
|
|
73
|
-
stderr: options.binary ? buffers.stderr : buffers.stderr.toString('utf8'),
|
|
72
|
+
stdout: options.binary ? buffers.stdout : buffers.stdout.toString(subProcess.stdout?.readableEncoding ?? 'utf8'),
|
|
73
|
+
stderr: options.binary ? buffers.stderr : buffers.stderr.toString(subProcess.stderr?.readableEncoding ?? 'utf8'),
|
|
74
74
|
...finalResult
|
|
75
75
|
};
|
|
76
76
|
|
|
@@ -80,8 +80,8 @@ export class ExecUtil {
|
|
|
80
80
|
);
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
-
subProcess.stdout?.on('data',
|
|
84
|
-
subProcess.stderr?.on('data',
|
|
83
|
+
subProcess.stdout?.on('data', data => stdout.push(CodecUtil.readChunk(data, subProcess.stdout?.readableEncoding)));
|
|
84
|
+
subProcess.stderr?.on('data', data => stderr.push(CodecUtil.readChunk(data, subProcess.stderr?.readableEncoding)));
|
|
85
85
|
|
|
86
86
|
subProcess.on('error', (error: Error) =>
|
|
87
87
|
finish({ code: 1, message: error.message, valid: false }));
|
|
@@ -103,15 +103,6 @@ export class ExecUtil {
|
|
|
103
103
|
}));
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
/**
|
|
107
|
-
* Consume lines
|
|
108
|
-
*/
|
|
109
|
-
static async readLines(stream: Readable, handler: (input: string) => unknown | Promise<unknown>): Promise<void> {
|
|
110
|
-
for await (const item of createInterface(stream)) {
|
|
111
|
-
await handler(item);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
106
|
/** Spawn a package command */
|
|
116
107
|
static spawnPackageCommand(cmd: string, args: string[], config: SpawnOptions = {}): ChildProcess {
|
|
117
108
|
return spawn(process.argv0, [RuntimeIndex.resolvePackageCommand(cmd), ...args], config);
|
package/src/file-loader.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { createReadStream } from 'node:fs';
|
|
2
|
-
import type { Readable } from 'node:stream';
|
|
3
2
|
import fs from 'node:fs/promises';
|
|
4
3
|
import path from 'node:path';
|
|
5
4
|
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
5
|
+
import { RuntimeError } from './error.ts';
|
|
6
|
+
import { BinaryUtil, type BinaryArray, type BinaryStream } from './binary.ts';
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
9
|
* File loader that will search for files across the provided search paths
|
|
@@ -35,42 +34,42 @@ export class FileLoader {
|
|
|
35
34
|
return resolved;
|
|
36
35
|
}
|
|
37
36
|
}
|
|
38
|
-
throw new
|
|
37
|
+
throw new RuntimeError(`Unable to find: ${relativePath}, searched=${this.searchPaths.join(',')}`, { category: 'notfound' });
|
|
39
38
|
}
|
|
40
39
|
|
|
41
40
|
/**
|
|
42
|
-
* Read a file, after resolving the path
|
|
41
|
+
* Read a file as utf8 text, after resolving the path
|
|
43
42
|
* @param relativePath The path to read
|
|
44
43
|
*/
|
|
45
|
-
async
|
|
46
|
-
async read(relativePath: string, binary: true): Promise<Buffer>;
|
|
47
|
-
async read(relativePath: string, binary = false): Promise<string | Buffer> {
|
|
44
|
+
async readText(relativePath: string): Promise<string> {
|
|
48
45
|
const file = await this.resolve(relativePath);
|
|
49
|
-
return fs.readFile(file,
|
|
46
|
+
return fs.readFile(file, 'utf8');
|
|
50
47
|
}
|
|
51
48
|
|
|
52
49
|
/**
|
|
53
|
-
* Read a file as a
|
|
50
|
+
* Read a file as a byte array, after resolving the path
|
|
54
51
|
* @param relativePath The path to read
|
|
55
52
|
*/
|
|
56
|
-
async
|
|
53
|
+
async readBinaryArray(relativePath: string): Promise<BinaryArray> {
|
|
57
54
|
const file = await this.resolve(relativePath);
|
|
58
|
-
return
|
|
55
|
+
return fs.readFile(file);
|
|
59
56
|
}
|
|
60
57
|
|
|
61
58
|
/**
|
|
62
|
-
* Read a file as a
|
|
59
|
+
* Read a file as a stream
|
|
63
60
|
* @param relativePath The path to read
|
|
64
61
|
*/
|
|
65
|
-
async
|
|
66
|
-
|
|
62
|
+
async readBinaryStream(relativePath: string): Promise<BinaryStream> {
|
|
63
|
+
const file = await this.resolve(relativePath);
|
|
64
|
+
return createReadStream(file);
|
|
67
65
|
}
|
|
68
66
|
|
|
69
67
|
/**
|
|
70
|
-
* Read
|
|
68
|
+
* Read a file as a File object
|
|
69
|
+
* @param relativePath The path to read
|
|
71
70
|
*/
|
|
72
|
-
async
|
|
73
|
-
const
|
|
74
|
-
return
|
|
71
|
+
async readFile(relativePath: string): Promise<File> {
|
|
72
|
+
const buffer = BinaryUtil.binaryArrayToBuffer(await this.readBinaryArray(relativePath));
|
|
73
|
+
return new File([buffer], path.basename(relativePath));
|
|
75
74
|
}
|
|
76
75
|
}
|
package/src/function.ts
CHANGED
|
@@ -17,8 +17,8 @@ const pending = new Set<Function>([]);
|
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Initialize the meta data for a function/class
|
|
20
|
-
* @param
|
|
21
|
-
* @param
|
|
20
|
+
* @param input Class or function to register
|
|
21
|
+
* @param [module, relativePath] File location
|
|
22
22
|
* @param `hash` Hash of class contents
|
|
23
23
|
* @param `line` Line number in source
|
|
24
24
|
* @param `methods` Methods and their hashes
|
|
@@ -26,48 +26,44 @@ const pending = new Set<Function>([]);
|
|
|
26
26
|
* @private
|
|
27
27
|
*/
|
|
28
28
|
export function registerFunction(
|
|
29
|
-
|
|
29
|
+
input: Function, [module, relativePath]: [string, string], tag: FunctionMetadataTag,
|
|
30
30
|
methods?: Record<string, FunctionMetadataTag>, abstract?: boolean,
|
|
31
31
|
): void {
|
|
32
|
-
const modulePath = ManifestModuleUtil.withoutSourceExtension(
|
|
32
|
+
const modulePath = ManifestModuleUtil.withoutSourceExtension(relativePath);
|
|
33
33
|
|
|
34
34
|
const metadata: FunctionMetadata = {
|
|
35
|
-
id: (
|
|
36
|
-
import: `${
|
|
37
|
-
module
|
|
35
|
+
id: (input.name ? `${module}:${modulePath}#${input.name}` : `${module}:${modulePath}`),
|
|
36
|
+
import: `${module}/${relativePath}`,
|
|
37
|
+
module,
|
|
38
38
|
modulePath,
|
|
39
39
|
...tag,
|
|
40
40
|
methods,
|
|
41
41
|
abstract,
|
|
42
42
|
class: methods !== undefined
|
|
43
43
|
};
|
|
44
|
-
pending.add(
|
|
45
|
-
Object.defineProperties(
|
|
44
|
+
pending.add(input);
|
|
45
|
+
Object.defineProperties(input, { Ⲑid: { value: metadata.id }, [MetadataSymbol]: { value: metadata } });
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
49
|
* Flush all pending function registers
|
|
50
50
|
*/
|
|
51
51
|
export function flushPendingFunctions(): Function[] {
|
|
52
|
-
const
|
|
52
|
+
const functions = [...pending];
|
|
53
53
|
pending.clear();
|
|
54
|
-
return
|
|
54
|
+
return functions;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
/**
|
|
58
58
|
* Read metadata
|
|
59
59
|
*/
|
|
60
|
-
export function describeFunction(
|
|
61
|
-
export function describeFunction(
|
|
62
|
-
const
|
|
63
|
-
return
|
|
60
|
+
export function describeFunction(input: Function): FunctionMetadata;
|
|
61
|
+
export function describeFunction(input?: Function): FunctionMetadata | undefined {
|
|
62
|
+
const resolved: (Function & { [MetadataSymbol]?: FunctionMetadata }) | undefined = input;
|
|
63
|
+
return resolved?.[MetadataSymbol];
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
const foreignTypeRegistry = new Map<string, Function>();
|
|
67
67
|
export function foreignType(id: string): Function {
|
|
68
|
-
|
|
69
|
-
const type = class { static Ⲑid = id; };
|
|
70
|
-
foreignTypeRegistry.set(id, type);
|
|
71
|
-
}
|
|
72
|
-
return foreignTypeRegistry.get(id)!;
|
|
68
|
+
return foreignTypeRegistry.getOrInsert(id, class { static Ⲑid = id; });
|
|
73
69
|
}
|
package/src/global.d.ts
CHANGED
|
@@ -22,6 +22,16 @@ declare global {
|
|
|
22
22
|
*/
|
|
23
23
|
interface File { }
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* @concrete node:stream/web#ReadableStream
|
|
27
|
+
*/
|
|
28
|
+
interface ReadableStream { }
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @concrete node:buffer#Buffer
|
|
32
|
+
*/
|
|
33
|
+
interface Buffer { }
|
|
34
|
+
|
|
25
35
|
namespace NodeJS {
|
|
26
36
|
/**
|
|
27
37
|
* @concrete node:stream#Readable
|
|
@@ -30,9 +40,28 @@ declare global {
|
|
|
30
40
|
}
|
|
31
41
|
}
|
|
32
42
|
|
|
43
|
+
declare module 'buffer' {
|
|
44
|
+
/**
|
|
45
|
+
* @concrete node:buffer#Blob
|
|
46
|
+
*/
|
|
47
|
+
interface Blob { }
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @concrete node:buffer#File
|
|
51
|
+
*/
|
|
52
|
+
interface File { }
|
|
53
|
+
}
|
|
54
|
+
|
|
33
55
|
declare module 'stream' {
|
|
34
56
|
/**
|
|
35
57
|
* @concrete node:stream#Readable
|
|
36
58
|
*/
|
|
37
59
|
interface Readable { }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
declare module 'stream/web' {
|
|
63
|
+
/**
|
|
64
|
+
* @concrete node:stream/web#ReadableStream
|
|
65
|
+
*/
|
|
66
|
+
interface ReadableStream { }
|
|
38
67
|
}
|