@adviser/cement 0.0.0-jsr-t1
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/LICENSE +201 -0
- package/README.md +39 -0
- package/base-sys-abstraction-BkEiLHl0.d.ts +193 -0
- package/base-sys-abstraction-Qj7pkY1N.d.cts +193 -0
- package/chunk-7KFVMTOS.js +311 -0
- package/chunk-7KFVMTOS.js.map +1 -0
- package/chunk-GES3MUGV.js +92 -0
- package/chunk-GES3MUGV.js.map +1 -0
- package/chunk-Q65HLCNL.js +601 -0
- package/chunk-Q65HLCNL.js.map +1 -0
- package/chunk-WMMUXBDX.js +87 -0
- package/chunk-WMMUXBDX.js.map +1 -0
- package/index-Q3phXzYr.d.cts +75 -0
- package/index-tIGZMHTc.d.ts +75 -0
- package/index.cjs +2593 -0
- package/index.cjs.map +1 -0
- package/index.d.cts +532 -0
- package/index.d.ts +532 -0
- package/index.js +1533 -0
- package/index.js.map +1 -0
- package/node/index.cjs +924 -0
- package/node/index.cjs.map +1 -0
- package/node/index.d.cts +65 -0
- package/node/index.d.ts +65 -0
- package/node/index.js +398 -0
- package/node/index.js.map +1 -0
- package/package.json +81 -0
- package/src/base-sys-abstraction.test.ts +95 -0
- package/src/base-sys-abstraction.ts +242 -0
- package/src/bin2text.test.ts +59 -0
- package/src/bin2text.ts +47 -0
- package/src/crypto.test.ts +15 -0
- package/src/crypto.ts +125 -0
- package/src/file-service.ts +24 -0
- package/src/future.test.ts +32 -0
- package/src/future.ts +27 -0
- package/src/index.ts +22 -0
- package/src/jsr.json +20 -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.test.ts +1132 -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/resolve-once.test.ts +321 -0
- package/src/resolve-once.ts +179 -0
- package/src/result.test.ts +102 -0
- package/src/result.ts +165 -0
- package/src/runtime.ts +36 -0
- package/src/sys-abstraction.ts +53 -0
- package/src/sys-env.test.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.test.ts +314 -0
- package/src/tracer.ts +222 -0
- package/src/txt-en-decoder.ts +21 -0
- package/src/uri.test.ts +155 -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/LICENSE +201 -0
- package/ts/README.md +39 -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 +23 -0
- package/ts/index.d.ts.map +1 -0
- package/ts/index.js +23 -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 +87 -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/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/txt-en-decoder-CZYJUju2.d.cts +11 -0
- package/txt-en-decoder-CZYJUju2.d.ts +11 -0
- package/utils/index.cjs +341 -0
- package/utils/index.cjs.map +1 -0
- package/utils/index.d.cts +2 -0
- package/utils/index.d.ts +2 -0
- package/utils/index.js +32 -0
- package/utils/index.js.map +1 -0
- package/web/index.cjs +593 -0
- package/web/index.cjs.map +1 -0
- package/web/index.d.cts +6 -0
- package/web/index.d.ts +6 -0
- package/web/index.js +9 -0
- package/web/index.js.map +1 -0
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
|
+
}
|