utilium 2.0.0-pre.2 → 2.1.0
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/dist/buffer.d.ts +1 -1
- package/dist/buffer.js +4 -5
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -2
- package/dist/string.d.ts +5 -0
- package/dist/string.js +21 -0
- package/eslint.shared.js +66 -0
- package/package.json +4 -10
- package/readme.md +0 -1
- package/dist/internal/primitives.d.ts +0 -99
- package/dist/internal/primitives.js +0 -98
- package/dist/internal/struct.d.ts +0 -78
- package/dist/internal/struct.js +0 -44
- package/dist/struct.d.ts +0 -42
- package/dist/struct.js +0 -204
- package/src/buffer.ts +0 -419
- package/src/cache.ts +0 -241
- package/src/checksum.ts +0 -22
- package/src/debugging.ts +0 -113
- package/src/dom.ts +0 -43
- package/src/fs.ts +0 -213
- package/src/index.ts +0 -12
- package/src/internal/primitives.ts +0 -135
- package/src/internal/struct.ts +0 -154
- package/src/list.ts +0 -150
- package/src/misc.ts +0 -80
- package/src/numbers.ts +0 -19
- package/src/objects.ts +0 -145
- package/src/random.ts +0 -36
- package/src/requests.ts +0 -225
- package/src/shell.ts +0 -133
- package/src/string.ts +0 -62
- package/src/struct.ts +0 -295
- package/src/types.ts +0 -277
- package/src/version.ts +0 -54
- package/tsconfig.json +0 -21
package/src/random.ts
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
export function randomFloat(min = 0, max = 1): number {
|
2
|
-
return Math.random() * (max - min) + min;
|
3
|
-
}
|
4
|
-
|
5
|
-
export function randomHex(length = 1): string {
|
6
|
-
let s = '';
|
7
|
-
for (let i = 0; i < length; i++) {
|
8
|
-
s += Math.floor(Math.random() * 16).toString(16);
|
9
|
-
}
|
10
|
-
return s;
|
11
|
-
}
|
12
|
-
|
13
|
-
export function randomBoolean(): boolean {
|
14
|
-
return !!Math.round(Math.random());
|
15
|
-
}
|
16
|
-
|
17
|
-
export function randomBinaryString(length = 1): string {
|
18
|
-
let b = '';
|
19
|
-
for (let i = 0; i < length; i++) {
|
20
|
-
b += Math.round(Math.random());
|
21
|
-
}
|
22
|
-
return b;
|
23
|
-
}
|
24
|
-
|
25
|
-
export function randomInt(min = 0, max = 1): number {
|
26
|
-
return Math.round(Math.random() * (max - min) + min);
|
27
|
-
}
|
28
|
-
|
29
|
-
/**
|
30
|
-
* Gets a random int, r, with the probability P(r) = (base)**r
|
31
|
-
* For example, with a probability of 1/2: P(1) = 1/2, P(2) = 1/4, etc.
|
32
|
-
* @param probability the probability
|
33
|
-
*/
|
34
|
-
export function getRandomIntWithRecursiveProbability(probability = 0.5): number {
|
35
|
-
return -Math.floor(Math.log(Math.random()) / Math.log(1 / probability));
|
36
|
-
}
|
package/src/requests.ts
DELETED
@@ -1,225 +0,0 @@
|
|
1
|
-
/* Utilities for `fetch` when using range requests. It also allows you to handle errors easier */
|
2
|
-
|
3
|
-
import * as cache from './cache.js';
|
4
|
-
|
5
|
-
// Compatibility
|
6
|
-
|
7
|
-
/** @deprecated Use `cache.Options` */
|
8
|
-
export type ResourceCacheOptions = cache.Options;
|
9
|
-
/** @deprecated Use `cache.Resource` */
|
10
|
-
export const ResourceCache = cache.Resource;
|
11
|
-
/** @deprecated Use `cache.Resource` */
|
12
|
-
export type ResourceCache = cache.Resource<string>;
|
13
|
-
/** @deprecated Use `cache.Range` */
|
14
|
-
export type CacheRange = cache.Range;
|
15
|
-
/** @deprecated Use `cache.Options` */
|
16
|
-
export type CacheOptions = cache.Options;
|
17
|
-
|
18
|
-
/* eslint-disable @typescript-eslint/only-throw-error */
|
19
|
-
|
20
|
-
/**
|
21
|
-
* @internal
|
22
|
-
*/
|
23
|
-
export const resourcesCache = new Map<string, cache.Resource<string> | undefined>();
|
24
|
-
|
25
|
-
export type Issue =
|
26
|
-
| { tag: 'status'; response: Response }
|
27
|
-
| { tag: 'buffer'; response: Response; message: string }
|
28
|
-
| { tag: 'fetch' | 'size'; message: string }
|
29
|
-
| Error;
|
30
|
-
|
31
|
-
/**
|
32
|
-
* @deprecated Use `Issue`
|
33
|
-
*/
|
34
|
-
export type RequestError = Issue;
|
35
|
-
|
36
|
-
interface Fetched<TBodyOptional extends boolean> {
|
37
|
-
response: Response;
|
38
|
-
data: false extends TBodyOptional ? Uint8Array : Uint8Array | undefined;
|
39
|
-
}
|
40
|
-
|
41
|
-
/**
|
42
|
-
* Wraps `fetch`
|
43
|
-
* @throws RequestError
|
44
|
-
*/
|
45
|
-
async function _fetch<const TBodyOptional extends boolean>(
|
46
|
-
input: RequestInfo,
|
47
|
-
init: RequestInit = {},
|
48
|
-
bodyOptional: TBodyOptional = false as TBodyOptional
|
49
|
-
): Promise<Fetched<TBodyOptional>> {
|
50
|
-
const response = await fetch(input, init).catch((error: Error) => {
|
51
|
-
throw { tag: 'fetch', message: error.message } satisfies Issue;
|
52
|
-
});
|
53
|
-
|
54
|
-
if (!response.ok) throw { tag: 'status', response } satisfies Issue;
|
55
|
-
|
56
|
-
const raw = await response.arrayBuffer().catch((error: Error) => {
|
57
|
-
if (bodyOptional) return;
|
58
|
-
throw { tag: 'buffer', response, message: error.message } satisfies Issue;
|
59
|
-
});
|
60
|
-
|
61
|
-
return { response, data: raw ? new Uint8Array(raw) : undefined } as Fetched<TBodyOptional>;
|
62
|
-
}
|
63
|
-
|
64
|
-
export interface Options extends cache.Options {
|
65
|
-
/** Optionally provide a function for logging warnings */
|
66
|
-
warn?(message: string): unknown;
|
67
|
-
}
|
68
|
-
|
69
|
-
/**
|
70
|
-
* @deprecated Use `Options`
|
71
|
-
*/
|
72
|
-
export type RequestOptions = Options;
|
73
|
-
|
74
|
-
export interface GetOptions extends Options {
|
75
|
-
/**
|
76
|
-
* When using range requests,
|
77
|
-
* a HEAD request must normally be used to determine the full size of the resource.
|
78
|
-
* This allows that request to be skipped
|
79
|
-
*/
|
80
|
-
size?: number;
|
81
|
-
|
82
|
-
/** The start of the range */
|
83
|
-
start?: number;
|
84
|
-
|
85
|
-
/** The end of the range */
|
86
|
-
end?: number;
|
87
|
-
}
|
88
|
-
|
89
|
-
/**
|
90
|
-
* Make a GET request without worrying about ranges
|
91
|
-
* @throws RequestError
|
92
|
-
*/
|
93
|
-
export async function get(url: string, options: GetOptions, init: RequestInit = {}): Promise<Uint8Array> {
|
94
|
-
const req = new Request(url, init);
|
95
|
-
|
96
|
-
// Request no using ranges
|
97
|
-
if (typeof options.start != 'number' || typeof options.end != 'number') {
|
98
|
-
const { data } = await _fetch(url, init);
|
99
|
-
new cache.Resource(url, data.byteLength, options, resourcesCache).add(data, 0);
|
100
|
-
return data;
|
101
|
-
}
|
102
|
-
|
103
|
-
// Range requests
|
104
|
-
|
105
|
-
if (typeof options.size != 'number') {
|
106
|
-
options.warn?.(url + ': Size not provided, an additional HEAD request is being made');
|
107
|
-
|
108
|
-
const { headers } = await fetch(req, { method: 'HEAD' });
|
109
|
-
const size = parseInt(headers.get('Content-Length') ?? '');
|
110
|
-
if (typeof size != 'number')
|
111
|
-
throw {
|
112
|
-
tag: 'size',
|
113
|
-
message: 'Response is missing content-length header and no size was provided',
|
114
|
-
} satisfies Issue;
|
115
|
-
options.size = size;
|
116
|
-
}
|
117
|
-
|
118
|
-
const { size, start, end } = options;
|
119
|
-
const resource = resourcesCache.get(url) ?? new cache.Resource(url, size, options, resourcesCache);
|
120
|
-
|
121
|
-
req.headers.set('If-Range', new Date().toUTCString());
|
122
|
-
|
123
|
-
for (const { start: from, end: to } of resource.missing(start, end)) {
|
124
|
-
const { data, response } = await _fetch(req, { headers: { Range: `bytes=${from}-${to}` } });
|
125
|
-
|
126
|
-
if (response.status == 206) {
|
127
|
-
resource.add(data, from);
|
128
|
-
continue;
|
129
|
-
}
|
130
|
-
|
131
|
-
// The first response doesn't have a "partial content" (206) status
|
132
|
-
options.warn?.(url + ': Remote does not support range requests with bytes. Falling back to full data.');
|
133
|
-
new cache.Resource(url, size, options, resourcesCache).add(data, 0);
|
134
|
-
return data.subarray(start, end);
|
135
|
-
}
|
136
|
-
|
137
|
-
// This ensures we get a single buffer with the entire requested range
|
138
|
-
resource.collect();
|
139
|
-
|
140
|
-
const region = resource.regionAt(start)!;
|
141
|
-
return region.data.subarray(start - region.offset, end - region.offset);
|
142
|
-
}
|
143
|
-
|
144
|
-
/**
|
145
|
-
* @deprecated Use `get`
|
146
|
-
*/
|
147
|
-
export const GET = get;
|
148
|
-
|
149
|
-
/**
|
150
|
-
* Synchronously gets a cached resource
|
151
|
-
* Assumes you pass valid start and end when using ranges
|
152
|
-
*/
|
153
|
-
export function getCached(url: string, options: GetOptions): { data?: Uint8Array; missing: cache.Range[] } {
|
154
|
-
const cache = resourcesCache.get(url);
|
155
|
-
|
156
|
-
/**
|
157
|
-
* @todo Make sure we have a size?
|
158
|
-
*/
|
159
|
-
if (!cache) {
|
160
|
-
if (options.size) return { data: new Uint8Array(0), missing: [{ start: 0, end: options.size ?? 0 }] };
|
161
|
-
options.warn?.(url + ': Size not provided and cache is empty, can not determine missing range');
|
162
|
-
return { data: undefined, missing: [] };
|
163
|
-
}
|
164
|
-
|
165
|
-
const { start = 0, end = cache.size } = options;
|
166
|
-
|
167
|
-
const data = new Uint8Array(end - start);
|
168
|
-
|
169
|
-
for (const region of cache.regions) {
|
170
|
-
if (region.offset + region.data.byteLength <= start) continue;
|
171
|
-
if (region.offset >= end) break;
|
172
|
-
|
173
|
-
for (const range of region.ranges) {
|
174
|
-
if (range.end <= start) continue;
|
175
|
-
if (range.start >= end) break;
|
176
|
-
|
177
|
-
const overlapStart = Math.max(range.start, start);
|
178
|
-
const overlapEnd = Math.min(range.end, end);
|
179
|
-
|
180
|
-
if (overlapStart >= overlapEnd) continue;
|
181
|
-
|
182
|
-
data.set(
|
183
|
-
region.data.subarray(overlapStart - region.offset, overlapEnd - region.offset),
|
184
|
-
overlapStart - start
|
185
|
-
);
|
186
|
-
}
|
187
|
-
}
|
188
|
-
|
189
|
-
return { data, missing: cache.missing(start, end) };
|
190
|
-
}
|
191
|
-
|
192
|
-
interface SetOptions extends Options {
|
193
|
-
/** The offset we are updating at */
|
194
|
-
offset?: number;
|
195
|
-
|
196
|
-
/** If a cache for the resource doesn't exist, this will be used as the full size */
|
197
|
-
size?: number;
|
198
|
-
}
|
199
|
-
|
200
|
-
/**
|
201
|
-
* Make a POST request to set (or create) data on the server and update the cache.
|
202
|
-
* @throws RequestError
|
203
|
-
*/
|
204
|
-
export async function set(url: string, data: Uint8Array, options: SetOptions, init: RequestInit = {}): Promise<void> {
|
205
|
-
if (!resourcesCache.has(url)) {
|
206
|
-
new cache.Resource(url, options.size ?? data.byteLength, options, resourcesCache);
|
207
|
-
}
|
208
|
-
|
209
|
-
const resource = resourcesCache.get(url)!;
|
210
|
-
|
211
|
-
const { offset = 0 } = options;
|
212
|
-
|
213
|
-
if (!options.cacheOnly) await _fetch(new Request(url, init), { method: 'POST' }, true);
|
214
|
-
|
215
|
-
resource.add(data, offset);
|
216
|
-
}
|
217
|
-
|
218
|
-
/**
|
219
|
-
* Make a DELETE request to remove the resource from the server and clear it from the cache.
|
220
|
-
* @throws RequestError
|
221
|
-
*/
|
222
|
-
export async function remove(url: string, options: Options = {}, init: RequestInit = {}): Promise<void> {
|
223
|
-
if (!options.cacheOnly) await _fetch(new Request(url, init), { method: 'DELETE' }, true);
|
224
|
-
resourcesCache.delete(url);
|
225
|
-
}
|
package/src/shell.ts
DELETED
@@ -1,133 +0,0 @@
|
|
1
|
-
/* A simple wrapper for xterm.js that makes implementing shells easier */
|
2
|
-
import type { Terminal } from '@xterm/xterm';
|
3
|
-
|
4
|
-
export interface ShellOptions {
|
5
|
-
/**
|
6
|
-
* The terminal associated with the context
|
7
|
-
*/
|
8
|
-
terminal: Terminal;
|
9
|
-
|
10
|
-
/**
|
11
|
-
* The prompt to use, can be a getter.
|
12
|
-
*/
|
13
|
-
readonly prompt?: string;
|
14
|
-
|
15
|
-
/**
|
16
|
-
* The length to use for the prompt. Useful if escape sequences are used in the prompt.
|
17
|
-
*/
|
18
|
-
readonly promptLength?: number;
|
19
|
-
|
20
|
-
/**
|
21
|
-
* The handler for when a line is parsed
|
22
|
-
*/
|
23
|
-
onLine?(this: void, line: string): unknown;
|
24
|
-
}
|
25
|
-
|
26
|
-
export interface ShellContext extends Required<ShellOptions> {
|
27
|
-
/**
|
28
|
-
* The input currently being shown
|
29
|
-
*/
|
30
|
-
input: string;
|
31
|
-
|
32
|
-
/**
|
33
|
-
* The index for which input is being shown
|
34
|
-
*/
|
35
|
-
index: number;
|
36
|
-
|
37
|
-
/**
|
38
|
-
* The current, uncached input
|
39
|
-
*/
|
40
|
-
currentInput: string;
|
41
|
-
|
42
|
-
/**
|
43
|
-
* array of previous inputs
|
44
|
-
*/
|
45
|
-
inputs: string[];
|
46
|
-
}
|
47
|
-
|
48
|
-
async function handleData($: ShellContext, data: string) {
|
49
|
-
if ($.index == -1) {
|
50
|
-
$.currentInput = $.input;
|
51
|
-
}
|
52
|
-
|
53
|
-
function clear(): void {
|
54
|
-
$.terminal.write('\x1b[2K\r' + $.prompt);
|
55
|
-
}
|
56
|
-
const x = $.terminal.buffer.active.cursorX - $.promptLength;
|
57
|
-
switch (data) {
|
58
|
-
case 'ArrowUp':
|
59
|
-
case '\x1b[A':
|
60
|
-
clear();
|
61
|
-
if ($.index < $.inputs.length - 1) {
|
62
|
-
$.input = $.inputs[++$.index];
|
63
|
-
}
|
64
|
-
$.terminal.write($.input);
|
65
|
-
break;
|
66
|
-
case 'ArrowDown':
|
67
|
-
case '\x1b[B':
|
68
|
-
clear();
|
69
|
-
if ($.index >= 0) {
|
70
|
-
$.input = $.index-- == 0 ? $.currentInput : $.inputs[$.index];
|
71
|
-
}
|
72
|
-
$.terminal.write($.input);
|
73
|
-
break;
|
74
|
-
case '\x1b[D':
|
75
|
-
if (x > 0) {
|
76
|
-
$.terminal.write(data);
|
77
|
-
}
|
78
|
-
break;
|
79
|
-
case '\x1b[C':
|
80
|
-
if (x < $.input.length) {
|
81
|
-
$.terminal.write(data);
|
82
|
-
}
|
83
|
-
break;
|
84
|
-
case '\x1b[F':
|
85
|
-
$.terminal.write(`\x1b[${$.promptLength + $.input.length + 1}G`);
|
86
|
-
break;
|
87
|
-
case '\x1b[H':
|
88
|
-
$.terminal.write(`\x1b[${$.promptLength + 1}G`);
|
89
|
-
break;
|
90
|
-
case '\x7f':
|
91
|
-
if (x <= 0) {
|
92
|
-
return;
|
93
|
-
}
|
94
|
-
$.terminal.write('\b\x1b[P');
|
95
|
-
$.input = $.input.slice(0, x - 1) + $.input.slice(x);
|
96
|
-
break;
|
97
|
-
case '\r':
|
98
|
-
if ($.input != $.inputs[0]) {
|
99
|
-
$.inputs.unshift($.input);
|
100
|
-
}
|
101
|
-
$.terminal.write('\r\n');
|
102
|
-
await $.onLine($.input);
|
103
|
-
$.index = -1;
|
104
|
-
$.input = '';
|
105
|
-
$.terminal.write($.prompt);
|
106
|
-
break;
|
107
|
-
default:
|
108
|
-
$.terminal.write(data);
|
109
|
-
$.input = $.input.slice(0, x) + data + $.input.slice(x);
|
110
|
-
}
|
111
|
-
}
|
112
|
-
|
113
|
-
/**
|
114
|
-
* Creates a new shell using the provided options
|
115
|
-
*/
|
116
|
-
export function createShell(options: ShellOptions): ShellContext {
|
117
|
-
const context: ShellContext = {
|
118
|
-
terminal: options.terminal,
|
119
|
-
get prompt() {
|
120
|
-
return options.prompt ?? '';
|
121
|
-
},
|
122
|
-
get promptLength() {
|
123
|
-
return options.promptLength ?? this.prompt.length;
|
124
|
-
},
|
125
|
-
onLine: options.onLine ?? (() => {}),
|
126
|
-
input: '',
|
127
|
-
index: -1,
|
128
|
-
currentInput: '',
|
129
|
-
inputs: [],
|
130
|
-
};
|
131
|
-
options.terminal.onData(data => handleData(context, data));
|
132
|
-
return context;
|
133
|
-
}
|
package/src/string.ts
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
export function capitalize<T extends string>(value: T): Capitalize<T> {
|
2
|
-
return (value.at(0)!.toUpperCase() + value.slice(1)) as Capitalize<T>;
|
3
|
-
}
|
4
|
-
|
5
|
-
export function uncapitalize<T extends string>(value: T): Uncapitalize<T> {
|
6
|
-
return (value.at(0)!.toLowerCase() + value.slice(1)) as Uncapitalize<T>;
|
7
|
-
}
|
8
|
-
|
9
|
-
export type ConcatString<T extends string[]> = T extends [infer F extends string, ...infer R extends string[]]
|
10
|
-
? `${F}${ConcatString<R>}`
|
11
|
-
: '';
|
12
|
-
|
13
|
-
export type Join<T extends string[], S extends string = ','> = T extends [
|
14
|
-
infer F extends string,
|
15
|
-
...infer R extends string[],
|
16
|
-
]
|
17
|
-
? `${F}${R extends [] ? '' : `${S}${Join<R, S>}`}`
|
18
|
-
: '';
|
19
|
-
|
20
|
-
export type Whitespace = ' ' | '\t';
|
21
|
-
|
22
|
-
export type Trim<T extends string> = T extends `${Whitespace}${infer R extends string}` ? Trim<R> : T;
|
23
|
-
|
24
|
-
const encoder = new TextEncoder();
|
25
|
-
|
26
|
-
/**
|
27
|
-
* Encodes a UTF-8 string into a buffer
|
28
|
-
*/
|
29
|
-
export function encodeUTF8(input: string): Uint8Array {
|
30
|
-
return encoder.encode(input);
|
31
|
-
}
|
32
|
-
|
33
|
-
const decoder = new TextDecoder();
|
34
|
-
|
35
|
-
/**
|
36
|
-
* Decodes a UTF-8 string from a buffer
|
37
|
-
*/
|
38
|
-
export function decodeUTF8(input?: Uint8Array): string {
|
39
|
-
if (!input) return '';
|
40
|
-
|
41
|
-
if (input.buffer instanceof ArrayBuffer && !input.buffer.resizable) return decoder.decode(input);
|
42
|
-
|
43
|
-
const buffer = new Uint8Array(input.byteLength);
|
44
|
-
buffer.set(input);
|
45
|
-
return decoder.decode(buffer);
|
46
|
-
}
|
47
|
-
|
48
|
-
export function encodeASCII(input: string): Uint8Array {
|
49
|
-
const data = new Uint8Array(input.length);
|
50
|
-
for (let i = 0; i < input.length; i++) {
|
51
|
-
data[i] = input.charCodeAt(i);
|
52
|
-
}
|
53
|
-
return data;
|
54
|
-
}
|
55
|
-
|
56
|
-
export function decodeASCII(input: Uint8Array): string {
|
57
|
-
let output = '';
|
58
|
-
for (let i = 0; i < input.length; i++) {
|
59
|
-
output += String.fromCharCode(input[i]);
|
60
|
-
}
|
61
|
-
return output;
|
62
|
-
}
|