Files
wasm/packages/quantus-crypto/src/base64.ts
T
rob thijssenandClaude Opus 5 a6d3685c59 refactor(quantus-crypto): drop the @polkadot/wasm-util dependency
It cost more than it saved. Two problems, the second only visible once
quantus/common tried to consume this package:

Its index re-exports packageDetect, whose only job is a side effect registering
with @polkadot/util — a peer dependency inherited for nothing. Deep imports
(/base64, /fflate) avoided that.

But it is a workspace package, so a symlinked consumer resolves its dependencies
through *this* repo's node_modules, where @polkadot/wasm-util points at the
package source rather than its build and carries no exports map. Node follows
symlinks to their realpath, so `@polkadot/wasm-util/base64` failed to resolve
from quantus/common no matter which yarn protocol was used — portal: and link:
behave the same once the realpath is taken.

So: fflate directly for zlib inflate, and fifteen lines for base64 rather than a
dependency at all. Deliberately not atob or Buffer.from — the first is
browser-only, the second node-only, and this runs in an MV3 service worker, a
Worker, node tests and a bundled extension page.

The package is now self-contained apart from fflate, which resolves normally from
any checkout. Size is unchanged at 234,292 raw / 109,649 zlib / 146,200 base64.

Refs quantus/wasm#1, quantus/common#2

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012uDUodEcRbBwNRi3UCmw8f
2026-09-10 18:39:54 +03:00

52 lines
1.6 KiB
TypeScript

// Copyright 2026 @quantus/crypto authors & contributors
// SPDX-License-Identifier: Apache-2.0
const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
// An array indexer rather than a Map: the input is ASCII by construction, so it
// cannot overflow, and array access is measurably faster on the hot loop.
const MAP = new Array<number>(256);
for (let i = 0; i < CHARS.length; i++) {
MAP[CHARS.charCodeAt(i)] = i;
}
/**
* Decode base64 into a caller-supplied buffer.
*
* Deliberately not `atob` or `Buffer.from`: the first is browser-only, the second
* node-only, and this runs in an MV3 service worker, a Worker, node tests and a
* bundled extension page. The output length is known at build time, so the
* caller provides the buffer and there is no growth or reallocation.
*
* This is a reimplementation of `@polkadot/wasm-util`'s base64Decode, which was
* the dependency it replaced. That package's index re-exports `packageDetect`,
* dragging in a `@polkadot/util` peer dependency for a side effect we do not
* want, and being a workspace package it resolved through its own repo's
* node_modules when consumed by symlink from another checkout. Fifteen lines is
* cheaper than either problem.
*/
export function base64Decode (data: string, out: Uint8Array): Uint8Array {
let byte = 0;
let bits = 0;
let pos = 0;
for (let i = 0; i < data.length && pos < out.length; i++) {
const value = MAP[data.charCodeAt(i)];
if (value === undefined) {
continue;
}
byte = (byte << 6) | value;
bits += 6;
if (bits >= 8) {
bits -= 8;
out[pos++] = (byte >>> bits) & 0xff;
}
}
return out;
}