quadqr-js 1.3.0 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,6 +12,8 @@ import {
12
12
  decodeMatrix,
13
13
  getVersionInfo,
14
14
  compressPayload,
15
+ compressDeflatePayload,
16
+ compressBrotliPayload,
15
17
  MAX_VERSION
16
18
  } from "./quadqr.js";
17
19
 
@@ -130,29 +132,57 @@ export function calculateCapacityPlan(options = {}) {
130
132
  else if (typeof options.payload === "string") sourceBytes = new TextEncoder().encode(options.payload);
131
133
  else sourceBytes = new Uint8Array(Math.max(0, Math.floor(options.payloadBytes ?? 0)));
132
134
 
133
- const requestedCompression = options.compression ?? "none";
135
+ const requestedCompression = String(options.compression ?? "none").toLowerCase();
136
+ if (!["none", "auto", "smart", "lz", "deflate", "brotli"].includes(requestedCompression)) {
137
+ throw new Error("compression must be none, auto, smart, lz, deflate, or brotli.");
138
+ }
134
139
  const signed = Boolean(options.signed);
135
140
  const keyIdBytes = options.keyId ? new TextEncoder().encode(String(options.keyId)).length : 0;
136
141
  const envelopeHeaderBytes = 16;
137
142
  const signingBytes = signed ? 64 + keyIdBytes + (options.embedPublicKey ? 32 : 0) : 0;
138
143
  let compression = requestedCompression;
144
+ let compressionLevel = null;
139
145
  let storedBytes = sourceBytes.length;
140
146
  let compressed = false;
141
147
 
142
148
  if (requestedCompression !== "none" && hasConcretePayload) {
143
- const candidate = compressPayload(sourceBytes);
144
- if (requestedCompression === "lz" || candidate.length < sourceBytes.length - 2) {
145
- storedBytes = candidate.length;
149
+ const candidates = [];
150
+ const explicitLevel = options.compressionLevel;
151
+ if (requestedCompression === "auto" || requestedCompression === "smart" || requestedCompression === "lz") {
152
+ const level = requestedCompression === "lz" ? (explicitLevel ?? options.lzLevel ?? 6) : 6;
153
+ candidates.push({ compression: "lz", bytes: compressPayload(sourceBytes, { level }).length, level });
154
+ }
155
+ if (requestedCompression === "auto") {
156
+ candidates.push({ compression: "deflate", bytes: compressDeflatePayload(sourceBytes, { level: 6 }).length, level: 6 });
157
+ candidates.push({ compression: "brotli", bytes: compressBrotliPayload(sourceBytes, { quality: 6 }).length, level: 6 });
158
+ } else if (requestedCompression === "smart") {
159
+ for (const level of [6, 8, 9]) candidates.push({ compression: "deflate", bytes: compressDeflatePayload(sourceBytes, { level }).length, level });
160
+ for (const level of [6, 9, 11]) candidates.push({ compression: "brotli", bytes: compressBrotliPayload(sourceBytes, { quality: level }).length, level });
161
+ } else if (requestedCompression === "deflate") {
162
+ const level = explicitLevel ?? options.deflateLevel ?? 6;
163
+ candidates.push({ compression: "deflate", bytes: compressDeflatePayload(sourceBytes, { level }).length, level });
164
+ } else if (requestedCompression === "brotli") {
165
+ const level = explicitLevel ?? options.brotliQuality ?? 11;
166
+ candidates.push({ compression: "brotli", bytes: compressBrotliPayload(sourceBytes, { quality: level }).length, level });
167
+ }
168
+ if (!candidates.length) throw new Error("compression must be none, auto, smart, lz, deflate, or brotli.");
169
+ candidates.sort((a, b) => a.bytes - b.bytes);
170
+ const best = candidates[0];
171
+ const compressionOverhead = signed ? 0 : envelopeHeaderBytes;
172
+ if (!["auto", "smart"].includes(requestedCompression) || best.bytes + compressionOverhead < sourceBytes.length) {
173
+ storedBytes = best.bytes;
146
174
  compressed = true;
147
- compression = "lz";
175
+ compression = best.compression;
176
+ compressionLevel = best.level ?? null;
148
177
  } else {
149
178
  compression = "none";
179
+ compressionLevel = null;
150
180
  }
151
181
  } else if (requestedCompression !== "none" && !hasConcretePayload) {
152
182
  compression = "unknown";
153
183
  }
154
184
 
155
- const needsEnvelope = signed || compressed || requestedCompression === "lz";
185
+ const needsEnvelope = signed || compressed || requestedCompression === "lz" || requestedCompression === "deflate" || requestedCompression === "brotli";
156
186
  const encodedBytes = storedBytes + (needsEnvelope ? envelopeHeaderBytes + signingBytes : 0);
157
187
  const extensionOverheadBytes = encodedBytes - storedBytes;
158
188
 
@@ -185,6 +215,7 @@ export function calculateCapacityPlan(options = {}) {
185
215
  storedBytes,
186
216
  extensionOverheadBytes,
187
217
  compression,
218
+ compressionLevel,
188
219
  compressed,
189
220
  signed,
190
221
  quadqrVersion,