diff --git a/src/media/qr-image.ts b/src/media/qr-image.ts index e0a0a276acc..942cfd4b03c 100644 --- a/src/media/qr-image.ts +++ b/src/media/qr-image.ts @@ -1,5 +1,3 @@ -import QRCodeModule from "qrcode-terminal/vendor/QRCode/index.js"; -import QRErrorCorrectLevelModule from "qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js"; import { encodePngRgba, fillPixel } from "./png-encode.ts"; type QRCodeConstructor = new ( @@ -12,10 +10,26 @@ type QRCodeConstructor = new ( isDark: (row: number, col: number) => boolean; }; -const QRCode = QRCodeModule as QRCodeConstructor; -const QRErrorCorrectLevel = QRErrorCorrectLevelModule; +let qrCodeRuntimePromise: Promise<{ + QRCode: QRCodeConstructor; + QRErrorCorrectLevel: Record; +}> | null = null; -function createQrMatrix(input: string) { +async function loadQrCodeRuntime() { + if (!qrCodeRuntimePromise) { + qrCodeRuntimePromise = Promise.all([ + import("qrcode-terminal/vendor/QRCode/index.js"), + import("qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js"), + ]).then(([qrCodeModule, errorCorrectLevelModule]) => ({ + QRCode: qrCodeModule.default as QRCodeConstructor, + QRErrorCorrectLevel: errorCorrectLevelModule.default, + })); + } + return await qrCodeRuntimePromise; +} + +async function createQrMatrix(input: string) { + const { QRCode, QRErrorCorrectLevel } = await loadQrCodeRuntime(); const qr = new QRCode(-1, QRErrorCorrectLevel.L); qr.addData(input); qr.make(); @@ -27,7 +41,7 @@ export async function renderQrPngBase64( opts: { scale?: number; marginModules?: number } = {}, ): Promise { const { scale = 6, marginModules = 4 } = opts; - const qr = createQrMatrix(input); + const qr = await createQrMatrix(input); const modules = qr.getModuleCount(); const size = (modules + marginModules * 2) * scale; diff --git a/src/types/qrcode-terminal.d.ts b/src/types/qrcode-terminal.d.ts index 3cd866f1b1c..ebcdfbc2682 100644 --- a/src/types/qrcode-terminal.d.ts +++ b/src/types/qrcode-terminal.d.ts @@ -1,3 +1,16 @@ +declare module "qrcode-terminal" { + type GenerateOptions = { + small?: boolean; + }; + + type QrCodeTerminal = { + generate: (input: string, options?: GenerateOptions, cb?: (output: string) => void) => void; + }; + + const qrcode: QrCodeTerminal; + export default qrcode; +} + declare module "qrcode-terminal/vendor/QRCode/index.js" { const QRCode: unknown; export default QRCode;