@adviser/cement 0.2.28 → 0.2.30
Sign up to get free protection for your applications and to get access to all the features.
- package/{base-sys-abstraction-C9WW3w57.d.cts → base-sys-abstraction-BkEiLHl0.d.ts} +8 -4
- package/{base-sys-abstraction-C9WW3w57.d.ts → base-sys-abstraction-Qj7pkY1N.d.cts} +8 -4
- package/{chunk-OXD3YZZ7.js → chunk-7KFVMTOS.js} +3 -47
- package/chunk-7KFVMTOS.js.map +1 -0
- package/{chunk-P5RXA4C4.js → chunk-GES3MUGV.js} +24 -27
- package/{chunk-LCPYQVWT.js.map → chunk-GES3MUGV.js.map} +1 -1
- package/{chunk-YDIUMYIE.js → chunk-Q65HLCNL.js} +8 -7
- package/chunk-Q65HLCNL.js.map +1 -0
- package/{chunk-DPIL5UIL.js → chunk-WMMUXBDX.js} +6 -2
- package/chunk-WMMUXBDX.js.map +1 -0
- package/{index-Dhb2fQiw.d.cts → index-Q3phXzYr.d.cts} +2 -21
- package/{index-CcsGcehs.d.ts → index-tIGZMHTc.d.ts} +2 -21
- package/index.cjs +288 -7345
- package/index.cjs.map +1 -1
- package/index.d.cts +74 -12
- package/index.d.ts +74 -12
- package/index.js +239 -7266
- package/index.js.map +1 -1
- package/node/index.cjs +220 -39
- package/node/index.cjs.map +1 -1
- package/node/index.d.cts +22 -4
- package/node/index.d.ts +22 -4
- package/node/index.js +201 -25
- package/node/index.js.map +1 -1
- package/package.json +34 -23
- package/src/LICENSE +201 -0
- package/src/README.md +39 -0
- package/src/base-sys-abstraction.ts +242 -0
- package/src/bin2text.ts +47 -0
- package/src/crypto.ts +125 -0
- package/src/file-service.ts +24 -0
- package/src/future.ts +27 -0
- package/src/index.ts +23 -0
- package/src/jsr.json +22 -0
- package/src/log-level-impl.ts +87 -0
- package/src/log-writer-impl.ts +58 -0
- package/src/logger-impl.ts +498 -0
- package/src/logger.ts +208 -0
- package/src/node/deno-file-service.ts +92 -0
- package/src/node/deno-sys-abstraction.ts +133 -0
- package/src/node/index.ts +4 -0
- package/src/node/mock-file-service.ts +45 -0
- package/src/node/node-file-service.ts +91 -0
- package/src/node/node-sys-abstraction.ts +121 -0
- package/src/option.ts +60 -0
- package/src/refcounted.ts +23 -0
- package/src/resolve-once.ts +179 -0
- package/src/result.ts +165 -0
- package/src/runtime.ts +36 -0
- package/src/sys-abstraction.ts +53 -0
- package/src/sys-env.ts +216 -0
- package/src/test/log-write-stream.ts +95 -0
- package/src/test/mock-logger.ts +40 -0
- package/src/time.ts +20 -0
- package/src/tracer.ts +222 -0
- package/src/txt-en-decoder.ts +21 -0
- package/src/uri.ts +421 -0
- package/src/utils/console-write-stream.ts +72 -0
- package/src/utils/fanout-write-stream.ts +32 -0
- package/src/utils/index.ts +6 -0
- package/src/utils/rebuffer.ts +75 -0
- package/src/utils/stream-map.ts +67 -0
- package/src/utils/stream2string.ts +47 -0
- package/src/utils/string2stream.ts +14 -0
- package/src/version.ts +3 -0
- package/src/web/index.ts +1 -0
- package/src/web/web-sys-abstraction.ts +80 -0
- package/ts/base-sys-abstraction.d.ts +84 -0
- package/ts/base-sys-abstraction.d.ts.map +1 -0
- package/ts/base-sys-abstraction.js +178 -0
- package/ts/base-sys-abstraction.js.map +1 -0
- package/ts/base-sys-abstraction.test.d.ts +2 -0
- package/ts/base-sys-abstraction.test.d.ts.map +1 -0
- package/ts/base-sys-abstraction.test.js +82 -0
- package/ts/base-sys-abstraction.test.js.map +1 -0
- package/ts/bin2text.d.ts +3 -0
- package/ts/bin2text.d.ts.map +1 -0
- package/ts/bin2text.js +43 -0
- package/ts/bin2text.js.map +1 -0
- package/ts/bin2text.test.d.ts +2 -0
- package/ts/bin2text.test.d.ts.map +1 -0
- package/ts/bin2text.test.js +51 -0
- package/ts/bin2text.test.js.map +1 -0
- package/ts/crypto.d.ts +76 -0
- package/ts/crypto.d.ts.map +1 -0
- package/ts/crypto.js +22 -0
- package/ts/crypto.js.map +1 -0
- package/ts/crypto.test.d.ts +2 -0
- package/ts/crypto.test.d.ts.map +1 -0
- package/ts/crypto.test.js +14 -0
- package/ts/crypto.test.js.map +1 -0
- package/ts/file-service.d.ts +17 -0
- package/ts/file-service.d.ts.map +1 -0
- package/ts/file-service.js +2 -0
- package/ts/file-service.js.map +1 -0
- package/ts/future.d.ts +8 -0
- package/ts/future.d.ts.map +1 -0
- package/ts/future.js +38 -0
- package/ts/future.js.map +1 -0
- package/ts/future.test.d.ts +2 -0
- package/ts/future.test.d.ts.map +1 -0
- package/ts/future.test.js +28 -0
- package/ts/future.test.js.map +1 -0
- package/ts/index.d.ts +24 -0
- package/ts/index.d.ts.map +1 -0
- package/ts/index.js +24 -0
- package/ts/index.js.map +1 -0
- package/ts/log-level-impl.d.ts +14 -0
- package/ts/log-level-impl.d.ts.map +1 -0
- package/ts/log-level-impl.js +72 -0
- package/ts/log-level-impl.js.map +1 -0
- package/ts/log-writer-impl.d.ts +10 -0
- package/ts/log-writer-impl.d.ts.map +1 -0
- package/ts/log-writer-impl.js +45 -0
- package/ts/log-writer-impl.js.map +1 -0
- package/ts/logger-impl.d.ts +71 -0
- package/ts/logger-impl.d.ts.map +1 -0
- package/ts/logger-impl.js +412 -0
- package/ts/logger-impl.js.map +1 -0
- package/ts/logger.d.ts +84 -0
- package/ts/logger.d.ts.map +1 -0
- package/ts/logger.js +114 -0
- package/ts/logger.js.map +1 -0
- package/ts/logger.test.d.ts +2 -0
- package/ts/logger.test.d.ts.map +1 -0
- package/ts/logger.test.js +1023 -0
- package/ts/logger.test.js.map +1 -0
- package/ts/node/deno-file-service.d.ts +17 -0
- package/ts/node/deno-file-service.d.ts.map +1 -0
- package/ts/node/deno-file-service.js +65 -0
- package/ts/node/deno-file-service.js.map +1 -0
- package/ts/node/deno-sys-abstraction.d.ts +22 -0
- package/ts/node/deno-sys-abstraction.d.ts.map +1 -0
- package/ts/node/deno-sys-abstraction.js +101 -0
- package/ts/node/deno-sys-abstraction.js.map +1 -0
- package/ts/node/index.d.ts +5 -0
- package/ts/node/index.d.ts.map +1 -0
- package/ts/node/index.js +5 -0
- package/ts/node/index.js.map +1 -0
- package/ts/node/mock-file-service.d.ts +11 -0
- package/ts/node/mock-file-service.d.ts.map +1 -0
- package/ts/node/mock-file-service.js +34 -0
- package/ts/node/mock-file-service.js.map +1 -0
- package/ts/node/mock-file-service.test.d.ts +2 -0
- package/ts/node/mock-file-service.test.d.ts.map +1 -0
- package/ts/node/mock-file-service.test.js +31 -0
- package/ts/node/mock-file-service.test.js.map +1 -0
- package/ts/node/node-file-service.d.ts +16 -0
- package/ts/node/node-file-service.d.ts.map +1 -0
- package/ts/node/node-file-service.js +71 -0
- package/ts/node/node-file-service.js.map +1 -0
- package/ts/node/node-sys-abstraction.d.ts +22 -0
- package/ts/node/node-sys-abstraction.d.ts.map +1 -0
- package/ts/node/node-sys-abstraction.js +99 -0
- package/ts/node/node-sys-abstraction.js.map +1 -0
- package/ts/node/node-sys-abstraction.test.d.ts +2 -0
- package/ts/node/node-sys-abstraction.test.d.ts.map +1 -0
- package/ts/node/node-sys-abstraction.test.js +83 -0
- package/ts/node/node-sys-abstraction.test.js.map +1 -0
- package/ts/option.d.ts +25 -0
- package/ts/option.d.ts.map +1 -0
- package/ts/option.js +47 -0
- package/ts/option.js.map +1 -0
- package/ts/refcounted.d.ts +2 -0
- package/ts/refcounted.d.ts.map +1 -0
- package/ts/refcounted.js +19 -0
- package/ts/refcounted.js.map +1 -0
- package/ts/refcounted.test.d.ts +2 -0
- package/ts/refcounted.test.d.ts.map +1 -0
- package/ts/refcounted.test.js +39 -0
- package/ts/refcounted.test.js.map +1 -0
- package/ts/resolve-once.d.ts +46 -0
- package/ts/resolve-once.d.ts.map +1 -0
- package/ts/resolve-once.js +152 -0
- package/ts/resolve-once.js.map +1 -0
- package/ts/resolve-once.test.d.ts +2 -0
- package/ts/resolve-once.test.d.ts.map +1 -0
- package/ts/resolve-once.test.js +283 -0
- package/ts/resolve-once.test.js.map +1 -0
- package/ts/result.d.ts +34 -0
- package/ts/result.d.ts.map +1 -0
- package/ts/result.js +85 -0
- package/ts/result.js.map +1 -0
- package/ts/result.test.d.ts +2 -0
- package/ts/result.test.d.ts.map +1 -0
- package/ts/result.test.js +79 -0
- package/ts/result.test.js.map +1 -0
- package/ts/runtime.d.ts +8 -0
- package/ts/runtime.d.ts.map +1 -0
- package/ts/runtime.js +26 -0
- package/ts/runtime.js.map +1 -0
- package/ts/sys-abstraction.d.ts +36 -0
- package/ts/sys-abstraction.d.ts.map +1 -0
- package/ts/sys-abstraction.js +31 -0
- package/ts/sys-abstraction.js.map +1 -0
- package/ts/sys-env.d.ts +48 -0
- package/ts/sys-env.d.ts.map +1 -0
- package/ts/sys-env.js +176 -0
- package/ts/sys-env.js.map +1 -0
- package/ts/sys-env.test.d.ts +2 -0
- package/ts/sys-env.test.d.ts.map +1 -0
- package/ts/sys-env.test.js +51 -0
- package/ts/sys-env.test.js.map +1 -0
- package/ts/test/log-write-stream.d.ts +27 -0
- package/ts/test/log-write-stream.d.ts.map +1 -0
- package/ts/test/log-write-stream.js +74 -0
- package/ts/test/log-write-stream.js.map +1 -0
- package/ts/test/mock-logger.d.ts +14 -0
- package/ts/test/mock-logger.d.ts.map +1 -0
- package/ts/test/mock-logger.js +29 -0
- package/ts/test/mock-logger.js.map +1 -0
- package/ts/test/mock-logger.test.d.ts +2 -0
- package/ts/test/mock-logger.test.d.ts.map +1 -0
- package/ts/test/mock-logger.test.js +63 -0
- package/ts/test/mock-logger.test.js.map +1 -0
- package/ts/test/test-exit-handler.d.ts +2 -0
- package/ts/test/test-exit-handler.d.ts.map +1 -0
- package/ts/test/test-exit-handler.js +57 -0
- package/ts/test/test-exit-handler.js.map +1 -0
- package/ts/time.d.ts +13 -0
- package/ts/time.d.ts.map +1 -0
- package/ts/time.js +14 -0
- package/ts/time.js.map +1 -0
- package/ts/tracer.d.ts +59 -0
- package/ts/tracer.d.ts.map +1 -0
- package/ts/tracer.js +148 -0
- package/ts/tracer.js.map +1 -0
- package/ts/tracer.test.d.ts +2 -0
- package/ts/tracer.test.d.ts.map +1 -0
- package/ts/tracer.test.js +311 -0
- package/ts/tracer.test.js.map +1 -0
- package/ts/txt-en-decoder.d.ts +10 -0
- package/ts/txt-en-decoder.d.ts.map +1 -0
- package/ts/txt-en-decoder.js +15 -0
- package/ts/txt-en-decoder.js.map +1 -0
- package/ts/uri.d.ts +67 -0
- package/ts/uri.d.ts.map +1 -0
- package/ts/uri.js +283 -0
- package/ts/uri.js.map +1 -0
- package/ts/uri.test.d.ts +2 -0
- package/ts/uri.test.d.ts.map +1 -0
- package/ts/uri.test.js +119 -0
- package/ts/uri.test.js.map +1 -0
- package/ts/utils/console-write-stream.d.ts +21 -0
- package/ts/utils/console-write-stream.d.ts.map +1 -0
- package/ts/utils/console-write-stream.js +62 -0
- package/ts/utils/console-write-stream.js.map +1 -0
- package/ts/utils/fanout-write-stream.d.ts +12 -0
- package/ts/utils/fanout-write-stream.d.ts.map +1 -0
- package/ts/utils/fanout-write-stream.js +24 -0
- package/ts/utils/fanout-write-stream.js.map +1 -0
- package/ts/utils/index.d.ts +7 -0
- package/ts/utils/index.d.ts.map +1 -0
- package/ts/utils/index.js +7 -0
- package/ts/utils/index.js.map +1 -0
- package/ts/utils/rebuffer.d.ts +3 -0
- package/ts/utils/rebuffer.d.ts.map +1 -0
- package/ts/utils/rebuffer.js +60 -0
- package/ts/utils/rebuffer.js.map +1 -0
- package/ts/utils/rebuffer.test.d.ts +2 -0
- package/ts/utils/rebuffer.test.d.ts.map +1 -0
- package/ts/utils/rebuffer.test.js +77 -0
- package/ts/utils/rebuffer.test.js.map +1 -0
- package/ts/utils/stream-map.d.ts +9 -0
- package/ts/utils/stream-map.d.ts.map +1 -0
- package/ts/utils/stream-map.js +62 -0
- package/ts/utils/stream-map.js.map +1 -0
- package/ts/utils/stream-map.test.d.ts +2 -0
- package/ts/utils/stream-map.test.d.ts.map +1 -0
- package/ts/utils/stream-map.test.js +87 -0
- package/ts/utils/stream-map.test.js.map +1 -0
- package/ts/utils/stream-test-helper.d.ts +17 -0
- package/ts/utils/stream-test-helper.d.ts.map +1 -0
- package/ts/utils/stream-test-helper.js +37 -0
- package/ts/utils/stream-test-helper.js.map +1 -0
- package/ts/utils/stream2string.d.ts +3 -0
- package/ts/utils/stream2string.d.ts.map +1 -0
- package/ts/utils/stream2string.js +48 -0
- package/ts/utils/stream2string.js.map +1 -0
- package/ts/utils/stream2string.test.d.ts +2 -0
- package/ts/utils/stream2string.test.d.ts.map +1 -0
- package/ts/utils/stream2string.test.js +29 -0
- package/ts/utils/stream2string.test.js.map +1 -0
- package/ts/utils/string2stream.d.ts +4 -0
- package/ts/utils/string2stream.d.ts.map +1 -0
- package/ts/utils/string2stream.js +13 -0
- package/ts/utils/string2stream.js.map +1 -0
- package/ts/utils/string2stream.test.d.ts +2 -0
- package/ts/utils/string2stream.test.d.ts.map +1 -0
- package/ts/utils/string2stream.test.js +6 -0
- package/ts/utils/string2stream.test.js.map +1 -0
- package/ts/version.d.ts +2 -0
- package/ts/version.d.ts.map +1 -0
- package/ts/version.js +4 -0
- package/ts/version.js.map +1 -0
- package/ts/web/index.d.ts +2 -0
- package/ts/web/index.d.ts.map +1 -0
- package/ts/web/index.js +2 -0
- package/ts/web/index.js.map +1 -0
- package/ts/web/web-sys-abstraction.d.ts +4 -0
- package/ts/web/web-sys-abstraction.d.ts.map +1 -0
- package/ts/web/web-sys-abstraction.js +64 -0
- package/ts/web/web-sys-abstraction.js.map +1 -0
- package/utils/index.cjs +0 -42
- package/utils/index.cjs.map +1 -1
- package/utils/index.d.cts +1 -2
- package/utils/index.d.ts +1 -2
- package/utils/index.js +2 -7
- package/web/index.cjs +25 -7
- package/web/index.cjs.map +1 -1
- package/web/index.d.cts +2 -1
- package/web/index.d.ts +2 -1
- package/web/index.js +3 -3
- package/chunk-DPIL5UIL.js.map +0 -1
- package/chunk-LCPYQVWT.js +0 -21
- package/chunk-OXD3YZZ7.js.map +0 -1
- package/chunk-P5RXA4C4.js.map +0 -1
- package/chunk-YDIUMYIE.js.map +0 -1
package/src/uri.ts
ADDED
@@ -0,0 +1,421 @@
|
|
1
|
+
import { exception2Result, Result } from "./result.js";
|
2
|
+
|
3
|
+
type NullOrUndef = null | undefined;
|
4
|
+
|
5
|
+
function falsy2undef<T>(value: T | NullOrUndef): T | undefined {
|
6
|
+
return value === undefined || value === null ? undefined : value;
|
7
|
+
}
|
8
|
+
|
9
|
+
function ensureURLWithDefaultProto(url: string | URL, defaultProtocol: string): MutableURL {
|
10
|
+
if (!url) {
|
11
|
+
return new MutableURL(`${defaultProtocol}//`);
|
12
|
+
}
|
13
|
+
if (typeof url === "string") {
|
14
|
+
try {
|
15
|
+
return new MutableURL(url);
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
17
|
+
} catch (e) {
|
18
|
+
return new MutableURL(`${defaultProtocol}//${url}`);
|
19
|
+
}
|
20
|
+
} else {
|
21
|
+
return new MutableURL(url.toString());
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
export function isURL(value: unknown): value is URL {
|
26
|
+
return (
|
27
|
+
value instanceof URL ||
|
28
|
+
(!!value &&
|
29
|
+
typeof (value as URL).searchParams === "object" &&
|
30
|
+
typeof (value as URL).searchParams.sort === "function" &&
|
31
|
+
typeof (value as URL).hash === "string")
|
32
|
+
);
|
33
|
+
}
|
34
|
+
|
35
|
+
// due to that the System URL class is has a strange behavior
|
36
|
+
// on different platforms, we need to implement our own URL class
|
37
|
+
export class MutableURL extends URL {
|
38
|
+
private readonly _sysURL: URL;
|
39
|
+
// private readonly _urlStr: string;
|
40
|
+
|
41
|
+
private _protocol: string;
|
42
|
+
private _pathname: string;
|
43
|
+
private _hasHostpart: boolean;
|
44
|
+
|
45
|
+
readonly hash: string;
|
46
|
+
|
47
|
+
constructor(urlStr: string) {
|
48
|
+
super("defect://does.not.exist");
|
49
|
+
const partedURL = urlStr.split(":");
|
50
|
+
this._hasHostpart = protocols.has(partedURL[0]);
|
51
|
+
let hostPartUrl = ["http", ...partedURL.slice(1)].join(":");
|
52
|
+
if (!this._hasHostpart) {
|
53
|
+
const pathname = hostPartUrl.replace(/http:\/\/[/]*/, "").replace(/[#?].*$/, "");
|
54
|
+
hostPartUrl = hostPartUrl.replace(/http:\/\//, `http://localhost/${pathname}`);
|
55
|
+
}
|
56
|
+
try {
|
57
|
+
this._sysURL = new URL(hostPartUrl);
|
58
|
+
} catch (ie) {
|
59
|
+
const e = ie as Error;
|
60
|
+
e.message = `${e.message} for URL: ${urlStr}`;
|
61
|
+
throw e;
|
62
|
+
}
|
63
|
+
this._protocol = `${partedURL[0]}:`; // this._sysURL.protocol.replace(new RegExp("^cement-"), "");
|
64
|
+
if (this._hasHostpart) {
|
65
|
+
this._pathname = this._sysURL.pathname;
|
66
|
+
} else {
|
67
|
+
this._pathname = urlStr.replace(new RegExp(`^${this._protocol}//`), "").replace(/[#?].*$/, "");
|
68
|
+
}
|
69
|
+
this.hash = this._sysURL.hash;
|
70
|
+
}
|
71
|
+
|
72
|
+
clone(): MutableURL {
|
73
|
+
return new MutableURL(this.toString());
|
74
|
+
}
|
75
|
+
|
76
|
+
get host(): string {
|
77
|
+
if (!this._hasHostpart) {
|
78
|
+
throw new Error(
|
79
|
+
`you can use hostname only if protocol is ${this.toString()} ${JSON.stringify(Array.from(protocols.keys()))}`,
|
80
|
+
);
|
81
|
+
}
|
82
|
+
return this._sysURL.host;
|
83
|
+
}
|
84
|
+
|
85
|
+
get port(): string {
|
86
|
+
if (!this._hasHostpart) {
|
87
|
+
throw new Error(`you can use hostname only if protocol is ${JSON.stringify(Array.from(protocols.keys()))}`);
|
88
|
+
}
|
89
|
+
return this._sysURL.port;
|
90
|
+
}
|
91
|
+
|
92
|
+
set port(p: string) {
|
93
|
+
if (!this._hasHostpart) {
|
94
|
+
throw new Error(`you can use port only if protocol is ${JSON.stringify(Array.from(protocols.keys()))}`);
|
95
|
+
}
|
96
|
+
this._sysURL.port = p;
|
97
|
+
}
|
98
|
+
|
99
|
+
get hostname(): string {
|
100
|
+
if (!this._hasHostpart) {
|
101
|
+
throw new Error(`you can use hostname only if protocol is ${JSON.stringify(Array.from(protocols.keys()))}`);
|
102
|
+
}
|
103
|
+
return this._sysURL.hostname;
|
104
|
+
}
|
105
|
+
|
106
|
+
set hostname(h: string) {
|
107
|
+
if (!this._hasHostpart) {
|
108
|
+
throw new Error(`you can use hostname only if protocol is ${JSON.stringify(Array.from(protocols.keys()))}`);
|
109
|
+
}
|
110
|
+
this._sysURL.hostname = h;
|
111
|
+
}
|
112
|
+
|
113
|
+
set pathname(p: string) {
|
114
|
+
this._pathname = p;
|
115
|
+
}
|
116
|
+
|
117
|
+
get pathname(): string {
|
118
|
+
return this._pathname;
|
119
|
+
}
|
120
|
+
|
121
|
+
get protocol(): string {
|
122
|
+
return this._protocol;
|
123
|
+
}
|
124
|
+
|
125
|
+
set protocol(p: string) {
|
126
|
+
if (!p.endsWith(":")) {
|
127
|
+
p = `${p}:`;
|
128
|
+
}
|
129
|
+
this._protocol = p;
|
130
|
+
}
|
131
|
+
|
132
|
+
get searchParams(): URLSearchParams {
|
133
|
+
return this._sysURL.searchParams;
|
134
|
+
}
|
135
|
+
|
136
|
+
toString(): string {
|
137
|
+
let search = "";
|
138
|
+
if (this._sysURL.searchParams.size) {
|
139
|
+
for (const [key, value] of Array.from(this._sysURL.searchParams.entries()).sort((a, b) => a[0].localeCompare(b[0]))) {
|
140
|
+
search += `${!search.length ? "?" : "&"}${key}=${encodeURIComponent(value)}`;
|
141
|
+
}
|
142
|
+
}
|
143
|
+
let hostpart = "";
|
144
|
+
if (this._hasHostpart) {
|
145
|
+
hostpart = this._sysURL.hostname;
|
146
|
+
if (this._sysURL.port) {
|
147
|
+
hostpart += `:${this._sysURL.port}`;
|
148
|
+
}
|
149
|
+
if (!this._pathname.startsWith("/")) {
|
150
|
+
hostpart += "/";
|
151
|
+
}
|
152
|
+
}
|
153
|
+
return `${this._protocol}//${hostpart}${this._pathname}${search}`;
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
function from<T>(fac: (url: MutableURL) => T, strURLUri: CoerceURI | undefined, defaultProtocol: string): T {
|
158
|
+
switch (typeof falsy2undef(strURLUri)) {
|
159
|
+
case "undefined":
|
160
|
+
return fac(new MutableURL(`${defaultProtocol}///`));
|
161
|
+
case "string":
|
162
|
+
return fac(ensureURLWithDefaultProto(strURLUri as string, defaultProtocol));
|
163
|
+
case "object":
|
164
|
+
if (BuildURI.is(strURLUri)) {
|
165
|
+
return fac(new MutableURL(strURLUri._url.toString()));
|
166
|
+
} else if (URI.is(strURLUri)) {
|
167
|
+
return fac(new MutableURL(strURLUri._url.toString()));
|
168
|
+
} else if (isURL(strURLUri)) {
|
169
|
+
return fac(new MutableURL(strURLUri.toString()));
|
170
|
+
}
|
171
|
+
throw new Error(`unknown object type: ${strURLUri}`);
|
172
|
+
default:
|
173
|
+
throw new Error(`Invalid argument: ${typeof strURLUri}`);
|
174
|
+
}
|
175
|
+
}
|
176
|
+
|
177
|
+
export class BuildURI {
|
178
|
+
_url: MutableURL; // pathname needs this
|
179
|
+
private constructor(url: MutableURL) {
|
180
|
+
this._url = url;
|
181
|
+
}
|
182
|
+
|
183
|
+
static is(value: unknown): value is BuildURI {
|
184
|
+
return (
|
185
|
+
value instanceof BuildURI ||
|
186
|
+
(!!value && typeof (value as BuildURI).delParam === "function" && typeof (value as BuildURI).setParam === "function")
|
187
|
+
);
|
188
|
+
}
|
189
|
+
static from(strURLUri?: CoerceURI, defaultProtocol = "file:"): BuildURI {
|
190
|
+
return from((url) => new BuildURI(url), strURLUri, defaultProtocol);
|
191
|
+
}
|
192
|
+
|
193
|
+
port(p: string): BuildURI {
|
194
|
+
this._url.port = p;
|
195
|
+
return this;
|
196
|
+
}
|
197
|
+
|
198
|
+
hostname(h: string): BuildURI {
|
199
|
+
this._url.hostname = h;
|
200
|
+
return this;
|
201
|
+
}
|
202
|
+
|
203
|
+
// password(p: string) {
|
204
|
+
// this._url.password = p;
|
205
|
+
// return this;
|
206
|
+
// }
|
207
|
+
|
208
|
+
// port(p: string) {
|
209
|
+
// this._url.port = p;
|
210
|
+
// return this;
|
211
|
+
// }
|
212
|
+
|
213
|
+
// username(u: string) {
|
214
|
+
// this._url.username = u;
|
215
|
+
// return this;
|
216
|
+
// }
|
217
|
+
|
218
|
+
// search(s: string) {
|
219
|
+
// this._url.search = s;
|
220
|
+
// return this;
|
221
|
+
// }
|
222
|
+
|
223
|
+
protocol(p: string): BuildURI {
|
224
|
+
this._url.protocol = p;
|
225
|
+
// if (!p.endsWith(":")) {
|
226
|
+
// p = `${p}:`;
|
227
|
+
// }
|
228
|
+
// const mySrc = this._url.toString();
|
229
|
+
// const myDst = mySrc.replace(new RegExp(`^${this._url.protocol}`), `${p}`);
|
230
|
+
// this._url = new URL(myDst);
|
231
|
+
return this;
|
232
|
+
}
|
233
|
+
|
234
|
+
pathname(p: string): BuildURI {
|
235
|
+
// const myp = this.URI().pathname;
|
236
|
+
// const mySrc = this._url.toString();
|
237
|
+
// const myDst = mySrc.replace(new RegExp(`^${this._url.protocol}//${myp}`), `${this._url.protocol}//${p}`);
|
238
|
+
// this._url = new URL(myDst);
|
239
|
+
this._url.pathname = p;
|
240
|
+
return this;
|
241
|
+
}
|
242
|
+
|
243
|
+
// hash(h: string) {
|
244
|
+
// this._url.hash = h;
|
245
|
+
// return this;
|
246
|
+
// }
|
247
|
+
|
248
|
+
// host(h: string) {
|
249
|
+
// this._url.host = h;
|
250
|
+
// return this;
|
251
|
+
// }
|
252
|
+
|
253
|
+
delParam(key: string): BuildURI {
|
254
|
+
this._url.searchParams.delete(key);
|
255
|
+
return this;
|
256
|
+
}
|
257
|
+
|
258
|
+
defParam(key: string, str: string): BuildURI {
|
259
|
+
if (!this._url.searchParams.has(key)) {
|
260
|
+
this._url.searchParams.set(key, str);
|
261
|
+
}
|
262
|
+
return this;
|
263
|
+
}
|
264
|
+
|
265
|
+
setParam(key: string, str: string): BuildURI {
|
266
|
+
this._url.searchParams.set(key, str);
|
267
|
+
return this;
|
268
|
+
}
|
269
|
+
|
270
|
+
hasParam(key: string): boolean {
|
271
|
+
return this._url.searchParams.has(key);
|
272
|
+
}
|
273
|
+
|
274
|
+
getParam(key: string): string | undefined {
|
275
|
+
return falsy2undef(this._url.searchParams.get(key));
|
276
|
+
}
|
277
|
+
|
278
|
+
toString(): string {
|
279
|
+
this._url.searchParams.sort();
|
280
|
+
return this._url.toString();
|
281
|
+
}
|
282
|
+
toJSON(): string {
|
283
|
+
return this.toString();
|
284
|
+
}
|
285
|
+
|
286
|
+
URI(): URI {
|
287
|
+
return URI.from(this._url);
|
288
|
+
}
|
289
|
+
}
|
290
|
+
|
291
|
+
export type CoerceURI = string | URI | MutableURL | URL | BuildURI | NullOrUndef;
|
292
|
+
|
293
|
+
export const protocols: Set<string> = new Set<string>(["http", "https", "ws", "wss"]);
|
294
|
+
|
295
|
+
// non mutable URL Implementation
|
296
|
+
export class URI {
|
297
|
+
static protocolHasHostpart(protocol: string): () => void {
|
298
|
+
protocol = protocol.replace(/:$/, "");
|
299
|
+
protocols.add(protocol);
|
300
|
+
return () => {
|
301
|
+
protocols.delete(protocol);
|
302
|
+
};
|
303
|
+
}
|
304
|
+
|
305
|
+
// if no protocol is provided, default to file:
|
306
|
+
static merge(into: CoerceURI, from: CoerceURI, defaultProtocol = "file:"): URI {
|
307
|
+
const intoUrl = BuildURI.from(into, defaultProtocol);
|
308
|
+
const fromUrl = URI.from(from, defaultProtocol);
|
309
|
+
|
310
|
+
intoUrl.protocol(fromUrl.protocol);
|
311
|
+
const fPath = fromUrl.pathname;
|
312
|
+
if (!(fPath.length === 0 || fPath === "/" || fPath === "./")) {
|
313
|
+
intoUrl.pathname(fromUrl.pathname);
|
314
|
+
}
|
315
|
+
for (const [key, value] of fromUrl.getParams) {
|
316
|
+
intoUrl.setParam(key, value);
|
317
|
+
}
|
318
|
+
return intoUrl.URI();
|
319
|
+
}
|
320
|
+
|
321
|
+
static is(value: unknown): value is URI {
|
322
|
+
return (
|
323
|
+
value instanceof URI ||
|
324
|
+
(!!value &&
|
325
|
+
typeof (value as URI).asURL === "function" &&
|
326
|
+
typeof (value as URI).getParam === "function" &&
|
327
|
+
typeof (value as URI).hasParam === "function")
|
328
|
+
);
|
329
|
+
}
|
330
|
+
|
331
|
+
// if no protocol is provided, default to file:
|
332
|
+
static from(strURLUri?: CoerceURI, defaultProtocol = "file:"): URI {
|
333
|
+
return from((url) => new URI(url), strURLUri, defaultProtocol);
|
334
|
+
}
|
335
|
+
|
336
|
+
static fromResult(strURLUri?: CoerceURI, defaultProtocol = "file:"): Result<URI> {
|
337
|
+
return exception2Result(() => from((url) => new URI(url), strURLUri, defaultProtocol)) as Result<URI>;
|
338
|
+
}
|
339
|
+
|
340
|
+
readonly _url: MutableURL;
|
341
|
+
private constructor(url: MutableURL) {
|
342
|
+
this._url = url.clone();
|
343
|
+
}
|
344
|
+
|
345
|
+
build(): BuildURI {
|
346
|
+
return BuildURI.from(this._url);
|
347
|
+
}
|
348
|
+
|
349
|
+
get hostname(): string {
|
350
|
+
return this._url.hostname;
|
351
|
+
}
|
352
|
+
|
353
|
+
// get password(): string {
|
354
|
+
// return this._url.password;
|
355
|
+
// }
|
356
|
+
|
357
|
+
get port(): string {
|
358
|
+
return this._url.port;
|
359
|
+
}
|
360
|
+
|
361
|
+
get host(): string {
|
362
|
+
return this._url.host;
|
363
|
+
}
|
364
|
+
|
365
|
+
// get username(): string {
|
366
|
+
// return this._url.username;
|
367
|
+
// }
|
368
|
+
|
369
|
+
// get search(): string {
|
370
|
+
// return this._url.search;
|
371
|
+
// }
|
372
|
+
|
373
|
+
get protocol(): string {
|
374
|
+
return this._url.protocol;
|
375
|
+
}
|
376
|
+
|
377
|
+
get pathname(): string {
|
378
|
+
return this._url.pathname;
|
379
|
+
// return this._url
|
380
|
+
// .toString()
|
381
|
+
// .replace(/^.*:\/\//, "")
|
382
|
+
// .replace(/\?.*$/, "");
|
383
|
+
}
|
384
|
+
|
385
|
+
// get hash(): string {
|
386
|
+
// return this._url.hash;
|
387
|
+
// }
|
388
|
+
|
389
|
+
// get host(): string {
|
390
|
+
// return this._url.host;
|
391
|
+
// }
|
392
|
+
|
393
|
+
get getParams(): Iterable<[string, string]> {
|
394
|
+
return this._url.searchParams.entries();
|
395
|
+
}
|
396
|
+
|
397
|
+
hasParam(key: string): boolean {
|
398
|
+
return this._url.searchParams.has(key);
|
399
|
+
}
|
400
|
+
getParam(key: string): string | undefined {
|
401
|
+
return falsy2undef(this._url.searchParams.get(key));
|
402
|
+
}
|
403
|
+
|
404
|
+
clone(): URI {
|
405
|
+
return new URI(this._url);
|
406
|
+
}
|
407
|
+
|
408
|
+
asURL(): URL {
|
409
|
+
// const url = new URL(this._url.toString());
|
410
|
+
// url.searchParams.sort();
|
411
|
+
return this._url.clone() as unknown as URL;
|
412
|
+
}
|
413
|
+
|
414
|
+
toString(): string {
|
415
|
+
// this._url.searchParams.sort();
|
416
|
+
return this._url.toString();
|
417
|
+
}
|
418
|
+
toJSON(): string {
|
419
|
+
return this.toString();
|
420
|
+
}
|
421
|
+
}
|
@@ -0,0 +1,72 @@
|
|
1
|
+
export class ConsoleWriterStreamDefaultWriter implements WritableStreamDefaultWriter<Uint8Array> {
|
2
|
+
readonly desiredSize: number | null = null;
|
3
|
+
readonly decoder: TextDecoder = new TextDecoder();
|
4
|
+
|
5
|
+
closed: Promise<undefined>;
|
6
|
+
ready: Promise<undefined>;
|
7
|
+
readonly _stream: ConsoleWriterStream;
|
8
|
+
|
9
|
+
constructor(private stream: ConsoleWriterStream) {
|
10
|
+
this._stream = stream;
|
11
|
+
this.ready = Promise.resolve(undefined);
|
12
|
+
this.closed = Promise.resolve(undefined);
|
13
|
+
}
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
|
15
|
+
abort(reason?: any): Promise<void> {
|
16
|
+
throw new Error("Method not implemented.");
|
17
|
+
}
|
18
|
+
async close(): Promise<void> {
|
19
|
+
// noop
|
20
|
+
}
|
21
|
+
releaseLock(): void {
|
22
|
+
this._stream.locked = false;
|
23
|
+
this.ready = Promise.resolve(undefined);
|
24
|
+
this.closed = Promise.resolve(undefined);
|
25
|
+
}
|
26
|
+
async write(chunk?: Uint8Array | undefined): Promise<void> {
|
27
|
+
const str = this.decoder.decode(chunk).trimEnd();
|
28
|
+
let output = "log";
|
29
|
+
try {
|
30
|
+
const decode = JSON.parse(str);
|
31
|
+
output = decode.level;
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
33
|
+
} catch (e) {
|
34
|
+
/* noop */
|
35
|
+
}
|
36
|
+
switch (output) {
|
37
|
+
case "error":
|
38
|
+
// eslint-disable-next-line no-console
|
39
|
+
console.error(str);
|
40
|
+
break;
|
41
|
+
case "warn":
|
42
|
+
// eslint-disable-next-line no-console
|
43
|
+
console.warn(str);
|
44
|
+
break;
|
45
|
+
default:
|
46
|
+
// eslint-disable-next-line no-console
|
47
|
+
console.log(str);
|
48
|
+
}
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
export class ConsoleWriterStream implements WritableStream<Uint8Array> {
|
53
|
+
locked = false;
|
54
|
+
_writer?: WritableStreamDefaultWriter<Uint8Array>;
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
|
56
|
+
abort(reason?: any): Promise<void> {
|
57
|
+
throw new Error("Method not implemented.");
|
58
|
+
}
|
59
|
+
async close(): Promise<void> {
|
60
|
+
return;
|
61
|
+
}
|
62
|
+
getWriter(): WritableStreamDefaultWriter<Uint8Array> {
|
63
|
+
if (this.locked) {
|
64
|
+
throw new Error("Stream is locked");
|
65
|
+
}
|
66
|
+
this.locked = true;
|
67
|
+
if (!this._writer) {
|
68
|
+
this._writer = new ConsoleWriterStreamDefaultWriter(this);
|
69
|
+
}
|
70
|
+
return this._writer;
|
71
|
+
}
|
72
|
+
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
export class FanoutWriteStream implements WritableStreamDefaultWriter<Uint8Array> {
|
2
|
+
readonly _writers: WritableStreamDefaultWriter<Uint8Array>[];
|
3
|
+
readonly ready: Promise<undefined>;
|
4
|
+
readonly closed: Promise<undefined>;
|
5
|
+
readonly desiredSize: number | null = null;
|
6
|
+
constructor(writers: WritableStreamDefaultWriter<Uint8Array>[]) {
|
7
|
+
this._writers = writers;
|
8
|
+
this.ready = Promise.all(this._writers.map((w) => w.ready)).then(() => undefined);
|
9
|
+
this.closed = Promise.all(this._writers.map((w) => w.closed)).then(() => undefined);
|
10
|
+
}
|
11
|
+
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
13
|
+
abort(reason?: any): Promise<void> {
|
14
|
+
return Promise.all(this._writers.map((w) => w.abort(reason))).then(() => {
|
15
|
+
/* do nothing */
|
16
|
+
});
|
17
|
+
}
|
18
|
+
close(): Promise<void> {
|
19
|
+
return Promise.all(this._writers.map((w) => w.close())).then(() => {
|
20
|
+
/* do nothing */
|
21
|
+
});
|
22
|
+
}
|
23
|
+
releaseLock(): void {
|
24
|
+
this._writers.map((w) => w.releaseLock());
|
25
|
+
}
|
26
|
+
|
27
|
+
write(chunk?: Uint8Array | undefined): Promise<void> {
|
28
|
+
return Promise.all(this._writers.map((w) => w.write(chunk))).then(() => {
|
29
|
+
/* do nothing */
|
30
|
+
});
|
31
|
+
}
|
32
|
+
}
|
@@ -0,0 +1,75 @@
|
|
1
|
+
import { array2stream, stream2array } from "./stream-map.js";
|
2
|
+
|
3
|
+
interface ReChunkResult {
|
4
|
+
readonly rest: Uint8Array;
|
5
|
+
readonly chunk: Uint8Array;
|
6
|
+
}
|
7
|
+
|
8
|
+
export async function rebufferArray(a: Uint8Array[], chunkSize: number): Promise<Uint8Array[]> {
|
9
|
+
return stream2array(rebuffer(array2stream(a), chunkSize));
|
10
|
+
}
|
11
|
+
|
12
|
+
function reChunk(cs: Uint8Array[], chunkSize: number): ReChunkResult {
|
13
|
+
const len = cs.reduce((acc, v) => acc + v.length, 0);
|
14
|
+
const last = cs[cs.length - 1];
|
15
|
+
const lastOfs = len - last.length;
|
16
|
+
// console.log("reChunk", len, lastOfs, last.length, chunkSize, chunkSize - lastOfs)
|
17
|
+
const rest = last.subarray(chunkSize - lastOfs);
|
18
|
+
cs[cs.length - 1] = last.subarray(0, chunkSize - lastOfs);
|
19
|
+
const chunk = new Uint8Array(chunkSize);
|
20
|
+
let ofs = 0;
|
21
|
+
for (const c of cs) {
|
22
|
+
chunk.set(c, ofs);
|
23
|
+
ofs += c.length;
|
24
|
+
}
|
25
|
+
return { rest, chunk };
|
26
|
+
}
|
27
|
+
|
28
|
+
interface pumpState {
|
29
|
+
readonly reader: ReadableStreamDefaultReader<Uint8Array>;
|
30
|
+
tmp: Uint8Array[];
|
31
|
+
tmpLen: number;
|
32
|
+
readonly chunkSize: number;
|
33
|
+
}
|
34
|
+
|
35
|
+
function pump(ps: pumpState, controller: ReadableStreamDefaultController<Uint8Array>, next: () => void): void {
|
36
|
+
ps.reader.read().then(({ done, value }) => {
|
37
|
+
if (done) {
|
38
|
+
if (ps.tmpLen > 0) {
|
39
|
+
controller.enqueue(reChunk(ps.tmp, ps.tmpLen).chunk);
|
40
|
+
}
|
41
|
+
controller.close();
|
42
|
+
next();
|
43
|
+
return;
|
44
|
+
}
|
45
|
+
if (ps.tmpLen + value.length > ps.chunkSize) {
|
46
|
+
ps.tmp.push(value);
|
47
|
+
const res = reChunk(ps.tmp, ps.chunkSize);
|
48
|
+
controller.enqueue(res.chunk);
|
49
|
+
ps.tmp = [res.rest];
|
50
|
+
ps.tmpLen = res.rest.length;
|
51
|
+
next();
|
52
|
+
return;
|
53
|
+
} else if (value.length) {
|
54
|
+
ps.tmp.push(value);
|
55
|
+
ps.tmpLen += value.length;
|
56
|
+
}
|
57
|
+
pump(ps, controller, next);
|
58
|
+
});
|
59
|
+
}
|
60
|
+
|
61
|
+
export function rebuffer(a: ReadableStream<Uint8Array>, chunkSize: number): ReadableStream<Uint8Array> {
|
62
|
+
const state: pumpState = {
|
63
|
+
reader: a.getReader(),
|
64
|
+
tmp: [],
|
65
|
+
tmpLen: 0,
|
66
|
+
chunkSize,
|
67
|
+
};
|
68
|
+
return new ReadableStream<Uint8Array>({
|
69
|
+
async pull(controller): Promise<void> {
|
70
|
+
return new Promise<void>((resolve) => {
|
71
|
+
pump(state, controller, resolve);
|
72
|
+
});
|
73
|
+
},
|
74
|
+
});
|
75
|
+
}
|
@@ -0,0 +1,67 @@
|
|
1
|
+
export interface StreamMap<T, U> {
|
2
|
+
Map(s: T, idx: number): U | Promise<U>;
|
3
|
+
readonly Close?: () => void;
|
4
|
+
}
|
5
|
+
export function streamMap<T, U>(s: ReadableStream<T>, sm: StreamMap<T, U>): ReadableStream<U> {
|
6
|
+
const state = { reader: s.getReader(), streamMap: sm, idx: 0 };
|
7
|
+
return new ReadableStream<U>({
|
8
|
+
async pull(controller): Promise<void> {
|
9
|
+
const { done, value } = await state.reader.read();
|
10
|
+
if (done) {
|
11
|
+
if (state.streamMap.Close) {
|
12
|
+
state.streamMap.Close();
|
13
|
+
}
|
14
|
+
controller.close();
|
15
|
+
return;
|
16
|
+
}
|
17
|
+
const promiseOrU = state.streamMap.Map(value, state.idx++);
|
18
|
+
let mapped: U;
|
19
|
+
if (promiseOrU instanceof Promise || typeof (promiseOrU as { then: () => void }).then === "function") {
|
20
|
+
mapped = await promiseOrU;
|
21
|
+
} else {
|
22
|
+
mapped = promiseOrU;
|
23
|
+
}
|
24
|
+
controller.enqueue(mapped);
|
25
|
+
},
|
26
|
+
});
|
27
|
+
}
|
28
|
+
|
29
|
+
export async function devnull<T>(a: ReadableStream<T>): Promise<number> {
|
30
|
+
const reader = a.getReader();
|
31
|
+
let cnt = 0;
|
32
|
+
while (true) {
|
33
|
+
const { done } = await reader.read();
|
34
|
+
if (done) {
|
35
|
+
break;
|
36
|
+
}
|
37
|
+
cnt++;
|
38
|
+
}
|
39
|
+
return cnt;
|
40
|
+
}
|
41
|
+
|
42
|
+
export function array2stream<T>(a: T[]): ReadableStream<T> {
|
43
|
+
let i = 0;
|
44
|
+
return new ReadableStream<T>({
|
45
|
+
pull(controller): void {
|
46
|
+
if (i >= a.length) {
|
47
|
+
controller.close();
|
48
|
+
return;
|
49
|
+
}
|
50
|
+
controller.enqueue(a[i]);
|
51
|
+
i++;
|
52
|
+
},
|
53
|
+
});
|
54
|
+
}
|
55
|
+
|
56
|
+
export async function stream2array<T>(a: ReadableStream<T>): Promise<T[]> {
|
57
|
+
const ret: T[] = [];
|
58
|
+
const reader = a.getReader();
|
59
|
+
while (true) {
|
60
|
+
const { done, value } = await reader.read();
|
61
|
+
if (done) {
|
62
|
+
break;
|
63
|
+
}
|
64
|
+
ret.push(value);
|
65
|
+
}
|
66
|
+
return ret;
|
67
|
+
}
|