diff --git a/node_modules/@peculiar/utils/build/cjs/package.json b/node_modules/@peculiar/utils/build/cjs/package.json new file mode 100644 index 0000000..5bbefff --- /dev/null +++ b/node_modules/@peculiar/utils/build/cjs/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/node_modules/@peculiar/utils/build/cjs/pem/index.js b/node_modules/@peculiar/utils/build/cjs/pem/index.js new file mode 100644 index 0000000..f94d30c --- /dev/null +++ b/node_modules/@peculiar/utils/build/cjs/pem/index.js @@ -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; } }); diff --git a/node_modules/@peculiar/utils/build/cjs/pem/pem.js b/node_modules/@peculiar/utils/build/cjs/pem/pem.js new file mode 100644 index 0000000..f272a0d --- /dev/null +++ b/node_modules/@peculiar/utils/build/cjs/pem/pem.js @@ -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, +}; diff --git a/node_modules/@peculiar/utils/build/cjs/pem/types.js b/node_modules/@peculiar/utils/build/cjs/pem/types.js new file mode 100644 index 0000000..c8ad2e5 --- /dev/null +++ b/node_modules/@peculiar/utils/build/cjs/pem/types.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/node_modules/@peculiar/utils/build/esm/bytes/buffer-source.js b/node_modules/@peculiar/utils/build/esm/bytes/buffer-source.js new file mode 100644 index 0000000..1d3f947 --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/bytes/buffer-source.js @@ -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); +} diff --git a/node_modules/@peculiar/utils/build/esm/bytes/concat.js b/node_modules/@peculiar/utils/build/esm/bytes/concat.js new file mode 100644 index 0000000..0a27427 --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/bytes/concat.js @@ -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; +} diff --git a/node_modules/@peculiar/utils/build/esm/bytes/equal.js b/node_modules/@peculiar/utils/build/esm/bytes/equal.js new file mode 100644 index 0000000..53adbec --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/bytes/equal.js @@ -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; +} diff --git a/node_modules/@peculiar/utils/build/esm/bytes/index.js b/node_modules/@peculiar/utils/build/esm/bytes/index.js new file mode 100644 index 0000000..77e4f3b --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/bytes/index.js @@ -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"; diff --git a/node_modules/@peculiar/utils/build/esm/bytes/sequence.js b/node_modules/@peculiar/utils/build/esm/bytes/sequence.js new file mode 100644 index 0000000..df18490 --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/bytes/sequence.js @@ -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; +} diff --git a/node_modules/@peculiar/utils/build/esm/bytes/types.js b/node_modules/@peculiar/utils/build/esm/bytes/types.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/bytes/types.js @@ -0,0 +1 @@ +export {}; diff --git a/node_modules/@peculiar/utils/build/esm/converters/convert.js b/node_modules/@peculiar/utils/build/esm/converters/convert.js new file mode 100644 index 0000000..901b477 --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/converters/convert.js @@ -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, +}; diff --git a/node_modules/@peculiar/utils/build/esm/converters/defaults.js b/node_modules/@peculiar/utils/build/esm/converters/defaults.js new file mode 100644 index 0000000..ba22db8 --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/converters/defaults.js @@ -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); diff --git a/node_modules/@peculiar/utils/build/esm/converters/index.js b/node_modules/@peculiar/utils/build/esm/converters/index.js new file mode 100644 index 0000000..b9ab687 --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/converters/index.js @@ -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"; diff --git a/node_modules/@peculiar/utils/build/esm/converters/registry.js b/node_modules/@peculiar/utils/build/esm/converters/registry.js new file mode 100644 index 0000000..b0237da --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/converters/registry.js @@ -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; +} diff --git a/node_modules/@peculiar/utils/build/esm/converters/types.js b/node_modules/@peculiar/utils/build/esm/converters/types.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/converters/types.js @@ -0,0 +1 @@ +export {}; diff --git a/node_modules/@peculiar/utils/build/esm/encoding/base64.js b/node_modules/@peculiar/utils/build/esm/encoding/base64.js new file mode 100644 index 0000000..b442aa3 --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/encoding/base64.js @@ -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 }; diff --git a/node_modules/@peculiar/utils/build/esm/encoding/base64url.js b/node_modules/@peculiar/utils/build/esm/encoding/base64url.js new file mode 100644 index 0000000..e12f3fa --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/encoding/base64url.js @@ -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 }; diff --git a/node_modules/@peculiar/utils/build/esm/encoding/binary.js b/node_modules/@peculiar/utils/build/esm/encoding/binary.js new file mode 100644 index 0000000..05fe786 --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/encoding/binary.js @@ -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 }; diff --git a/node_modules/@peculiar/utils/build/esm/encoding/hex.js b/node_modules/@peculiar/utils/build/esm/encoding/hex.js new file mode 100644 index 0000000..61bebf6 --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/encoding/hex.js @@ -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 }; diff --git a/node_modules/@peculiar/utils/build/esm/encoding/index.js b/node_modules/@peculiar/utils/build/esm/encoding/index.js new file mode 100644 index 0000000..c89396f --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/encoding/index.js @@ -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"; diff --git a/node_modules/@peculiar/utils/build/esm/encoding/utf16.js b/node_modules/@peculiar/utils/build/esm/encoding/utf16.js new file mode 100644 index 0000000..4a80e24 --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/encoding/utf16.js @@ -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 }; diff --git a/node_modules/@peculiar/utils/build/esm/encoding/utf8.js b/node_modules/@peculiar/utils/build/esm/encoding/utf8.js new file mode 100644 index 0000000..03d8ed5 --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/encoding/utf8.js @@ -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 }; diff --git a/node_modules/@peculiar/utils/build/esm/index.js b/node_modules/@peculiar/utils/build/esm/index.js new file mode 100644 index 0000000..9c736ed --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/index.js @@ -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"; diff --git a/node_modules/@peculiar/utils/build/esm/legacy/buffer-source-converter.js b/node_modules/@peculiar/utils/build/esm/legacy/buffer-source-converter.js new file mode 100644 index 0000000..d2e40ac --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/legacy/buffer-source-converter.js @@ -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); + } +} diff --git a/node_modules/@peculiar/utils/build/esm/legacy/convert.js b/node_modules/@peculiar/utils/build/esm/legacy/convert.js new file mode 100644 index 0000000..8f5db1f --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/legacy/convert.js @@ -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); + } +} diff --git a/node_modules/@peculiar/utils/build/esm/legacy/functions.js b/node_modules/@peculiar/utils/build/esm/legacy/functions.js new file mode 100644 index 0000000..160c366 --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/legacy/functions.js @@ -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); +} diff --git a/node_modules/@peculiar/utils/build/esm/legacy/index.js b/node_modules/@peculiar/utils/build/esm/legacy/index.js new file mode 100644 index 0000000..afd7a35 --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/legacy/index.js @@ -0,0 +1,3 @@ +export { BufferSourceConverter } from "./buffer-source-converter.js"; +export { Convert } from "./convert.js"; +export { assign, combine, isEqual } from "./functions.js"; diff --git a/node_modules/@peculiar/utils/build/esm/pem/index.js b/node_modules/@peculiar/utils/build/esm/pem/index.js new file mode 100644 index 0000000..dfadeb7 --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/pem/index.js @@ -0,0 +1 @@ +export { decode, decodeFirst, encode, encodeMany, find, findAll, format, parse, pem, pemConverter } from "./pem.js"; diff --git a/node_modules/@peculiar/utils/build/esm/pem/pem.js b/node_modules/@peculiar/utils/build/esm/pem/pem.js new file mode 100644 index 0000000..5ad65bc --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/pem/pem.js @@ -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, +}; diff --git a/node_modules/@peculiar/utils/build/esm/pem/types.js b/node_modules/@peculiar/utils/build/esm/pem/types.js new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/node_modules/@peculiar/utils/build/esm/pem/types.js @@ -0,0 +1 @@ +export {}; diff --git a/node_modules/@peculiar/utils/build/types/bytes/buffer-source.d.ts b/node_modules/@peculiar/utils/build/types/bytes/buffer-source.d.ts new file mode 100644 index 0000000..e03d7eb --- /dev/null +++ b/node_modules/@peculiar/utils/build/types/bytes/buffer-source.d.ts @@ -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(data: BufferSourceLike, type: ViewConstructor): T; +/** Copies buffer data into the requested view type. */ +export declare function toViewCopy(data: BufferSourceLike, type: ViewConstructor): T; diff --git a/node_modules/@peculiar/utils/build/types/bytes/concat.d.ts b/node_modules/@peculiar/utils/build/types/bytes/concat.d.ts new file mode 100644 index 0000000..1dfbed9 --- /dev/null +++ b/node_modules/@peculiar/utils/build/types/bytes/concat.d.ts @@ -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): 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): ArrayBufferLike; +export declare function concat(buffers: Iterable, type: ViewConstructor): T; diff --git a/node_modules/@peculiar/utils/build/types/bytes/equal.d.ts b/node_modules/@peculiar/utils/build/types/bytes/equal.d.ts new file mode 100644 index 0000000..8632ef9 --- /dev/null +++ b/node_modules/@peculiar/utils/build/types/bytes/equal.d.ts @@ -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; diff --git a/node_modules/@peculiar/utils/build/types/bytes/index.d.ts b/node_modules/@peculiar/utils/build/types/bytes/index.d.ts new file mode 100644 index 0000000..99d5d13 --- /dev/null +++ b/node_modules/@peculiar/utils/build/types/bytes/index.d.ts @@ -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"; diff --git a/node_modules/@peculiar/utils/build/types/bytes/sequence.d.ts b/node_modules/@peculiar/utils/build/types/bytes/sequence.d.ts new file mode 100644 index 0000000..c4b6131 --- /dev/null +++ b/node_modules/@peculiar/utils/build/types/bytes/sequence.d.ts @@ -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): boolean; +/** Returns `true` when the byte sequence ends with the requested pattern. */ +export declare function endsWith(data: BufferSourceLike, pattern: BytePattern, options?: Pick): 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; diff --git a/node_modules/@peculiar/utils/build/types/bytes/types.d.ts b/node_modules/@peculiar/utils/build/types/bytes/types.d.ts new file mode 100644 index 0000000..858b8e0 --- /dev/null +++ b/node_modules/@peculiar/utils/build/types/bytes/types.d.ts @@ -0,0 +1,29 @@ +/** Describes a buffer-backed view with offset and length metadata. */ +export interface ArrayBufferViewLike { + 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; +/** Constructor shape for typed array-like views. */ +export interface ArrayBufferViewConstructor { + readonly prototype: T; + readonly BYTES_PER_ELEMENT?: number; + readonly name: string; + new (length: number): T; + new (array: ArrayLike): T; + new (buffer: ArrayBufferLike, byteOffset?: number, length?: number): T; +} +/** Constructor shape for DataView-like views. */ +export interface DataViewConstructorLike { + 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 = ArrayBufferViewConstructor | DataViewConstructorLike; diff --git a/node_modules/@peculiar/utils/build/types/converters/convert.d.ts b/node_modules/@peculiar/utils/build/types/converters/convert.d.ts new file mode 100644 index 0000000..4e91a24 --- /dev/null +++ b/node_modules/@peculiar/utils/build/types/converters/convert.d.ts @@ -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(name: TName, data: BufferSourceLike, ...args: OptionsArgument>): string; + /** Decodes text with a named converter. */ + decode(name: TName, text: string, ...args: OptionsArgument>): Uint8Array; + /** Safely decodes text with a named converter. */ + tryDecode(name: TName, text: string, ...args: OptionsArgument>): DecodeResult; + /** Normalizes text with a named converter. */ + normalize(name: TName, text: string, ...args: OptionsArgument>): string; + /** Parses text while preserving formatting metadata. */ + parse(name: TName, text: string, ...args: OptionsArgument>): ParsedBytes>; + /** Formats bytes using preserved formatting metadata. */ + format(name: TName, data: BufferSourceLike, format: FormatFor): string; + /** Converts text directly between registered formats. */ + transcode(text: string, options: TranscodeOptions): string; + /** Detects likely formats for an input string. */ + detect(text: string, options?: DetectOptions): FormatDetection[]; + /** @deprecated Use encode() instead. */ + to(format: TName, data: BufferSourceLike, ...args: OptionsArgument>): string; + /** @deprecated Use decode() instead. */ + from(format: TName, text: string, ...args: OptionsArgument>): 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; diff --git a/node_modules/@peculiar/utils/build/types/converters/defaults.d.ts b/node_modules/@peculiar/utils/build/types/converters/defaults.d.ts new file mode 100644 index 0000000..6325054 --- /dev/null +++ b/node_modules/@peculiar/utils/build/types/converters/defaults.d.ts @@ -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, Converter, Converter, Converter, Converter, Converter, Converter, Converter]; +/** The default registry preloaded with the built-in converters. */ +export declare const defaultConverterRegistry: import("./types.js").ConverterRegistry; diff --git a/node_modules/@peculiar/utils/build/types/converters/index.d.ts b/node_modules/@peculiar/utils/build/types/converters/index.d.ts new file mode 100644 index 0000000..9f9fa2c --- /dev/null +++ b/node_modules/@peculiar/utils/build/types/converters/index.d.ts @@ -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"; diff --git a/node_modules/@peculiar/utils/build/types/converters/registry.d.ts b/node_modules/@peculiar/utils/build/types/converters/registry.d.ts new file mode 100644 index 0000000..969f9c0 --- /dev/null +++ b/node_modules/@peculiar/utils/build/types/converters/registry.d.ts @@ -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): ConverterRegistry; diff --git a/node_modules/@peculiar/utils/build/types/converters/types.d.ts b/node_modules/@peculiar/utils/build/types/converters/types.d.ts new file mode 100644 index 0000000..1a04475 --- /dev/null +++ b/node_modules/@peculiar/utils/build/types/converters/types.d.ts @@ -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 = (data: BufferSourceLike, options?: TOptions) => string; +/** Converts text back into bytes using decoder-specific options. */ +export type ByteDecoder = (text: string, options?: TOptions) => Uint8Array; +/** Parsed text that preserves both decoded bytes and the detected format metadata. */ +export interface ParsedBytes { + /** 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; +type EmptyObject = Record; +type RequiredKeys = { + [TKey in keyof T]-?: EmptyObject extends Pick ? never : TKey; +}[keyof T]; +type NonUndefined = Exclude; +type CapabilityOptions = TName extends KnownConverterName ? ConverterOptionsMap[TName] extends Record ? TOptions : unknown : unknown; +/** Resolves typed encode options for a known converter name. */ +export type EncodeOptionsFor = CapabilityOptions; +/** Resolves typed decode options for a known converter name. */ +export type DecodeOptionsFor = CapabilityOptions; +/** Resolves typed format metadata for a known converter name. */ +export type FormatFor = CapabilityOptions; +/** Builds an optional or required options tuple depending on the options type. */ +export type OptionsArgument = [TOptions] extends [never] ? [] : unknown extends TOptions ? [options?: TOptions] : [NonUndefined] extends [object] ? RequiredKeys> extends never ? [options?: TOptions] : [options: TOptions] : [options: TOptions]; +/** Options for direct format-to-format transcoding. */ +export interface TranscodeOptions { + /** Source format name. */ + readonly from: TFrom; + /** Source decoder options. */ + readonly fromOptions?: DecodeOptionsFor; + /** Destination format name. */ + readonly to: TTo; + /** Destination encoder options. */ + readonly toOptions?: EncodeOptionsFor; +} +/** Options for ranked format detection. */ +export interface DetectOptions { + /** 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 { + /** 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; + /** Decodes text into bytes. */ + readonly decode: ByteDecoder; + /** 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; + /** 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(name: TName, data: BufferSourceLike, ...args: OptionsArgument>): string; + /** Decodes text with a named converter. */ + decode(name: TName, text: string, ...args: OptionsArgument>): Uint8Array; + /** Safely decodes text with a named converter without throwing. */ + tryDecode(name: TName, text: string, ...args: OptionsArgument>): DecodeResult; + /** Normalizes text with a named converter. */ + normalize(name: TName, text: string, ...args: OptionsArgument>): string; + /** Parses text with a named converter. */ + parse(name: TName, text: string, ...args: OptionsArgument>): ParsedBytes>; + /** Formats bytes with a named converter using preserved formatting metadata. */ + format(name: TName, data: BufferSourceLike, format: FormatFor): string; + /** Converts text directly from one registered format to another. */ + transcode(text: string, options: TranscodeOptions): string; + /** Detects likely formats for the provided text. */ + detect(text: string, options?: DetectOptions): FormatDetection[]; +} +export {}; diff --git a/node_modules/@peculiar/utils/build/types/encoding/base64.d.ts b/node_modules/@peculiar/utils/build/types/encoding/base64.d.ts new file mode 100644 index 0000000..9390bf5 --- /dev/null +++ b/node_modules/@peculiar/utils/build/types/encoding/base64.d.ts @@ -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; +}; diff --git a/node_modules/@peculiar/utils/build/types/encoding/base64url.d.ts b/node_modules/@peculiar/utils/build/types/encoding/base64url.d.ts new file mode 100644 index 0000000..9704c8f --- /dev/null +++ b/node_modules/@peculiar/utils/build/types/encoding/base64url.d.ts @@ -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; +}; diff --git a/node_modules/@peculiar/utils/build/types/encoding/binary.d.ts b/node_modules/@peculiar/utils/build/types/encoding/binary.d.ts new file mode 100644 index 0000000..660f17f --- /dev/null +++ b/node_modules/@peculiar/utils/build/types/encoding/binary.d.ts @@ -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; +}; diff --git a/node_modules/@peculiar/utils/build/types/encoding/hex.d.ts b/node_modules/@peculiar/utils/build/types/encoding/hex.d.ts new file mode 100644 index 0000000..cbbc1bd --- /dev/null +++ b/node_modules/@peculiar/utils/build/types/encoding/hex.d.ts @@ -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; +/** 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; + readonly upper: Readonly; + readonly colon: Readonly; + readonly colonUpper: Readonly; + readonly groupsOf4: Readonly; + readonly prefixed: Readonly; +}; +/** Hexadecimal codec helpers. */ +export declare const hex: { + readonly encode: typeof encode; + readonly decode: typeof decode; + readonly format: typeof format; + readonly formats: { + readonly compact: Readonly; + readonly upper: Readonly; + readonly colon: Readonly; + readonly colonUpper: Readonly; + readonly groupsOf4: Readonly; + readonly prefixed: Readonly; + }; + readonly is: typeof is; + readonly normalize: typeof normalize; + readonly parse: typeof parse; +}; diff --git a/node_modules/@peculiar/utils/build/types/encoding/index.d.ts b/node_modules/@peculiar/utils/build/types/encoding/index.d.ts new file mode 100644 index 0000000..051a951 --- /dev/null +++ b/node_modules/@peculiar/utils/build/types/encoding/index.d.ts @@ -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"; diff --git a/node_modules/@peculiar/utils/build/types/encoding/utf16.d.ts b/node_modules/@peculiar/utils/build/types/encoding/utf16.d.ts new file mode 100644 index 0000000..84267ec --- /dev/null +++ b/node_modules/@peculiar/utils/build/types/encoding/utf16.d.ts @@ -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; +}; diff --git a/node_modules/@peculiar/utils/build/types/encoding/utf8.d.ts b/node_modules/@peculiar/utils/build/types/encoding/utf8.d.ts new file mode 100644 index 0000000..3960268 --- /dev/null +++ b/node_modules/@peculiar/utils/build/types/encoding/utf8.d.ts @@ -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; +}; diff --git a/node_modules/@peculiar/utils/build/types/index.d.ts b/node_modules/@peculiar/utils/build/types/index.d.ts new file mode 100644 index 0000000..16a9ec1 --- /dev/null +++ b/node_modules/@peculiar/utils/build/types/index.d.ts @@ -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"; diff --git a/node_modules/@peculiar/utils/build/types/legacy/buffer-source-converter.d.ts b/node_modules/@peculiar/utils/build/types/legacy/buffer-source-converter.d.ts new file mode 100644 index 0000000..bc1c494 --- /dev/null +++ b/node_modules/@peculiar/utils/build/types/legacy/buffer-source-converter.d.ts @@ -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(data: BufferSourceLike, type: ViewConstructor): 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(buffers: BufferSourceLike[], type: ArrayBufferViewConstructor): T; +}