update electron to v43

This commit is contained in:
olcxja 2026-07-09 22:38:33 +02:00
commit fb6c8b6ee9
5385 changed files with 513060 additions and 123058 deletions

21
electron/node_modules/@peculiar/utils/LICENSE generated vendored Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017-2026 Peculiar Ventures, LLC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

299
electron/node_modules/@peculiar/utils/README.md generated vendored Normal file
View file

@ -0,0 +1,299 @@
# @peculiar/utils
[![npm version](https://img.shields.io/npm/v/%40peculiar%2Futils.svg)](https://www.npmjs.com/package/@peculiar/utils)
[![Test](https://github.com/PeculiarVentures/pvtsutils/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/PeculiarVentures/pvtsutils/actions/workflows/test.yml)
[![Coverage Status](https://coveralls.io/repos/github/PeculiarVentures/pvtsutils/badge.svg?branch=master)](https://coveralls.io/github/PeculiarVentures/pvtsutils?branch=master)
[![License: MIT](https://img.shields.io/github/license/PeculiarVentures/pvtsutils.svg)](https://github.com/PeculiarVentures/pvtsutils/blob/master/LICENSE)
Modern byte, text, converter registry, and PEM utilities for TypeScript projects.
The package is designed around a modular v2 API:
- multi-entry exports for tree-shake-friendly imports;
- `encode` and `decode` terminology;
- an extensible runtime converter registry;
- generic PEM helpers without PKI-specific parsing;
- a legacy compatibility layer for historical `pvtsutils` consumers.
## Install
```bash
npm install @peculiar/utils
```
## Entry Points
```ts
import { bytes } from "@peculiar/utils";
import { hex, base64, base64url } from "@peculiar/utils/encoding";
import { pem } from "@peculiar/utils/pem";
import { convert, createConverterRegistry, defaultConverters } from "@peculiar/utils/converters";
import { Convert } from "@peculiar/utils/legacy";
```
## Bytes Helpers
`@peculiar/utils/bytes` stays focused on stateless byte sequence utilities. It does not include stateful readers, writers, ASN.1 parsing, PDF parsing, or other structured binary readers. For structured binary parsing, use a dedicated binary reader package.
```ts
import { bytes } from "@peculiar/utils";
const offset = bytes.indexOf(new Uint8Array([0x25, 0x25, 0x45, 0x4f, 0x46]), "%%EOF", {
encoding: "ascii",
});
const suffix = bytes.endsWith(new Uint8Array([0x25, 0x25, 0x45, 0x4f, 0x46]), "%%EOF", {
encoding: "ascii",
});
```
### Find `startxref` In A PDF Tail
```ts
import { lastIndexOf } from "@peculiar/utils/bytes";
const tailStart = Math.max(0, pdf.byteLength - 4096);
const offset = lastIndexOf(pdf, "startxref", {
encoding: "ascii",
start: pdf.byteLength,
end: tailStart,
});
if (offset === -1) {
throw new Error("PDF startxref marker not found");
}
```
### Find `startxref` Via `tail`
```ts
import { lastIndexOf, tail } from "@peculiar/utils/bytes";
const pdfTail = tail(pdf, 4096);
const localOffset = lastIndexOf(pdfTail, "startxref", {
encoding: "ascii",
});
const offset =
localOffset === -1
? -1
: pdf.byteLength - pdfTail.byteLength + localOffset;
```
### Check Prefixes And Suffixes
```ts
import { bytes } from "@peculiar/utils";
bytes.startsWith(data, "-----BEGIN", { encoding: "ascii" });
bytes.endsWith(data, "%%EOF", { encoding: "ascii" });
```
### Compare Byte Sequences
```ts
import { bytes } from "@peculiar/utils";
const result = bytes.compare(a, b);
if (result === 0) {
console.log("equal");
}
```
## Convert API
The default `convert` facade is a convenience singleton backed by the built-in registry.
```ts
import { convert } from "@peculiar/utils/converters";
const bytes = convert.decode("base64", "AQID");
const text = convert.encode("hex", bytes, { case: "upper" });
```
Deprecated `convert.to(...)` and `convert.from(...)` aliases are still available for temporary migration, but the primary v2 API is `encode` and `decode`.
## Transcode
Direct text-to-text transcoding goes through the registry without a manual intermediate step.
```ts
import { convert } from "@peculiar/utils/converters";
import { hex } from "@peculiar/utils/encoding";
const pemText = convert.transcode("AQID", {
from: "base64",
to: "pem",
toOptions: {
label: "CERTIFICATE",
},
});
const hexText = convert.transcode(pemText, {
from: "pem",
fromOptions: { label: "CERTIFICATE" },
to: "hex",
toOptions: hex.formats.colonUpper,
});
```
There is intentionally no chain API.
## Hex Formatting
The `hex` codec accepts common input styles and can format output explicitly.
```ts
import { hex } from "@peculiar/utils/encoding";
hex.decode("0102030405060708090a0b0c");
hex.decode("01020304 05060708 090a0b0c");
hex.decode("01:02:03:04:05:06:07:08:09:0A:0B:0C");
hex.decode("0x0102030405060708090a0b0c");
hex.encode(new Uint8Array([1, 2, 3, 4]), hex.formats.colonUpper);
hex.encode(new Uint8Array([1, 2, 3, 4]), {
prefix: "0x",
group: {
size: 2,
separator: " ",
},
});
```
Available presets:
- `hex.formats.compact`
- `hex.formats.upper`
- `hex.formats.colon`
- `hex.formats.colonUpper`
- `hex.formats.groupsOf4`
- `hex.formats.prefixed`
## Preserve Formatting
Use `parse` and `format` when you want to keep the original visual style of a hex string.
```ts
import { hex } from "@peculiar/utils/encoding";
const parsed = hex.parse("01:02:03:04:05:06");
parsed.bytes;
parsed.format;
parsed.normalized;
const updated = hex.format(new Uint8Array([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]), parsed.format);
```
The same capabilities are available through the registry facade:
```ts
import { convert } from "@peculiar/utils/converters";
const parsed = convert.parse("hex", "01:02:03:04");
const formatted = convert.format("hex", new Uint8Array([0xaa, 0xbb, 0xcc, 0xdd]), parsed.format);
```
## PEM Helpers
PEM support stays generic. The package does not parse ASN.1, validate PKI semantics, or handle encrypted PEM containers.
```ts
import { pem } from "@peculiar/utils/pem";
const text = pem.encode("CERTIFICATE", new Uint8Array([1, 2, 3]));
const blocks = pem.decode(text);
const block = pem.find(text, "CERTIFICATE");
const matches = pem.findAll(text, "CERTIFICATE");
const bundle = pem.encodeMany([
{ label: "CERTIFICATE", data: new Uint8Array([1, 2, 3]) },
{ label: "PRIVATE KEY", data: new Uint8Array([4, 5, 6]) },
]);
```
## Safe Decode And Detection
```ts
import { convert } from "@peculiar/utils/converters";
const result = convert.tryDecode("hex", "01:02:03");
if (result.ok) {
console.log(result.bytes);
} else {
console.error(result.error);
}
const candidates = convert.detect("-----BEGIN DATA-----\nAQID\n-----END DATA-----\n", {
formats: ["pem", "base64", "hex"],
});
```
## Custom Registries
Applications can create isolated registries instead of mutating global state.
```ts
import { createConverterRegistry, defaultConverters } from "@peculiar/utils/converters";
const registry = createConverterRegistry(defaultConverters);
registry.register({
name: "base58btc",
aliases: ["b58"],
encode(data) {
return base58btcEncode(data);
},
decode(text) {
return base58btcDecode(text);
},
});
```
Name and alias conflicts throw by default. Use `{ override: true }` only when replacement is intentional.
## Typed Converter Options
Built-in converters expose typed options through the registry facade.
```ts
import { convert } from "@peculiar/utils/converters";
convert.encode("hex", new Uint8Array([1, 2, 3]), {
case: "upper",
});
```
Wrong options are rejected by TypeScript:
```ts
convert.encode("hex", new Uint8Array([1, 2, 3]), {
label: "CERTIFICATE",
});
```
Custom converters can extend the options map via module augmentation:
```ts
declare module "@peculiar/utils/converters" {
interface ConverterOptionsMap {
base58btc: {
encode: Base58EncodeOptions;
decode: Base58DecodeOptions;
};
}
}
```
## Legacy Compatibility
The old `pvtsutils`-style surface is preserved under the legacy entry point.
```ts
import { BufferSourceConverter, Convert, assign, combine, isEqual } from "@peculiar/utils/legacy";
```

View file

@ -0,0 +1,115 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isArrayBuffer = isArrayBuffer;
exports.isSharedArrayBuffer = isSharedArrayBuffer;
exports.isArrayBufferLike = isArrayBufferLike;
exports.isArrayBufferView = isArrayBufferView;
exports.isBufferSource = isBufferSource;
exports.assertBufferSource = assertBufferSource;
exports.toUint8Array = toUint8Array;
exports.toUint8ArrayCopy = toUint8ArrayCopy;
exports.toArrayBuffer = toArrayBuffer;
exports.toArrayBufferLike = toArrayBufferLike;
exports.toView = toView;
exports.toViewCopy = toViewCopy;
const ARRAY_BUFFER_TAG = "[object ArrayBuffer]";
const SHARED_ARRAY_BUFFER_TAG = "[object SharedArrayBuffer]";
function tagOf(value) {
return Object.prototype.toString.call(value);
}
function isDataViewConstructor(type) {
return type === DataView || type.prototype instanceof DataView;
}
function bytesPerElement(type) {
if (isDataViewConstructor(type)) {
return 1;
}
const value = type.BYTES_PER_ELEMENT;
return value ?? 1;
}
function isArrayBufferViewLike(value) {
if (ArrayBuffer.isView(value)) {
return true;
}
if (!value || typeof value !== "object") {
return false;
}
const view = value;
return typeof view.byteOffset === "number"
&& typeof view.byteLength === "number"
&& isArrayBufferLike(view.buffer);
}
function copyBytes(data) {
const view = toUint8Array(data);
const copy = new Uint8Array(view.byteLength);
copy.set(view);
return copy;
}
function isArrayBuffer(value) {
return tagOf(value) === ARRAY_BUFFER_TAG;
}
function isSharedArrayBuffer(value) {
return typeof SharedArrayBuffer !== "undefined" && tagOf(value) === SHARED_ARRAY_BUFFER_TAG;
}
function isArrayBufferLike(value) {
return isArrayBuffer(value) || isSharedArrayBuffer(value);
}
function isArrayBufferView(value) {
return isArrayBufferViewLike(value);
}
function isBufferSource(value) {
return isArrayBufferLike(value) || isArrayBufferView(value);
}
function assertBufferSource(value) {
if (!isBufferSource(value)) {
throw new TypeError("Expected ArrayBuffer, SharedArrayBuffer, or ArrayBufferView");
}
}
function toUint8Array(data) {
assertBufferSource(data);
if (isArrayBufferLike(data)) {
return new Uint8Array(data);
}
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
}
function toUint8ArrayCopy(data) {
return copyBytes(data);
}
function toArrayBuffer(data) {
assertBufferSource(data);
if (isArrayBuffer(data)) {
return data;
}
const buffer = new ArrayBuffer(data.byteLength);
new Uint8Array(buffer).set(toUint8Array(data));
return buffer;
}
function toArrayBufferLike(data) {
assertBufferSource(data);
if (isArrayBufferLike(data)) {
return data;
}
if (data.byteOffset === 0 && data.byteLength === data.buffer.byteLength) {
return data.buffer;
}
return copyBytes(data).buffer;
}
function toView(data, type) {
assertBufferSource(data);
if (ArrayBuffer.isView(data) && data.constructor === type) {
return data;
}
const view = toUint8Array(data);
const elementSize = bytesPerElement(type);
if (view.byteOffset % elementSize !== 0 || view.byteLength % elementSize !== 0) {
throw new RangeError(`Cannot create ${type.name} over unaligned byte range`);
}
if (isDataViewConstructor(type)) {
return new type(view.buffer, view.byteOffset, view.byteLength);
}
return new type(view.buffer, view.byteOffset, view.byteLength / elementSize);
}
function toViewCopy(data, type) {
const copy = toUint8ArrayCopy(data);
return toView(copy, type);
}

View file

@ -0,0 +1,41 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.concatToUint8Array = concatToUint8Array;
exports.concat = concat;
const buffer_source_js_1 = require("./buffer-source.js");
function concatToUint8Array(buffers) {
const views = [];
let length = 0;
for (const buffer of buffers) {
const view = (0, buffer_source_js_1.toUint8Array)(buffer);
views.push(view);
length += view.byteLength;
}
const result = new Uint8Array(length);
let offset = 0;
for (const view of views) {
result.set(view, offset);
offset += view.byteLength;
}
return result;
}
function concat(first, second, ...rest) {
let buffers;
let type;
if (typeof second === "function") {
buffers = Array.from(first);
type = second;
}
else if ((0, buffer_source_js_1.isBufferSource)(first)) {
buffers = [first, second, ...rest].filter(buffer_source_js_1.isBufferSource);
}
else {
buffers = Array.from(first);
if (second) {
buffers.push(second);
}
buffers.push(...rest);
}
const bytes = concatToUint8Array(buffers);
return type ? (0, buffer_source_js_1.toView)(bytes, type) : bytes.buffer;
}

View file

@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.equal = equal;
const buffer_source_js_1 = require("./buffer-source.js");
function equal(a, b, options = {}) {
const left = (0, buffer_source_js_1.toUint8Array)(a);
const right = (0, buffer_source_js_1.toUint8Array)(b);
if (!options.constantTime && left.byteLength !== right.byteLength) {
return false;
}
const length = Math.max(left.byteLength, right.byteLength);
let diff = left.byteLength ^ right.byteLength;
for (let i = 0; i < length; i++) {
diff |= (left[i] ?? 0) ^ (right[i] ?? 0);
}
return diff === 0;
}

View file

@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.tail = exports.startsWith = exports.slice = exports.lastIndexOf = exports.indexOf = exports.includes = exports.endsWith = exports.copy = exports.compare = exports.equal = exports.concatToUint8Array = exports.concat = exports.toViewCopy = exports.toView = exports.toUint8ArrayCopy = exports.toUint8Array = exports.toArrayBufferLike = exports.toArrayBuffer = exports.isSharedArrayBuffer = exports.isBufferSource = exports.isArrayBufferView = exports.isArrayBufferLike = exports.isArrayBuffer = exports.assertBufferSource = void 0;
var buffer_source_js_1 = require("./buffer-source.js");
Object.defineProperty(exports, "assertBufferSource", { enumerable: true, get: function () { return buffer_source_js_1.assertBufferSource; } });
Object.defineProperty(exports, "isArrayBuffer", { enumerable: true, get: function () { return buffer_source_js_1.isArrayBuffer; } });
Object.defineProperty(exports, "isArrayBufferLike", { enumerable: true, get: function () { return buffer_source_js_1.isArrayBufferLike; } });
Object.defineProperty(exports, "isArrayBufferView", { enumerable: true, get: function () { return buffer_source_js_1.isArrayBufferView; } });
Object.defineProperty(exports, "isBufferSource", { enumerable: true, get: function () { return buffer_source_js_1.isBufferSource; } });
Object.defineProperty(exports, "isSharedArrayBuffer", { enumerable: true, get: function () { return buffer_source_js_1.isSharedArrayBuffer; } });
Object.defineProperty(exports, "toArrayBuffer", { enumerable: true, get: function () { return buffer_source_js_1.toArrayBuffer; } });
Object.defineProperty(exports, "toArrayBufferLike", { enumerable: true, get: function () { return buffer_source_js_1.toArrayBufferLike; } });
Object.defineProperty(exports, "toUint8Array", { enumerable: true, get: function () { return buffer_source_js_1.toUint8Array; } });
Object.defineProperty(exports, "toUint8ArrayCopy", { enumerable: true, get: function () { return buffer_source_js_1.toUint8ArrayCopy; } });
Object.defineProperty(exports, "toView", { enumerable: true, get: function () { return buffer_source_js_1.toView; } });
Object.defineProperty(exports, "toViewCopy", { enumerable: true, get: function () { return buffer_source_js_1.toViewCopy; } });
var concat_js_1 = require("./concat.js");
Object.defineProperty(exports, "concat", { enumerable: true, get: function () { return concat_js_1.concat; } });
Object.defineProperty(exports, "concatToUint8Array", { enumerable: true, get: function () { return concat_js_1.concatToUint8Array; } });
var equal_js_1 = require("./equal.js");
Object.defineProperty(exports, "equal", { enumerable: true, get: function () { return equal_js_1.equal; } });
var sequence_js_1 = require("./sequence.js");
Object.defineProperty(exports, "compare", { enumerable: true, get: function () { return sequence_js_1.compare; } });
Object.defineProperty(exports, "copy", { enumerable: true, get: function () { return sequence_js_1.copy; } });
Object.defineProperty(exports, "endsWith", { enumerable: true, get: function () { return sequence_js_1.endsWith; } });
Object.defineProperty(exports, "includes", { enumerable: true, get: function () { return sequence_js_1.includes; } });
Object.defineProperty(exports, "indexOf", { enumerable: true, get: function () { return sequence_js_1.indexOf; } });
Object.defineProperty(exports, "lastIndexOf", { enumerable: true, get: function () { return sequence_js_1.lastIndexOf; } });
Object.defineProperty(exports, "slice", { enumerable: true, get: function () { return sequence_js_1.slice; } });
Object.defineProperty(exports, "startsWith", { enumerable: true, get: function () { return sequence_js_1.startsWith; } });
Object.defineProperty(exports, "tail", { enumerable: true, get: function () { return sequence_js_1.tail; } });

View file

@ -0,0 +1,161 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.indexOf = indexOf;
exports.lastIndexOf = lastIndexOf;
exports.includes = includes;
exports.startsWith = startsWith;
exports.endsWith = endsWith;
exports.slice = slice;
exports.tail = tail;
exports.copy = copy;
exports.compare = compare;
const buffer_source_js_1 = require("./buffer-source.js");
function clampIndex(value, fallback, length) {
const normalized = Number.isFinite(value) ? Math.trunc(value) : fallback;
if (normalized <= 0) {
return 0;
}
if (normalized >= length) {
return length;
}
return normalized;
}
function normalizeForwardRange(length, options) {
const start = clampIndex(options?.start, 0, length);
const end = clampIndex(options?.end, length, length);
return end >= start ? [start, end] : [start, start];
}
function normalizeReverseRange(length, options) {
const start = clampIndex(options?.start, length, length);
const end = clampIndex(options?.end, 0, length);
return start >= end ? [end, start] : [start, start];
}
function normalizeSliceIndex(value, fallback, length) {
const normalized = Number.isFinite(value) ? Math.trunc(value) : fallback;
if (normalized < 0) {
return Math.max(length + normalized, 0);
}
if (normalized > length) {
return length;
}
return normalized;
}
function encodeAscii(text) {
const bytes = new Uint8Array(text.length);
for (let i = 0; i < text.length; i++) {
bytes[i] = text.charCodeAt(i) & 0xff;
}
return bytes;
}
function encodeUtf8(text) {
return new TextEncoder().encode(text);
}
function toPatternBytes(pattern, options) {
if (typeof pattern === "string") {
return options?.encoding === "utf8" ? encodeUtf8(pattern) : encodeAscii(pattern);
}
return (0, buffer_source_js_1.toUint8Array)(pattern);
}
function bytesEqualAt(data, pattern, offset) {
for (let index = 0; index < pattern.byteLength; index++) {
if (data[offset + index] !== pattern[index]) {
return false;
}
}
return true;
}
function indexOf(data, pattern, options) {
const bytes = (0, buffer_source_js_1.toUint8Array)(data);
const needle = toPatternBytes(pattern, options);
const [start, end] = normalizeForwardRange(bytes.byteLength, options);
if (needle.byteLength === 0) {
return start;
}
const lastOffset = end - needle.byteLength;
if (lastOffset < start) {
return -1;
}
for (let offset = start; offset <= lastOffset; offset++) {
if (bytesEqualAt(bytes, needle, offset)) {
return offset;
}
}
return -1;
}
function lastIndexOf(data, pattern, options) {
const bytes = (0, buffer_source_js_1.toUint8Array)(data);
const needle = toPatternBytes(pattern, options);
const [end, start] = normalizeReverseRange(bytes.byteLength, options);
if (needle.byteLength === 0) {
return start;
}
const firstOffset = start - needle.byteLength;
if (firstOffset < end) {
return -1;
}
for (let offset = firstOffset; offset >= end; offset--) {
if (bytesEqualAt(bytes, needle, offset)) {
return offset;
}
}
return -1;
}
function includes(data, pattern, options) {
return indexOf(data, pattern, options) !== -1;
}
function startsWith(data, pattern, options) {
const bytes = (0, buffer_source_js_1.toUint8Array)(data);
const needle = toPatternBytes(pattern, options);
if (needle.byteLength > bytes.byteLength) {
return false;
}
return bytesEqualAt(bytes, needle, 0);
}
function endsWith(data, pattern, options) {
const bytes = (0, buffer_source_js_1.toUint8Array)(data);
const needle = toPatternBytes(pattern, options);
if (needle.byteLength > bytes.byteLength) {
return false;
}
return bytesEqualAt(bytes, needle, bytes.byteLength - needle.byteLength);
}
function slice(data, start, end) {
const bytes = (0, buffer_source_js_1.toUint8Array)(data);
const normalizedStart = normalizeSliceIndex(start, 0, bytes.byteLength);
const normalizedEnd = normalizeSliceIndex(end, bytes.byteLength, bytes.byteLength);
if (normalizedEnd <= normalizedStart) {
return bytes.subarray(normalizedStart, normalizedStart);
}
return bytes.subarray(normalizedStart, normalizedEnd);
}
function tail(data, length) {
const bytes = (0, buffer_source_js_1.toUint8Array)(data);
const normalizedLength = Number.isFinite(length) ? Math.max(0, Math.trunc(length)) : 0;
if (normalizedLength >= bytes.byteLength) {
return bytes;
}
return bytes.subarray(bytes.byteLength - normalizedLength);
}
function copy(data) {
return (0, buffer_source_js_1.toUint8ArrayCopy)(data);
}
function compare(a, b) {
const left = (0, buffer_source_js_1.toUint8Array)(a);
const right = (0, buffer_source_js_1.toUint8Array)(b);
const limit = Math.min(left.byteLength, right.byteLength);
for (let index = 0; index < limit; index++) {
if (left[index] < right[index]) {
return -1;
}
if (left[index] > right[index]) {
return 1;
}
}
if (left.byteLength < right.byteLength) {
return -1;
}
if (left.byteLength > right.byteLength) {
return 1;
}
return 0;
}

View file

@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View file

@ -0,0 +1,74 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convert = void 0;
const index_js_1 = require("../bytes/index.js");
const index_js_2 = require("../encoding/index.js");
const defaults_js_1 = require("./defaults.js");
function encode(name, data, ...args) {
return defaults_js_1.defaultConverterRegistry.encode(name, data, ...args);
}
function decode(name, text, ...args) {
return defaults_js_1.defaultConverterRegistry.decode(name, text, ...args);
}
function tryDecode(name, text, ...args) {
return defaults_js_1.defaultConverterRegistry.tryDecode(name, text, ...args);
}
function normalize(name, text, ...args) {
return defaults_js_1.defaultConverterRegistry.normalize(name, text, ...args);
}
function parse(name, text, ...args) {
return defaults_js_1.defaultConverterRegistry.parse(name, text, ...args);
}
function format(name, data, value) {
return defaults_js_1.defaultConverterRegistry.format(name, data, value);
}
function transcode(text, options) {
return defaults_js_1.defaultConverterRegistry.transcode(text, options);
}
function detect(text, options) {
return defaults_js_1.defaultConverterRegistry.detect(text, options);
}
function normalizeEncodingName(encoding) {
return encoding.toLowerCase();
}
exports.convert = {
encode,
decode,
tryDecode,
normalize,
parse,
format,
transcode,
detect,
to(format, data, ...args) {
return encode(format, data, ...args);
},
from(format, text, ...args) {
return decode(format, text, ...args);
},
toString(data, encoding = "utf8") {
return encode(encoding, data);
},
fromString(text, encoding = "utf8") {
if (normalizeEncodingName(encoding) === "hex") {
return (0, index_js_1.toArrayBuffer)(index_js_2.hex.decode(text, { allowOddLength: true }));
}
return (0, index_js_1.toArrayBuffer)(decode(encoding, text));
},
toBase64: index_js_2.base64.encode,
fromBase64: (text) => (0, index_js_1.toArrayBuffer)(index_js_2.base64.decode(text)),
toBase64Url: index_js_2.base64url.encode,
fromBase64Url: (text) => (0, index_js_1.toArrayBuffer)(index_js_2.base64url.decode(text)),
toHex: index_js_2.hex.encode,
fromHex: (text) => (0, index_js_1.toArrayBuffer)(index_js_2.hex.decode(text, { allowOddLength: true })),
toBinary: index_js_2.binary.encode,
fromBinary: (text) => (0, index_js_1.toArrayBuffer)(index_js_2.binary.decode(text)),
toUtf8String: index_js_2.utf8.decode,
fromUtf8String: (text) => (0, index_js_1.toArrayBuffer)(index_js_2.utf8.encode(text)),
toUtf16String: (data, littleEndian = false) => index_js_2.utf16.decode(data, { littleEndian }),
fromUtf16String: (text, littleEndian = false) => (0, index_js_1.toArrayBuffer)(index_js_2.utf16.encode(text, { littleEndian })),
isHex: index_js_2.hex.is,
isBase64: index_js_2.base64.is,
isBase64Url: index_js_2.base64url.is,
formatString: index_js_2.base64.normalize,
};

View file

@ -0,0 +1,72 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultConverterRegistry = exports.defaultConverters = exports.utf16leConverter = exports.utf16beConverter = exports.utf8Converter = exports.base64urlConverter = exports.base64Converter = exports.hexConverter = exports.binaryConverter = exports.pemConverter = void 0;
const index_js_1 = require("../encoding/index.js");
const index_js_2 = require("../pem/index.js");
var index_js_3 = require("../pem/index.js");
Object.defineProperty(exports, "pemConverter", { enumerable: true, get: function () { return index_js_3.pemConverter; } });
const registry_js_1 = require("./registry.js");
exports.binaryConverter = {
name: "binary",
aliases: ["latin1"],
encode: index_js_1.binary.encode,
decode: index_js_1.binary.decode,
is: index_js_1.binary.is,
};
exports.hexConverter = {
name: "hex",
encode: index_js_1.hex.encode,
decode: index_js_1.hex.decode,
format: index_js_1.hex.format,
is: index_js_1.hex.is,
normalize: index_js_1.hex.normalize,
parse: index_js_1.hex.parse,
};
exports.base64Converter = {
name: "base64",
aliases: ["b64"],
encode: index_js_1.base64.encode,
decode: index_js_1.base64.decode,
is: index_js_1.base64.is,
normalize: index_js_1.base64.normalize,
};
exports.base64urlConverter = {
name: "base64url",
aliases: ["base64-url", "b64url"],
encode: index_js_1.base64url.encode,
decode: index_js_1.base64url.decode,
is: index_js_1.base64url.is,
normalize: index_js_1.base64url.normalize,
};
exports.utf8Converter = {
name: "utf8",
aliases: ["utf-8"],
encode: (data) => index_js_1.utf8.decode(data),
decode: (text) => index_js_1.utf8.encode(text),
is: (text) => typeof text === "string",
};
exports.utf16beConverter = {
name: "utf16be",
aliases: ["utf16", "utf-16", "utf-16be"],
encode: (data) => index_js_1.utf16.decode(data),
decode: (text) => index_js_1.utf16.encode(text),
is: (text) => typeof text === "string",
};
exports.utf16leConverter = {
name: "utf16le",
aliases: ["utf-16le", "ucs2", "usc2"],
encode: (data) => index_js_1.utf16.decode(data, { littleEndian: true }),
decode: (text) => index_js_1.utf16.encode(text, { littleEndian: true }),
is: (text) => typeof text === "string",
};
exports.defaultConverters = [
exports.binaryConverter,
exports.hexConverter,
exports.base64Converter,
exports.base64urlConverter,
exports.utf8Converter,
exports.utf16beConverter,
exports.utf16leConverter,
index_js_2.pemConverter,
];
exports.defaultConverterRegistry = (0, registry_js_1.createConverterRegistry)(exports.defaultConverters);

View file

@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convert = exports.utf8Converter = exports.utf16leConverter = exports.utf16beConverter = exports.pemConverter = exports.hexConverter = exports.defaultConverters = exports.defaultConverterRegistry = exports.binaryConverter = exports.base64urlConverter = exports.base64Converter = exports.createConverterRegistry = void 0;
var registry_js_1 = require("./registry.js");
Object.defineProperty(exports, "createConverterRegistry", { enumerable: true, get: function () { return registry_js_1.createConverterRegistry; } });
var defaults_js_1 = require("./defaults.js");
Object.defineProperty(exports, "base64Converter", { enumerable: true, get: function () { return defaults_js_1.base64Converter; } });
Object.defineProperty(exports, "base64urlConverter", { enumerable: true, get: function () { return defaults_js_1.base64urlConverter; } });
Object.defineProperty(exports, "binaryConverter", { enumerable: true, get: function () { return defaults_js_1.binaryConverter; } });
Object.defineProperty(exports, "defaultConverterRegistry", { enumerable: true, get: function () { return defaults_js_1.defaultConverterRegistry; } });
Object.defineProperty(exports, "defaultConverters", { enumerable: true, get: function () { return defaults_js_1.defaultConverters; } });
Object.defineProperty(exports, "hexConverter", { enumerable: true, get: function () { return defaults_js_1.hexConverter; } });
Object.defineProperty(exports, "pemConverter", { enumerable: true, get: function () { return defaults_js_1.pemConverter; } });
Object.defineProperty(exports, "utf16beConverter", { enumerable: true, get: function () { return defaults_js_1.utf16beConverter; } });
Object.defineProperty(exports, "utf16leConverter", { enumerable: true, get: function () { return defaults_js_1.utf16leConverter; } });
Object.defineProperty(exports, "utf8Converter", { enumerable: true, get: function () { return defaults_js_1.utf8Converter; } });
var convert_js_1 = require("./convert.js");
Object.defineProperty(exports, "convert", { enumerable: true, get: function () { return convert_js_1.convert; } });

View file

@ -0,0 +1,188 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createConverterRegistry = createConverterRegistry;
function keyOf(name) {
return name.trim().toLowerCase();
}
function toError(error) {
return error instanceof Error ? error : new Error(String(error));
}
function removeConverter(converters, primaryNames, converter) {
for (const alias of [converter.name, ...(converter.aliases ?? [])]) {
converters.delete(keyOf(alias));
}
primaryNames.delete(keyOf(converter.name));
}
function requireCapability(converter, name, capability) {
const method = converter[capability];
if (typeof method !== "function") {
throw new Error(`Converter '${name}' does not support ${capability}()`);
}
return method;
}
function detectConfidence(name, text, converter) {
const normalizedName = keyOf(converter.name || name);
const trimmed = text.trim();
if (!trimmed) {
return 0;
}
let accepted = false;
if (converter.is) {
accepted = converter.is(text);
}
let decodable = false;
try {
converter.decode(text);
decodable = true;
}
catch {
decodable = false;
}
if (!accepted && !decodable) {
return 0;
}
switch (normalizedName) {
case "pem":
return /-----BEGIN [^-]+-----/.test(text) ? 1 : 0;
case "hex": {
const compact = trimmed.replace(/^0x/i, "").replace(/[\s:.-]/g, "");
if (!compact || /[^0-9a-f]/i.test(compact) || compact.length % 2 !== 0) {
return 0;
}
if (/^0x/i.test(trimmed) || /[:\s.-]/.test(trimmed)) {
return 0.95;
}
if (/[a-f]/.test(trimmed) || /[A-F]/.test(trimmed)) {
return 0.8;
}
return 0.45;
}
case "base64url":
if (/[-_]/.test(trimmed)) {
return 0.95;
}
if (/=/.test(trimmed)) {
return 0.1;
}
return 0.6;
case "base64":
if (/[+/=]/.test(trimmed)) {
return 0.9;
}
return 0.55;
case "binary":
case "utf8":
case "utf16be":
case "utf16le":
return 0;
default:
return accepted && decodable ? 0.75 : 0.5;
}
}
function createConverterRegistry(initialConverters = []) {
const converters = new Map();
const primaryNames = new Set();
const api = {
register(converter, options = {}) {
if (!converter.name || !keyOf(converter.name)) {
throw new TypeError("Converter name is required");
}
const names = [...new Set([converter.name, ...(converter.aliases ?? [])].map(keyOf))];
const conflicts = new Set();
for (const name of names) {
const existing = converters.get(name);
if (!existing) {
continue;
}
if (!options.override) {
throw new Error(`Converter '${name}' is already registered`);
}
conflicts.add(existing);
}
for (const conflicting of conflicts) {
removeConverter(converters, primaryNames, conflicting);
}
for (const name of names) {
converters.set(name, converter);
}
primaryNames.add(keyOf(converter.name));
return this;
},
unregister(name) {
const converter = converters.get(keyOf(name));
if (!converter) {
return false;
}
removeConverter(converters, primaryNames, converter);
return true;
},
has(name) {
return converters.has(keyOf(name));
},
get(name) {
const converter = converters.get(keyOf(name));
if (!converter) {
throw new Error(`Converter '${name}' is not registered`);
}
return converter;
},
list() {
return [...primaryNames].map((name) => this.get(name));
},
encode(name, data, options) {
return this.get(name).encode(data, options);
},
decode(name, text, options) {
return this.get(name).decode(text, options);
},
tryDecode(name, text, options) {
try {
return { ok: true, bytes: this.decode(name, text, options) };
}
catch (error) {
return { ok: false, error: toError(error) };
}
},
normalize(name, text, options) {
const converter = this.get(name);
return requireCapability(converter, name, "normalize").call(converter, text, options);
},
parse(name, text, options) {
const converter = this.get(name);
return requireCapability(converter, name, "parse").call(converter, text, options);
},
format(name, data, format) {
const converter = this.get(name);
return requireCapability(converter, name, "format").call(converter, data, format);
},
transcode(text, options) {
const bytes = this.decode(options.from, text, options.fromOptions);
return this.encode(options.to, bytes, options.toOptions);
},
detect(text, options = {}) {
const formatNames = options.formats?.length
? options.formats.map((name) => String(name))
: this.list()
.map((converter) => converter.name)
.filter((name) => !["binary", "utf8", "utf16be", "utf16le"].includes(keyOf(name)));
const detections = new Map();
for (const requestedName of formatNames) {
const converter = this.get(requestedName);
const confidence = detectConfidence(requestedName, text, converter);
if (confidence <= 0) {
continue;
}
const format = converter.name;
const current = detections.get(format);
if (!current || confidence > current.confidence) {
detections.set(format, { format, confidence });
}
}
return [...detections.values()].sort((left, right) => right.confidence - left.confidence);
},
};
for (const converter of initialConverters) {
api.register(converter);
}
return api;
}

View file

@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View file

@ -0,0 +1,48 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.base64 = void 0;
exports.normalize = normalize;
exports.pad = pad;
exports.is = is;
exports.encode = encode;
exports.decode = decode;
const index_js_1 = require("../bytes/index.js");
const binary_js_1 = require("./binary.js");
const BASE64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
function nodeBuffer() {
return globalThis.Buffer;
}
function normalize(text) {
return text.replace(/[\n\r\t ]/g, "");
}
function pad(text) {
const remainder = text.length % 4;
return remainder ? text + "=".repeat(4 - remainder) : text;
}
function is(text) {
if (typeof text !== "string") {
return false;
}
const normalized = normalize(text);
return normalized === "" || BASE64_REGEX.test(normalized);
}
function encode(data, _options) {
const bytes = (0, index_js_1.toUint8Array)(data);
const buffer = nodeBuffer();
if (buffer) {
return buffer.from(bytes).toString("base64");
}
return btoa((0, binary_js_1.encode)(bytes));
}
function decode(text, _options) {
const normalized = normalize(text);
if (!is(normalized)) {
throw new TypeError("Input is not valid Base64 text");
}
const buffer = nodeBuffer();
if (buffer) {
return new Uint8Array(buffer.from(normalized, "base64"));
}
return (0, binary_js_1.decode)(atob(normalized));
}
exports.base64 = { encode, decode, is, normalize, pad };

View file

@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.base64url = void 0;
exports.normalize = normalize;
exports.is = is;
exports.encode = encode;
exports.decode = decode;
const base64_js_1 = require("./base64.js");
const BASE64URL_REGEX = /^[A-Za-z0-9_-]*$/;
function normalize(text) {
return text.replace(/[\n\r\t ]/g, "");
}
function is(text) {
return typeof text === "string" && BASE64URL_REGEX.test(normalize(text));
}
function encode(data, _options) {
return base64_js_1.base64.encode(data).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
}
function decode(text, _options) {
const normalized = normalize(text);
if (!is(normalized)) {
throw new TypeError("Input is not valid Base64Url text");
}
return base64_js_1.base64.decode(base64_js_1.base64.pad(normalized.replace(/-/g, "+").replace(/_/g, "/")));
}
exports.base64url = { encode, decode, is, normalize };

View file

@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.binary = void 0;
exports.encode = encode;
exports.decode = decode;
exports.is = is;
const index_js_1 = require("../bytes/index.js");
function encode(data) {
const bytes = (0, index_js_1.toUint8Array)(data);
let result = "";
for (const byte of bytes) {
result += String.fromCharCode(byte);
}
return result;
}
function decode(text) {
const result = new Uint8Array(text.length);
for (let i = 0; i < text.length; i++) {
result[i] = text.charCodeAt(i) & 0xff;
}
return result;
}
function is(text) {
return typeof text === "string";
}
exports.binary = { encode, decode, is };

View file

@ -0,0 +1,229 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.hex = exports.formats = void 0;
exports.normalize = normalize;
exports.is = is;
exports.encode = encode;
exports.decode = decode;
exports.parse = parse;
exports.format = format;
const index_js_1 = require("../bytes/index.js");
const HEX_CHARACTER_REGEX = /^[0-9a-f]$/i;
const COMMON_SEPARATORS = [" ", "\t", "\n", "\r", ":", "-", "."];
function resolveSeparators(options) {
if (options.separators === "none") {
return [];
}
if (!options.separators || options.separators === "common") {
return COMMON_SEPARATORS;
}
return options.separators;
}
function validateSeparator(separator) {
if (!separator) {
throw new TypeError("Hex separators must be non-empty strings");
}
}
function matchSeparator(text, index, separators) {
for (const separator of separators) {
if (text.startsWith(separator, index)) {
return separator;
}
}
return undefined;
}
function detectCase(text) {
const hasUpper = /[A-F]/.test(text);
const hasLower = /[a-f]/.test(text);
return hasUpper && !hasLower ? "upper" : "lower";
}
function detectLineSeparator(text) {
const match = /\r\n|\n/.exec(text);
if (!match) {
return undefined;
}
return match[0] === "\r\n" ? "\r\n" : "\n";
}
function compactForDetection(text) {
return text.replace(/[^0-9a-f]/gi, "");
}
function detectGroup(text) {
const segments = text.match(/[0-9A-Fa-f]+|[^0-9A-Fa-f]+/g) ?? [];
if (segments.length < 3) {
return undefined;
}
const hexSegments = segments.filter((_, index) => index % 2 === 0);
const separators = segments.filter((_, index) => index % 2 === 1);
const separator = separators[0];
if (!separator || separators.some((item) => item !== separator)) {
return undefined;
}
if (hexSegments.some((segment) => segment.length === 0 || segment.length % 2 !== 0)) {
return undefined;
}
const firstLength = hexSegments[0]?.length ?? 0;
if (!firstLength) {
return undefined;
}
if (hexSegments.slice(0, -1).some((segment) => segment.length !== firstLength)) {
return undefined;
}
if ((hexSegments[hexSegments.length - 1]?.length ?? 0) > firstLength) {
return undefined;
}
return {
size: firstLength / 2,
separator,
};
}
function detectFormat(text) {
const trimmed = text.trim();
const prefix = /^0x/i.test(trimmed) ? "0x" : "";
const body = prefix ? trimmed.slice(2) : trimmed;
const lineSeparator = detectLineSeparator(body);
const lines = body.split(/\r\n|\n/).filter((line) => line.length > 0);
const sampleLine = lines[0]?.trim() ?? "";
const group = detectGroup(sampleLine);
const format = {
case: detectCase(trimmed),
prefix,
};
if (group) {
format.group = group;
}
if (lineSeparator && lines.length > 1) {
const firstLineBytes = compactForDetection(lines[0] ?? "").length / 2;
if (firstLineBytes > 0 && lines.slice(0, -1).every((line) => compactForDetection(line).length / 2 === firstLineBytes)) {
format.line = {
bytesPerLine: firstLineBytes,
separator: lineSeparator,
};
}
}
return format;
}
function normalizeText(text, options) {
const allowPrefix = options.allowPrefix ?? true;
const separators = [...resolveSeparators(options)].sort((left, right) => right.length - left.length);
for (const separator of separators) {
validateSeparator(separator);
}
let working = text.trim();
if (/^0x/i.test(working)) {
if (!allowPrefix) {
throw new TypeError("Hexadecimal text must not include a 0x prefix");
}
working = working.slice(2);
}
let normalized = "";
let lastTokenWasSeparator = false;
for (let index = 0; index < working.length;) {
const character = working[index] ?? "";
if (HEX_CHARACTER_REGEX.test(character)) {
normalized += character;
lastTokenWasSeparator = false;
index += 1;
continue;
}
const separator = matchSeparator(working, index, separators);
if (!separator) {
throw new TypeError("Input is not valid hexadecimal text");
}
if (options.strict && (lastTokenWasSeparator || normalized.length === 0)) {
throw new TypeError("Hexadecimal text contains misplaced separators");
}
lastTokenWasSeparator = true;
index += separator.length;
}
if (options.strict && lastTokenWasSeparator && normalized.length > 0) {
throw new TypeError("Hexadecimal text must not end with a separator");
}
if (normalized.length % 2 !== 0) {
if (!options.allowOddLength) {
throw new TypeError("Hexadecimal text must contain an even number of characters");
}
normalized = `0${normalized}`;
}
return normalized.toLowerCase();
}
function groupPairs(pairs, group) {
if (!group) {
return pairs.join("");
}
if (!Number.isInteger(group.size) || group.size < 1) {
throw new RangeError("Hex group size must be a positive integer");
}
const chunks = [];
for (let index = 0; index < pairs.length; index += group.size) {
chunks.push(pairs.slice(index, index + group.size).join(""));
}
return chunks.join(group.separator);
}
function normalize(text, options = {}) {
return normalizeText(text, options);
}
function is(text, options = {}) {
if (typeof text !== "string") {
return false;
}
try {
normalize(text, options);
return true;
}
catch {
return false;
}
}
function encode(data, options = {}) {
const bytes = (0, index_js_1.toUint8Array)(data);
const casing = options.case ?? "lower";
const pairs = Array.from(bytes, (byte) => {
const text = byte.toString(16).padStart(2, "0");
return casing === "upper" ? text.toUpperCase() : text;
});
let body = "";
if (options.line) {
const bytesPerLine = options.line.bytesPerLine;
if (!Number.isInteger(bytesPerLine) || bytesPerLine < 1) {
throw new RangeError("Hex bytesPerLine must be a positive integer");
}
const separator = options.line.separator ?? "\n";
const lines = [];
for (let index = 0; index < pairs.length; index += bytesPerLine) {
lines.push(groupPairs(pairs.slice(index, index + bytesPerLine), options.group));
}
body = lines.join(separator);
}
else {
body = groupPairs(pairs, options.group);
}
return `${options.prefix ?? ""}${body}`;
}
function decode(text, options = {}) {
const normalized = normalize(text, options);
const result = new Uint8Array(normalized.length / 2);
for (let i = 0; i < normalized.length; i += 2) {
result[i / 2] = Number.parseInt(normalized.slice(i, i + 2), 16);
}
return result;
}
function parse(text, options = {}) {
const normalized = normalize(text, options);
return {
bytes: decode(normalized),
format: detectFormat(text),
normalized,
};
}
function format(data, value) {
return encode(data, value);
}
exports.formats = {
compact: Object.freeze({}),
upper: Object.freeze({ case: "upper" }),
colon: Object.freeze({ group: { size: 1, separator: ":" } }),
colonUpper: Object.freeze({ case: "upper", group: { size: 1, separator: ":" } }),
groupsOf4: Object.freeze({ group: { size: 4, separator: " " } }),
prefixed: Object.freeze({ prefix: "0x" }),
};
exports.hex = { encode, decode, format, formats: exports.formats, is, normalize, parse };

View file

@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.base64url = exports.base64 = exports.utf16 = exports.utf8 = exports.hex = exports.binary = void 0;
const tslib_1 = require("tslib");
exports.binary = tslib_1.__importStar(require("./binary.js"));
exports.hex = tslib_1.__importStar(require("./hex.js"));
exports.utf8 = tslib_1.__importStar(require("./utf8.js"));
exports.utf16 = tslib_1.__importStar(require("./utf16.js"));
exports.base64 = tslib_1.__importStar(require("./base64.js"));
exports.base64url = tslib_1.__importStar(require("./base64url.js"));

View file

@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.utf16 = void 0;
exports.encode = encode;
exports.decode = decode;
const index_js_1 = require("../bytes/index.js");
function encode(text, options = {}) {
const result = new ArrayBuffer(text.length * 2);
const view = new DataView(result);
for (let i = 0; i < text.length; i++) {
view.setUint16(i * 2, text.charCodeAt(i), options.littleEndian ?? false);
}
return new Uint8Array(result);
}
function decode(data, options = {}) {
const buffer = (0, index_js_1.toArrayBuffer)(data);
const view = new DataView(buffer);
let result = "";
for (let i = 0; i < buffer.byteLength; i += 2) {
result += String.fromCharCode(view.getUint16(i, options.littleEndian ?? false));
}
return result;
}
exports.utf16 = { encode, decode };

View file

@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.utf8 = void 0;
exports.encode = encode;
exports.decode = decode;
const index_js_1 = require("../bytes/index.js");
function encode(text) {
return new TextEncoder().encode(text);
}
function decode(data) {
return new TextDecoder("utf-8", { fatal: false }).decode((0, index_js_1.toUint8Array)(data));
}
exports.utf8 = { encode, decode };

View file

@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.bytes = void 0;
const tslib_1 = require("tslib");
tslib_1.__exportStar(require("./bytes/index.js"), exports);
exports.bytes = tslib_1.__importStar(require("./bytes/index.js"));
tslib_1.__exportStar(require("./encoding/index.js"), exports);
tslib_1.__exportStar(require("./pem/index.js"), exports);
tslib_1.__exportStar(require("./converters/index.js"), exports);
tslib_1.__exportStar(require("./legacy/index.js"), exports);

View file

@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BufferSourceConverter = void 0;
const index_js_1 = require("../bytes/index.js");
class BufferSourceConverter {
static isArrayBuffer(data) {
return (0, index_js_1.isArrayBuffer)(data);
}
static toArrayBuffer(data) {
return (0, index_js_1.toArrayBuffer)(data);
}
static toUint8Array(data) {
return (0, index_js_1.toUint8Array)(data);
}
static toView(data, type) {
return (0, index_js_1.toView)(data, type);
}
static isBufferSource(data) {
return (0, index_js_1.isBufferSource)(data);
}
static isArrayBufferView(data) {
return (0, index_js_1.isArrayBufferView)(data);
}
static isEqual(a, b) {
return (0, index_js_1.equal)(a, b);
}
static concat(first, second, ...rest) {
if (Array.isArray(first)) {
return typeof second === "function"
? (0, index_js_1.concat)(first, second)
: (0, index_js_1.concat)(first);
}
const buffers = [first, second, ...rest].filter(Boolean);
return (0, index_js_1.concat)(buffers);
}
}
exports.BufferSourceConverter = BufferSourceConverter;

View file

@ -0,0 +1,72 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Convert = void 0;
const index_js_1 = require("../converters/index.js");
function normalizeTextEncoding(encoding) {
return encoding === "ascii" ? "binary" : encoding;
}
class Convert {
static DEFAULT_UTF8_ENCODING = "utf8";
static isHex(data) {
return index_js_1.convert.isHex(data);
}
static isBase64(data) {
return index_js_1.convert.isBase64(data);
}
static isBase64Url(data) {
return index_js_1.convert.isBase64Url(data);
}
static ToString(buffer, enc = "utf8") {
return index_js_1.convert.toString(buffer, enc);
}
static FromString(str, enc = "utf8") {
if (!str) {
return new ArrayBuffer(0);
}
return index_js_1.convert.fromString(str, enc);
}
static ToBase64(buffer) {
return index_js_1.convert.toBase64(buffer);
}
static FromBase64(base64) {
return index_js_1.convert.fromBase64(base64);
}
static FromBase64Url(base64url) {
return index_js_1.convert.fromBase64Url(base64url);
}
static ToBase64Url(data) {
return index_js_1.convert.toBase64Url(data);
}
static FromUtf8String(text, encoding = Convert.DEFAULT_UTF8_ENCODING) {
return index_js_1.convert.fromString(text, normalizeTextEncoding(encoding));
}
static ToUtf8String(buffer, encoding = Convert.DEFAULT_UTF8_ENCODING) {
return index_js_1.convert.toString(buffer, normalizeTextEncoding(encoding));
}
static FromBinary(text) {
return index_js_1.convert.fromBinary(text);
}
static ToBinary(buffer) {
return index_js_1.convert.toBinary(buffer);
}
static ToHex(buffer) {
return index_js_1.convert.toHex(buffer);
}
static FromHex(hexString) {
return index_js_1.convert.fromHex(hexString);
}
static ToUtf16String(buffer, littleEndian = false) {
return index_js_1.convert.toUtf16String(buffer, littleEndian);
}
static FromUtf16String(text, littleEndian = false) {
return index_js_1.convert.fromUtf16String(text, littleEndian);
}
static Base64Padding(base64) {
const padCount = 4 - (base64.length % 4);
return padCount < 4 ? base64 + "=".repeat(padCount) : base64;
}
static formatString(data) {
return index_js_1.convert.formatString(data);
}
}
exports.Convert = Convert;

View file

@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.assign = assign;
exports.combine = combine;
exports.isEqual = isEqual;
const index_js_1 = require("../bytes/index.js");
function assign(target, ...sources) {
for (const source of sources) {
if (!source) {
continue;
}
for (const prop in source) {
target[prop] = source[prop];
}
}
return target;
}
function combine(...buf) {
return (0, index_js_1.concat)(buf);
}
function isEqual(bytes1, bytes2) {
return (0, index_js_1.equal)(bytes1, bytes2);
}

View file

@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isEqual = exports.combine = exports.assign = exports.Convert = exports.BufferSourceConverter = void 0;
var buffer_source_converter_js_1 = require("./buffer-source-converter.js");
Object.defineProperty(exports, "BufferSourceConverter", { enumerable: true, get: function () { return buffer_source_converter_js_1.BufferSourceConverter; } });
var convert_js_1 = require("./convert.js");
Object.defineProperty(exports, "Convert", { enumerable: true, get: function () { return convert_js_1.Convert; } });
var functions_js_1 = require("./functions.js");
Object.defineProperty(exports, "assign", { enumerable: true, get: function () { return functions_js_1.assign; } });
Object.defineProperty(exports, "combine", { enumerable: true, get: function () { return functions_js_1.combine; } });
Object.defineProperty(exports, "isEqual", { enumerable: true, get: function () { return functions_js_1.isEqual; } });

View file

@ -0,0 +1,3 @@
{
"type": "commonjs"
}

View file

@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.pemConverter = exports.pem = exports.parse = exports.format = exports.findAll = exports.find = exports.encodeMany = exports.encode = exports.decodeFirst = exports.decode = void 0;
var pem_js_1 = require("./pem.js");
Object.defineProperty(exports, "decode", { enumerable: true, get: function () { return pem_js_1.decode; } });
Object.defineProperty(exports, "decodeFirst", { enumerable: true, get: function () { return pem_js_1.decodeFirst; } });
Object.defineProperty(exports, "encode", { enumerable: true, get: function () { return pem_js_1.encode; } });
Object.defineProperty(exports, "encodeMany", { enumerable: true, get: function () { return pem_js_1.encodeMany; } });
Object.defineProperty(exports, "find", { enumerable: true, get: function () { return pem_js_1.find; } });
Object.defineProperty(exports, "findAll", { enumerable: true, get: function () { return pem_js_1.findAll; } });
Object.defineProperty(exports, "format", { enumerable: true, get: function () { return pem_js_1.format; } });
Object.defineProperty(exports, "parse", { enumerable: true, get: function () { return pem_js_1.parse; } });
Object.defineProperty(exports, "pem", { enumerable: true, get: function () { return pem_js_1.pem; } });
Object.defineProperty(exports, "pemConverter", { enumerable: true, get: function () { return pem_js_1.pemConverter; } });

View file

@ -0,0 +1,140 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.pemConverter = exports.pem = void 0;
exports.encode = encode;
exports.encodeMany = encodeMany;
exports.decode = decode;
exports.find = find;
exports.findAll = findAll;
exports.decodeFirst = decodeFirst;
exports.parse = parse;
exports.format = format;
const base64_js_1 = require("../encoding/base64.js");
const LABEL_REGEX = /^[A-Z0-9][A-Z0-9 ._-]*[A-Z0-9]$/i;
const PEM_BLOCK_REGEX = /-----BEGIN ([^-]+)-----([\s\S]*?)-----END \1-----/g;
function assertLabel(label) {
if (!LABEL_REGEX.test(label)) {
throw new TypeError(`Invalid PEM label '${label}'`);
}
}
function wrap(text, lineLength) {
const result = [];
for (let i = 0; i < text.length; i += lineLength) {
result.push(text.slice(i, i + lineLength));
}
return result;
}
function parseBody(body) {
const normalized = body.trim().replace(/\r\n/g, "\n");
const lines = normalized.split("\n").map((line) => line.trim()).filter(Boolean);
const headers = {};
let index = 0;
for (; index < lines.length; index++) {
const line = lines[index];
const separator = line.indexOf(":");
if (separator <= 0) {
break;
}
headers[line.slice(0, separator).trim()] = line.slice(separator + 1).trim();
}
return {
headers: Object.keys(headers).length ? headers : undefined,
base64Lines: lines.slice(index),
base64Text: lines.slice(index).join(""),
};
}
function detectNewline(text) {
return /\r\n/.test(text) ? "\r\n" : "\n";
}
function collectBlocks(text, options = {}) {
const blocks = [];
const requestedLabel = options.label;
let match;
PEM_BLOCK_REGEX.lastIndex = 0;
while ((match = PEM_BLOCK_REGEX.exec(text))) {
const label = match[1].trim();
if (requestedLabel && label !== requestedLabel) {
continue;
}
assertLabel(label);
const parsed = parseBody(match[2]);
blocks.push({
label,
data: base64_js_1.base64.decode(parsed.base64Text),
headers: parsed.headers,
lineLength: parsed.base64Lines[0]?.length ?? 64,
newline: detectNewline(match[0]),
});
}
if (options.strict && blocks.length === 0) {
throw new TypeError(requestedLabel
? `No PEM block with label '${requestedLabel}' was found`
: "No PEM blocks were found");
}
return blocks;
}
function encode(label, data, options = {}) {
assertLabel(label);
const lineLength = options.lineLength ?? 64;
if (!Number.isInteger(lineLength) || lineLength < 1) {
throw new RangeError("PEM lineLength must be a positive integer");
}
const newline = options.newline ?? "\n";
const lines = [`-----BEGIN ${label}-----`];
if (options.headers) {
for (const [name, value] of Object.entries(options.headers)) {
lines.push(`${name}: ${value}`);
}
lines.push("");
}
lines.push(...wrap(base64_js_1.base64.encode(data), lineLength));
lines.push(`-----END ${label}-----`);
return `${lines.join(newline)}${newline}`;
}
function encodeMany(blocks, options = {}) {
return blocks.map((block) => encode(block.label, block.data, { ...options, headers: block.headers ?? options.headers })).join("");
}
function decode(text, options = {}) {
return collectBlocks(text, options).map(({ lineLength: _lineLength, newline: _newline, ...block }) => block);
}
function find(text, label) {
return decode(text, { label })[0];
}
function findAll(text, label) {
return decode(text, { label });
}
function decodeFirst(text, label) {
const [block] = decode(text, { label, strict: true });
return block.data;
}
function parse(text, options = {}) {
const [block] = collectBlocks(text, { ...options, strict: true });
const format = {
label: block.label,
headers: block.headers,
lineLength: block.lineLength,
newline: block.newline,
};
return {
bytes: block.data,
format,
normalized: encode(block.label, block.data, format),
};
}
function format(data, value) {
return encode(value.label, data, value);
}
exports.pem = { decode, decodeFirst, encode, encodeMany, find, findAll, format, parse };
exports.pemConverter = {
name: "pem",
encode: (data, options) => {
if (!options?.label) {
throw new TypeError("PEM label is required");
}
return encode(options.label, data, options);
},
decode: (text, options) => decodeFirst(text, options?.label),
format,
is: (text) => typeof text === "string" && /-----BEGIN [^-]+-----/.test(text),
parse,
};

View file

@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View file

@ -0,0 +1,101 @@
const ARRAY_BUFFER_TAG = "[object ArrayBuffer]";
const SHARED_ARRAY_BUFFER_TAG = "[object SharedArrayBuffer]";
function tagOf(value) {
return Object.prototype.toString.call(value);
}
function isDataViewConstructor(type) {
return type === DataView || type.prototype instanceof DataView;
}
function bytesPerElement(type) {
if (isDataViewConstructor(type)) {
return 1;
}
const value = type.BYTES_PER_ELEMENT;
return value ?? 1;
}
function isArrayBufferViewLike(value) {
if (ArrayBuffer.isView(value)) {
return true;
}
if (!value || typeof value !== "object") {
return false;
}
const view = value;
return typeof view.byteOffset === "number"
&& typeof view.byteLength === "number"
&& isArrayBufferLike(view.buffer);
}
function copyBytes(data) {
const view = toUint8Array(data);
const copy = new Uint8Array(view.byteLength);
copy.set(view);
return copy;
}
export function isArrayBuffer(value) {
return tagOf(value) === ARRAY_BUFFER_TAG;
}
export function isSharedArrayBuffer(value) {
return typeof SharedArrayBuffer !== "undefined" && tagOf(value) === SHARED_ARRAY_BUFFER_TAG;
}
export function isArrayBufferLike(value) {
return isArrayBuffer(value) || isSharedArrayBuffer(value);
}
export function isArrayBufferView(value) {
return isArrayBufferViewLike(value);
}
export function isBufferSource(value) {
return isArrayBufferLike(value) || isArrayBufferView(value);
}
export function assertBufferSource(value) {
if (!isBufferSource(value)) {
throw new TypeError("Expected ArrayBuffer, SharedArrayBuffer, or ArrayBufferView");
}
}
export function toUint8Array(data) {
assertBufferSource(data);
if (isArrayBufferLike(data)) {
return new Uint8Array(data);
}
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
}
export function toUint8ArrayCopy(data) {
return copyBytes(data);
}
export function toArrayBuffer(data) {
assertBufferSource(data);
if (isArrayBuffer(data)) {
return data;
}
const buffer = new ArrayBuffer(data.byteLength);
new Uint8Array(buffer).set(toUint8Array(data));
return buffer;
}
export function toArrayBufferLike(data) {
assertBufferSource(data);
if (isArrayBufferLike(data)) {
return data;
}
if (data.byteOffset === 0 && data.byteLength === data.buffer.byteLength) {
return data.buffer;
}
return copyBytes(data).buffer;
}
export function toView(data, type) {
assertBufferSource(data);
if (ArrayBuffer.isView(data) && data.constructor === type) {
return data;
}
const view = toUint8Array(data);
const elementSize = bytesPerElement(type);
if (view.byteOffset % elementSize !== 0 || view.byteLength % elementSize !== 0) {
throw new RangeError(`Cannot create ${type.name} over unaligned byte range`);
}
if (isDataViewConstructor(type)) {
return new type(view.buffer, view.byteOffset, view.byteLength);
}
return new type(view.buffer, view.byteOffset, view.byteLength / elementSize);
}
export function toViewCopy(data, type) {
const copy = toUint8ArrayCopy(data);
return toView(copy, type);
}

View file

@ -0,0 +1,37 @@
import { isBufferSource, toUint8Array, toView } from "./buffer-source.js";
export function concatToUint8Array(buffers) {
const views = [];
let length = 0;
for (const buffer of buffers) {
const view = toUint8Array(buffer);
views.push(view);
length += view.byteLength;
}
const result = new Uint8Array(length);
let offset = 0;
for (const view of views) {
result.set(view, offset);
offset += view.byteLength;
}
return result;
}
export function concat(first, second, ...rest) {
let buffers;
let type;
if (typeof second === "function") {
buffers = Array.from(first);
type = second;
}
else if (isBufferSource(first)) {
buffers = [first, second, ...rest].filter(isBufferSource);
}
else {
buffers = Array.from(first);
if (second) {
buffers.push(second);
}
buffers.push(...rest);
}
const bytes = concatToUint8Array(buffers);
return type ? toView(bytes, type) : bytes.buffer;
}

View file

@ -0,0 +1,14 @@
import { toUint8Array } from "./buffer-source.js";
export function equal(a, b, options = {}) {
const left = toUint8Array(a);
const right = toUint8Array(b);
if (!options.constantTime && left.byteLength !== right.byteLength) {
return false;
}
const length = Math.max(left.byteLength, right.byteLength);
let diff = left.byteLength ^ right.byteLength;
for (let i = 0; i < length; i++) {
diff |= (left[i] ?? 0) ^ (right[i] ?? 0);
}
return diff === 0;
}

View file

@ -0,0 +1,4 @@
export { assertBufferSource, isArrayBuffer, isArrayBufferLike, isArrayBufferView, isBufferSource, isSharedArrayBuffer, toArrayBuffer, toArrayBufferLike, toUint8Array, toUint8ArrayCopy, toView, toViewCopy, } from "./buffer-source.js";
export { concat, concatToUint8Array } from "./concat.js";
export { equal } from "./equal.js";
export { compare, copy, endsWith, includes, indexOf, lastIndexOf, slice, startsWith, tail, } from "./sequence.js";

View file

@ -0,0 +1,150 @@
import { toUint8Array, toUint8ArrayCopy } from "./buffer-source.js";
function clampIndex(value, fallback, length) {
const normalized = Number.isFinite(value) ? Math.trunc(value) : fallback;
if (normalized <= 0) {
return 0;
}
if (normalized >= length) {
return length;
}
return normalized;
}
function normalizeForwardRange(length, options) {
const start = clampIndex(options?.start, 0, length);
const end = clampIndex(options?.end, length, length);
return end >= start ? [start, end] : [start, start];
}
function normalizeReverseRange(length, options) {
const start = clampIndex(options?.start, length, length);
const end = clampIndex(options?.end, 0, length);
return start >= end ? [end, start] : [start, start];
}
function normalizeSliceIndex(value, fallback, length) {
const normalized = Number.isFinite(value) ? Math.trunc(value) : fallback;
if (normalized < 0) {
return Math.max(length + normalized, 0);
}
if (normalized > length) {
return length;
}
return normalized;
}
function encodeAscii(text) {
const bytes = new Uint8Array(text.length);
for (let i = 0; i < text.length; i++) {
bytes[i] = text.charCodeAt(i) & 0xff;
}
return bytes;
}
function encodeUtf8(text) {
return new TextEncoder().encode(text);
}
function toPatternBytes(pattern, options) {
if (typeof pattern === "string") {
return options?.encoding === "utf8" ? encodeUtf8(pattern) : encodeAscii(pattern);
}
return toUint8Array(pattern);
}
function bytesEqualAt(data, pattern, offset) {
for (let index = 0; index < pattern.byteLength; index++) {
if (data[offset + index] !== pattern[index]) {
return false;
}
}
return true;
}
export function indexOf(data, pattern, options) {
const bytes = toUint8Array(data);
const needle = toPatternBytes(pattern, options);
const [start, end] = normalizeForwardRange(bytes.byteLength, options);
if (needle.byteLength === 0) {
return start;
}
const lastOffset = end - needle.byteLength;
if (lastOffset < start) {
return -1;
}
for (let offset = start; offset <= lastOffset; offset++) {
if (bytesEqualAt(bytes, needle, offset)) {
return offset;
}
}
return -1;
}
export function lastIndexOf(data, pattern, options) {
const bytes = toUint8Array(data);
const needle = toPatternBytes(pattern, options);
const [end, start] = normalizeReverseRange(bytes.byteLength, options);
if (needle.byteLength === 0) {
return start;
}
const firstOffset = start - needle.byteLength;
if (firstOffset < end) {
return -1;
}
for (let offset = firstOffset; offset >= end; offset--) {
if (bytesEqualAt(bytes, needle, offset)) {
return offset;
}
}
return -1;
}
export function includes(data, pattern, options) {
return indexOf(data, pattern, options) !== -1;
}
export function startsWith(data, pattern, options) {
const bytes = toUint8Array(data);
const needle = toPatternBytes(pattern, options);
if (needle.byteLength > bytes.byteLength) {
return false;
}
return bytesEqualAt(bytes, needle, 0);
}
export function endsWith(data, pattern, options) {
const bytes = toUint8Array(data);
const needle = toPatternBytes(pattern, options);
if (needle.byteLength > bytes.byteLength) {
return false;
}
return bytesEqualAt(bytes, needle, bytes.byteLength - needle.byteLength);
}
export function slice(data, start, end) {
const bytes = toUint8Array(data);
const normalizedStart = normalizeSliceIndex(start, 0, bytes.byteLength);
const normalizedEnd = normalizeSliceIndex(end, bytes.byteLength, bytes.byteLength);
if (normalizedEnd <= normalizedStart) {
return bytes.subarray(normalizedStart, normalizedStart);
}
return bytes.subarray(normalizedStart, normalizedEnd);
}
export function tail(data, length) {
const bytes = toUint8Array(data);
const normalizedLength = Number.isFinite(length) ? Math.max(0, Math.trunc(length)) : 0;
if (normalizedLength >= bytes.byteLength) {
return bytes;
}
return bytes.subarray(bytes.byteLength - normalizedLength);
}
export function copy(data) {
return toUint8ArrayCopy(data);
}
export function compare(a, b) {
const left = toUint8Array(a);
const right = toUint8Array(b);
const limit = Math.min(left.byteLength, right.byteLength);
for (let index = 0; index < limit; index++) {
if (left[index] < right[index]) {
return -1;
}
if (left[index] > right[index]) {
return 1;
}
}
if (left.byteLength < right.byteLength) {
return -1;
}
if (left.byteLength > right.byteLength) {
return 1;
}
return 0;
}

View file

@ -0,0 +1 @@
export {};

View file

@ -0,0 +1,71 @@
import { toArrayBuffer } from "../bytes/index.js";
import { base64, base64url, binary, hex, utf8, utf16 } from "../encoding/index.js";
import { defaultConverterRegistry } from "./defaults.js";
function encode(name, data, ...args) {
return defaultConverterRegistry.encode(name, data, ...args);
}
function decode(name, text, ...args) {
return defaultConverterRegistry.decode(name, text, ...args);
}
function tryDecode(name, text, ...args) {
return defaultConverterRegistry.tryDecode(name, text, ...args);
}
function normalize(name, text, ...args) {
return defaultConverterRegistry.normalize(name, text, ...args);
}
function parse(name, text, ...args) {
return defaultConverterRegistry.parse(name, text, ...args);
}
function format(name, data, value) {
return defaultConverterRegistry.format(name, data, value);
}
function transcode(text, options) {
return defaultConverterRegistry.transcode(text, options);
}
function detect(text, options) {
return defaultConverterRegistry.detect(text, options);
}
function normalizeEncodingName(encoding) {
return encoding.toLowerCase();
}
export const convert = {
encode,
decode,
tryDecode,
normalize,
parse,
format,
transcode,
detect,
to(format, data, ...args) {
return encode(format, data, ...args);
},
from(format, text, ...args) {
return decode(format, text, ...args);
},
toString(data, encoding = "utf8") {
return encode(encoding, data);
},
fromString(text, encoding = "utf8") {
if (normalizeEncodingName(encoding) === "hex") {
return toArrayBuffer(hex.decode(text, { allowOddLength: true }));
}
return toArrayBuffer(decode(encoding, text));
},
toBase64: base64.encode,
fromBase64: (text) => toArrayBuffer(base64.decode(text)),
toBase64Url: base64url.encode,
fromBase64Url: (text) => toArrayBuffer(base64url.decode(text)),
toHex: hex.encode,
fromHex: (text) => toArrayBuffer(hex.decode(text, { allowOddLength: true })),
toBinary: binary.encode,
fromBinary: (text) => toArrayBuffer(binary.decode(text)),
toUtf8String: utf8.decode,
fromUtf8String: (text) => toArrayBuffer(utf8.encode(text)),
toUtf16String: (data, littleEndian = false) => utf16.decode(data, { littleEndian }),
fromUtf16String: (text, littleEndian = false) => toArrayBuffer(utf16.encode(text, { littleEndian })),
isHex: hex.is,
isBase64: base64.is,
isBase64Url: base64url.is,
formatString: base64.normalize,
};

View file

@ -0,0 +1,68 @@
import { base64, base64url, binary, hex, utf8, utf16 } from "../encoding/index.js";
import { pemConverter } from "../pem/index.js";
export { pemConverter } from "../pem/index.js";
import { createConverterRegistry } from "./registry.js";
export const binaryConverter = {
name: "binary",
aliases: ["latin1"],
encode: binary.encode,
decode: binary.decode,
is: binary.is,
};
export const hexConverter = {
name: "hex",
encode: hex.encode,
decode: hex.decode,
format: hex.format,
is: hex.is,
normalize: hex.normalize,
parse: hex.parse,
};
export const base64Converter = {
name: "base64",
aliases: ["b64"],
encode: base64.encode,
decode: base64.decode,
is: base64.is,
normalize: base64.normalize,
};
export const base64urlConverter = {
name: "base64url",
aliases: ["base64-url", "b64url"],
encode: base64url.encode,
decode: base64url.decode,
is: base64url.is,
normalize: base64url.normalize,
};
export const utf8Converter = {
name: "utf8",
aliases: ["utf-8"],
encode: (data) => utf8.decode(data),
decode: (text) => utf8.encode(text),
is: (text) => typeof text === "string",
};
export const utf16beConverter = {
name: "utf16be",
aliases: ["utf16", "utf-16", "utf-16be"],
encode: (data) => utf16.decode(data),
decode: (text) => utf16.encode(text),
is: (text) => typeof text === "string",
};
export const utf16leConverter = {
name: "utf16le",
aliases: ["utf-16le", "ucs2", "usc2"],
encode: (data) => utf16.decode(data, { littleEndian: true }),
decode: (text) => utf16.encode(text, { littleEndian: true }),
is: (text) => typeof text === "string",
};
export const defaultConverters = [
binaryConverter,
hexConverter,
base64Converter,
base64urlConverter,
utf8Converter,
utf16beConverter,
utf16leConverter,
pemConverter,
];
export const defaultConverterRegistry = createConverterRegistry(defaultConverters);

View file

@ -0,0 +1,3 @@
export { createConverterRegistry } from "./registry.js";
export { base64Converter, base64urlConverter, binaryConverter, defaultConverterRegistry, defaultConverters, hexConverter, pemConverter, utf16beConverter, utf16leConverter, utf8Converter, } from "./defaults.js";
export { convert } from "./convert.js";

View file

@ -0,0 +1,185 @@
function keyOf(name) {
return name.trim().toLowerCase();
}
function toError(error) {
return error instanceof Error ? error : new Error(String(error));
}
function removeConverter(converters, primaryNames, converter) {
for (const alias of [converter.name, ...(converter.aliases ?? [])]) {
converters.delete(keyOf(alias));
}
primaryNames.delete(keyOf(converter.name));
}
function requireCapability(converter, name, capability) {
const method = converter[capability];
if (typeof method !== "function") {
throw new Error(`Converter '${name}' does not support ${capability}()`);
}
return method;
}
function detectConfidence(name, text, converter) {
const normalizedName = keyOf(converter.name || name);
const trimmed = text.trim();
if (!trimmed) {
return 0;
}
let accepted = false;
if (converter.is) {
accepted = converter.is(text);
}
let decodable = false;
try {
converter.decode(text);
decodable = true;
}
catch {
decodable = false;
}
if (!accepted && !decodable) {
return 0;
}
switch (normalizedName) {
case "pem":
return /-----BEGIN [^-]+-----/.test(text) ? 1 : 0;
case "hex": {
const compact = trimmed.replace(/^0x/i, "").replace(/[\s:.-]/g, "");
if (!compact || /[^0-9a-f]/i.test(compact) || compact.length % 2 !== 0) {
return 0;
}
if (/^0x/i.test(trimmed) || /[:\s.-]/.test(trimmed)) {
return 0.95;
}
if (/[a-f]/.test(trimmed) || /[A-F]/.test(trimmed)) {
return 0.8;
}
return 0.45;
}
case "base64url":
if (/[-_]/.test(trimmed)) {
return 0.95;
}
if (/=/.test(trimmed)) {
return 0.1;
}
return 0.6;
case "base64":
if (/[+/=]/.test(trimmed)) {
return 0.9;
}
return 0.55;
case "binary":
case "utf8":
case "utf16be":
case "utf16le":
return 0;
default:
return accepted && decodable ? 0.75 : 0.5;
}
}
export function createConverterRegistry(initialConverters = []) {
const converters = new Map();
const primaryNames = new Set();
const api = {
register(converter, options = {}) {
if (!converter.name || !keyOf(converter.name)) {
throw new TypeError("Converter name is required");
}
const names = [...new Set([converter.name, ...(converter.aliases ?? [])].map(keyOf))];
const conflicts = new Set();
for (const name of names) {
const existing = converters.get(name);
if (!existing) {
continue;
}
if (!options.override) {
throw new Error(`Converter '${name}' is already registered`);
}
conflicts.add(existing);
}
for (const conflicting of conflicts) {
removeConverter(converters, primaryNames, conflicting);
}
for (const name of names) {
converters.set(name, converter);
}
primaryNames.add(keyOf(converter.name));
return this;
},
unregister(name) {
const converter = converters.get(keyOf(name));
if (!converter) {
return false;
}
removeConverter(converters, primaryNames, converter);
return true;
},
has(name) {
return converters.has(keyOf(name));
},
get(name) {
const converter = converters.get(keyOf(name));
if (!converter) {
throw new Error(`Converter '${name}' is not registered`);
}
return converter;
},
list() {
return [...primaryNames].map((name) => this.get(name));
},
encode(name, data, options) {
return this.get(name).encode(data, options);
},
decode(name, text, options) {
return this.get(name).decode(text, options);
},
tryDecode(name, text, options) {
try {
return { ok: true, bytes: this.decode(name, text, options) };
}
catch (error) {
return { ok: false, error: toError(error) };
}
},
normalize(name, text, options) {
const converter = this.get(name);
return requireCapability(converter, name, "normalize").call(converter, text, options);
},
parse(name, text, options) {
const converter = this.get(name);
return requireCapability(converter, name, "parse").call(converter, text, options);
},
format(name, data, format) {
const converter = this.get(name);
return requireCapability(converter, name, "format").call(converter, data, format);
},
transcode(text, options) {
const bytes = this.decode(options.from, text, options.fromOptions);
return this.encode(options.to, bytes, options.toOptions);
},
detect(text, options = {}) {
const formatNames = options.formats?.length
? options.formats.map((name) => String(name))
: this.list()
.map((converter) => converter.name)
.filter((name) => !["binary", "utf8", "utf16be", "utf16le"].includes(keyOf(name)));
const detections = new Map();
for (const requestedName of formatNames) {
const converter = this.get(requestedName);
const confidence = detectConfidence(requestedName, text, converter);
if (confidence <= 0) {
continue;
}
const format = converter.name;
const current = detections.get(format);
if (!current || confidence > current.confidence) {
detections.set(format, { format, confidence });
}
}
return [...detections.values()].sort((left, right) => right.confidence - left.confidence);
},
};
for (const converter of initialConverters) {
api.register(converter);
}
return api;
}

View file

@ -0,0 +1 @@
export {};

View file

@ -0,0 +1,40 @@
import { toUint8Array } from "../bytes/index.js";
import { encode as encodeBinary, decode as decodeBinary } from "./binary.js";
const BASE64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
function nodeBuffer() {
return globalThis.Buffer;
}
export function normalize(text) {
return text.replace(/[\n\r\t ]/g, "");
}
export function pad(text) {
const remainder = text.length % 4;
return remainder ? text + "=".repeat(4 - remainder) : text;
}
export function is(text) {
if (typeof text !== "string") {
return false;
}
const normalized = normalize(text);
return normalized === "" || BASE64_REGEX.test(normalized);
}
export function encode(data, _options) {
const bytes = toUint8Array(data);
const buffer = nodeBuffer();
if (buffer) {
return buffer.from(bytes).toString("base64");
}
return btoa(encodeBinary(bytes));
}
export function decode(text, _options) {
const normalized = normalize(text);
if (!is(normalized)) {
throw new TypeError("Input is not valid Base64 text");
}
const buffer = nodeBuffer();
if (buffer) {
return new Uint8Array(buffer.from(normalized, "base64"));
}
return decodeBinary(atob(normalized));
}
export const base64 = { encode, decode, is, normalize, pad };

View file

@ -0,0 +1,19 @@
import { base64 } from "./base64.js";
const BASE64URL_REGEX = /^[A-Za-z0-9_-]*$/;
export function normalize(text) {
return text.replace(/[\n\r\t ]/g, "");
}
export function is(text) {
return typeof text === "string" && BASE64URL_REGEX.test(normalize(text));
}
export function encode(data, _options) {
return base64.encode(data).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
}
export function decode(text, _options) {
const normalized = normalize(text);
if (!is(normalized)) {
throw new TypeError("Input is not valid Base64Url text");
}
return base64.decode(base64.pad(normalized.replace(/-/g, "+").replace(/_/g, "/")));
}
export const base64url = { encode, decode, is, normalize };

View file

@ -0,0 +1,20 @@
import { toUint8Array } from "../bytes/index.js";
export function encode(data) {
const bytes = toUint8Array(data);
let result = "";
for (const byte of bytes) {
result += String.fromCharCode(byte);
}
return result;
}
export function decode(text) {
const result = new Uint8Array(text.length);
for (let i = 0; i < text.length; i++) {
result[i] = text.charCodeAt(i) & 0xff;
}
return result;
}
export function is(text) {
return typeof text === "string";
}
export const binary = { encode, decode, is };

View file

@ -0,0 +1,220 @@
import { toUint8Array } from "../bytes/index.js";
const HEX_CHARACTER_REGEX = /^[0-9a-f]$/i;
const COMMON_SEPARATORS = [" ", "\t", "\n", "\r", ":", "-", "."];
function resolveSeparators(options) {
if (options.separators === "none") {
return [];
}
if (!options.separators || options.separators === "common") {
return COMMON_SEPARATORS;
}
return options.separators;
}
function validateSeparator(separator) {
if (!separator) {
throw new TypeError("Hex separators must be non-empty strings");
}
}
function matchSeparator(text, index, separators) {
for (const separator of separators) {
if (text.startsWith(separator, index)) {
return separator;
}
}
return undefined;
}
function detectCase(text) {
const hasUpper = /[A-F]/.test(text);
const hasLower = /[a-f]/.test(text);
return hasUpper && !hasLower ? "upper" : "lower";
}
function detectLineSeparator(text) {
const match = /\r\n|\n/.exec(text);
if (!match) {
return undefined;
}
return match[0] === "\r\n" ? "\r\n" : "\n";
}
function compactForDetection(text) {
return text.replace(/[^0-9a-f]/gi, "");
}
function detectGroup(text) {
const segments = text.match(/[0-9A-Fa-f]+|[^0-9A-Fa-f]+/g) ?? [];
if (segments.length < 3) {
return undefined;
}
const hexSegments = segments.filter((_, index) => index % 2 === 0);
const separators = segments.filter((_, index) => index % 2 === 1);
const separator = separators[0];
if (!separator || separators.some((item) => item !== separator)) {
return undefined;
}
if (hexSegments.some((segment) => segment.length === 0 || segment.length % 2 !== 0)) {
return undefined;
}
const firstLength = hexSegments[0]?.length ?? 0;
if (!firstLength) {
return undefined;
}
if (hexSegments.slice(0, -1).some((segment) => segment.length !== firstLength)) {
return undefined;
}
if ((hexSegments[hexSegments.length - 1]?.length ?? 0) > firstLength) {
return undefined;
}
return {
size: firstLength / 2,
separator,
};
}
function detectFormat(text) {
const trimmed = text.trim();
const prefix = /^0x/i.test(trimmed) ? "0x" : "";
const body = prefix ? trimmed.slice(2) : trimmed;
const lineSeparator = detectLineSeparator(body);
const lines = body.split(/\r\n|\n/).filter((line) => line.length > 0);
const sampleLine = lines[0]?.trim() ?? "";
const group = detectGroup(sampleLine);
const format = {
case: detectCase(trimmed),
prefix,
};
if (group) {
format.group = group;
}
if (lineSeparator && lines.length > 1) {
const firstLineBytes = compactForDetection(lines[0] ?? "").length / 2;
if (firstLineBytes > 0 && lines.slice(0, -1).every((line) => compactForDetection(line).length / 2 === firstLineBytes)) {
format.line = {
bytesPerLine: firstLineBytes,
separator: lineSeparator,
};
}
}
return format;
}
function normalizeText(text, options) {
const allowPrefix = options.allowPrefix ?? true;
const separators = [...resolveSeparators(options)].sort((left, right) => right.length - left.length);
for (const separator of separators) {
validateSeparator(separator);
}
let working = text.trim();
if (/^0x/i.test(working)) {
if (!allowPrefix) {
throw new TypeError("Hexadecimal text must not include a 0x prefix");
}
working = working.slice(2);
}
let normalized = "";
let lastTokenWasSeparator = false;
for (let index = 0; index < working.length;) {
const character = working[index] ?? "";
if (HEX_CHARACTER_REGEX.test(character)) {
normalized += character;
lastTokenWasSeparator = false;
index += 1;
continue;
}
const separator = matchSeparator(working, index, separators);
if (!separator) {
throw new TypeError("Input is not valid hexadecimal text");
}
if (options.strict && (lastTokenWasSeparator || normalized.length === 0)) {
throw new TypeError("Hexadecimal text contains misplaced separators");
}
lastTokenWasSeparator = true;
index += separator.length;
}
if (options.strict && lastTokenWasSeparator && normalized.length > 0) {
throw new TypeError("Hexadecimal text must not end with a separator");
}
if (normalized.length % 2 !== 0) {
if (!options.allowOddLength) {
throw new TypeError("Hexadecimal text must contain an even number of characters");
}
normalized = `0${normalized}`;
}
return normalized.toLowerCase();
}
function groupPairs(pairs, group) {
if (!group) {
return pairs.join("");
}
if (!Number.isInteger(group.size) || group.size < 1) {
throw new RangeError("Hex group size must be a positive integer");
}
const chunks = [];
for (let index = 0; index < pairs.length; index += group.size) {
chunks.push(pairs.slice(index, index + group.size).join(""));
}
return chunks.join(group.separator);
}
export function normalize(text, options = {}) {
return normalizeText(text, options);
}
export function is(text, options = {}) {
if (typeof text !== "string") {
return false;
}
try {
normalize(text, options);
return true;
}
catch {
return false;
}
}
export function encode(data, options = {}) {
const bytes = toUint8Array(data);
const casing = options.case ?? "lower";
const pairs = Array.from(bytes, (byte) => {
const text = byte.toString(16).padStart(2, "0");
return casing === "upper" ? text.toUpperCase() : text;
});
let body = "";
if (options.line) {
const bytesPerLine = options.line.bytesPerLine;
if (!Number.isInteger(bytesPerLine) || bytesPerLine < 1) {
throw new RangeError("Hex bytesPerLine must be a positive integer");
}
const separator = options.line.separator ?? "\n";
const lines = [];
for (let index = 0; index < pairs.length; index += bytesPerLine) {
lines.push(groupPairs(pairs.slice(index, index + bytesPerLine), options.group));
}
body = lines.join(separator);
}
else {
body = groupPairs(pairs, options.group);
}
return `${options.prefix ?? ""}${body}`;
}
export function decode(text, options = {}) {
const normalized = normalize(text, options);
const result = new Uint8Array(normalized.length / 2);
for (let i = 0; i < normalized.length; i += 2) {
result[i / 2] = Number.parseInt(normalized.slice(i, i + 2), 16);
}
return result;
}
export function parse(text, options = {}) {
const normalized = normalize(text, options);
return {
bytes: decode(normalized),
format: detectFormat(text),
normalized,
};
}
export function format(data, value) {
return encode(data, value);
}
export const formats = {
compact: Object.freeze({}),
upper: Object.freeze({ case: "upper" }),
colon: Object.freeze({ group: { size: 1, separator: ":" } }),
colonUpper: Object.freeze({ case: "upper", group: { size: 1, separator: ":" } }),
groupsOf4: Object.freeze({ group: { size: 4, separator: " " } }),
prefixed: Object.freeze({ prefix: "0x" }),
};
export const hex = { encode, decode, format, formats, is, normalize, parse };

View file

@ -0,0 +1,6 @@
export * as binary from "./binary.js";
export * as hex from "./hex.js";
export * as utf8 from "./utf8.js";
export * as utf16 from "./utf16.js";
export * as base64 from "./base64.js";
export * as base64url from "./base64url.js";

View file

@ -0,0 +1,19 @@
import { toArrayBuffer } from "../bytes/index.js";
export function encode(text, options = {}) {
const result = new ArrayBuffer(text.length * 2);
const view = new DataView(result);
for (let i = 0; i < text.length; i++) {
view.setUint16(i * 2, text.charCodeAt(i), options.littleEndian ?? false);
}
return new Uint8Array(result);
}
export function decode(data, options = {}) {
const buffer = toArrayBuffer(data);
const view = new DataView(buffer);
let result = "";
for (let i = 0; i < buffer.byteLength; i += 2) {
result += String.fromCharCode(view.getUint16(i, options.littleEndian ?? false));
}
return result;
}
export const utf16 = { encode, decode };

View file

@ -0,0 +1,8 @@
import { toUint8Array } from "../bytes/index.js";
export function encode(text) {
return new TextEncoder().encode(text);
}
export function decode(data) {
return new TextDecoder("utf-8", { fatal: false }).decode(toUint8Array(data));
}
export const utf8 = { encode, decode };

View file

@ -0,0 +1,6 @@
export * from "./bytes/index.js";
export * as bytes from "./bytes/index.js";
export * from "./encoding/index.js";
export * from "./pem/index.js";
export * from "./converters/index.js";
export * from "./legacy/index.js";

View file

@ -0,0 +1,33 @@
import { concat, equal, isArrayBuffer, isArrayBufferView, isBufferSource, toArrayBuffer, toUint8Array, toView, } from "../bytes/index.js";
export class BufferSourceConverter {
static isArrayBuffer(data) {
return isArrayBuffer(data);
}
static toArrayBuffer(data) {
return toArrayBuffer(data);
}
static toUint8Array(data) {
return toUint8Array(data);
}
static toView(data, type) {
return toView(data, type);
}
static isBufferSource(data) {
return isBufferSource(data);
}
static isArrayBufferView(data) {
return isArrayBufferView(data);
}
static isEqual(a, b) {
return equal(a, b);
}
static concat(first, second, ...rest) {
if (Array.isArray(first)) {
return typeof second === "function"
? concat(first, second)
: concat(first);
}
const buffers = [first, second, ...rest].filter(Boolean);
return concat(buffers);
}
}

View file

@ -0,0 +1,68 @@
import { convert } from "../converters/index.js";
function normalizeTextEncoding(encoding) {
return encoding === "ascii" ? "binary" : encoding;
}
export class Convert {
static DEFAULT_UTF8_ENCODING = "utf8";
static isHex(data) {
return convert.isHex(data);
}
static isBase64(data) {
return convert.isBase64(data);
}
static isBase64Url(data) {
return convert.isBase64Url(data);
}
static ToString(buffer, enc = "utf8") {
return convert.toString(buffer, enc);
}
static FromString(str, enc = "utf8") {
if (!str) {
return new ArrayBuffer(0);
}
return convert.fromString(str, enc);
}
static ToBase64(buffer) {
return convert.toBase64(buffer);
}
static FromBase64(base64) {
return convert.fromBase64(base64);
}
static FromBase64Url(base64url) {
return convert.fromBase64Url(base64url);
}
static ToBase64Url(data) {
return convert.toBase64Url(data);
}
static FromUtf8String(text, encoding = Convert.DEFAULT_UTF8_ENCODING) {
return convert.fromString(text, normalizeTextEncoding(encoding));
}
static ToUtf8String(buffer, encoding = Convert.DEFAULT_UTF8_ENCODING) {
return convert.toString(buffer, normalizeTextEncoding(encoding));
}
static FromBinary(text) {
return convert.fromBinary(text);
}
static ToBinary(buffer) {
return convert.toBinary(buffer);
}
static ToHex(buffer) {
return convert.toHex(buffer);
}
static FromHex(hexString) {
return convert.fromHex(hexString);
}
static ToUtf16String(buffer, littleEndian = false) {
return convert.toUtf16String(buffer, littleEndian);
}
static FromUtf16String(text, littleEndian = false) {
return convert.fromUtf16String(text, littleEndian);
}
static Base64Padding(base64) {
const padCount = 4 - (base64.length % 4);
return padCount < 4 ? base64 + "=".repeat(padCount) : base64;
}
static formatString(data) {
return convert.formatString(data);
}
}

View file

@ -0,0 +1,18 @@
import { concat, equal } from "../bytes/index.js";
export function assign(target, ...sources) {
for (const source of sources) {
if (!source) {
continue;
}
for (const prop in source) {
target[prop] = source[prop];
}
}
return target;
}
export function combine(...buf) {
return concat(buf);
}
export function isEqual(bytes1, bytes2) {
return equal(bytes1, bytes2);
}

View file

@ -0,0 +1,3 @@
export { BufferSourceConverter } from "./buffer-source-converter.js";
export { Convert } from "./convert.js";
export { assign, combine, isEqual } from "./functions.js";

View file

@ -0,0 +1 @@
export { decode, decodeFirst, encode, encodeMany, find, findAll, format, parse, pem, pemConverter } from "./pem.js";

View file

@ -0,0 +1,129 @@
import { base64 } from "../encoding/base64.js";
const LABEL_REGEX = /^[A-Z0-9][A-Z0-9 ._-]*[A-Z0-9]$/i;
const PEM_BLOCK_REGEX = /-----BEGIN ([^-]+)-----([\s\S]*?)-----END \1-----/g;
function assertLabel(label) {
if (!LABEL_REGEX.test(label)) {
throw new TypeError(`Invalid PEM label '${label}'`);
}
}
function wrap(text, lineLength) {
const result = [];
for (let i = 0; i < text.length; i += lineLength) {
result.push(text.slice(i, i + lineLength));
}
return result;
}
function parseBody(body) {
const normalized = body.trim().replace(/\r\n/g, "\n");
const lines = normalized.split("\n").map((line) => line.trim()).filter(Boolean);
const headers = {};
let index = 0;
for (; index < lines.length; index++) {
const line = lines[index];
const separator = line.indexOf(":");
if (separator <= 0) {
break;
}
headers[line.slice(0, separator).trim()] = line.slice(separator + 1).trim();
}
return {
headers: Object.keys(headers).length ? headers : undefined,
base64Lines: lines.slice(index),
base64Text: lines.slice(index).join(""),
};
}
function detectNewline(text) {
return /\r\n/.test(text) ? "\r\n" : "\n";
}
function collectBlocks(text, options = {}) {
const blocks = [];
const requestedLabel = options.label;
let match;
PEM_BLOCK_REGEX.lastIndex = 0;
while ((match = PEM_BLOCK_REGEX.exec(text))) {
const label = match[1].trim();
if (requestedLabel && label !== requestedLabel) {
continue;
}
assertLabel(label);
const parsed = parseBody(match[2]);
blocks.push({
label,
data: base64.decode(parsed.base64Text),
headers: parsed.headers,
lineLength: parsed.base64Lines[0]?.length ?? 64,
newline: detectNewline(match[0]),
});
}
if (options.strict && blocks.length === 0) {
throw new TypeError(requestedLabel
? `No PEM block with label '${requestedLabel}' was found`
: "No PEM blocks were found");
}
return blocks;
}
export function encode(label, data, options = {}) {
assertLabel(label);
const lineLength = options.lineLength ?? 64;
if (!Number.isInteger(lineLength) || lineLength < 1) {
throw new RangeError("PEM lineLength must be a positive integer");
}
const newline = options.newline ?? "\n";
const lines = [`-----BEGIN ${label}-----`];
if (options.headers) {
for (const [name, value] of Object.entries(options.headers)) {
lines.push(`${name}: ${value}`);
}
lines.push("");
}
lines.push(...wrap(base64.encode(data), lineLength));
lines.push(`-----END ${label}-----`);
return `${lines.join(newline)}${newline}`;
}
export function encodeMany(blocks, options = {}) {
return blocks.map((block) => encode(block.label, block.data, { ...options, headers: block.headers ?? options.headers })).join("");
}
export function decode(text, options = {}) {
return collectBlocks(text, options).map(({ lineLength: _lineLength, newline: _newline, ...block }) => block);
}
export function find(text, label) {
return decode(text, { label })[0];
}
export function findAll(text, label) {
return decode(text, { label });
}
export function decodeFirst(text, label) {
const [block] = decode(text, { label, strict: true });
return block.data;
}
export function parse(text, options = {}) {
const [block] = collectBlocks(text, { ...options, strict: true });
const format = {
label: block.label,
headers: block.headers,
lineLength: block.lineLength,
newline: block.newline,
};
return {
bytes: block.data,
format,
normalized: encode(block.label, block.data, format),
};
}
export function format(data, value) {
return encode(value.label, data, value);
}
export const pem = { decode, decodeFirst, encode, encodeMany, find, findAll, format, parse };
export const pemConverter = {
name: "pem",
encode: (data, options) => {
if (!options?.label) {
throw new TypeError("PEM label is required");
}
return encode(options.label, data, options);
},
decode: (text, options) => decodeFirst(text, options?.label),
format,
is: (text) => typeof text === "string" && /-----BEGIN [^-]+-----/.test(text),
parse,
};

View file

@ -0,0 +1 @@
export {};

View file

@ -0,0 +1,25 @@
import type { ArrayBufferViewLike, BufferSourceLike, ViewConstructor } from "./types.js";
/** Checks whether a value is an ArrayBuffer. */
export declare function isArrayBuffer(value: unknown): value is ArrayBuffer;
/** Checks whether a value is a SharedArrayBuffer. */
export declare function isSharedArrayBuffer(value: unknown): value is SharedArrayBuffer;
/** Checks whether a value is an ArrayBuffer-like object. */
export declare function isArrayBufferLike(value: unknown): value is ArrayBufferLike;
/** Checks whether a value is an ArrayBufferView. */
export declare function isArrayBufferView(value: unknown): value is ArrayBufferViewLike;
/** Checks whether a value can be treated as a buffer source. */
export declare function isBufferSource(value: unknown): value is BufferSourceLike;
/** Throws when a value is not a supported buffer source. */
export declare function assertBufferSource(value: unknown): asserts value is BufferSourceLike;
/** Returns a Uint8Array view over the input without copying. */
export declare function toUint8Array(data: BufferSourceLike): Uint8Array;
/** Returns a copied Uint8Array for the input buffer source. */
export declare function toUint8ArrayCopy(data: BufferSourceLike): Uint8Array;
/** Returns the underlying ArrayBuffer, copying when required. */
export declare function toArrayBuffer(data: BufferSourceLike): ArrayBuffer;
/** Returns an ArrayBuffer-like value, copying only when needed. */
export declare function toArrayBufferLike(data: BufferSourceLike): ArrayBufferLike;
/** Casts buffer data into the requested view type. */
export declare function toView<T extends ArrayBufferViewLike>(data: BufferSourceLike, type: ViewConstructor<T>): T;
/** Copies buffer data into the requested view type. */
export declare function toViewCopy<T extends ArrayBufferViewLike>(data: BufferSourceLike, type: ViewConstructor<T>): T;

View file

@ -0,0 +1,7 @@
import type { ArrayBufferViewLike, BufferSourceLike, ViewConstructor } from "./types.js";
/** Concatenates buffer sources into a new Uint8Array. */
export declare function concatToUint8Array(buffers: Iterable<BufferSourceLike>): Uint8Array;
/** Concatenates buffer sources and returns either an ArrayBufferLike or a typed view. */
export declare function concat(...buffers: BufferSourceLike[]): ArrayBufferLike;
export declare function concat(buffers: Iterable<BufferSourceLike>): ArrayBufferLike;
export declare function concat<T extends ArrayBufferViewLike>(buffers: Iterable<BufferSourceLike>, type: ViewConstructor<T>): T;

View file

@ -0,0 +1,7 @@
import type { BufferSourceLike } from "./types.js";
/** Options that control how byte comparisons are performed. */
export interface EqualOptions {
constantTime?: boolean;
}
/** Compares two buffer sources for byte equality. */
export declare function equal(a: BufferSourceLike, b: BufferSourceLike, options?: EqualOptions): boolean;

View file

@ -0,0 +1,8 @@
/** Barrel export for buffer-related types and helpers. */
export type { ArrayBufferViewLike, ArrayBufferViewConstructor, BufferSource, BufferSourceLike, DataViewConstructorLike, StrictBufferSource, ViewConstructor, } from "./types.js";
export { assertBufferSource, isArrayBuffer, isArrayBufferLike, isArrayBufferView, isBufferSource, isSharedArrayBuffer, toArrayBuffer, toArrayBufferLike, toUint8Array, toUint8ArrayCopy, toView, toViewCopy, } from "./buffer-source.js";
export { concat, concatToUint8Array } from "./concat.js";
export type { EqualOptions } from "./equal.js";
export { equal } from "./equal.js";
export type { BytePattern, ByteSearchOptions } from "./sequence.js";
export { compare, copy, endsWith, includes, indexOf, lastIndexOf, slice, startsWith, tail, } from "./sequence.js";

View file

@ -0,0 +1,48 @@
import type { BufferSourceLike } from "./types.js";
/** String or byte pattern accepted by the byte search helpers. */
export type BytePattern = BufferSourceLike | string;
/** Options shared by the stateless byte search helpers. */
export interface ByteSearchOptions {
/**
* Start offset for forward search.
* For reverse search this is the upper bound / starting point.
*/
start?: number;
/**
* End offset, exclusive.
* For reverse search this is the lower bound.
*/
end?: number;
/**
* Encoding used when pattern is a string.
* Defaults to ASCII for marker-style byte searches.
*/
encoding?: "ascii" | "utf8";
}
/**
* Searches for the first occurrence of a byte pattern within the requested range.
* Returns the absolute byte offset or `-1` when the pattern is not found.
*/
export declare function indexOf(data: BufferSourceLike, pattern: BytePattern, options?: ByteSearchOptions): number;
/**
* Searches backwards for the last occurrence of a byte pattern within the requested range.
* Returns the absolute byte offset or `-1` when the pattern is not found.
*/
export declare function lastIndexOf(data: BufferSourceLike, pattern: BytePattern, options?: ByteSearchOptions): number;
/** Returns `true` when the pattern exists anywhere in the requested range. */
export declare function includes(data: BufferSourceLike, pattern: BytePattern, options?: ByteSearchOptions): boolean;
/** Returns `true` when the byte sequence starts with the requested pattern. */
export declare function startsWith(data: BufferSourceLike, pattern: BytePattern, options?: Pick<ByteSearchOptions, "encoding">): boolean;
/** Returns `true` when the byte sequence ends with the requested pattern. */
export declare function endsWith(data: BufferSourceLike, pattern: BytePattern, options?: Pick<ByteSearchOptions, "encoding">): boolean;
/**
* Returns a Uint8Array view over the requested byte range.
* Negative indexes follow `Array.prototype.slice` semantics.
*/
export declare function slice(data: BufferSourceLike, start?: number, end?: number): Uint8Array;
/** Returns the last `length` bytes of the input as a Uint8Array view. */
export declare function tail(data: BufferSourceLike, length: number): Uint8Array;
/** Returns a new Uint8Array copy that never shares memory with the input. */
export declare function copy(data: BufferSourceLike): Uint8Array;
/** Compares two byte sequences lexicographically. */
export declare function compare(a: BufferSourceLike, b: BufferSourceLike): -1 | 0 | 1;

View file

@ -0,0 +1,29 @@
/** Describes a buffer-backed view with offset and length metadata. */
export interface ArrayBufferViewLike<TBuffer extends ArrayBufferLike = ArrayBufferLike> {
readonly buffer: TBuffer;
readonly byteOffset: number;
readonly byteLength: number;
}
/** A buffer source backed by either an ArrayBuffer-like value or a view. */
export type BufferSourceLike = ArrayBufferLike | ArrayBufferViewLike;
/** Historical BufferSource alias preserved for compatibility. */
export type BufferSource = BufferSourceLike;
/** A strict buffer source limited to ArrayBuffer and ArrayBuffer-backed views. */
export type StrictBufferSource = ArrayBuffer | ArrayBufferViewLike<ArrayBuffer>;
/** Constructor shape for typed array-like views. */
export interface ArrayBufferViewConstructor<T extends ArrayBufferViewLike = ArrayBufferViewLike> {
readonly prototype: T;
readonly BYTES_PER_ELEMENT?: number;
readonly name: string;
new (length: number): T;
new (array: ArrayLike<number>): T;
new (buffer: ArrayBufferLike, byteOffset?: number, length?: number): T;
}
/** Constructor shape for DataView-like views. */
export interface DataViewConstructorLike<T extends ArrayBufferViewLike = ArrayBufferViewLike> {
readonly prototype: T;
readonly name: string;
new (buffer: ArrayBufferLike, byteOffset?: number, byteLength?: number): T;
}
/** A constructor that can create a typed view over buffer data. */
export type ViewConstructor<T extends ArrayBufferViewLike = ArrayBufferViewLike> = ArrayBufferViewConstructor<T> | DataViewConstructorLike<T>;

View file

@ -0,0 +1,65 @@
import type { BufferSourceLike } from "../bytes/index.js";
import type { DecodeOptionsFor, DetectOptions, EncodeOptionsFor, FormatDetection, FormatFor, OptionsArgument, ParsedBytes, TranscodeOptions, DecodeResult } from "./types.js";
/** Text encodings supported by the legacy converter facade. */
export type BufferEncoding = "utf8" | "utf-8" | "binary" | "latin1" | "base64" | "base64url" | "base64-url" | "hex" | "utf16" | "utf16be" | "utf16le" | string;
/** Public converter facade backed by the default registry. */
export interface ConvertFacade {
/** Encodes bytes with a named converter. */
encode<TName extends string>(name: TName, data: BufferSourceLike, ...args: OptionsArgument<EncodeOptionsFor<TName>>): string;
/** Decodes text with a named converter. */
decode<TName extends string>(name: TName, text: string, ...args: OptionsArgument<DecodeOptionsFor<TName>>): Uint8Array;
/** Safely decodes text with a named converter. */
tryDecode<TName extends string>(name: TName, text: string, ...args: OptionsArgument<DecodeOptionsFor<TName>>): DecodeResult;
/** Normalizes text with a named converter. */
normalize<TName extends string>(name: TName, text: string, ...args: OptionsArgument<DecodeOptionsFor<TName>>): string;
/** Parses text while preserving formatting metadata. */
parse<TName extends string>(name: TName, text: string, ...args: OptionsArgument<DecodeOptionsFor<TName>>): ParsedBytes<FormatFor<TName>>;
/** Formats bytes using preserved formatting metadata. */
format<TName extends string>(name: TName, data: BufferSourceLike, format: FormatFor<TName>): string;
/** Converts text directly between registered formats. */
transcode<TFrom extends string, TTo extends string>(text: string, options: TranscodeOptions<TFrom, TTo>): string;
/** Detects likely formats for an input string. */
detect<TName extends string = string>(text: string, options?: DetectOptions<TName>): FormatDetection[];
/** @deprecated Use encode() instead. */
to<TName extends string>(format: TName, data: BufferSourceLike, ...args: OptionsArgument<EncodeOptionsFor<TName>>): string;
/** @deprecated Use decode() instead. */
from<TName extends string>(format: TName, text: string, ...args: OptionsArgument<DecodeOptionsFor<TName>>): Uint8Array;
/** Converts buffer data to a string using a known encoding. */
toString(data: BufferSourceLike, encoding?: BufferEncoding): string;
/** Converts a string to bytes using a known encoding. */
fromString(text: string, encoding?: BufferEncoding): ArrayBufferLike;
/** Encodes bytes as Base64 text. */
toBase64(data: BufferSourceLike): string;
/** Decodes Base64 text into bytes. */
fromBase64(text: string): ArrayBufferLike;
/** Encodes bytes as Base64Url text. */
toBase64Url(data: BufferSourceLike): string;
/** Decodes Base64Url text into bytes. */
fromBase64Url(text: string): ArrayBufferLike;
/** Encodes bytes as hexadecimal text. */
toHex(data: BufferSourceLike): string;
/** Decodes hexadecimal text into bytes. */
fromHex(text: string): ArrayBufferLike;
/** Encodes bytes as binary text. */
toBinary(data: BufferSourceLike): string;
/** Decodes binary text into bytes. */
fromBinary(text: string): ArrayBufferLike;
/** Decodes UTF-8 bytes into text. */
toUtf8String(data: BufferSourceLike): string;
/** Encodes UTF-8 text into bytes. */
fromUtf8String(text: string): ArrayBufferLike;
/** Decodes UTF-16 bytes into text. */
toUtf16String(data: BufferSourceLike, littleEndian?: boolean): string;
/** Encodes UTF-16 text into bytes. */
fromUtf16String(text: string, littleEndian?: boolean): ArrayBufferLike;
/** Checks whether a value is hexadecimal text. */
isHex(text: unknown): text is string;
/** Checks whether a value is Base64 text. */
isBase64(text: unknown): text is string;
/** Checks whether a value is Base64Url text. */
isBase64Url(text: unknown): text is string;
/** Normalizes whitespace in a Base64-style string. */
formatString(text: string): string;
}
/** Converter helpers for common text and binary encodings. */
export declare const convert: ConvertFacade;

View file

@ -0,0 +1,22 @@
export { pemConverter } from "../pem/index.js";
import type { Converter } from "./types.js";
/** Converter for binary text where each character maps to one byte. */
export declare const binaryConverter: Converter;
/** Converter for hexadecimal text. */
export declare const hexConverter: Converter;
/** Converter for standard Base64 text. */
export declare const base64Converter: Converter;
/** Converter for URL-safe Base64 text. */
export declare const base64urlConverter: Converter;
/** Converter for UTF-8 text. */
export declare const utf8Converter: Converter;
/** Converter for big-endian UTF-16 text. */
export declare const utf16beConverter: Converter;
/** Converter for little-endian UTF-16 text. */
export declare const utf16leConverter: Converter;
/** The built-in converter set shipped with the package. */
export declare const defaultConverters: readonly [Converter<any, any, any>, Converter<any, any, any>, Converter<any, any, any>, Converter<any, any, any>, Converter<any, any, any>, Converter<any, any, any>, Converter<any, any, any>, Converter<import("../index.js").PemEncodeOptions & {
label: string;
}, import("../index.js").PemDecodeOptions, import("../index.js").PemFormat>];
/** The default registry preloaded with the built-in converters. */
export declare const defaultConverterRegistry: import("./types.js").ConverterRegistry;

View file

@ -0,0 +1,6 @@
/** Barrel export for converter registry types and default codecs. */
export type { ByteDecoder, ByteEncoder, Converter, ConverterOptionsMap, ConverterRegistry, DecodeOptionsFor, DecodeResult, DetectOptions, EncodeOptionsFor, FormatDetection, FormatFor, OptionsArgument, ParsedBytes, RegisterOptions, TranscodeOptions, } from "./types.js";
export { createConverterRegistry } from "./registry.js";
export { base64Converter, base64urlConverter, binaryConverter, defaultConverterRegistry, defaultConverters, hexConverter, pemConverter, utf16beConverter, utf16leConverter, utf8Converter, } from "./defaults.js";
export type { BufferEncoding, ConvertFacade } from "./convert.js";
export { convert } from "./convert.js";

View file

@ -0,0 +1,3 @@
import type { Converter, ConverterRegistry } from "./types.js";
/** Creates a converter registry and optionally seeds it with converters. */
export declare function createConverterRegistry(initialConverters?: Iterable<Converter>): ConverterRegistry;

View file

@ -0,0 +1,141 @@
import type { BufferSourceLike } from "../bytes/index.js";
import type { Base64DecodeOptions, Base64EncodeOptions } from "../encoding/base64.js";
import type { Base64UrlDecodeOptions, Base64UrlEncodeOptions } from "../encoding/base64url.js";
import type { HexDecodeOptions, HexEncodeOptions, HexFormat } from "../encoding/hex.js";
import type { PemDecodeOptions, PemEncodeOptions, PemFormat } from "../pem/types.js";
/** Converts buffer data into text using encoder-specific options. */
export type ByteEncoder<TOptions = any> = (data: BufferSourceLike, options?: TOptions) => string;
/** Converts text back into bytes using decoder-specific options. */
export type ByteDecoder<TOptions = any> = (text: string, options?: TOptions) => Uint8Array;
/** Parsed text that preserves both decoded bytes and the detected format metadata. */
export interface ParsedBytes<TFormat = unknown> {
/** Decoded bytes. */
readonly bytes: Uint8Array;
/** Detected formatting metadata. */
readonly format: TFormat;
/** Canonical normalized text representation. */
readonly normalized: string;
}
/** Result of a safe decode operation that does not throw. */
export type DecodeResult = {
ok: true;
bytes: Uint8Array;
} | {
ok: false;
error: Error;
};
/** Ranked format detection candidate. */
export interface FormatDetection {
/** Registered converter name. */
readonly format: string;
/** Confidence score in the range from 0 to 1. */
readonly confidence: number;
}
/** Open interface that standard and user converters can augment with typed options. */
export interface ConverterOptionsMap {
base64: {
decode: Base64DecodeOptions;
encode: Base64EncodeOptions;
};
base64url: {
decode: Base64UrlDecodeOptions;
encode: Base64UrlEncodeOptions;
};
hex: {
decode: HexDecodeOptions;
encode: HexEncodeOptions;
format: HexFormat;
};
pem: {
decode: PemDecodeOptions;
encode: PemEncodeOptions & {
label: string;
};
format: PemFormat;
};
}
type KnownConverterName = Extract<keyof ConverterOptionsMap, string>;
type EmptyObject = Record<never, never>;
type RequiredKeys<T extends object> = {
[TKey in keyof T]-?: EmptyObject extends Pick<T, TKey> ? never : TKey;
}[keyof T];
type NonUndefined<T> = Exclude<T, undefined>;
type CapabilityOptions<TName extends string, TCapability extends "encode" | "decode" | "format"> = TName extends KnownConverterName ? ConverterOptionsMap[TName] extends Record<TCapability, infer TOptions> ? TOptions : unknown : unknown;
/** Resolves typed encode options for a known converter name. */
export type EncodeOptionsFor<TName extends string> = CapabilityOptions<TName, "encode">;
/** Resolves typed decode options for a known converter name. */
export type DecodeOptionsFor<TName extends string> = CapabilityOptions<TName, "decode">;
/** Resolves typed format metadata for a known converter name. */
export type FormatFor<TName extends string> = CapabilityOptions<TName, "format">;
/** Builds an optional or required options tuple depending on the options type. */
export type OptionsArgument<TOptions> = [TOptions] extends [never] ? [] : unknown extends TOptions ? [options?: TOptions] : [NonUndefined<TOptions>] extends [object] ? RequiredKeys<NonUndefined<TOptions>> extends never ? [options?: TOptions] : [options: TOptions] : [options: TOptions];
/** Options for direct format-to-format transcoding. */
export interface TranscodeOptions<TFrom extends string = string, TTo extends string = string> {
/** Source format name. */
readonly from: TFrom;
/** Source decoder options. */
readonly fromOptions?: DecodeOptionsFor<TFrom>;
/** Destination format name. */
readonly to: TTo;
/** Destination encoder options. */
readonly toOptions?: EncodeOptionsFor<TTo>;
}
/** Options for ranked format detection. */
export interface DetectOptions<TName extends string = string> {
/** Formats to check. Defaults to the registered non-generic codecs. */
readonly formats?: readonly TName[];
}
/** Describes a named text converter with optional aliases and validation. */
export interface Converter<TEncodeOptions = any, TDecodeOptions = any, TFormat = any> {
/** The primary converter name. */
readonly name: string;
/** Additional names that resolve to the same converter. */
readonly aliases?: readonly string[];
/** Encodes buffer data into text. */
readonly encode: ByteEncoder<TEncodeOptions>;
/** Decodes text into bytes. */
readonly decode: ByteDecoder<TDecodeOptions>;
/** Normalizes input text into the canonical representation accepted by the converter. */
readonly normalize?: (text: string, options?: TDecodeOptions) => string;
/** Parses text into bytes while preserving formatting metadata. */
readonly parse?: (text: string, options?: TDecodeOptions) => ParsedBytes<TFormat>;
/** Formats bytes using previously detected formatting metadata. */
readonly format?: (data: BufferSourceLike, format: TFormat) => string;
/** Checks whether a text value is accepted by the converter. */
readonly is?: (text: unknown) => text is string;
}
/** Options that control how a converter is registered. */
export interface RegisterOptions {
/** Replaces an existing converter with the same name or alias. */
override?: boolean;
}
/** Registry API for looking up, registering, and using converters. */
export interface ConverterRegistry {
/** Registers a converter. */
register(converter: Converter, options?: RegisterOptions): this;
/** Removes a converter by name or alias. */
unregister(name: string): boolean;
/** Checks whether a converter is registered. */
has(name: string): boolean;
/** Returns a registered converter. */
get(name: string): Converter;
/** Returns the list of primary registered converters. */
list(): readonly Converter[];
/** Encodes buffer data with a named converter. */
encode<TName extends string>(name: TName, data: BufferSourceLike, ...args: OptionsArgument<EncodeOptionsFor<TName>>): string;
/** Decodes text with a named converter. */
decode<TName extends string>(name: TName, text: string, ...args: OptionsArgument<DecodeOptionsFor<TName>>): Uint8Array;
/** Safely decodes text with a named converter without throwing. */
tryDecode<TName extends string>(name: TName, text: string, ...args: OptionsArgument<DecodeOptionsFor<TName>>): DecodeResult;
/** Normalizes text with a named converter. */
normalize<TName extends string>(name: TName, text: string, ...args: OptionsArgument<DecodeOptionsFor<TName>>): string;
/** Parses text with a named converter. */
parse<TName extends string>(name: TName, text: string, ...args: OptionsArgument<DecodeOptionsFor<TName>>): ParsedBytes<FormatFor<TName>>;
/** Formats bytes with a named converter using preserved formatting metadata. */
format<TName extends string>(name: TName, data: BufferSourceLike, format: FormatFor<TName>): string;
/** Converts text directly from one registered format to another. */
transcode<TFrom extends string, TTo extends string>(text: string, options: TranscodeOptions<TFrom, TTo>): string;
/** Detects likely formats for the provided text. */
detect<TName extends string = string>(text: string, options?: DetectOptions<TName>): FormatDetection[];
}
export {};

View file

@ -0,0 +1,27 @@
import type { BufferSourceLike } from "../bytes/index.js";
/** Options that control Base64 encoding. */
export interface Base64EncodeOptions {
readonly __base64EncodeOptionsBrand?: never;
}
/** Options that control Base64 decoding. */
export interface Base64DecodeOptions {
readonly __base64DecodeOptionsBrand?: never;
}
/** Removes whitespace from Base64 text. */
export declare function normalize(text: string): string;
/** Pads Base64 text to a multiple of four characters. */
export declare function pad(text: string): string;
/** Checks whether a value is valid Base64 text. */
export declare function is(text: unknown): text is string;
/** Encodes buffer data as Base64 text. */
export declare function encode(data: BufferSourceLike, _options?: Base64EncodeOptions): string;
/** Decodes Base64 text into bytes. */
export declare function decode(text: string, _options?: Base64DecodeOptions): Uint8Array;
/** Base64 codec helpers. */
export declare const base64: {
readonly encode: typeof encode;
readonly decode: typeof decode;
readonly is: typeof is;
readonly normalize: typeof normalize;
readonly pad: typeof pad;
};

View file

@ -0,0 +1,24 @@
import type { BufferSourceLike } from "../bytes/index.js";
/** Options that control Base64Url encoding. */
export interface Base64UrlEncodeOptions {
readonly __base64UrlEncodeOptionsBrand?: never;
}
/** Options that control Base64Url decoding. */
export interface Base64UrlDecodeOptions {
readonly __base64UrlDecodeOptionsBrand?: never;
}
/** Removes whitespace from Base64Url text. */
export declare function normalize(text: string): string;
/** Checks whether a value is valid Base64Url text. */
export declare function is(text: unknown): text is string;
/** Encodes buffer data as Base64Url text. */
export declare function encode(data: BufferSourceLike, _options?: Base64UrlEncodeOptions): string;
/** Decodes Base64Url text into bytes. */
export declare function decode(text: string, _options?: Base64UrlDecodeOptions): Uint8Array;
/** Base64Url codec helpers. */
export declare const base64url: {
readonly encode: typeof encode;
readonly decode: typeof decode;
readonly is: typeof is;
readonly normalize: typeof normalize;
};

View file

@ -0,0 +1,13 @@
import type { BufferSourceLike } from "../bytes/index.js";
/** Encodes bytes as a one-byte-per-character string. */
export declare function encode(data: BufferSourceLike): string;
/** Decodes a one-byte-per-character string into bytes. */
export declare function decode(text: string): Uint8Array;
/** Checks whether a value is a string suitable for binary text handling. */
export declare function is(text: unknown): text is string;
/** Binary codec helpers. */
export declare const binary: {
readonly encode: typeof encode;
readonly decode: typeof decode;
readonly is: typeof is;
};

View file

@ -0,0 +1,76 @@
import type { BufferSourceLike } from "../bytes/index.js";
import type { ParsedBytes } from "../converters/types.js";
/** Hex casing modes used by format-aware helpers. */
export type HexCase = "lower" | "upper";
/** Options that control hexadecimal decoding. */
export interface HexDecodeOptions {
allowPrefix?: boolean;
allowOddLength?: boolean;
separators?: readonly string[] | "common" | "none";
strict?: boolean;
}
/** Grouping information for formatted hexadecimal output. */
export interface HexGroupFormat {
size: number;
separator: string;
}
/** Line wrapping information for formatted hexadecimal output. */
export interface HexLineFormat {
bytesPerLine: number;
separator?: "\n" | "\r\n";
}
/** Options that control hexadecimal encoding. */
export interface HexEncodeOptions {
case?: HexCase;
prefix?: "" | "0x";
group?: HexGroupFormat;
line?: HexLineFormat;
}
/** Preserved formatting metadata for parsed hexadecimal text. */
export interface HexFormat {
case: HexCase;
prefix: "" | "0x";
group?: HexGroupFormat;
line?: {
bytesPerLine: number;
separator: "\n" | "\r\n";
};
}
/** Removes separators and normalizes hexadecimal text. */
export declare function normalize(text: string, options?: HexDecodeOptions): string;
/** Checks whether a value is normalized hexadecimal text. */
export declare function is(text: unknown, options?: HexDecodeOptions): text is string;
/** Encodes buffer data as formatted hexadecimal text. */
export declare function encode(data: BufferSourceLike, options?: HexEncodeOptions): string;
/** Decodes hexadecimal text into bytes. */
export declare function decode(text: string, options?: HexDecodeOptions): Uint8Array;
/** Parses hexadecimal text into bytes plus detected formatting metadata. */
export declare function parse(text: string, options?: HexDecodeOptions): ParsedBytes<HexFormat>;
/** Formats bytes using preserved hexadecimal formatting metadata. */
export declare function format(data: BufferSourceLike, value: HexFormat): string;
/** Reusable hexadecimal formatting presets. */
export declare const formats: {
readonly compact: Readonly<HexEncodeOptions>;
readonly upper: Readonly<HexEncodeOptions>;
readonly colon: Readonly<HexEncodeOptions>;
readonly colonUpper: Readonly<HexEncodeOptions>;
readonly groupsOf4: Readonly<HexEncodeOptions>;
readonly prefixed: Readonly<HexEncodeOptions>;
};
/** Hexadecimal codec helpers. */
export declare const hex: {
readonly encode: typeof encode;
readonly decode: typeof decode;
readonly format: typeof format;
readonly formats: {
readonly compact: Readonly<HexEncodeOptions>;
readonly upper: Readonly<HexEncodeOptions>;
readonly colon: Readonly<HexEncodeOptions>;
readonly colonUpper: Readonly<HexEncodeOptions>;
readonly groupsOf4: Readonly<HexEncodeOptions>;
readonly prefixed: Readonly<HexEncodeOptions>;
};
readonly is: typeof is;
readonly normalize: typeof normalize;
readonly parse: typeof parse;
};

View file

@ -0,0 +1,7 @@
/** Barrel export for binary and text encoding helpers. */
export * as binary from "./binary.js";
export * as hex from "./hex.js";
export * as utf8 from "./utf8.js";
export * as utf16 from "./utf16.js";
export * as base64 from "./base64.js";
export * as base64url from "./base64url.js";

View file

@ -0,0 +1,14 @@
import type { BufferSourceLike } from "../bytes/index.js";
/** Options that control UTF-16 endianness. */
export interface Utf16Options {
littleEndian?: boolean;
}
/** Encodes UTF-16 text into bytes. */
export declare function encode(text: string, options?: Utf16Options): Uint8Array;
/** Decodes UTF-16 bytes into text. */
export declare function decode(data: BufferSourceLike, options?: Utf16Options): string;
/** UTF-16 codec helpers. */
export declare const utf16: {
readonly encode: typeof encode;
readonly decode: typeof decode;
};

View file

@ -0,0 +1,10 @@
import type { BufferSourceLike } from "../bytes/index.js";
/** Encodes UTF-8 text into bytes. */
export declare function encode(text: string): Uint8Array;
/** Decodes UTF-8 bytes into text. */
export declare function decode(data: BufferSourceLike): string;
/** UTF-8 codec helpers. */
export declare const utf8: {
readonly encode: typeof encode;
readonly decode: typeof decode;
};

View file

@ -0,0 +1,7 @@
/** Public entry point for bytes, encodings, PEM helpers, converters, and legacy compatibility APIs. */
export * from "./bytes/index.js";
export * as bytes from "./bytes/index.js";
export * from "./encoding/index.js";
export * from "./pem/index.js";
export * from "./converters/index.js";
export * from "./legacy/index.js";

View file

@ -0,0 +1,24 @@
import type { ArrayBufferViewConstructor, ArrayBufferViewLike, BufferSourceLike, ViewConstructor } from "../bytes/index.js";
/** Legacy static helpers for buffer source conversion.
* @deprecated Use functions from `@peculiar/utils/bytes` instead.
*/
export declare class BufferSourceConverter {
/** Checks whether a value is an ArrayBuffer. */
static isArrayBuffer(data: unknown): data is ArrayBuffer;
/** Converts buffer data to an ArrayBuffer. */
static toArrayBuffer(data: BufferSourceLike): ArrayBuffer;
/** Converts buffer data to a Uint8Array view. */
static toUint8Array(data: BufferSourceLike): Uint8Array;
/** Converts buffer data into the requested view type. */
static toView<T extends ArrayBufferViewLike>(data: BufferSourceLike, type: ViewConstructor<T>): T;
/** Checks whether a value can be treated as a buffer source. */
static isBufferSource(data: unknown): data is BufferSourceLike;
/** Checks whether a value is an ArrayBufferView. */
static isArrayBufferView(data: unknown): data is ArrayBufferViewLike;
/** Compares two buffer sources for byte equality. */
static isEqual(a: BufferSourceLike, b: BufferSourceLike): boolean;
/** Concatenates buffer sources into an ArrayBuffer or a typed view. */
static concat(...buffers: BufferSourceLike[]): ArrayBufferLike;
static concat(buffers: BufferSourceLike[]): ArrayBufferLike;
static concat<T extends ArrayBufferViewLike>(buffers: BufferSourceLike[], type: ArrayBufferViewConstructor<T>): T;
}

View file

@ -0,0 +1,52 @@
import type { BufferSourceLike } from "../bytes/index.js";
import { type BufferEncoding } from "../converters/index.js";
import type { Utf16Options } from "../encoding/utf16.js";
/** Legacy text encodings accepted by the deprecated facade. */
export type TextEncoding = "ascii" | "utf8" | "utf16" | "utf16be" | "utf16le" | "usc2";
/**
* Legacy converter facade that mirrors the historical API surface.
* @deprecated Use the camelCase `convert` object or specific encoding modules instead.
*/
export declare class Convert {
/** Default UTF-8 encoding used by the legacy facade. */
static DEFAULT_UTF8_ENCODING: TextEncoding;
/** Checks whether the input is hexadecimal text. */
static isHex(data: unknown): data is string;
/** Checks whether the input is Base64 text. */
static isBase64(data: unknown): data is string;
/** Checks whether the input is Base64Url text. */
static isBase64Url(data: unknown): data is string;
/** Converts buffer data to text. */
static ToString(buffer: BufferSourceLike, enc?: BufferEncoding): string;
/** Converts text to bytes. */
static FromString(str: string, enc?: BufferEncoding): ArrayBufferLike;
/** Encodes bytes as Base64 text. */
static ToBase64(buffer: BufferSourceLike): string;
/** Decodes Base64 text into bytes. */
static FromBase64(base64: string): ArrayBufferLike;
/** Decodes Base64Url text into bytes. */
static FromBase64Url(base64url: string): ArrayBufferLike;
/** Encodes bytes as Base64Url text. */
static ToBase64Url(data: BufferSourceLike): string;
/** Converts UTF-8 or UTF-16 text to bytes. */
static FromUtf8String(text: string, encoding?: TextEncoding): ArrayBufferLike;
/** Converts bytes to UTF-8 or UTF-16 text. */
static ToUtf8String(buffer: BufferSourceLike, encoding?: TextEncoding): string;
/** Decodes binary text into bytes. */
static FromBinary(text: string): ArrayBufferLike;
/** Encodes bytes as binary text. */
static ToBinary(buffer: BufferSourceLike): string;
/** Encodes bytes as hexadecimal text. */
static ToHex(buffer: BufferSourceLike): string;
/** Decodes hexadecimal text into bytes. */
static FromHex(hexString: string): ArrayBufferLike;
/** Converts UTF-16 bytes into text. */
static ToUtf16String(buffer: BufferSourceLike, littleEndian?: boolean): string;
/** Converts UTF-16 text into bytes. */
static FromUtf16String(text: string, littleEndian?: boolean): ArrayBufferLike;
protected static Base64Padding(base64: string): string;
/** Normalizes whitespace in Base64-style text. */
static formatString(data: string): string;
}
/** Legacy text encoding aliases re-exported for compatibility. */
export type { BufferEncoding, Utf16Options };

View file

@ -0,0 +1,16 @@
import type { BufferSourceLike } from "../bytes/index.js";
/**
* Assigns own properties from source objects into the target object.
* @deprecated Prefer object spread or Object.assign.
*/
export declare function assign<T extends object>(target: T, ...sources: (Partial<T> | undefined | null)[]): T;
/**
* Concatenates buffer sources into a single ArrayBuffer.
* @deprecated Use `concat` from `@peculiar/utils/bytes` instead.
*/
export declare function combine(...buf: BufferSourceLike[]): ArrayBufferLike;
/**
* Compares two buffer sources for equality.
* @deprecated Use `equal` from `@peculiar/utils/bytes` instead.
*/
export declare function isEqual(bytes1: BufferSourceLike, bytes2: BufferSourceLike): boolean;

View file

@ -0,0 +1,5 @@
/** Barrel export for the deprecated compatibility layer. */
export { BufferSourceConverter } from "./buffer-source-converter.js";
export { Convert } from "./convert.js";
export type { BufferEncoding, TextEncoding } from "./convert.js";
export { assign, combine, isEqual } from "./functions.js";

View file

@ -0,0 +1,3 @@
/** Barrel export for PEM helpers, codecs, and related types. */
export type { PemBlock, PemCodec, PemDecodeOptions, PemEncodeBlock, PemEncodeOptions, PemFormat } from "./types.js";
export { decode, decodeFirst, encode, encodeMany, find, findAll, format, parse, pem, pemConverter } from "./pem.js";

View file

@ -0,0 +1,34 @@
import type { BufferSourceLike } from "../bytes/index.js";
import type { ParsedBytes, Converter } from "../converters/types.js";
import type { PemBlock, PemDecodeOptions, PemEncodeBlock, PemEncodeOptions, PemFormat } from "./types.js";
/** Encodes buffer data into a PEM block. */
export declare function encode(label: string, data: BufferSourceLike, options?: PemEncodeOptions): string;
/** Encodes multiple PEM blocks into one PEM bundle. */
export declare function encodeMany(blocks: readonly PemEncodeBlock[], options?: PemEncodeOptions): string;
/** Decodes PEM text into the contained blocks. */
export declare function decode(text: string, options?: PemDecodeOptions): PemBlock[];
/** Finds the first PEM block with the requested label. */
export declare function find(text: string, label: string): PemBlock | undefined;
/** Finds all PEM blocks with the requested label. */
export declare function findAll(text: string, label: string): PemBlock[];
/** Decodes the first matching PEM block. */
export declare function decodeFirst(text: string, label?: string): Uint8Array;
/** Parses the first matching PEM block and preserves its formatting metadata. */
export declare function parse(text: string, options?: PemDecodeOptions): ParsedBytes<PemFormat>;
/** Formats bytes with preserved PEM metadata. */
export declare function format(data: BufferSourceLike, value: PemFormat): string;
/** PEM codec helpers. */
export declare const pem: {
readonly decode: typeof decode;
readonly decodeFirst: typeof decodeFirst;
readonly encode: typeof encode;
readonly encodeMany: typeof encodeMany;
readonly find: typeof find;
readonly findAll: typeof findAll;
readonly format: typeof format;
readonly parse: typeof parse;
};
/** Converter wrapper for PEM text. */
export declare const pemConverter: Converter<PemEncodeOptions & {
label: string;
}, PemDecodeOptions, PemFormat>;

View file

@ -0,0 +1,48 @@
import type { BufferSourceLike } from "../bytes/index.js";
import type { ParsedBytes } from "../converters/types.js";
/** Represents a decoded PEM block with label, data, and optional headers. */
export interface PemBlock {
readonly label: string;
readonly data: Uint8Array;
readonly headers?: Readonly<Record<string, string>>;
}
/** Options that control PEM encoding. */
export interface PemEncodeOptions {
lineLength?: number;
newline?: "\n" | "\r\n";
headers?: Readonly<Record<string, string>>;
}
/** Options that control PEM decoding. */
export interface PemDecodeOptions {
label?: string;
strict?: boolean;
}
/** Format metadata that can be reused to re-encode PEM text. */
export interface PemFormat extends PemEncodeOptions {
readonly label: string;
}
/** Input block used by multi-block PEM encoding helpers. */
export interface PemEncodeBlock {
readonly label: string;
readonly data: BufferSourceLike;
readonly headers?: Readonly<Record<string, string>>;
}
/** Encodes and decodes PEM blocks. */
export interface PemCodec {
/** Encodes a buffer source into a PEM block. */
encode(label: string, data: BufferSourceLike, options?: PemEncodeOptions): string;
/** Encodes multiple PEM blocks into a single string. */
encodeMany(blocks: readonly PemEncodeBlock[], options?: PemEncodeOptions): string;
/** Decodes PEM text into blocks. */
decode(text: string, options?: PemDecodeOptions): PemBlock[];
/** Decodes the first matching PEM block. */
decodeFirst(text: string, label?: string): Uint8Array;
/** Finds the first PEM block with the requested label. */
find(text: string, label: string): PemBlock | undefined;
/** Finds all PEM blocks with the requested label. */
findAll(text: string, label: string): PemBlock[];
/** Parses the first matching PEM block and preserves the detected formatting. */
parse(text: string, options?: PemDecodeOptions): ParsedBytes<PemFormat>;
/** Formats bytes with previously detected PEM metadata. */
format(data: BufferSourceLike, format: PemFormat): string;
}

111
electron/node_modules/@peculiar/utils/package.json generated vendored Normal file
View file

@ -0,0 +1,111 @@
{
"name": "@peculiar/utils",
"version": "2.0.3",
"description": "Modern byte, encoding, converter registry, and PEM utilities for TypeScript projects.",
"type": "module",
"main": "./build/cjs/index.js",
"module": "./build/esm/index.js",
"types": "./build/types/index.d.ts",
"exports": {
".": {
"types": "./build/types/index.d.ts",
"import": "./build/esm/index.js",
"require": "./build/cjs/index.js"
},
"./bytes": {
"types": "./build/types/bytes/index.d.ts",
"import": "./build/esm/bytes/index.js",
"require": "./build/cjs/bytes/index.js"
},
"./encoding": {
"types": "./build/types/encoding/index.d.ts",
"import": "./build/esm/encoding/index.js",
"require": "./build/cjs/encoding/index.js"
},
"./encoding/*": {
"types": "./build/types/encoding/*.d.ts",
"import": "./build/esm/encoding/*.js",
"require": "./build/cjs/encoding/*.js"
},
"./converters": {
"types": "./build/types/converters/index.d.ts",
"import": "./build/esm/converters/index.js",
"require": "./build/cjs/converters/index.js"
},
"./pem": {
"types": "./build/types/pem/index.d.ts",
"import": "./build/esm/pem/index.js",
"require": "./build/cjs/pem/index.js"
},
"./legacy": {
"types": "./build/types/legacy/index.d.ts",
"import": "./build/esm/legacy/index.js",
"require": "./build/cjs/legacy/index.js"
},
"./package.json": "./package.json"
},
"files": [
"build/cjs/**/*.js",
"build/cjs/package.json",
"build/esm/**/*.js",
"build/types/**/*.d.ts",
"README.md",
"LICENSE"
],
"publishConfig": {
"access": "public"
},
"scripts": {
"test": "vitest run",
"coverage": "vitest run --coverage",
"clear": "rimraf build",
"rebuild": "npm run clear && npm run build",
"build": "node scripts/prune-legacy-build-outputs.mjs && tsc -p tsconfig.build.types.json && tsc -p tsconfig.build.esm.json && tsc -p tsconfig.build.cjs.json && node scripts/write-cjs-package-json.mjs",
"prepack": "npm run build",
"publish:manual": "npm run check && npm run build && npm publish --ignore-scripts",
"lint:check": "eslint . --fix-dry-run",
"check": "npm run lint:check && tsc --noEmit && npm test",
"lint": "eslint .",
"lint:fix": "eslint . --fix"
},
"keywords": [
"typescript",
"utils",
"buffer",
"bytes",
"convert",
"encoding",
"base64",
"base64url",
"hex",
"utf8",
"utf16",
"pem",
"pki",
"peculiar"
],
"author": "PeculiarVentures",
"contributors": [
"Miroshin Stepan<microshine@mail.ru>"
],
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/PeculiarVentures/pvtsutils"
},
"bugs": {
"url": "https://github.com/PeculiarVentures/pvtsutils/issues"
},
"homepage": "https://github.com/PeculiarVentures/pvtsutils#readme",
"dependencies": {
"tslib": "^2.8.1"
},
"devDependencies": {
"@peculiar/eslint-config-base": "^0.2.9",
"@types/node": "^25.6.0",
"@vitest/coverage-v8": "^4.1.5",
"rimraf": "^6.1.3",
"typescript": "^6.0.3",
"vitest": "^4.1.5"
}
}