@fluid-internal/client-utils 2.118.0 → 3.0.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/CHANGELOG.md +1 -5
- package/README.md +13 -15
- package/dist/base64EncodingBrowser.d.ts +2 -1
- package/dist/base64EncodingBrowser.d.ts.map +1 -1
- package/dist/base64EncodingBrowser.js +1 -1
- package/dist/base64EncodingBrowser.js.map +1 -1
- package/dist/base64EncodingNode.d.ts +2 -1
- package/dist/base64EncodingNode.d.ts.map +1 -1
- package/dist/base64EncodingNode.js.map +1 -1
- package/dist/buffer.d.ts +93 -0
- package/dist/buffer.d.ts.map +1 -0
- package/dist/buffer.js +7 -0
- package/dist/buffer.js.map +1 -0
- package/dist/bufferBrowser.d.ts +18 -49
- package/dist/bufferBrowser.d.ts.map +1 -1
- package/dist/bufferBrowser.js +49 -52
- package/dist/bufferBrowser.js.map +1 -1
- package/dist/bufferNode.d.ts +67 -19
- package/dist/bufferNode.d.ts.map +1 -1
- package/dist/bufferNode.js +10 -12
- package/dist/bufferNode.js.map +1 -1
- package/dist/bufferShared.d.ts +38 -3
- package/dist/bufferShared.d.ts.map +1 -1
- package/dist/bufferShared.js +67 -5
- package/dist/bufferShared.js.map +1 -1
- package/dist/events/emitter.d.ts.map +1 -1
- package/dist/events/emitter.js +4 -3
- package/dist/events/emitter.js.map +1 -1
- package/dist/hashFileBrowser.d.ts +1 -1
- package/dist/hashFileBrowser.d.ts.map +1 -1
- package/dist/hashFileBrowser.js +23 -11
- package/dist/hashFileBrowser.js.map +1 -1
- package/dist/hashFileNode.d.ts +10 -2
- package/dist/hashFileNode.d.ts.map +1 -1
- package/dist/hashFileNode.js +10 -3
- package/dist/hashFileNode.js.map +1 -1
- package/dist/indexBrowser.d.ts +5 -3
- package/dist/indexBrowser.d.ts.map +1 -1
- package/dist/indexBrowser.js +5 -5
- package/dist/indexBrowser.js.map +1 -1
- package/dist/indexNode.d.ts +4 -3
- package/dist/indexNode.d.ts.map +1 -1
- package/dist/indexNode.js +5 -2
- package/dist/indexNode.js.map +1 -1
- package/dist/layerCompat.d.ts +37 -13
- package/dist/layerCompat.d.ts.map +1 -1
- package/dist/layerCompat.js +19 -14
- package/dist/layerCompat.js.map +1 -1
- package/dist/trace.js +2 -0
- package/dist/trace.js.map +1 -1
- package/dist/typedEventEmitter.js +7 -0
- package/dist/typedEventEmitter.js.map +1 -1
- package/eslint.config.mts +2 -2
- package/lib/base64EncodingBrowser.d.ts +2 -1
- package/lib/base64EncodingBrowser.d.ts.map +1 -1
- package/lib/base64EncodingBrowser.js +1 -1
- package/lib/base64EncodingBrowser.js.map +1 -1
- package/lib/base64EncodingNode.d.ts +2 -1
- package/lib/base64EncodingNode.d.ts.map +1 -1
- package/lib/base64EncodingNode.js.map +1 -1
- package/lib/buffer.d.ts +93 -0
- package/lib/buffer.d.ts.map +1 -0
- package/lib/buffer.js +6 -0
- package/lib/buffer.js.map +1 -0
- package/lib/bufferBrowser.d.ts +18 -49
- package/lib/bufferBrowser.d.ts.map +1 -1
- package/lib/bufferBrowser.js +29 -40
- package/lib/bufferBrowser.js.map +1 -1
- package/lib/bufferNode.d.ts +67 -19
- package/lib/bufferNode.d.ts.map +1 -1
- package/lib/bufferNode.js +7 -9
- package/lib/bufferNode.js.map +1 -1
- package/lib/bufferShared.d.ts +38 -3
- package/lib/bufferShared.d.ts.map +1 -1
- package/lib/bufferShared.js +64 -3
- package/lib/bufferShared.js.map +1 -1
- package/lib/events/emitter.d.ts.map +1 -1
- package/lib/events/emitter.js +2 -1
- package/lib/events/emitter.js.map +1 -1
- package/lib/hashFileBrowser.d.ts +1 -1
- package/lib/hashFileBrowser.d.ts.map +1 -1
- package/lib/hashFileBrowser.js +4 -1
- package/lib/hashFileBrowser.js.map +1 -1
- package/lib/hashFileNode.d.ts +10 -2
- package/lib/hashFileNode.d.ts.map +1 -1
- package/lib/hashFileNode.js +8 -0
- package/lib/hashFileNode.js.map +1 -1
- package/lib/indexBrowser.d.ts +5 -3
- package/lib/indexBrowser.d.ts.map +1 -1
- package/lib/indexBrowser.js +3 -5
- package/lib/indexBrowser.js.map +1 -1
- package/lib/indexNode.d.ts +4 -3
- package/lib/indexNode.d.ts.map +1 -1
- package/lib/indexNode.js +2 -2
- package/lib/indexNode.js.map +1 -1
- package/lib/layerCompat.d.ts +37 -13
- package/lib/layerCompat.d.ts.map +1 -1
- package/lib/layerCompat.js +17 -12
- package/lib/layerCompat.js.map +1 -1
- package/lib/trace.js +2 -0
- package/lib/trace.js.map +1 -1
- package/lib/typedEventEmitter.js +7 -0
- package/lib/typedEventEmitter.js.map +1 -1
- package/package.json +65 -62
- package/playwright.config.ts +23 -0
- package/src/base64EncodingBrowser.ts +3 -2
- package/src/base64EncodingNode.ts +2 -1
- package/src/buffer.ts +112 -0
- package/src/bufferBrowser.ts +98 -60
- package/src/bufferNode.ts +86 -30
- package/src/bufferShared.ts +74 -4
- package/src/hashFileBrowser.ts +6 -3
- package/src/hashFileNode.ts +10 -2
- package/src/indexBrowser.ts +13 -2
- package/src/indexNode.ts +13 -2
- package/src/layerCompat.ts +41 -13
- package/tsconfig.json +1 -2
- package/webpack.playwright.cjs +22 -0
- package/jest-puppeteer.config.cjs +0 -16
- package/jest.config.cjs +0 -21
package/src/buffer.ts
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Declare the subset of node:Buffer functionality we want to make available instead of
|
|
8
|
+
* exposing the entirely of Node's typings. These serve as the public interface
|
|
9
|
+
* of the browser and node implementation.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Set of supported encodings for string to buffer conversion.
|
|
14
|
+
*
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
export type IsoBufferEncoding =
|
|
18
|
+
| "utf8"
|
|
19
|
+
// eslint-disable-next-line unicorn/text-encoding-identifier-case -- "utf-8" value is supported, just discouraged
|
|
20
|
+
| "utf-8"
|
|
21
|
+
| "base64";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Minimal Buffer interface for our usages in the browser or Node environments.
|
|
25
|
+
*
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
export interface IsoBuffer<TArrayBuffer extends ArrayBufferLike>
|
|
29
|
+
extends Uint8Array<TArrayBuffer> {
|
|
30
|
+
/**
|
|
31
|
+
* Convert the buffer to a string.
|
|
32
|
+
* Only supports encoding the whole string (unlike the Node `Buffer` equivalent)
|
|
33
|
+
* and only utf8 and base64 encodings.
|
|
34
|
+
*
|
|
35
|
+
* @param encoding - The encoding to use.
|
|
36
|
+
*/
|
|
37
|
+
toString(encoding?: IsoBufferEncoding): string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Constructor for {@link (IsoBuffer:type)}.
|
|
42
|
+
*
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
45
|
+
export interface IsoBufferConstructor {
|
|
46
|
+
readonly prototype: IsoBuffer<ArrayBufferLike>;
|
|
47
|
+
|
|
48
|
+
new (length: number): IsoBuffer<ArrayBuffer>;
|
|
49
|
+
new (array: ArrayLike<number>): IsoBuffer<ArrayBuffer>;
|
|
50
|
+
new <TArrayBuffer extends ArrayBufferLike = ArrayBuffer>(
|
|
51
|
+
buffer: TArrayBuffer,
|
|
52
|
+
byteOffset?: number,
|
|
53
|
+
length?: number,
|
|
54
|
+
): IsoBuffer<TArrayBuffer>;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Creates a new `IsoBuffer` containing `string`. The `encoding` parameter identifies
|
|
58
|
+
* the character encoding to be used when converting `string` into bytes.
|
|
59
|
+
*
|
|
60
|
+
* @param string - A string to encode.
|
|
61
|
+
* @param encoding - The encoding of `string`. **Default:** `'utf8'`.
|
|
62
|
+
*
|
|
63
|
+
* @privateRemarks
|
|
64
|
+
* Node buffer.buffer.d.ts declaration:
|
|
65
|
+
* `from(string: WithImplicitCoercion<string>, encoding?: IsoBufferEncoding): Buffer<ArrayBuffer>;`
|
|
66
|
+
*/
|
|
67
|
+
from(string: string, encoding?: IsoBufferEncoding): IsoBuffer<ArrayBuffer>;
|
|
68
|
+
/**
|
|
69
|
+
* Allocates a new `IsoBuffer` using an `array` of bytes in the range `0` – `255`.
|
|
70
|
+
* Array entries outside that range will be truncated to fit into it.
|
|
71
|
+
*
|
|
72
|
+
* @param value - `Uint8Array`.
|
|
73
|
+
*
|
|
74
|
+
* @remarks
|
|
75
|
+
* This is limited to `Uint8Array` input to match Node implementation that
|
|
76
|
+
* takes `ArrayLike<number>` and returns `IsoBuffer<ArrayBuffer>`.
|
|
77
|
+
*
|
|
78
|
+
* @privateRemarks
|
|
79
|
+
* Node buffer.buffer.d.ts declaration:
|
|
80
|
+
* `from(array: WithImplicitCoercion<ArrayLike<number>>): IsoBuffer<ArrayBuffer>;`
|
|
81
|
+
*/
|
|
82
|
+
from(array: Uint8Array): IsoBuffer<ArrayBuffer>;
|
|
83
|
+
/**
|
|
84
|
+
* This creates a view of the `ArrayBuffer` without copying the underlying
|
|
85
|
+
* memory. For example, when passed a reference to the `.buffer` property of a
|
|
86
|
+
* `TypedArray` instance, the newly created `Buffer` will share the same
|
|
87
|
+
* allocated memory as the `TypedArray`'s underlying `ArrayBuffer`.
|
|
88
|
+
*
|
|
89
|
+
* @param arrayBuffer - An `ArrayBuffer`, `SharedArrayBuffer`, for example the
|
|
90
|
+
* `.buffer` property of a `TypedArray`.
|
|
91
|
+
* @param byteOffset - Index of first byte to expose. **Default:** `0`.
|
|
92
|
+
* @param length - Number of bytes to expose. **Default:**
|
|
93
|
+
* `arrayBuffer.byteLength - byteOffset`.
|
|
94
|
+
*
|
|
95
|
+
* @privateRemarks
|
|
96
|
+
* Node buffer.buffer.d.ts declaration:
|
|
97
|
+
* ```
|
|
98
|
+
* public static from<TArrayBuffer extends WithImplicitCoercion<ArrayBufferLike>>(
|
|
99
|
+
* arrayBuffer: TArrayBuffer,
|
|
100
|
+
* byteOffset?: number,
|
|
101
|
+
* length?: number,
|
|
102
|
+
* ): Buffer<ImplicitArrayBuffer<TArrayBuffer>>;
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
from<TArrayBuffer extends ArrayBufferLike>(
|
|
106
|
+
arrayBuffer: TArrayBuffer,
|
|
107
|
+
byteOffset?: number,
|
|
108
|
+
length?: number,
|
|
109
|
+
): IsoBuffer<TArrayBuffer>;
|
|
110
|
+
|
|
111
|
+
isBuffer(obj: unknown): obj is IsoBuffer<ArrayBufferLike>;
|
|
112
|
+
}
|
package/src/bufferBrowser.ts
CHANGED
|
@@ -5,9 +5,30 @@
|
|
|
5
5
|
|
|
6
6
|
import * as base64js from "base64-js";
|
|
7
7
|
|
|
8
|
+
import type {
|
|
9
|
+
IsoBufferConstructor,
|
|
10
|
+
IsoBufferEncoding,
|
|
11
|
+
IsoBuffer as IsoBufferInterface,
|
|
12
|
+
} from "./buffer.js";
|
|
13
|
+
|
|
14
|
+
export type {
|
|
15
|
+
IsoBufferConstructor,
|
|
16
|
+
IsoBufferEncoding,
|
|
17
|
+
} from "./buffer.js";
|
|
8
18
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
19
|
+
* Minimal `Buffer` interface for our usages in the browser or Node.js environments.
|
|
20
|
+
*
|
|
21
|
+
* @internal
|
|
22
|
+
*
|
|
23
|
+
* @privateRemarks
|
|
24
|
+
* This type is exported specifically from here to respect combo type+value of same name rules.
|
|
25
|
+
*/
|
|
26
|
+
export type IsoBuffer<TArrayBuffer extends ArrayBufferLike = ArrayBufferLike> =
|
|
27
|
+
IsoBufferInterface<TArrayBuffer>;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Converts a `Uint8Array` to a string of the provided encoding
|
|
31
|
+
* Useful when the array might be an {@link (IsoBuffer:type)}.
|
|
11
32
|
*
|
|
12
33
|
* @param arr - The array to convert.
|
|
13
34
|
* @param encoding - Optional target encoding; only "utf8" and "base64" are
|
|
@@ -16,11 +37,7 @@ import * as base64js from "base64-js";
|
|
|
16
37
|
*
|
|
17
38
|
* @internal
|
|
18
39
|
*/
|
|
19
|
-
export function Uint8ArrayToString(
|
|
20
|
-
arr: Uint8Array,
|
|
21
|
-
// eslint-disable-next-line unicorn/text-encoding-identifier-case -- this value is supported, just discouraged
|
|
22
|
-
encoding?: "utf8" | "utf-8" | "base64",
|
|
23
|
-
): string {
|
|
40
|
+
export function Uint8ArrayToString(arr: Uint8Array, encoding?: IsoBufferEncoding): string {
|
|
24
41
|
switch (encoding) {
|
|
25
42
|
case "base64": {
|
|
26
43
|
return base64js.fromByteArray(arr);
|
|
@@ -45,7 +62,7 @@ export function Uint8ArrayToString(
|
|
|
45
62
|
*
|
|
46
63
|
* @internal
|
|
47
64
|
*/
|
|
48
|
-
export const stringToBuffer = (input: string, encoding:
|
|
65
|
+
export const stringToBuffer = (input: string, encoding: IsoBufferEncoding): ArrayBuffer =>
|
|
49
66
|
IsoBuffer.from(input, encoding).buffer;
|
|
50
67
|
|
|
51
68
|
/**
|
|
@@ -58,10 +75,10 @@ export const stringToBuffer = (input: string, encoding: string): ArrayBuffer =>
|
|
|
58
75
|
* @internal
|
|
59
76
|
*/
|
|
60
77
|
export const bufferToString = (
|
|
61
|
-
blob: ArrayBufferLike,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
78
|
+
blob: ArrayBufferLike | Uint8Array,
|
|
79
|
+
encoding: IsoBufferEncoding,
|
|
80
|
+
): string =>
|
|
81
|
+
Uint8ArrayToString(blob instanceof Uint8Array ? blob : IsoBuffer.from(blob), encoding);
|
|
65
82
|
|
|
66
83
|
/**
|
|
67
84
|
* Determines if an object is an array buffer.
|
|
@@ -73,12 +90,16 @@ export const bufferToString = (
|
|
|
73
90
|
* new TypedArray(buffer, byteOffset, length), but passing TypedArray will result in fist path (and
|
|
74
91
|
* ignoring byteOffice, length).
|
|
75
92
|
*
|
|
76
|
-
* @param obj - The object to determine if it is
|
|
93
|
+
* @param obj - The object to determine if it is `ArrayBufferLike`.
|
|
77
94
|
*
|
|
78
|
-
* @
|
|
95
|
+
* @privateRemarks
|
|
96
|
+
* This function preserves runtime functionality as it has been in the past.
|
|
97
|
+
* Typing has been adjusted to reflect the only use that remains and (assuming
|
|
98
|
+
* is called as expected) will always return true as the input is already
|
|
99
|
+
* expected to be `ArrayBufferLike`.
|
|
79
100
|
*/
|
|
80
|
-
|
|
81
|
-
const maybe = obj as (Partial<
|
|
101
|
+
function isArrayBufferLike(obj: ArrayBufferLike): obj is ArrayBufferLike {
|
|
102
|
+
const maybe = obj as (Partial<ArrayBufferLike> & Partial<Uint8Array>) | undefined;
|
|
82
103
|
return (
|
|
83
104
|
obj instanceof ArrayBuffer ||
|
|
84
105
|
(typeof maybe === "object" &&
|
|
@@ -91,59 +112,71 @@ export function isArrayBuffer(obj: unknown): obj is ArrayBuffer {
|
|
|
91
112
|
}
|
|
92
113
|
|
|
93
114
|
/**
|
|
94
|
-
* Minimal implementation of Buffer for our usages in the browser environment.
|
|
115
|
+
* Minimal implementation of `Buffer` for our usages in the browser environment.
|
|
95
116
|
*
|
|
96
117
|
* @internal
|
|
97
118
|
*/
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
119
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow -- Preserve the public constructor name at runtime.
|
|
120
|
+
export const IsoBuffer: IsoBufferConstructor = class IsoBuffer<
|
|
121
|
+
TArrayBuffer extends ArrayBufferLike = ArrayBufferLike,
|
|
122
|
+
>
|
|
123
|
+
extends Uint8Array<TArrayBuffer>
|
|
124
|
+
implements IsoBufferInterface<TArrayBuffer>
|
|
125
|
+
{
|
|
126
|
+
public constructor(
|
|
127
|
+
value: number | ArrayLike<number> | TArrayBuffer,
|
|
128
|
+
byteOffset?: number,
|
|
129
|
+
length?: number,
|
|
130
|
+
) {
|
|
131
|
+
super(value as TArrayBuffer, byteOffset, length);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
public toString(encoding?: IsoBufferEncoding): string {
|
|
108
135
|
return Uint8ArrayToString(this, encoding);
|
|
109
136
|
}
|
|
110
137
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
138
|
+
public static from(
|
|
139
|
+
value: string,
|
|
140
|
+
encoding?: IsoBufferEncoding,
|
|
141
|
+
): IsoBufferInterface<ArrayBuffer>;
|
|
142
|
+
public static from(value: Uint8Array): IsoBufferInterface<ArrayBuffer>;
|
|
143
|
+
public static from<TFArrayBuffer extends ArrayBufferLike>(
|
|
144
|
+
value: TFArrayBuffer,
|
|
145
|
+
byteOffset?: number,
|
|
146
|
+
length?: number,
|
|
147
|
+
): IsoBufferInterface<TFArrayBuffer>;
|
|
148
|
+
public static from<TFArrayBuffer extends ArrayBufferLike>(
|
|
149
|
+
value: string | Uint8Array | TFArrayBuffer,
|
|
150
|
+
encodingOrOffset?: IsoBufferEncoding | number,
|
|
151
|
+
length?: number,
|
|
152
|
+
): IsoBufferInterface<ArrayBufferLike> {
|
|
121
153
|
if (typeof value === "string") {
|
|
122
|
-
return IsoBuffer.fromString(
|
|
154
|
+
return IsoBuffer.fromString(
|
|
155
|
+
value,
|
|
156
|
+
encodingOrOffset as IsoBufferEncoding | undefined,
|
|
157
|
+
) satisfies IsoBufferInterface<ArrayBuffer>;
|
|
123
158
|
// Capture any typed arrays, including Uint8Array (and thus - IsoBuffer!)
|
|
124
|
-
|
|
125
|
-
} else if (value !== null && typeof value === "object" && isArrayBuffer(value.buffer)) {
|
|
159
|
+
} else if (value instanceof Uint8Array) {
|
|
126
160
|
// The version of the from function for the node buffer, which takes a buffer or typed array
|
|
127
161
|
// as first parameter, does not have any offset or length parameters. Those are just silently
|
|
128
162
|
// ignored and not taken into account
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
encodingOrOffset as number | undefined,
|
|
135
|
-
length as number,
|
|
136
|
-
);
|
|
163
|
+
const copy = new Uint8Array(value.byteLength);
|
|
164
|
+
copy.set(value);
|
|
165
|
+
return new IsoBuffer<ArrayBuffer>(copy.buffer) satisfies IsoBufferInterface<ArrayBuffer>;
|
|
166
|
+
} else if (isArrayBufferLike(value)) {
|
|
167
|
+
return IsoBuffer.fromArrayBuffer(value, encodingOrOffset as number | undefined, length);
|
|
137
168
|
} else {
|
|
138
|
-
throw new TypeError(
|
|
169
|
+
throw new TypeError(
|
|
170
|
+
"Input value was neither a string, a Uint8Array, nor an ArrayBuffer.",
|
|
171
|
+
);
|
|
139
172
|
}
|
|
140
173
|
}
|
|
141
174
|
|
|
142
|
-
public static fromArrayBuffer(
|
|
143
|
-
arrayBuffer:
|
|
175
|
+
public static fromArrayBuffer<TFArrayBuffer extends ArrayBufferLike>(
|
|
176
|
+
arrayBuffer: TFArrayBuffer,
|
|
144
177
|
byteOffset?: number,
|
|
145
178
|
byteLength?: number,
|
|
146
|
-
):
|
|
179
|
+
): IsoBufferInterface<TFArrayBuffer> {
|
|
147
180
|
const offset = byteOffset ?? 0;
|
|
148
181
|
const validLength = byteLength ?? arrayBuffer.byteLength - offset;
|
|
149
182
|
if (
|
|
@@ -155,22 +188,27 @@ export class IsoBuffer extends Uint8Array {
|
|
|
155
188
|
throw new RangeError("Invalid range specified.");
|
|
156
189
|
}
|
|
157
190
|
|
|
158
|
-
return new IsoBuffer(arrayBuffer, offset, validLength);
|
|
191
|
+
return new IsoBuffer<TFArrayBuffer>(arrayBuffer, offset, validLength);
|
|
159
192
|
}
|
|
160
193
|
|
|
161
|
-
public static fromString(
|
|
194
|
+
public static fromString(
|
|
195
|
+
str: string,
|
|
196
|
+
encoding?: IsoBufferEncoding,
|
|
197
|
+
): IsoBufferInterface<ArrayBuffer> {
|
|
162
198
|
switch (encoding) {
|
|
163
199
|
case "base64": {
|
|
164
200
|
const sanitizedString = this.sanitizeBase64(str);
|
|
165
|
-
|
|
166
|
-
|
|
201
|
+
// base64-js will always return a Uint8Array<ArrayBuffer>, but typing has not
|
|
202
|
+
// been updated to reflect that yet. Cast to the correct type here.
|
|
203
|
+
const encoded = base64js.toByteArray(sanitizedString) as Uint8Array<ArrayBuffer>;
|
|
204
|
+
return new IsoBuffer(encoded.buffer, encoded.byteOffset, encoded.byteLength);
|
|
167
205
|
}
|
|
168
206
|
case "utf8":
|
|
169
207
|
// eslint-disable-next-line unicorn/text-encoding-identifier-case -- this value is supported, just discouraged
|
|
170
208
|
case "utf-8":
|
|
171
209
|
case undefined: {
|
|
172
210
|
const encoded = new TextEncoder().encode(str);
|
|
173
|
-
return new IsoBuffer(encoded.buffer);
|
|
211
|
+
return new IsoBuffer(encoded.buffer, encoded.byteOffset, encoded.byteLength);
|
|
174
212
|
}
|
|
175
213
|
default: {
|
|
176
214
|
throw new Error("invalid/unsupported encoding");
|
|
@@ -178,8 +216,8 @@ export class IsoBuffer extends Uint8Array {
|
|
|
178
216
|
}
|
|
179
217
|
}
|
|
180
218
|
|
|
181
|
-
public static isBuffer(obj: unknown):
|
|
182
|
-
|
|
219
|
+
public static isBuffer(obj: unknown): obj is IsoBuffer {
|
|
220
|
+
return obj instanceof IsoBuffer;
|
|
183
221
|
}
|
|
184
222
|
|
|
185
223
|
/**
|
|
@@ -205,4 +243,4 @@ export class IsoBuffer extends Uint8Array {
|
|
|
205
243
|
}
|
|
206
244
|
return sanitizedStr;
|
|
207
245
|
}
|
|
208
|
-
}
|
|
246
|
+
} satisfies IsoBufferConstructor;
|
package/src/bufferNode.ts
CHANGED
|
@@ -3,43 +3,103 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import type {
|
|
7
|
+
IsoBufferConstructor,
|
|
8
|
+
IsoBufferEncoding,
|
|
9
|
+
IsoBuffer as IsoBufferInterface,
|
|
10
|
+
} from "./buffer.js";
|
|
11
|
+
|
|
12
|
+
export type { IsoBufferConstructor, IsoBufferEncoding } from "./buffer.js";
|
|
13
|
+
/**
|
|
14
|
+
* Minimal `Buffer` interface for our usages in the browser or Node.js environments.
|
|
15
|
+
*
|
|
16
|
+
* @internal
|
|
17
|
+
*
|
|
18
|
+
* @privateRemarks
|
|
19
|
+
* This type is exported specifically from here to respect combo type+value of same name rules.
|
|
20
|
+
*/
|
|
21
|
+
export type IsoBuffer<TArrayBuffer extends ArrayBufferLike = ArrayBufferLike> =
|
|
22
|
+
IsoBufferInterface<TArrayBuffer>;
|
|
23
|
+
|
|
6
24
|
/**
|
|
7
25
|
* Declare the subset of Buffer functionality we want to make available instead of
|
|
8
26
|
* exposing the entirely of Node's typings. This should match the public interface
|
|
9
|
-
* of the browser implementation
|
|
27
|
+
* of the browser implementation -- see {@link (IsoBuffer:type)} and {@link IsoBufferConstructor}.
|
|
10
28
|
*
|
|
11
29
|
* @internal
|
|
12
30
|
*/
|
|
13
|
-
export declare class Buffer extends
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
31
|
+
export declare class Buffer<TArrayBuffer extends ArrayBufferLike = ArrayBufferLike>
|
|
32
|
+
extends Uint8Array<TArrayBuffer>
|
|
33
|
+
implements IsoBuffer<TArrayBuffer>
|
|
34
|
+
{
|
|
17
35
|
/**
|
|
18
|
-
*
|
|
36
|
+
* Creates a new `IsoBuffer` containing `string`. The `encoding` parameter identifies
|
|
37
|
+
* the character encoding to be used when converting `string` into bytes.
|
|
19
38
|
*
|
|
20
|
-
* @param
|
|
21
|
-
* @param
|
|
22
|
-
* @param length - (number).
|
|
39
|
+
* @param string - A string to encode.
|
|
40
|
+
* @param encoding - The encoding of `string`. **Default:** `'utf8'`.
|
|
23
41
|
*
|
|
24
|
-
* @privateRemarks
|
|
42
|
+
* @privateRemarks
|
|
43
|
+
* Node buffer.buffer.d.ts declaration:
|
|
44
|
+
* `from(string: WithImplicitCoercion<string>, encoding?: IsoBufferEncoding): Buffer<ArrayBuffer>;`
|
|
25
45
|
*/
|
|
26
|
-
public static from(
|
|
46
|
+
public static from(string: string, encoding?: IsoBufferEncoding): IsoBuffer<ArrayBuffer>;
|
|
47
|
+
/**
|
|
48
|
+
* Allocates a new `IsoBuffer` using an `array` of bytes in the range `0` – `255`.
|
|
49
|
+
* Array entries outside that range will be truncated to fit into it.
|
|
50
|
+
*
|
|
51
|
+
* @param value - `Uint8Array`.
|
|
52
|
+
*
|
|
53
|
+
* @remarks
|
|
54
|
+
* This is limited to `Uint8Array` input to match Node implementation that
|
|
55
|
+
* takes `ArrayLike<number>` and returns `IsoBuffer<ArrayBuffer>`.
|
|
56
|
+
*
|
|
57
|
+
* @privateRemarks
|
|
58
|
+
* Node buffer.buffer.d.ts declaration:
|
|
59
|
+
* `from(array: WithImplicitCoercion<ArrayLike<number>>): IsoBuffer<ArrayBuffer>;`
|
|
60
|
+
*/
|
|
61
|
+
public static from(array: Uint8Array): IsoBuffer<ArrayBuffer>;
|
|
62
|
+
/**
|
|
63
|
+
* This creates a view of the `ArrayBuffer` without copying the underlying
|
|
64
|
+
* memory. For example, when passed a reference to the `.buffer` property of a
|
|
65
|
+
* `TypedArray` instance, the newly created `Buffer` will share the same
|
|
66
|
+
* allocated memory as the `TypedArray`'s underlying `ArrayBuffer`.
|
|
67
|
+
*
|
|
68
|
+
* @param arrayBuffer - An `ArrayBuffer`, `SharedArrayBuffer`, for example the
|
|
69
|
+
* `.buffer` property of a `TypedArray`.
|
|
70
|
+
* @param byteOffset - Index of first byte to expose. **Default:** `0`.
|
|
71
|
+
* @param length - Number of bytes to expose. **Default:**
|
|
72
|
+
* `arrayBuffer.byteLength - byteOffset`.
|
|
73
|
+
*
|
|
74
|
+
* @privateRemarks
|
|
75
|
+
* Node buffer.buffer.d.ts declaration:
|
|
76
|
+
* ```
|
|
77
|
+
* public static from<TArrayBuffer extends WithImplicitCoercion<ArrayBufferLike>>(
|
|
78
|
+
* arrayBuffer: TArrayBuffer,
|
|
79
|
+
* byteOffset?: number,
|
|
80
|
+
* length?: number,
|
|
81
|
+
* ): Buffer<ImplicitArrayBuffer<TArrayBuffer>>;
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
public static from<TArrayBuffer extends ArrayBufferLike>(
|
|
85
|
+
arrayBuffer: TArrayBuffer,
|
|
86
|
+
byteOffset?: number,
|
|
87
|
+
length?: number,
|
|
88
|
+
): IsoBuffer<TArrayBuffer>;
|
|
89
|
+
|
|
27
90
|
public static isBuffer(obj: unknown): obj is Buffer;
|
|
28
91
|
}
|
|
29
92
|
|
|
30
93
|
/**
|
|
94
|
+
* The native Node.js Buffer implementation.
|
|
95
|
+
*
|
|
31
96
|
* @internal
|
|
32
97
|
*/
|
|
33
|
-
export const IsoBuffer = Buffer;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* @internal
|
|
37
|
-
*/
|
|
38
|
-
export type IsoBuffer = Buffer;
|
|
98
|
+
export const IsoBuffer: IsoBufferConstructor = Buffer;
|
|
39
99
|
|
|
40
100
|
/**
|
|
41
|
-
* Converts a Uint8Array to a string of the provided encoding.
|
|
42
|
-
* @remarks Useful when the array might be an IsoBuffer
|
|
101
|
+
* Converts a `Uint8Array` to a string of the provided encoding.
|
|
102
|
+
* @remarks Useful when the array might be an `IsoBuffer`.
|
|
43
103
|
* @param arr - The array to convert.
|
|
44
104
|
* @param encoding - Optional target encoding; only "utf8" and "base64" are
|
|
45
105
|
* supported, with "utf8" being default.
|
|
@@ -47,14 +107,10 @@ export type IsoBuffer = Buffer;
|
|
|
47
107
|
*
|
|
48
108
|
* @internal
|
|
49
109
|
*/
|
|
50
|
-
export function Uint8ArrayToString(
|
|
51
|
-
arr: Uint8Array,
|
|
52
|
-
// eslint-disable-next-line unicorn/text-encoding-identifier-case -- this value is supported, just discouraged
|
|
53
|
-
encoding?: "utf8" | "utf-8" | "base64",
|
|
54
|
-
): string {
|
|
110
|
+
export function Uint8ArrayToString(arr: Uint8Array, encoding?: IsoBufferEncoding): string {
|
|
55
111
|
// Buffer extends Uint8Array. Therefore, 'arr' may already be a Buffer, in
|
|
56
112
|
// which case we can avoid copying the Uint8Array into a new Buffer instance.
|
|
57
|
-
return (
|
|
113
|
+
return (IsoBuffer.isBuffer(arr) ? arr : IsoBuffer.from(arr)).toString(encoding);
|
|
58
114
|
}
|
|
59
115
|
|
|
60
116
|
/**
|
|
@@ -63,7 +119,7 @@ export function Uint8ArrayToString(
|
|
|
63
119
|
*
|
|
64
120
|
* @internal
|
|
65
121
|
*/
|
|
66
|
-
export function stringToBuffer(input: string, encoding:
|
|
122
|
+
export function stringToBuffer(input: string, encoding: IsoBufferEncoding): ArrayBuffer {
|
|
67
123
|
const iso = IsoBuffer.from(input, encoding);
|
|
68
124
|
// In a Node environment, IsoBuffer may be a Node.js Buffer. Node.js will
|
|
69
125
|
// pool multiple small Buffer instances into a single ArrayBuffer, in which
|
|
@@ -83,7 +139,7 @@ export function stringToBuffer(input: string, encoding: string): ArrayBuffer {
|
|
|
83
139
|
* @internal
|
|
84
140
|
*/
|
|
85
141
|
export const bufferToString = (
|
|
86
|
-
blob: ArrayBufferLike,
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
142
|
+
blob: ArrayBufferLike | Uint8Array,
|
|
143
|
+
encoding: IsoBufferEncoding,
|
|
144
|
+
): string =>
|
|
145
|
+
Uint8ArrayToString(blob instanceof Uint8Array ? blob : IsoBuffer.from(blob), encoding);
|
package/src/bufferShared.ts
CHANGED
|
@@ -4,14 +4,84 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Distills an `ArrayBuffer` from an `ArrayBufferLike` or creates one from `SharedArrayBuffer` if needed.
|
|
8
|
+
*
|
|
9
|
+
* @param buffer - `ArrayBuffer` or any `ArrayBufferLike` to convert to `ArrayBuffer`.
|
|
10
|
+
*
|
|
11
|
+
* @remarks The returned buffer may be the input array's backing buffer or a copy of its bytes.
|
|
12
|
+
* Callers should not mutate the returned buffer unless they own the input array and its backing
|
|
13
|
+
* storage, and should not rely on mutations being reflected in the input array.
|
|
14
|
+
*
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
export function ArrayBufferLikeToArrayBuffer(buffer: ArrayBufferLike): ArrayBuffer {
|
|
18
|
+
if (buffer instanceof ArrayBuffer) {
|
|
19
|
+
return buffer;
|
|
20
|
+
}
|
|
21
|
+
// Use .slice to get `ArrayBuffer` backing that `Blob` requires.
|
|
22
|
+
// Note that `buffer.slice` preserves the underlying buffer type, so we
|
|
23
|
+
// need to use .slice on a `Uint8Array` to ensure we get an `ArrayBuffer`.
|
|
24
|
+
// eslint-disable-next-line unicorn/prefer-spread -- spread is not the same as slice for `Uint8Array`
|
|
25
|
+
return new Uint8Array(buffer).slice().buffer;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Distills a `Uint8Array` array to an `ArrayBuffer | SharedArrayBuffer` copying
|
|
30
|
+
* data as needed per the array's `byteOffset` and `byteLength` to have a full
|
|
31
|
+
* buffer (no offset and entire length).
|
|
32
|
+
*
|
|
33
|
+
* @param array - Array to extract buffer from.
|
|
34
|
+
*
|
|
35
|
+
* @remarks The returned buffer may be the input array's backing buffer or a copy of its bytes.
|
|
36
|
+
* Callers should not mutate the returned buffer unless they own the input array and its backing
|
|
37
|
+
* storage, and should not rely on mutations being reflected in the input array.
|
|
9
38
|
*
|
|
10
39
|
* @internal
|
|
11
40
|
*/
|
|
12
|
-
export function
|
|
41
|
+
export function Uint8ArrayToArrayBufferLike<TArrayBuffer extends ArrayBufferLike>(
|
|
42
|
+
array: Uint8Array<TArrayBuffer>,
|
|
43
|
+
): TArrayBuffer {
|
|
13
44
|
if (array.byteOffset === 0 && array.byteLength === array.buffer.byteLength) {
|
|
14
45
|
return array.buffer;
|
|
15
46
|
}
|
|
16
|
-
|
|
47
|
+
// Both ArrayBuffer and SharedArrayBuffer have a slice method and will return
|
|
48
|
+
// their same type, but TypeScript does not correctly determine that will
|
|
49
|
+
// satisfy TArrayBuffer. Cast to TArrayBuffer to indicate that.
|
|
50
|
+
return array.buffer.slice(
|
|
51
|
+
array.byteOffset,
|
|
52
|
+
array.byteOffset + array.byteLength,
|
|
53
|
+
) as TArrayBuffer;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Distills a `Uint8Array` array to an `ArrayBuffer` copying data as needed per the array's
|
|
58
|
+
* `byteOffset` and `byteLength` or if underlying buffer is not `ArrayBuffer`.
|
|
59
|
+
*
|
|
60
|
+
* @param array - Array to convert to `ArrayBuffer`.
|
|
61
|
+
*
|
|
62
|
+
* @remarks The returned buffer may be the input array's backing buffer or a copy of its bytes.
|
|
63
|
+
* Callers should not mutate the returned buffer unless they own the input array and its backing
|
|
64
|
+
* storage, and should not rely on mutations being reflected in the input array.
|
|
65
|
+
*
|
|
66
|
+
* Prefer to use {@link Uint8ArrayToArrayBufferLike} if the call site doesn't require
|
|
67
|
+
* an explicit `ArrayBuffer` (can also handle `SharedArrayBuffer`).
|
|
68
|
+
*
|
|
69
|
+
* @internal
|
|
70
|
+
*/
|
|
71
|
+
export function AnyUint8ArrayToArrayBuffer(array: Uint8Array): ArrayBuffer {
|
|
72
|
+
// Shortcut to provider underlying buffer as-is when possible.
|
|
73
|
+
if (
|
|
74
|
+
array.byteOffset === 0 &&
|
|
75
|
+
array.byteLength === array.buffer.byteLength &&
|
|
76
|
+
array.buffer instanceof ArrayBuffer
|
|
77
|
+
) {
|
|
78
|
+
return array.buffer;
|
|
79
|
+
}
|
|
80
|
+
// .slice is used to ensure underlying buffer is:
|
|
81
|
+
// 1. ArrayBuffer
|
|
82
|
+
// 2. the complete data (no offset, full length)
|
|
83
|
+
// Cloning specified per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/slice
|
|
84
|
+
// and ECMAScript https://tc39.es/ecma262/multipage/indexed-collections.html#sec-%typedarray%.prototype.slice.
|
|
85
|
+
// eslint-disable-next-line unicorn/prefer-spread -- spread is not the same as slice for `Uint8Array`
|
|
86
|
+
return array.slice().buffer;
|
|
17
87
|
}
|
package/src/hashFileBrowser.ts
CHANGED
|
@@ -9,7 +9,7 @@ import * as base64js from "base64-js";
|
|
|
9
9
|
import { IsoBuffer } from "./bufferBrowser.js";
|
|
10
10
|
|
|
11
11
|
async function digestBuffer(
|
|
12
|
-
file: IsoBuffer
|
|
12
|
+
file: IsoBuffer<ArrayBuffer>,
|
|
13
13
|
algorithm: "SHA-1" | "SHA-256",
|
|
14
14
|
): Promise<Uint8Array> {
|
|
15
15
|
const hash = await crypto.subtle.digest(algorithm, file);
|
|
@@ -48,7 +48,7 @@ function encodeDigest(hashArray: Uint8Array, encoding: "hex" | "base64"): string
|
|
|
48
48
|
* @internal
|
|
49
49
|
*/
|
|
50
50
|
export async function hashFile(
|
|
51
|
-
file: IsoBuffer
|
|
51
|
+
file: IsoBuffer<ArrayBuffer>,
|
|
52
52
|
algorithm: "SHA-1" | "SHA-256" = "SHA-1",
|
|
53
53
|
hashEncoding: "hex" | "base64" = "hex",
|
|
54
54
|
): Promise<string> {
|
|
@@ -82,7 +82,10 @@ export async function gitHashFile(file: IsoBuffer): Promise<string> {
|
|
|
82
82
|
const size = file.byteLength;
|
|
83
83
|
// eslint-disable-next-line unicorn/prefer-code-point
|
|
84
84
|
const filePrefix = `blob ${size.toString()}${String.fromCharCode(0)}`;
|
|
85
|
-
const
|
|
85
|
+
const prefixBuffer = IsoBuffer.from(filePrefix);
|
|
86
|
+
const hashBuffer = new IsoBuffer(prefixBuffer.byteLength + file.byteLength);
|
|
87
|
+
hashBuffer.set(prefixBuffer);
|
|
88
|
+
hashBuffer.set(file, prefixBuffer.byteLength);
|
|
86
89
|
|
|
87
90
|
// hashFile uses sha1; if that changes this will need to change too
|
|
88
91
|
return hashFile(hashBuffer);
|
package/src/hashFileNode.ts
CHANGED
|
@@ -20,9 +20,13 @@ import type { IsoBuffer } from "./bufferNode.js";
|
|
|
20
20
|
* @returns The hash of the content of the buffer.
|
|
21
21
|
*
|
|
22
22
|
* @internal
|
|
23
|
+
*
|
|
24
|
+
* @privateRemarks
|
|
25
|
+
* This function does not strictly require `<ArrayBuffer>` backing, but it is typed
|
|
26
|
+
* that way to match the browser implementation, which does require `<ArrayBuffer>` backing.
|
|
23
27
|
*/
|
|
24
28
|
export async function hashFile(
|
|
25
|
-
file: IsoBuffer
|
|
29
|
+
file: IsoBuffer<ArrayBuffer>,
|
|
26
30
|
algorithm: "SHA-1" | "SHA-256" = "SHA-1",
|
|
27
31
|
hashEncoding: "hex" | "base64" = "hex",
|
|
28
32
|
): Promise<string> {
|
|
@@ -50,8 +54,12 @@ export async function hashFile(
|
|
|
50
54
|
* @returns The sha1 hash of the content of the buffer with the `blob` prefix and size
|
|
51
55
|
*
|
|
52
56
|
* @internal
|
|
57
|
+
*
|
|
58
|
+
* @privateRemarks
|
|
59
|
+
* This function does not strictly require `<ArrayBuffer>` backing, but it is typed
|
|
60
|
+
* that way to match the browser implementation, which does require `<ArrayBuffer>` backing.
|
|
53
61
|
*/
|
|
54
|
-
export async function gitHashFile(file: IsoBuffer): Promise<string> {
|
|
62
|
+
export async function gitHashFile(file: IsoBuffer<ArrayBuffer>): Promise<string> {
|
|
55
63
|
const size = file.byteLength;
|
|
56
64
|
// eslint-disable-next-line unicorn/prefer-code-point
|
|
57
65
|
const filePrefix = `blob ${size.toString()}${String.fromCharCode(0)}`;
|