@api-client/core 0.3.4 → 0.3.7

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.
Files changed (109) hide show
  1. package/build/browser.d.ts +6 -0
  2. package/build/browser.js +15 -0
  3. package/build/browser.js.map +1 -1
  4. package/build/index.d.ts +14 -2
  5. package/build/index.js +26 -2
  6. package/build/index.js.map +1 -1
  7. package/build/src/lib/calculators/DataCalculator.d.ts +27 -0
  8. package/build/src/lib/calculators/DataCalculator.js +88 -0
  9. package/build/src/lib/calculators/DataCalculator.js.map +1 -0
  10. package/build/src/lib/fs/Fs.d.ts +52 -0
  11. package/build/src/lib/fs/Fs.js +245 -0
  12. package/build/src/lib/fs/Fs.js.map +1 -0
  13. package/build/src/lib/parsers/UrlEncoder.d.ts +51 -0
  14. package/build/src/lib/parsers/UrlEncoder.js +74 -0
  15. package/build/src/lib/parsers/UrlEncoder.js.map +1 -0
  16. package/build/src/lib/parsers/UrlParser.d.ts +104 -0
  17. package/build/src/lib/parsers/UrlParser.js +189 -0
  18. package/build/src/lib/parsers/UrlParser.js.map +1 -0
  19. package/build/src/lib/parsers/UrlValueParser.d.ts +92 -0
  20. package/build/src/lib/parsers/UrlValueParser.js +172 -0
  21. package/build/src/lib/parsers/UrlValueParser.js.map +1 -0
  22. package/build/src/lib/timers/Timers.d.ts +5 -0
  23. package/build/src/lib/timers/Timers.js +10 -0
  24. package/build/src/lib/timers/Timers.js.map +1 -0
  25. package/build/src/mocking/ProjectMock.d.ts +13 -0
  26. package/build/src/mocking/ProjectMock.js +16 -0
  27. package/build/src/mocking/ProjectMock.js.map +1 -0
  28. package/build/src/mocking/lib/Request.d.ts +32 -0
  29. package/build/src/mocking/lib/Request.js +63 -0
  30. package/build/src/mocking/lib/Request.js.map +1 -0
  31. package/build/src/mocking/lib/Response.d.ts +33 -0
  32. package/build/src/mocking/lib/Response.js +79 -0
  33. package/build/src/mocking/lib/Response.js.map +1 -0
  34. package/build/src/models/ErrorResponse.d.ts +5 -4
  35. package/build/src/models/ErrorResponse.js +18 -5
  36. package/build/src/models/ErrorResponse.js.map +1 -1
  37. package/build/src/models/SerializableError.d.ts +30 -0
  38. package/build/src/models/SerializableError.js +63 -0
  39. package/build/src/models/SerializableError.js.map +1 -0
  40. package/build/src/runtime/http-engine/ArcEngine.js +8 -4
  41. package/build/src/runtime/http-engine/ArcEngine.js.map +1 -1
  42. package/build/src/runtime/http-engine/HttpEngine.d.ts +3 -3
  43. package/build/src/runtime/http-engine/HttpEngine.js +3 -3
  44. package/build/src/runtime/http-engine/HttpEngine.js.map +1 -1
  45. package/build/src/runtime/http-engine/NodeEngine.js +9 -4
  46. package/build/src/runtime/http-engine/NodeEngine.js.map +1 -1
  47. package/build/src/runtime/http-engine/NodeEngineDirect.js +8 -2
  48. package/build/src/runtime/http-engine/NodeEngineDirect.js.map +1 -1
  49. package/build/src/runtime/node/BaseRunner.d.ts +21 -0
  50. package/build/src/runtime/node/BaseRunner.js +27 -0
  51. package/build/src/runtime/node/BaseRunner.js.map +1 -0
  52. package/build/src/runtime/node/ProjectParallelRunner.d.ts +81 -0
  53. package/build/src/runtime/node/ProjectParallelRunner.js +173 -0
  54. package/build/src/runtime/node/ProjectParallelRunner.js.map +1 -0
  55. package/build/src/runtime/node/ProjectRequestRunner.d.ts +125 -0
  56. package/build/src/runtime/node/ProjectRequestRunner.js +185 -0
  57. package/build/src/runtime/node/ProjectRequestRunner.js.map +1 -0
  58. package/build/src/runtime/node/ProjectRunner.d.ts +166 -64
  59. package/build/src/runtime/node/ProjectRunner.js +191 -139
  60. package/build/src/runtime/node/ProjectRunner.js.map +1 -1
  61. package/build/src/runtime/node/ProjectRunnerWorker.d.ts +1 -0
  62. package/build/src/runtime/node/ProjectRunnerWorker.js +58 -0
  63. package/build/src/runtime/node/ProjectRunnerWorker.js.map +1 -0
  64. package/build/src/runtime/node/ProjectSerialRunner.d.ts +11 -0
  65. package/build/src/runtime/node/ProjectSerialRunner.js +34 -0
  66. package/build/src/runtime/node/ProjectSerialRunner.js.map +1 -0
  67. package/build/src/runtime/reporters/ProjectRunCliReporter.d.ts +7 -0
  68. package/build/src/runtime/reporters/ProjectRunCliReporter.js +73 -0
  69. package/build/src/runtime/reporters/ProjectRunCliReporter.js.map +1 -0
  70. package/build/src/runtime/reporters/Reporter.d.ts +62 -0
  71. package/build/src/runtime/reporters/Reporter.js +98 -0
  72. package/build/src/runtime/reporters/Reporter.js.map +1 -0
  73. package/build/src/testing/TestCliHelper.d.ts +29 -0
  74. package/build/src/testing/TestCliHelper.js +80 -0
  75. package/build/src/testing/TestCliHelper.js.map +1 -0
  76. package/build/src/testing/getPort.d.ts +52 -0
  77. package/build/src/testing/getPort.js +169 -0
  78. package/build/src/testing/getPort.js.map +1 -0
  79. package/package.json +2 -1
  80. package/src/lib/calculators/DataCalculator.ts +91 -0
  81. package/src/lib/fs/Fs.ts +258 -0
  82. package/src/lib/parsers/UrlEncoder.ts +74 -0
  83. package/src/lib/parsers/UrlParser.ts +201 -0
  84. package/src/lib/parsers/UrlValueParser.ts +211 -0
  85. package/src/lib/timers/Timers.ts +9 -0
  86. package/src/mocking/LegacyInterfaces.ts +1 -1
  87. package/src/mocking/ProjectMock.ts +20 -0
  88. package/src/mocking/lib/Request.ts +85 -0
  89. package/src/mocking/lib/Response.ts +101 -0
  90. package/src/models/ErrorResponse.ts +20 -8
  91. package/src/models/SerializableError.ts +80 -0
  92. package/src/runtime/http-engine/ArcEngine.ts +8 -4
  93. package/src/runtime/http-engine/HttpEngine.ts +5 -5
  94. package/src/runtime/http-engine/NodeEngine.ts +10 -5
  95. package/src/runtime/http-engine/NodeEngineDirect.ts +9 -3
  96. package/src/runtime/node/BaseRunner.ts +29 -0
  97. package/src/runtime/node/ProjectParallelRunner.ts +234 -0
  98. package/src/runtime/node/ProjectRequestRunner.ts +281 -0
  99. package/src/runtime/node/ProjectRunner.ts +281 -182
  100. package/src/runtime/node/ProjectRunnerWorker.ts +62 -0
  101. package/src/runtime/node/ProjectSerialRunner.ts +36 -0
  102. package/src/runtime/reporters/ProjectRunCliReporter.ts +79 -0
  103. package/src/runtime/reporters/Reporter.ts +142 -0
  104. package/src/testing/TestCliHelper.ts +87 -0
  105. package/src/testing/getPort.ts +212 -0
  106. package/build/src/runtime/http-engine/Errors.d.ts +0 -10
  107. package/build/src/runtime/http-engine/Errors.js +0 -14
  108. package/build/src/runtime/http-engine/Errors.js.map +0 -1
  109. package/src/runtime/http-engine/Errors.ts +0 -13
@@ -0,0 +1,169 @@
1
+ import net from 'net';
2
+ import os from 'os';
3
+ class Locked extends Error {
4
+ constructor(port = 0) {
5
+ super(`${port} is locked`);
6
+ }
7
+ }
8
+ const lockedPorts = {
9
+ old: new Set(),
10
+ young: new Set(),
11
+ };
12
+ // On this interval, the old locked ports are discarded,
13
+ // the young locked ports are moved to old locked ports,
14
+ // and a new young set for locked ports are created.
15
+ const releaseOldLockedPortsIntervalMs = 1000 * 15;
16
+ // Lazily create interval on first use
17
+ let interval;
18
+ const getLocalHosts = () => {
19
+ const interfaces = os.networkInterfaces();
20
+ // Add undefined value for createServer function to use default host,
21
+ // and default IPv4 host in case createServer defaults to IPv6.
22
+ const results = new Set([undefined, '0.0.0.0']);
23
+ for (const _interface of Object.values(interfaces)) {
24
+ if (_interface) {
25
+ for (const config of _interface) {
26
+ results.add(config.address);
27
+ }
28
+ }
29
+ }
30
+ return results;
31
+ };
32
+ const checkAvailablePort = (options) => new Promise((resolve, reject) => {
33
+ const server = net.createServer();
34
+ server.unref();
35
+ server.on('error', reject);
36
+ server.listen(options, () => {
37
+ const { port } = server.address();
38
+ server.close(() => {
39
+ resolve(port);
40
+ });
41
+ });
42
+ });
43
+ const getAvailablePort = async (options, hosts) => {
44
+ if (options.host || options.port === 0) {
45
+ return checkAvailablePort(options);
46
+ }
47
+ for (const host of hosts) {
48
+ try {
49
+ await checkAvailablePort({ port: options.port, host }); // eslint-disable-line no-await-in-loop
50
+ }
51
+ catch (error) {
52
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
53
+ const typed = error;
54
+ if (!['EADDRNOTAVAIL', 'EINVAL'].includes(typed.code)) {
55
+ throw typed;
56
+ }
57
+ }
58
+ }
59
+ return options.port;
60
+ };
61
+ const portCheckSequence = function* (ports) {
62
+ if (ports) {
63
+ yield* ports;
64
+ }
65
+ yield 0; // Fall back to 0 if anything else failed
66
+ };
67
+ /**
68
+ Get an available TCP port number.
69
+
70
+ @returns Port number.
71
+
72
+ @example
73
+ ```
74
+ import getPort from 'get-port';
75
+
76
+ console.log(await getPort());
77
+ //=> 51402
78
+
79
+ // Pass in a preferred port
80
+ console.log(await getPort({port: 3000}));
81
+ // Will use 3000 if available, otherwise fall back to a random port
82
+
83
+ // Pass in an array of preferred ports
84
+ console.log(await getPort({port: [3000, 3001, 3002]}));
85
+ // Will use any element in the preferred ports array if available, otherwise fall back to a random port
86
+ ```
87
+ */
88
+ export async function getPort(options) {
89
+ let ports = [];
90
+ if (options) {
91
+ if (typeof options.port === 'number') {
92
+ ports = [options.port];
93
+ }
94
+ else if (options.port) {
95
+ ports = options.port;
96
+ }
97
+ }
98
+ if (interval === undefined) {
99
+ interval = setInterval(() => {
100
+ lockedPorts.old = lockedPorts.young;
101
+ lockedPorts.young = new Set();
102
+ }, releaseOldLockedPortsIntervalMs);
103
+ // Does not exist in some environments (Electron, Jest jsdom env, browser, etc).
104
+ if (interval.unref) {
105
+ interval.unref();
106
+ }
107
+ }
108
+ const hosts = getLocalHosts();
109
+ for (const port of portCheckSequence(ports)) {
110
+ try {
111
+ let availablePort = await getAvailablePort({ ...options, port }, hosts); // eslint-disable-line no-await-in-loop
112
+ while (lockedPorts.old.has(availablePort) || lockedPorts.young.has(availablePort)) {
113
+ if (port !== 0) {
114
+ throw new Locked(port);
115
+ }
116
+ availablePort = await getAvailablePort({ ...options, port }, hosts); // eslint-disable-line no-await-in-loop
117
+ }
118
+ lockedPorts.young.add(availablePort);
119
+ if (!availablePort) {
120
+ throw new Error('No available ports found');
121
+ }
122
+ return availablePort;
123
+ }
124
+ catch (error) {
125
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
126
+ const typed = error;
127
+ if (!['EADDRINUSE', 'EACCES'].includes(typed.code) && !(typed instanceof Locked)) {
128
+ throw error;
129
+ }
130
+ }
131
+ }
132
+ throw new Error('No available ports found');
133
+ }
134
+ /**
135
+ Generate port numbers in the given range `from`...`to`.
136
+
137
+ @param from - The first port of the range. Must be in the range `1024`...`65535`.
138
+ @param to - The last port of the range. Must be in the range `1024`...`65535` and must be greater than `from`.
139
+ @returns The port numbers in the range.
140
+
141
+ @example
142
+ ```
143
+ import getPort, {portNumbers} from 'get-port';
144
+
145
+ console.log(await getPort({port: portNumbers(3000, 3100)}));
146
+ // Will use any port from 3000 to 3100, otherwise fall back to a random port
147
+ ```
148
+ */
149
+ export function portNumbers(from, to) {
150
+ if (!Number.isInteger(from) || !Number.isInteger(to)) {
151
+ throw new TypeError('`from` and `to` must be integer numbers');
152
+ }
153
+ if (from < 1024 || from > 65_535) {
154
+ throw new RangeError('`from` must be between 1024 and 65535');
155
+ }
156
+ if (to < 1024 || to > 65_536) {
157
+ throw new RangeError('`to` must be between 1024 and 65536');
158
+ }
159
+ if (to < from) {
160
+ throw new RangeError('`to` must be greater than or equal to `from`');
161
+ }
162
+ const generator = function* (from, to) {
163
+ for (let port = from; port <= to; port++) {
164
+ yield port;
165
+ }
166
+ };
167
+ return generator(from, to);
168
+ }
169
+ //# sourceMappingURL=getPort.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getPort.js","sourceRoot":"","sources":["../../../src/testing/getPort.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@api-client/core",
3
3
  "description": "The ARC core client library. Works in NodeJS and in a ES enabled browser.",
4
- "version": "0.3.4",
4
+ "version": "0.3.7",
5
5
  "license": "Apache-2.0",
6
6
  "main": "build/index.js",
7
7
  "module": "build/index.js",
@@ -89,6 +89,7 @@
89
89
  "@metrichor/jmespath": "^0.3.1",
90
90
  "@pawel-up/jexl": "^3.0.0",
91
91
  "@xmldom/xmldom": "^0.8.1",
92
+ "console-table-printer": "^2.10.0",
92
93
  "form-data": "^4.0.0",
93
94
  "json8-patch": "^1.0.6",
94
95
  "ws": "^8.5.0",
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Computations related to the data like size.
3
+ */
4
+ export class DataCalculator {
5
+ /**
6
+ * Computes size in the nearest units
7
+ */
8
+ static bytesToSize(bytes: number, decimals = 2): string {
9
+ if (bytes === 0) {
10
+ return '0 Bytes';
11
+ }
12
+
13
+ const k = 1024;
14
+ const dm = decimals < 0 ? 0 : decimals;
15
+ const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
16
+
17
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
18
+ const result = parseFloat((bytes / k**i).toFixed(dm));
19
+ return `${result} ${sizes[i]}`;
20
+ }
21
+
22
+ /**
23
+ * Calculates size of the string
24
+ * @param str A string to compute size from.
25
+ * @returns The size of the string.
26
+ */
27
+ stringSize(str: string): number {
28
+ if (!str || !str.length || typeof str !== 'string') {
29
+ return 0;
30
+ }
31
+ let s = str.length;
32
+ for (let i = str.length - 1; i >= 0; i--) {
33
+ const code = str.charCodeAt(i);
34
+ if (code > 0x7f && code <= 0x7ff) {
35
+ s++;
36
+ } else if (code > 0x7ff && code <= 0xffff) {
37
+ /* istanbul ignore next */
38
+ s += 2;
39
+ }
40
+ /* istanbul ignore if */
41
+ if (code >= 0xDC00 && code <= 0xDFFF) {
42
+ i--; // trail surrogate
43
+ }
44
+ }
45
+ return s;
46
+ }
47
+
48
+ /**
49
+ * @param data The size of the form data
50
+ * @returns The size of the form data
51
+ */
52
+ async formDataSize(data: FormData): Promise<number> {
53
+ if (typeof Request === 'undefined') {
54
+ return 0;
55
+ }
56
+ const request = new Request('/', {
57
+ method: 'POST',
58
+ body: data,
59
+ });
60
+ if (!request.arrayBuffer) {
61
+ return 0;
62
+ }
63
+ const buffer = await request.arrayBuffer();
64
+ return buffer.byteLength;
65
+ }
66
+
67
+ /**
68
+ * Computes size of the payload.
69
+ *
70
+ * @param payload The payload to compute te size for
71
+ * @returns The size of the payload
72
+ */
73
+ async payloadSize(payload: unknown): Promise<number> {
74
+ if (!payload) {
75
+ return 0;
76
+ }
77
+ if (payload instanceof ArrayBuffer) {
78
+ return payload.byteLength;
79
+ }
80
+ if (typeof Buffer !== 'undefined' && payload instanceof Buffer) {
81
+ return payload.byteLength;
82
+ }
83
+ if (payload instanceof Blob) {
84
+ return payload.size;
85
+ }
86
+ if (payload instanceof FormData) {
87
+ return this.formDataSize(payload);
88
+ }
89
+ return this.stringSize(String(payload));
90
+ }
91
+ }
@@ -0,0 +1,258 @@
1
+ import { writeFile, mkdir, rm, readdir, stat, access, readFile, copyFile as fsCopyFile } from 'fs/promises';
2
+ import { constants } from 'fs';
3
+ import { join, dirname } from 'path';
4
+
5
+ export interface JsonReadOptions {
6
+ /**
7
+ * Whether it should throw an error when a reading error occurs.
8
+ */
9
+ throws?: boolean;
10
+ }
11
+
12
+ // function statPromise(filePath: string): Promise<fsSync.Stats> {
13
+ // return new Promise((resolve, reject) => {
14
+ // fsSync.stat(filePath, (err, stats) => {
15
+ // if (err) {
16
+ // reject(err);
17
+ // } else {
18
+ // resolve(stats);
19
+ // }
20
+ // });
21
+ // });
22
+ // }
23
+
24
+ /**
25
+ * Checks whether a file exists in the location.
26
+ */
27
+ export async function pathExists(filePath: string): Promise<boolean> {
28
+ // return new Promise((resolve) => {
29
+ // fsSync.stat(filePath, (err, stats) => {
30
+ // if (err) {
31
+ // resolve(false);
32
+ // } else {
33
+ // resolve(true);
34
+ // }
35
+ // });
36
+ // });
37
+ try {
38
+ await stat(filePath);
39
+ return true;
40
+ } catch (e) {
41
+ return false;
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Tests a user's permissions for the file or directory specified by filePath.
47
+ * @param filePath The path to test
48
+ * @returns True when the path can be read by the current user.
49
+ */
50
+ export async function canRead(filePath: string): Promise<boolean> {
51
+ const exists = await pathExists(filePath);
52
+ if (!exists) {
53
+ return false;
54
+ }
55
+
56
+ // return new Promise((resolve) => {
57
+ // fsSync.access(filePath, constants.R_OK, (err) => {
58
+ // if (err) {
59
+ // resolve(false);
60
+ // } else {
61
+ // resolve(true);
62
+ // }
63
+ // });
64
+ // });
65
+ try {
66
+ await access(filePath, constants.R_OK);
67
+ return true;
68
+ } catch (e) {
69
+ return false;
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Tests a user's permissions for the file or directory specified by filePath.
75
+ * @param filePath The path to test
76
+ * @returns True when the path can be written to by the current user.
77
+ */
78
+ export async function canWrite(filePath: string): Promise<boolean> {
79
+ const exists = await pathExists(filePath);
80
+ if (!exists) {
81
+ return false;
82
+ }
83
+ // return new Promise((resolve) => {
84
+ // fsSync.access(filePath, constants.W_OK, (err) => {
85
+ // if (err) {
86
+ // resolve(false);
87
+ // } else {
88
+ // resolve(true);
89
+ // }
90
+ // });
91
+ // });
92
+ try {
93
+ await access(filePath, constants.W_OK);
94
+ return true;
95
+ } catch (e) {
96
+ return false;
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Reads the contents of a JSON file.
102
+ *
103
+ * @param filePath The path to the JSON file to read.
104
+ * @returns The contents of the file. When `throws` options is not set and error occurs then it returns an empty file.
105
+ */
106
+ export async function readJson(filePath: string, opts: JsonReadOptions={}): Promise<unknown> {
107
+ const readable = await canRead(filePath);
108
+ if (!readable) {
109
+ if (opts.throws) {
110
+ throw new Error(`Unable to read file: ${filePath}. Access is denied.`);
111
+ }
112
+ return {};
113
+ }
114
+ // return new Promise((resolve, reject) => {
115
+ // fsSync.readFile(filePath, 'utf8', (err, contents) => {
116
+ // if (err) {
117
+ // reject(err);
118
+ // } else {
119
+ // let data = {};
120
+ // try {
121
+ // data = JSON.parse(contents);
122
+ // } catch (e) {
123
+ // if (opts.throws) {
124
+ // const err = new Error(`Invalid JSON contents for file: ${filePath}.`);
125
+ // reject(err);
126
+ // return;
127
+ // }
128
+ // }
129
+ // resolve(data);
130
+ // }
131
+ // });
132
+ // });
133
+ const contents = await readFile(filePath, 'utf8');
134
+ let data = {};
135
+ try {
136
+ data = JSON.parse(contents);
137
+ } catch (e) {
138
+ if (opts.throws) {
139
+ throw new Error(`Invalid JSON contents for file: ${filePath}.`);
140
+ }
141
+ }
142
+ return data;
143
+ }
144
+
145
+ /**
146
+ * Writes the contents to the file.
147
+ *
148
+ * @param filePath The file to write to. It replaces the contents.
149
+ * @param contents The contents to write.
150
+ */
151
+ export async function writeJson(filePath: string, contents: string|any): Promise<void> {
152
+ const destParent = dirname(filePath);
153
+ await ensureDir(destParent);
154
+ const parentWritable = await canWrite(destParent);
155
+ if (!parentWritable) {
156
+ throw new Error(`Unable to write to location: ${parentWritable}. Access is denied.`);
157
+ }
158
+ const data = typeof contents === 'string' ? contents : JSON.stringify(contents);
159
+ await writeFile(filePath, data);
160
+ }
161
+
162
+ /**
163
+ * Ensures the directory exists.
164
+ */
165
+ export async function ensureDir(dirPath: string): Promise<void> {
166
+ const readable = await canRead(dirPath);
167
+ if (readable) {
168
+ return;
169
+ }
170
+ await mkdir(dirPath, { recursive: true });
171
+ }
172
+
173
+ /**
174
+ * Removes contents of the directory, leaving the directory in the filesystem.
175
+ */
176
+ export async function emptyDir(dirPath: string): Promise<void> {
177
+ const exists = await pathExists(dirPath);
178
+ if (!exists) {
179
+ return;
180
+ }
181
+ const writeable = await canWrite(dirPath);
182
+ if (!writeable) {
183
+ throw new Error(`Unable to clear directory: ${dirPath}. Access is denied.`);
184
+ }
185
+ const items = await readdir(dirPath, 'utf8');
186
+ for (const item of items) {
187
+ const file = join(dirPath, item);
188
+ await rm(file, { recursive: true });
189
+ }
190
+ }
191
+
192
+ /**
193
+ * Copies a file
194
+ */
195
+ async function copyFile(source: string, dest: string): Promise<void> {
196
+ const destParent = dirname(dest);
197
+ await ensureDir(destParent);
198
+ await fsCopyFile(source, dest);
199
+ }
200
+
201
+ // /**
202
+ // * Copies a file
203
+ // * @param {string} source
204
+ // * @param {string} dest
205
+ // * @returns {Promise<void>}
206
+ // */
207
+ // async function copyFile(source, dest) {
208
+ // const destParent = dirname(dest);
209
+ // await ensureDir(destParent);
210
+ // return new Promise((resolve, reject) => {
211
+ // fsSync.copyFile(source, dest, (err) => {
212
+ // if (err) {
213
+ // reject(err);
214
+ // } else {
215
+ // resolve();
216
+ // }
217
+ // });
218
+ // });
219
+ // }
220
+
221
+ /**
222
+ * Copies a directory and its contents.
223
+ */
224
+ async function copyDirectory(source: string, dest: string): Promise<void> {
225
+ await ensureDir(dest);
226
+ // const entries = fsSync.readdirSync(source, { withFileTypes: true, encoding: 'utf8' });
227
+ const entries = await readdir(source, { withFileTypes: true, encoding: 'utf8' });
228
+ for (const entry of entries) {
229
+ const srcFile = join(source, entry.name);
230
+ const destFile = join(dest, entry.name);
231
+ const srcStat = await stat(srcFile);
232
+ if (srcStat.isDirectory()) {
233
+ await copyDirectory(srcFile, destFile);
234
+ } else {
235
+ await copyFile(srcFile, destFile);
236
+ }
237
+ }
238
+ }
239
+
240
+ /**
241
+ * Copies a file or a directory to the destination location.
242
+ * It creates the destination folder when missing.
243
+ *
244
+ * @param source The source file or folder.
245
+ * @param dest The destination file or folder.
246
+ */
247
+ export async function copy(source: string, dest: string): Promise<void> {
248
+ const existing = await pathExists(source);
249
+ if (!existing) {
250
+ throw new Error(`Specified path does not exist: ${source}`);
251
+ }
252
+ const srcStat = await stat(source);
253
+ if (srcStat.isDirectory()) {
254
+ await copyDirectory(source, dest);
255
+ } else {
256
+ await copyFile(source, dest);
257
+ }
258
+ }
@@ -0,0 +1,74 @@
1
+ export class UrlEncoder {
2
+ /**
3
+ * Returns a string where all characters that are not valid for a URL
4
+ * component have been escaped. The escaping of a character is done by
5
+ * converting it into its UTF-8 encoding and then encoding each of the
6
+ * resulting bytes as a %xx hexadecimal escape sequence.
7
+ * <p>
8
+ * Note: this method will convert any the space character into its escape
9
+ * short form, '+' rather than %20. It should therefore only be used for
10
+ * query-string parts.
11
+ *
12
+ * <p>
13
+ * The following character sets are <em>not</em> escaped by this method:
14
+ * <ul>
15
+ * <li>ASCII digits or letters</li>
16
+ * <li>ASCII punctuation characters:
17
+ *
18
+ * <pre>- _ . ! ~ * ' ( )</pre>
19
+ * </li>
20
+ * </ul>
21
+ * </p>
22
+ *
23
+ * <p>
24
+ * Notice that this method <em>does</em> encode the URL component delimiter
25
+ * characters:<blockquote>
26
+ *
27
+ * <pre>
28
+ * ; / ? : &amp; = + $ , #
29
+ * </pre>
30
+ *
31
+ * </blockquote>
32
+ * </p>
33
+ *
34
+ * @param str A string containing invalid URL characters
35
+ * @param replacePlus When set it replaces `%20` with `+`.
36
+ * @returns a string with all invalid URL characters escaped
37
+ */
38
+ static encodeQueryString(str: string, replacePlus?: boolean): string {
39
+ if (!str) {
40
+ return str;
41
+ }
42
+ // normalize
43
+ let result = str.toString().replace(/\r?\n/g, "\r\n");
44
+ // encode
45
+ result = encodeURIComponent(result);
46
+ if (replacePlus) {
47
+ // replace "%20" with "+" when needed
48
+ result = result.replace(/%20/g, "+");
49
+ }
50
+ return result;
51
+ }
52
+
53
+ /**
54
+ * Returns a string where all URL component escape sequences have been
55
+ * converted back to their original character representations.
56
+ *
57
+ * Note: this method will convert the space character escape short form, '+',
58
+ * into a space. It should therefore only be used for query-string parts.
59
+ *
60
+ * @param str A string containing encoded URL component sequences
61
+ * @param replacePlus When set it replaces `+` with `%20`.
62
+ * @returns string with no encoded URL component encoded sequences
63
+ */
64
+ static decodeQueryString(str: string, replacePlus?: boolean): string {
65
+ if (!str) {
66
+ return str;
67
+ }
68
+ let result = str;
69
+ if (replacePlus) {
70
+ result = str.replace(/\+/g, "%20");
71
+ }
72
+ return decodeURIComponent(result);
73
+ }
74
+ }