@adviser/cement 0.4.32 → 0.4.34
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/cjs/cli/patch-version-cmd.cjs +25 -9
- package/cjs/cli/patch-version-cmd.cjs.map +1 -1
- package/cjs/cli/patch-version-cmd.d.ts +1 -1
- package/cjs/cli/patch-version-cmd.d.ts.map +1 -1
- package/cjs/index.cjs +1 -0
- package/cjs/index.cjs.map +1 -1
- package/cjs/index.d.ts +1 -0
- package/cjs/index.d.ts.map +1 -1
- package/cjs/load-asset.cjs +6 -5
- package/cjs/load-asset.cjs.map +1 -1
- package/cjs/load-asset.d.ts.map +1 -1
- package/cjs/logger.cjs +2 -2
- package/cjs/logger.cjs.map +1 -1
- package/cjs/logger.d.ts.map +1 -1
- package/cjs/logger.test.cjs +1 -1
- package/cjs/logger.test.cjs.map +1 -1
- package/cjs/mutable-url.cjs +281 -0
- package/cjs/mutable-url.cjs.map +1 -0
- package/cjs/mutable-url.d.ts +72 -0
- package/cjs/mutable-url.d.ts.map +1 -0
- package/cjs/mutable-url.test.cjs +452 -0
- package/cjs/mutable-url.test.cjs.map +1 -0
- package/cjs/mutable-url.test.d.ts +2 -0
- package/cjs/mutable-url.test.d.ts.map +1 -0
- package/cjs/uri.cjs +32 -161
- package/cjs/uri.cjs.map +1 -1
- package/cjs/uri.d.ts +4 -30
- package/cjs/uri.d.ts.map +1 -1
- package/cjs/uri.test.cjs +24 -36
- package/cjs/uri.test.cjs.map +1 -1
- package/cjs/utils/coerce-uint8.cjs.map +1 -1
- package/cjs/utils/coerce-uint8.d.ts.map +1 -1
- package/cjs/version.cjs +1 -1
- package/deno.json +1 -1
- package/esm/cli/patch-version-cmd.d.ts +1 -1
- package/esm/cli/patch-version-cmd.d.ts.map +1 -1
- package/esm/cli/patch-version-cmd.js +25 -9
- package/esm/cli/patch-version-cmd.js.map +1 -1
- package/esm/index.d.ts +1 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -0
- package/esm/index.js.map +1 -1
- package/esm/load-asset.d.ts.map +1 -1
- package/esm/load-asset.js +7 -6
- package/esm/load-asset.js.map +1 -1
- package/esm/logger.d.ts.map +1 -1
- package/esm/logger.js +2 -2
- package/esm/logger.js.map +1 -1
- package/esm/logger.test.js +2 -2
- package/esm/logger.test.js.map +1 -1
- package/esm/mutable-url.d.ts +72 -0
- package/esm/mutable-url.d.ts.map +1 -0
- package/esm/mutable-url.js +275 -0
- package/esm/mutable-url.js.map +1 -0
- package/esm/mutable-url.test.d.ts +2 -0
- package/esm/mutable-url.test.d.ts.map +1 -0
- package/esm/mutable-url.test.js +450 -0
- package/esm/mutable-url.test.js.map +1 -0
- package/esm/uri.d.ts +4 -30
- package/esm/uri.d.ts.map +1 -1
- package/esm/uri.js +26 -154
- package/esm/uri.js.map +1 -1
- package/esm/uri.test.js +25 -37
- package/esm/uri.test.js.map +1 -1
- package/esm/utils/coerce-uint8.d.ts.map +1 -1
- package/esm/utils/coerce-uint8.js.map +1 -1
- package/esm/version.js +1 -1
- package/package.json +2 -1
- package/src/cli/patch-version-cmd.ts +26 -9
- package/src/index.ts +1 -0
- package/src/load-asset.ts +7 -6
- package/src/logger.ts +3 -2
- package/src/mutable-url.ts +365 -0
- package/src/uri.ts +51 -195
- package/src/utils/coerce-uint8.ts +1 -2
- package/ts/cjs/cli/patch-version-cmd.d.ts +1 -1
- package/ts/cjs/cli/patch-version-cmd.d.ts.map +1 -1
- package/ts/cjs/cli/patch-version-cmd.js +25 -9
- package/ts/cjs/cli/patch-version-cmd.js.map +1 -1
- package/ts/cjs/index.d.ts +1 -0
- package/ts/cjs/index.d.ts.map +1 -1
- package/ts/cjs/index.js +1 -0
- package/ts/cjs/index.js.map +1 -1
- package/ts/cjs/load-asset.d.ts.map +1 -1
- package/ts/cjs/load-asset.js +6 -5
- package/ts/cjs/load-asset.js.map +1 -1
- package/ts/cjs/logger.d.ts.map +1 -1
- package/ts/cjs/logger.js +2 -2
- package/ts/cjs/logger.js.map +1 -1
- package/ts/cjs/logger.test.js +1 -1
- package/ts/cjs/logger.test.js.map +1 -1
- package/ts/cjs/mutable-url.d.ts +72 -0
- package/ts/cjs/mutable-url.d.ts.map +1 -0
- package/ts/cjs/mutable-url.js +281 -0
- package/ts/cjs/mutable-url.js.map +1 -0
- package/ts/cjs/mutable-url.test.d.ts +2 -0
- package/ts/cjs/mutable-url.test.d.ts.map +1 -0
- package/ts/cjs/mutable-url.test.js +452 -0
- package/ts/cjs/mutable-url.test.js.map +1 -0
- package/ts/cjs/uri.d.ts +4 -30
- package/ts/cjs/uri.d.ts.map +1 -1
- package/ts/cjs/uri.js +32 -161
- package/ts/cjs/uri.js.map +1 -1
- package/ts/cjs/uri.test.js +24 -36
- package/ts/cjs/uri.test.js.map +1 -1
- package/ts/cjs/utils/coerce-uint8.d.ts.map +1 -1
- package/ts/cjs/utils/coerce-uint8.js.map +1 -1
- package/ts/cjs/version.js +1 -1
- package/ts/esm/cli/patch-version-cmd.d.ts +1 -1
- package/ts/esm/cli/patch-version-cmd.d.ts.map +1 -1
- package/ts/esm/cli/patch-version-cmd.js +25 -9
- package/ts/esm/cli/patch-version-cmd.js.map +1 -1
- package/ts/esm/index.d.ts +1 -0
- package/ts/esm/index.d.ts.map +1 -1
- package/ts/esm/index.js +1 -0
- package/ts/esm/index.js.map +1 -1
- package/ts/esm/load-asset.d.ts.map +1 -1
- package/ts/esm/load-asset.js +7 -6
- package/ts/esm/load-asset.js.map +1 -1
- package/ts/esm/logger.d.ts.map +1 -1
- package/ts/esm/logger.js +2 -2
- package/ts/esm/logger.js.map +1 -1
- package/ts/esm/logger.test.js +2 -2
- package/ts/esm/logger.test.js.map +1 -1
- package/ts/esm/mutable-url.d.ts +72 -0
- package/ts/esm/mutable-url.d.ts.map +1 -0
- package/ts/esm/mutable-url.js +275 -0
- package/ts/esm/mutable-url.js.map +1 -0
- package/ts/esm/mutable-url.test.d.ts +2 -0
- package/ts/esm/mutable-url.test.d.ts.map +1 -0
- package/ts/esm/mutable-url.test.js +450 -0
- package/ts/esm/mutable-url.test.js.map +1 -0
- package/ts/esm/uri.d.ts +4 -30
- package/ts/esm/uri.d.ts.map +1 -1
- package/ts/esm/uri.js +26 -154
- package/ts/esm/uri.js.map +1 -1
- package/ts/esm/uri.test.js +25 -37
- package/ts/esm/uri.test.js.map +1 -1
- package/ts/esm/utils/coerce-uint8.d.ts.map +1 -1
- package/ts/esm/utils/coerce-uint8.js.map +1 -1
- package/ts/esm/version.js +1 -1
@@ -72,6 +72,7 @@ export function generateVersionTsCmd(): ReturnType<typeof command> {
|
|
72
72
|
type: string,
|
73
73
|
description: "Path to the file containing the version, defaults to './src/version.ts'.",
|
74
74
|
}),
|
75
|
+
|
75
76
|
tsconfig: option({
|
76
77
|
long: "tsconfig",
|
77
78
|
short: "t",
|
@@ -145,7 +146,7 @@ function setupDenoJson(packageJsonFile: string, jsrJsonFile: string): void {
|
|
145
146
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonFile).toString()) as { dependencies: Record<string, string> };
|
146
147
|
const jsrJson = JSON.parse(fs.readFileSync(jsrJsonFile).toString()) as { imports: Record<string, string> };
|
147
148
|
jsrJson.imports = Object.fromEntries(
|
148
|
-
Array.from(Object.entries(packageJson.dependencies)).map(([k, v]) => [k, `npm:${k}@${v.replace(/^npm:/, "")}`]),
|
149
|
+
Array.from(Object.entries(packageJson.dependencies ?? {})).map(([k, v]) => [k, `npm:${k}@${v.replace(/^npm:/, "")}`]),
|
149
150
|
);
|
150
151
|
fs.writeFileSync(jsrJsonFile, JSON.stringify(jsrJson, undefined, 2) + "\n");
|
151
152
|
}
|
@@ -181,7 +182,7 @@ export function setUpDenoJsonCmd(): ReturnType<typeof command> {
|
|
181
182
|
});
|
182
183
|
}
|
183
184
|
|
184
|
-
export async function preparePubdir(pubdir: string, version: string): Promise<void> {
|
185
|
+
export async function preparePubdir(pubdir: string, version: string, baseDir: string, srcDir: string): Promise<void> {
|
185
186
|
// Set shell options equivalent to 'set -ex'
|
186
187
|
$.verbose = true;
|
187
188
|
|
@@ -195,7 +196,7 @@ export async function preparePubdir(pubdir: string, version: string): Promise<vo
|
|
195
196
|
await $`mkdir -p ${pubdir}`;
|
196
197
|
|
197
198
|
// Copy files to pubdir
|
198
|
-
await $`cp -pr
|
199
|
+
await $`cp -pr ${path.join(baseDir, ".gitignore")} ${path.join(baseDir, "README.md")} ${path.join(baseDir, "LICENSE")} ./dist/ts/ ${pubdir}/`;
|
199
200
|
|
200
201
|
// Copy from dist/pkg
|
201
202
|
cd("dist/pkg");
|
@@ -203,8 +204,8 @@ export async function preparePubdir(pubdir: string, version: string): Promise<vo
|
|
203
204
|
cd("../..");
|
204
205
|
|
205
206
|
// Copy from src
|
206
|
-
cd(
|
207
|
-
await $`cp -pr . ../${pubdir}
|
207
|
+
cd(srcDir);
|
208
|
+
await $`cp -pr . ../${pubdir}/${srcDir}/`;
|
208
209
|
cd("..");
|
209
210
|
|
210
211
|
// Rename .js files to .cjs in pubdir/cjs
|
@@ -231,20 +232,20 @@ export async function preparePubdir(pubdir: string, version: string): Promise<vo
|
|
231
232
|
await $`cp package.json ${pubdir}/`;
|
232
233
|
|
233
234
|
// Clean up test files in pubdir/src
|
234
|
-
cd(`${pubdir}
|
235
|
+
cd(`${pubdir}/${srcDir}`);
|
235
236
|
await $`rm -f test/test-exit-handler.* ./utils/stream-test-helper.ts`.catch(() => {
|
236
237
|
// Ignore errors if files don't exist
|
237
238
|
});
|
238
239
|
cd("../..");
|
239
240
|
|
240
241
|
// Remove __screenshots__ directories
|
241
|
-
const screenshotDirs = await glob(`${pubdir}
|
242
|
+
const screenshotDirs = await glob(`${pubdir}/${srcDir}/**/__screenshots__`);
|
242
243
|
for (const dir of screenshotDirs) {
|
243
244
|
await $`rm -rf ${dir}`;
|
244
245
|
}
|
245
246
|
|
246
247
|
// Remove test files
|
247
|
-
const testFiles = await glob(`${pubdir}
|
248
|
+
const testFiles = await glob(`${pubdir}/${srcDir}/**/*.test.ts`);
|
248
249
|
for (const file of testFiles) {
|
249
250
|
await $`rm -f ${file}`;
|
250
251
|
}
|
@@ -280,6 +281,22 @@ export function preparePubdirCmd(): ReturnType<typeof command> {
|
|
280
281
|
type: string,
|
281
282
|
description: "Path to the pubdir, defaults to './pubdir'.",
|
282
283
|
}),
|
284
|
+
srcDir: option({
|
285
|
+
long: "srcDir",
|
286
|
+
short: "s",
|
287
|
+
defaultValue: () => "src",
|
288
|
+
defaultValueIsSerializable: true,
|
289
|
+
type: string,
|
290
|
+
description: "Path to the src directory, defaults to './src'.",
|
291
|
+
}),
|
292
|
+
baseDir: option({
|
293
|
+
long: "baseDir",
|
294
|
+
short: "b",
|
295
|
+
defaultValue: () => "../",
|
296
|
+
defaultValueIsSerializable: true,
|
297
|
+
type: string,
|
298
|
+
description: "Path to the base directory of the project, defaults to '../'.",
|
299
|
+
}),
|
283
300
|
version: option({
|
284
301
|
long: "version",
|
285
302
|
short: "v",
|
@@ -290,7 +307,7 @@ export function preparePubdirCmd(): ReturnType<typeof command> {
|
|
290
307
|
}),
|
291
308
|
},
|
292
309
|
handler: async (args) => {
|
293
|
-
await preparePubdir(args.pubdir, args.version);
|
310
|
+
await preparePubdir(args.pubdir, args.version, args.baseDir, args.srcDir);
|
294
311
|
},
|
295
312
|
});
|
296
313
|
}
|
package/src/index.ts
CHANGED
package/src/load-asset.ts
CHANGED
@@ -2,7 +2,7 @@ import { pathOps } from "./path-ops.js";
|
|
2
2
|
import { Result, exception2Result } from "./result.js";
|
3
3
|
import { runtimeFn } from "./runtime.js";
|
4
4
|
import { TxtEnDecoderSingleton } from "./txt-en-decoder.js";
|
5
|
-
import { CoerceURI, URI } from "./uri.js";
|
5
|
+
import { BuildURI, CoerceURI, URI } from "./uri.js";
|
6
6
|
|
7
7
|
interface MockLoadAsset {
|
8
8
|
fetch: typeof globalThis.fetch;
|
@@ -95,25 +95,26 @@ async function loadAssetReal(
|
|
95
95
|
}
|
96
96
|
return Result.Err(`cannot load file: ${baseUrl.url.toString()} from ${baseUrl.src}`);
|
97
97
|
}
|
98
|
+
const urlToFetch = BuildURI.from(baseUrl.url);
|
98
99
|
switch (baseUrl.src) {
|
99
100
|
case "opts.fallBackUrl":
|
100
|
-
|
101
|
+
urlToFetch.pathname(opts.pathCleaner(baseUrl.url.pathname, localPath, "fallback"));
|
101
102
|
break;
|
102
103
|
case "import.meta.url":
|
103
|
-
|
104
|
+
urlToFetch.pathname(opts.pathCleaner(baseUrl.url.pathname, localPath, "normal"));
|
104
105
|
break;
|
105
106
|
}
|
106
107
|
|
107
108
|
const rRes = await exception2Result(() => {
|
108
|
-
if (!
|
109
|
+
if (!urlToFetch) {
|
109
110
|
throw Error(`base url not found from ${baseUrl.src}`);
|
110
111
|
}
|
111
|
-
return callFetch(opts.mock)(
|
112
|
+
return callFetch(opts.mock)(urlToFetch.asURL());
|
112
113
|
});
|
113
114
|
if (rRes.isErr()) {
|
114
115
|
if (baseUrl.src === "import.meta.url") {
|
115
116
|
// eslint-disable-next-line no-console
|
116
|
-
console.warn(`fetch failed for: ${
|
117
|
+
console.warn(`fetch failed for: ${urlToFetch.toString()}`);
|
117
118
|
return loadAssetReal(fallBackBaseUrl(opts), localPath, opts);
|
118
119
|
}
|
119
120
|
return Result.Err(rRes);
|
package/src/logger.ts
CHANGED
@@ -4,8 +4,9 @@ import { bin2string } from "./bin2text.js";
|
|
4
4
|
import { Option } from "./option.js";
|
5
5
|
import { Result } from "./result.js";
|
6
6
|
import { TxtEnDecoder, TxtEnDecoderSingleton } from "./txt-en-decoder.js";
|
7
|
-
import { CoerceURI
|
7
|
+
import { CoerceURI } from "./uri.js";
|
8
8
|
import { isJSON } from "./is-json.js";
|
9
|
+
import { ReadonlyURL } from "./mutable-url.js";
|
9
10
|
|
10
11
|
export const Level = {
|
11
12
|
WARN: "warn",
|
@@ -85,7 +86,7 @@ function logValueInternal(val: LogValueArg, ctx: LogValueStateInternal): LogValu
|
|
85
86
|
return logValueInternal(ret, ctx);
|
86
87
|
}
|
87
88
|
}
|
88
|
-
const resIsURI =
|
89
|
+
const resIsURI = ReadonlyURL.from(val);
|
89
90
|
if (resIsURI.isOk()) {
|
90
91
|
return new LogValue(() => resIsURI.Ok().toString());
|
91
92
|
}
|
@@ -0,0 +1,365 @@
|
|
1
|
+
import { exception2Result, Result } from "./result.js";
|
2
|
+
import { hasHostPartProtocols } from "./uri.js";
|
3
|
+
|
4
|
+
// due to that the System URL class is has a strange behavior
|
5
|
+
// on different platforms, we need to implement our own URL class
|
6
|
+
const customInspectSymbol = Symbol.for("nodejs.util.inspect.custom");
|
7
|
+
|
8
|
+
const urlRegex = /^([a-z][a-z0-9_-]*):\/\/[^:]*$/i;
|
9
|
+
|
10
|
+
// there are deno which does not have URLSearchParams.entries() in types
|
11
|
+
export function* URLSearchParamsEntries(src: URLSearchParams): IterableIterator<[string, string]> {
|
12
|
+
const entries: [string, string][] = [];
|
13
|
+
src.forEach((v, k) => {
|
14
|
+
entries.push([k, v]);
|
15
|
+
});
|
16
|
+
for (const [key, value] of entries) {
|
17
|
+
yield [key, value];
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
export class ReadonlyURL extends URL {
|
22
|
+
protected readonly _sysURL: URL;
|
23
|
+
// private readonly _urlStr: string;
|
24
|
+
|
25
|
+
protected _protocol: string;
|
26
|
+
protected _pathname: string;
|
27
|
+
protected _hasHostpart: boolean;
|
28
|
+
|
29
|
+
static readonly fromThrow = (urlStr: string): ReadonlyURL => {
|
30
|
+
return new ReadonlyURL(urlStr);
|
31
|
+
};
|
32
|
+
|
33
|
+
static from(urlStr: string): Result<ReadonlyURL> {
|
34
|
+
if (urlRegex.test(urlStr)) {
|
35
|
+
return exception2Result(() => new ReadonlyURL(urlStr));
|
36
|
+
}
|
37
|
+
return Result.Err(`Invalid URL: ${urlStr}`);
|
38
|
+
}
|
39
|
+
|
40
|
+
protected constructor(urlStr: string) {
|
41
|
+
super("defect://does.not.exist");
|
42
|
+
const partedURL = urlStr.split(":");
|
43
|
+
this._hasHostpart = hasHostPartProtocols.has(partedURL[0]);
|
44
|
+
let hostPartUrl = ["http", ...partedURL.slice(1)].join(":");
|
45
|
+
if (!this._hasHostpart) {
|
46
|
+
const pathname = hostPartUrl.replace(/http:\/\/[/]*/, "").replace(/[#?].*$/, "");
|
47
|
+
hostPartUrl = hostPartUrl.replace(/http:\/\//, `http://localhost/${pathname}`);
|
48
|
+
}
|
49
|
+
try {
|
50
|
+
this._sysURL = new URL(hostPartUrl);
|
51
|
+
} catch (ie) {
|
52
|
+
const e = ie as Error;
|
53
|
+
e.message = `${e.message} for URL: ${urlStr}`;
|
54
|
+
throw e;
|
55
|
+
}
|
56
|
+
this._protocol = `${partedURL[0]}:`; // this._sysURL.protocol.replace(new RegExp("^cement-"), "");
|
57
|
+
if (this._hasHostpart) {
|
58
|
+
this._pathname = this._sysURL.pathname;
|
59
|
+
} else {
|
60
|
+
this._pathname = urlStr.replace(new RegExp(`^${this._protocol}//`), "").replace(/[#?].*$/, "");
|
61
|
+
}
|
62
|
+
// this.hash = this._sysURL.hash;
|
63
|
+
}
|
64
|
+
|
65
|
+
set origin(h: string) {
|
66
|
+
throw new Error("origin is readonly");
|
67
|
+
}
|
68
|
+
|
69
|
+
override get href(): string {
|
70
|
+
return this.toString();
|
71
|
+
}
|
72
|
+
|
73
|
+
set href(h: string) {
|
74
|
+
throw new Error("href is readonly");
|
75
|
+
}
|
76
|
+
|
77
|
+
override get password(): string {
|
78
|
+
return this._sysURL.password;
|
79
|
+
}
|
80
|
+
|
81
|
+
set password(h: string) {
|
82
|
+
throw new Error("password is readonly");
|
83
|
+
}
|
84
|
+
|
85
|
+
override get username(): string {
|
86
|
+
return this._sysURL.username;
|
87
|
+
}
|
88
|
+
|
89
|
+
set username(h: string) {
|
90
|
+
throw new Error("username is readonly");
|
91
|
+
}
|
92
|
+
|
93
|
+
toJSON(): string {
|
94
|
+
return this.toString();
|
95
|
+
}
|
96
|
+
|
97
|
+
[customInspectSymbol](): string {
|
98
|
+
// make node inspect to show the URL and not crash if URI is not http/https/file
|
99
|
+
return this.toString();
|
100
|
+
}
|
101
|
+
|
102
|
+
clone(): ReadonlyURL {
|
103
|
+
return this;
|
104
|
+
}
|
105
|
+
|
106
|
+
// Hash getter and setter
|
107
|
+
override get hash(): string {
|
108
|
+
return this._sysURL.hash;
|
109
|
+
}
|
110
|
+
|
111
|
+
set hash(h: string) {
|
112
|
+
throw new Error("hash is readonly");
|
113
|
+
}
|
114
|
+
|
115
|
+
// Host getter and setter
|
116
|
+
get host(): string {
|
117
|
+
if (!this._hasHostpart) {
|
118
|
+
throw new Error(
|
119
|
+
`you can use hostname only if protocol is ${this.toString()} ${JSON.stringify(Array.from(hasHostPartProtocols.keys()))}`,
|
120
|
+
);
|
121
|
+
}
|
122
|
+
return this._sysURL.host;
|
123
|
+
}
|
124
|
+
|
125
|
+
set host(h: string) {
|
126
|
+
throw new Error("host is readonly");
|
127
|
+
}
|
128
|
+
|
129
|
+
// Hostname getter and setter
|
130
|
+
get hostname(): string {
|
131
|
+
if (!this._hasHostpart) {
|
132
|
+
throw new Error(`you can use hostname only if protocol is ${JSON.stringify(Array.from(hasHostPartProtocols.keys()))}`);
|
133
|
+
}
|
134
|
+
return this._sysURL.hostname;
|
135
|
+
}
|
136
|
+
|
137
|
+
set hostname(h: string) {
|
138
|
+
throw new Error("hostname is readonly");
|
139
|
+
}
|
140
|
+
|
141
|
+
// Pathname getter and setter
|
142
|
+
override get pathname(): string {
|
143
|
+
return this._pathname;
|
144
|
+
}
|
145
|
+
|
146
|
+
set pathname(h: string) {
|
147
|
+
throw new Error("pathname is readonly");
|
148
|
+
}
|
149
|
+
|
150
|
+
// Port getter and setter
|
151
|
+
override get port(): string {
|
152
|
+
if (!this._hasHostpart) {
|
153
|
+
throw new Error(`you can use hostname only if protocol is ${JSON.stringify(Array.from(hasHostPartProtocols.keys()))}`);
|
154
|
+
}
|
155
|
+
return this._sysURL.port;
|
156
|
+
}
|
157
|
+
|
158
|
+
set port(h: string) {
|
159
|
+
throw new Error("port is readonly");
|
160
|
+
}
|
161
|
+
|
162
|
+
// Protocol getter and setter
|
163
|
+
override get protocol(): string {
|
164
|
+
return this._protocol;
|
165
|
+
}
|
166
|
+
|
167
|
+
set protocol(h: string) {
|
168
|
+
throw new Error("protocol is readonly");
|
169
|
+
}
|
170
|
+
|
171
|
+
// Search getter and setter
|
172
|
+
get search(): string {
|
173
|
+
let search = "";
|
174
|
+
if (this._sysURL.searchParams.size) {
|
175
|
+
for (const [key, value] of Array.from(URLSearchParamsEntries(this._sysURL.searchParams)).sort((a, b) =>
|
176
|
+
a[0].localeCompare(b[0]),
|
177
|
+
)) {
|
178
|
+
search += `${!search.length ? "?" : "&"}${key}=${encodeURIComponent(value)}`;
|
179
|
+
}
|
180
|
+
}
|
181
|
+
return search;
|
182
|
+
}
|
183
|
+
|
184
|
+
set search(h: string) {
|
185
|
+
throw new Error("search is readonly");
|
186
|
+
}
|
187
|
+
|
188
|
+
// SearchParams getter and setter
|
189
|
+
override get searchParams(): URLSearchParams {
|
190
|
+
return this._sysURL.searchParams;
|
191
|
+
}
|
192
|
+
|
193
|
+
set searchParams(h: URLSearchParams) {
|
194
|
+
throw new Error("searchParams is readonly");
|
195
|
+
}
|
196
|
+
|
197
|
+
override toString(): string {
|
198
|
+
const search = this.search;
|
199
|
+
let hostpart = "";
|
200
|
+
if (this._hasHostpart) {
|
201
|
+
hostpart = this._sysURL.hostname;
|
202
|
+
if (this._sysURL.port) {
|
203
|
+
hostpart += `:${this._sysURL.port}`;
|
204
|
+
}
|
205
|
+
if (!this._pathname.startsWith("/")) {
|
206
|
+
hostpart += "/";
|
207
|
+
}
|
208
|
+
}
|
209
|
+
if (this.username || this.password) {
|
210
|
+
hostpart = `${this.username}:${this.password}@${hostpart}`;
|
211
|
+
}
|
212
|
+
return `${this._protocol}//${hostpart}${this._pathname}${search}${this.hash}`;
|
213
|
+
}
|
214
|
+
}
|
215
|
+
|
216
|
+
export class WritableURL extends ReadonlyURL {
|
217
|
+
// override readonly hash: string;
|
218
|
+
|
219
|
+
static readonly fromThrow = (urlStr: string): WritableURL => {
|
220
|
+
return new WritableURL(urlStr);
|
221
|
+
};
|
222
|
+
|
223
|
+
static from(urlStr: string): Result<WritableURL> {
|
224
|
+
if (urlRegex.test(urlStr)) {
|
225
|
+
return exception2Result(() => new WritableURL(urlStr));
|
226
|
+
}
|
227
|
+
return Result.Err(`Invalid URL: ${urlStr}`);
|
228
|
+
}
|
229
|
+
|
230
|
+
private constructor(urlStr: string) {
|
231
|
+
super(urlStr);
|
232
|
+
}
|
233
|
+
|
234
|
+
override toJSON(): string {
|
235
|
+
return this.toString();
|
236
|
+
}
|
237
|
+
|
238
|
+
[customInspectSymbol](): string {
|
239
|
+
// make node inspect to show the URL and not crash if URI is not http/https/file
|
240
|
+
return this.toString();
|
241
|
+
}
|
242
|
+
|
243
|
+
clone(): WritableURL {
|
244
|
+
return new WritableURL(this.toString());
|
245
|
+
}
|
246
|
+
|
247
|
+
set origin(_h: string) {
|
248
|
+
throw new Error("don't use origin");
|
249
|
+
}
|
250
|
+
|
251
|
+
get href(): string {
|
252
|
+
return super.href;
|
253
|
+
}
|
254
|
+
|
255
|
+
set href(h: string) {
|
256
|
+
throw new Error("don't use href");
|
257
|
+
}
|
258
|
+
|
259
|
+
override get password(): string {
|
260
|
+
return super.password;
|
261
|
+
}
|
262
|
+
|
263
|
+
set password(h: string) {
|
264
|
+
this._sysURL.password = h;
|
265
|
+
}
|
266
|
+
|
267
|
+
override get username(): string {
|
268
|
+
return super.username;
|
269
|
+
}
|
270
|
+
|
271
|
+
set username(h: string) {
|
272
|
+
this._sysURL.username = h;
|
273
|
+
}
|
274
|
+
|
275
|
+
// Hash getter and setter
|
276
|
+
override get hash(): string {
|
277
|
+
return super.hash;
|
278
|
+
}
|
279
|
+
|
280
|
+
override set hash(h: string) {
|
281
|
+
this._sysURL.hash = h;
|
282
|
+
}
|
283
|
+
|
284
|
+
// Host getter and setter
|
285
|
+
override get host(): string {
|
286
|
+
return super.host;
|
287
|
+
}
|
288
|
+
|
289
|
+
override set host(h: string) {
|
290
|
+
this._sysURL.host = h;
|
291
|
+
}
|
292
|
+
|
293
|
+
// Hostname getter and setter
|
294
|
+
override get hostname(): string {
|
295
|
+
return super.hostname;
|
296
|
+
}
|
297
|
+
|
298
|
+
override set hostname(h: string) {
|
299
|
+
if (!this._hasHostpart) {
|
300
|
+
throw new Error(`you can use hostname only if protocol is ${JSON.stringify(Array.from(hasHostPartProtocols.keys()))}`);
|
301
|
+
}
|
302
|
+
this._sysURL.hostname = h;
|
303
|
+
}
|
304
|
+
|
305
|
+
// Pathname getter and setter
|
306
|
+
override get pathname(): string {
|
307
|
+
return super.pathname;
|
308
|
+
}
|
309
|
+
|
310
|
+
override set pathname(p: string) {
|
311
|
+
this._pathname = p;
|
312
|
+
}
|
313
|
+
|
314
|
+
// Port getter and setter
|
315
|
+
override get port(): string {
|
316
|
+
return super.port;
|
317
|
+
}
|
318
|
+
|
319
|
+
override set port(p: string) {
|
320
|
+
if (!this._hasHostpart) {
|
321
|
+
throw new Error(`you can use port only if protocol is ${JSON.stringify(Array.from(hasHostPartProtocols.keys()))}`);
|
322
|
+
}
|
323
|
+
this._sysURL.port = p;
|
324
|
+
}
|
325
|
+
|
326
|
+
// Protocol getter and setter
|
327
|
+
override get protocol(): string {
|
328
|
+
return super.protocol;
|
329
|
+
}
|
330
|
+
|
331
|
+
override set protocol(p: string) {
|
332
|
+
if (!p.endsWith(":")) {
|
333
|
+
p = `${p}:`;
|
334
|
+
}
|
335
|
+
this._protocol = p;
|
336
|
+
}
|
337
|
+
|
338
|
+
// Search getter and setter
|
339
|
+
override get search(): string {
|
340
|
+
return super.search;
|
341
|
+
}
|
342
|
+
|
343
|
+
override set search(h: string) {
|
344
|
+
this._sysURL.search = h;
|
345
|
+
}
|
346
|
+
|
347
|
+
// SearchParams getter and setter
|
348
|
+
override get searchParams(): URLSearchParams {
|
349
|
+
return super.searchParams;
|
350
|
+
}
|
351
|
+
|
352
|
+
override set searchParams(h: URLSearchParams) {
|
353
|
+
const toDel = new Set<string>();
|
354
|
+
for (const [key] of URLSearchParamsEntries(this._sysURL.searchParams)) {
|
355
|
+
toDel.add(key);
|
356
|
+
}
|
357
|
+
for (const [key, value] of URLSearchParamsEntries(h)) {
|
358
|
+
this._sysURL.searchParams.set(key, value);
|
359
|
+
toDel.delete(key);
|
360
|
+
}
|
361
|
+
for (const key of toDel) {
|
362
|
+
this._sysURL.searchParams.delete(key);
|
363
|
+
}
|
364
|
+
}
|
365
|
+
}
|