deno add jsr:@nick/atobpnpm add jsr:@nick/atobyarn add jsr:@nick/atobbunx jsr add @nick/atobnpx -y jsr add @nick/atobThis package provides ponyfill exports for atob and btoa, as well as a
./shim entrypoint that will automatically polyfill the global scope with
atob and/or btoa if they are not already supported.
import { atob, btoa } from "@nick/atob";
import assert from "node:assert";
const datauri = `data:image/svg+xml;base64,${btoa("<svg>...</svg>")}`;
const base64 = datauri.split(",")[1]!;
const decoded = atob(base64); // "<svg>...</svg>"
assert.strictEqual(decoded, "<svg>...</svg>"); // OKWhile the primary focus of this package is providing a ponyfill for atob and
btoa, some users might need a polyfill instead.
Therefore, I've also provided an automatic shim module that gracefully installs these functions on an as-needed basis, as well as a manual install module that allows you to choose when and if you want it to mutate the global scope.
import "@nick/atob/shim"; // side-effect import
const bytes = "data:application/wasm;base64,AGFzbQEAAAABOwpgAn9/AX...";
const buf = Uint8Array.from(atob(bytes.split(",")[1]!), (b) => b.charCodeAt(0));
const module = new WebAssembly.Module(buf);
const instance = new WebAssembly.Instance(module);If you need explicit control over the polyfilling, install() can
be used to gracefully install the functions on-demand.
import { install } from "@nick/atob/install";
import assert from "node:assert";
if (typeof atob !== "function" || typeof btoa !== "function") {
install(); // ta da!
}
assert.strictEqual(btoa("hello world"), "aGVsbG8gd29ybGQ="); // OK
assert.strictEqual(atob("aGVsbG8gd29ybGQ="), "hello world"); // OKNote
This is used internally by the ./shim entrypoint.
Decodes a Base64-encoded string into a decoded string.
function atob(data: string): string;data The Base64-encoded string to decode.
A decoded string.
import { atob } from "@nick/atob";
import assert from "node:assert";
const encoded = "aGVsbG8gd29ybGQ=";
const decoded = atob(encoded);
assert.strictEqual(decoded, "hello world"); // OKEncodes a string into Base64.
function btoa(data: string): string;data The string to encode.
A Base64-encoded string.
import { btoa } from "@nick/atob";
import assert from "node:assert";
const data = "hello world";
const encoded = btoa(data);
assert.strictEqual(encoded, "aGVsbG8gd29ybGQ=");Gracefully polyfills the global atob and btoa functions if they are not
already present in the environment.
function install(): Result;- On success, returns a
Successobject containing the installed functions. - If the functions are already defined, returns a
Skippedresult. - If the installation fails, returns a
Failureresult with the error.
Represents a successful polyfill installation
interface Success<T> {
readonly type: "success";
readonly data: T;
}Indicates that the installation was skipped because atob and btoa are
already present. If available, the info property will contain extra context
about which functions were already defined and thus skipped.
interface Skipped {
readonly type: "skipped";
readonly info?: string;
}Represents a failed installation with an error.
interface Failure {
readonly type: "failure";
readonly error: unknown;
}Contains references to the installed polyfill functions. This is the type of the
data property within a Success result returned by calling install(). If
only one function was installed, it will be the only one present in the data
payload. Otherwise, both of the polyfilled functions will be referenced.
type Data =
| { readonly atob: typeof atob }
| { readonly btoa: typeof btoa }
| { readonly atob: typeof atob; readonly btoa: typeof btoa };Represents the union of all possible results of the installation process, which
are each documented in the sections above. This is a discriminated union type;
check against the type property to determine which variant you have and allow
TypeScript to narrow the type accordingly.
type Result = Success<Data> | Skipped | Failure;import { install } from "@nick/atob/install";
import assert from "node:assert";
if (typeof atob !== "function" || typeof btoa !== "function") {
const result = install();
if (result.type === "success") {
console.log("atob and btoa installed successfully.");
} else if (result.type === "skipped") {
console.log("atob and btoa already installed.");
} else {
console.error("Failed to install atob and btoa:", result.error);
}
}
assert.ok(typeof btoa === "function"); // OK
assert.strictEqual(btoa("hello world"), "aGVsbG8gd29ybGQ=");
assert.ok(typeof atob === "function"); // OK
assert.strictEqual(atob("aGVsbG8gd29ybGQ="), "hello world");Contributions are always welcome! Before submitting a pull request, I kindly ask that you first open an issue and start a discussion regarding the feature or bug you would like to address. This helps contributions align with the goals and scope of the project, ensuring a smoother integration process.
For additional details, please refer to the contributing guidelines. Thanks!