bysquare 2.2.0 → 2.3.0

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.
package/README.md CHANGED
@@ -110,26 +110,6 @@ const model =
110
110
  // ]
111
111
  // }
112
112
  //
113
- const qr =
114
- "0004A00090IFU27IV0J6HGGLIOTIBVHNQQJQ6LAVGNBT363HR13JC6CB54HSI0KH9FCRASHNQBSKAQD2LJ4AU400UVKDNDPFRKLOBEVVVU0QJ000"
115
-
116
- const model = parse(qr)
117
- /**
118
- * {
119
- * invoiceId: "random-id",
120
- * payments: [
121
- * {
122
- * type: PaymentOptions.PaymentOrder,
123
- * amount: 100.0,
124
- * bankAccounts: [
125
- * { iban: "SK9611000000002918599669" },
126
- * ],
127
- * currencyCode: "EUR",
128
- * variableSymbol: "123",
129
- * }
130
- * ]
131
- * }
132
- */
133
113
  ```
134
114
 
135
115
  You can use json file with valid model to generate qr-string.
@@ -1,27 +1,4 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
4
  };
@@ -29,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
29
6
  exports.generate = exports.serialize = exports.addChecksum = exports.headerDataLength = exports.headerBysquare = void 0;
30
7
  const crc_32_1 = __importDefault(require("crc-32"));
31
8
  const lodash_deburr_1 = __importDefault(require("lodash.deburr"));
32
- const lzma = __importStar(require("lzma1"));
9
+ const lzma1_1 = require("lzma1");
33
10
  const rfc4648_1 = require("rfc4648");
34
11
  const types_js_1 = require("./types.js");
35
12
  /**
@@ -66,33 +43,16 @@ header = [
66
43
  return mergedNibbles;
67
44
  }
68
45
  exports.headerBysquare = headerBysquare;
69
- /**
70
- * The function first sets default values for the lc, lp, and pb properties,
71
- * which represent the number of literal context bits, literal position bits,
72
- * and position bits, respectively. These values are then used to calculate the
73
- * properties value, which is a single byte that encodes all three properties.
74
- *
75
- * @see 3.11.
76
- */
77
- function headerLzmaProps() {
78
- const lc = 3;
79
- const lp = 0;
80
- const pb = 2;
81
- const properties = (((pb * 5) + lp) * 9) + lc;
82
- const header = new ArrayBuffer(1);
83
- new DataView(header).setUint8(0, properties);
84
- return new Uint8Array(header);
85
- }
86
46
  /**
87
47
  * Creates a one-byte array that represents the length of compressed data in
88
48
  * combination with CRC32 in bytes.
89
49
  */
90
50
  function headerDataLength(length) {
91
- if (length >= 2 ** 16) {
51
+ if (length >= 131072 /** 2^17 */) {
92
52
  throw new Error("The maximum compressed data size has been reached");
93
53
  }
94
- const header = new ArrayBuffer(1);
95
- new DataView(header).setUint8(0, length);
54
+ const header = new ArrayBuffer(2);
55
+ new DataView(header).setUint16(0, length);
96
56
  return new Uint8Array(header);
97
57
  }
98
58
  exports.headerDataLength = headerDataLength;
@@ -196,15 +156,17 @@ function generate(model, options = { deburr: true }) {
196
156
  }
197
157
  const payload = serialize(model);
198
158
  const withChecksum = addChecksum(payload);
199
- const compressed = Uint8Array.from(lzma.compress(withChecksum));
200
- /** Exclude the LZMA header and retain raw compressed data */
201
- const _headerLzma = Uint8Array.from(compressed.subarray(0, 13));
202
- const compressedPayload = Uint8Array.from(compressed.subarray(13));
159
+ const compressed = Uint8Array.from((0, lzma1_1.compress)(withChecksum));
160
+ const _lzmaHeader = Uint8Array.from(compressed.subarray(0, 13));
161
+ const lzmaBody = Uint8Array.from(compressed.subarray(13));
203
162
  const output = Uint8Array.from([
204
- ...headerBysquare([0x00, 1 /* Version["1.1.0"] */, 0x00, 0x00]),
205
- ...headerLzmaProps(),
163
+ // FIXME:
164
+ // for now other implementation of bysquare doesn't recognize header if
165
+ // version is specified like TatraBanka
166
+ // ...headerBysquare([0x00, Version["1.1.0"], 0x00, 0x00]),
167
+ ...headerBysquare([0x00, 0x00, 0x00, 0x00]),
206
168
  ...headerDataLength(withChecksum.byteLength),
207
- ...compressedPayload
169
+ ...lzmaBody
208
170
  ]);
209
171
  return rfc4648_1.base32hex.stringify(output, {
210
172
  pad: false
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bysquare",
3
3
  "description": "It's a national standard for payment QR codes adopted by Slovak Banking Association (SBA)",
4
- "version": "2.2.0",
4
+ "version": "2.3.0",
5
5
  "license": "Apache-2.0",
6
6
  "funding": "https://github.com/sponsors/xseman",
7
7
  "homepage": "https://github.com/xseman/bysquare#readme",
package/lib/cjs/parse.js CHANGED
@@ -1,30 +1,7 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  Object.defineProperty(exports, "__esModule", { value: true });
26
3
  exports.detect = exports.parse = exports.DecodeError = exports.deserialize = void 0;
27
- const lzma = __importStar(require("lzma1"));
4
+ const lzma1_1 = require("lzma1");
28
5
  const rfc4648_1 = require("rfc4648");
29
6
  const index_js_1 = require("./index.js");
30
7
  function cleanEmptyProps(obj) {
@@ -155,24 +132,6 @@ function deserialize(qr) {
155
132
  return output;
156
133
  }
157
134
  exports.deserialize = deserialize;
158
- /**
159
- * LZMA compression properties from the byte
160
- *
161
- * @param props 1-byte size
162
- */
163
- function LzmaPropertiesDecoder(props) {
164
- const byte = props[0];
165
- return {
166
- lc: byte >> 5,
167
- lp: byte >> 2 & 0b0111,
168
- pb: byte & 0b0011
169
- };
170
- }
171
- function calcLzmaDictionarySize(props) {
172
- const dictionarySize = new ArrayBuffer(4);
173
- new DataView(dictionarySize).setUint32(0, Math.pow(2, props.pb + props.lp));
174
- return new Uint8Array(dictionarySize);
175
- }
176
135
  /**
177
136
  * The function uses bit-shifting and masking to convert the first two bytes of
178
137
  * the input header array into four nibbles representing the bysquare header
@@ -183,9 +142,9 @@ function calcLzmaDictionarySize(props) {
183
142
  function bysquareHeaderDecoder(header) {
184
143
  const bytes = (header[0] << 8) | header[1];
185
144
  const bysquareType = bytes >> 12;
186
- const version = (bytes >> 8) & 0b1111;
187
- const documentType = (bytes >> 4) & 0b1111;
188
- const reserved = bytes & 0b1111;
145
+ const version = (bytes >> 8) & 15;
146
+ const documentType = (bytes >> 4) & 15;
147
+ const reserved = bytes & 15;
189
148
  return {
190
149
  bysquareType,
191
150
  version,
@@ -217,8 +176,7 @@ function parse(qr) {
217
176
  throw new DecodeError(error, "Unable to decode QR string base32hex encoding");
218
177
  }
219
178
  const bysquareHeader = bytes.slice(0, 2);
220
- const { version } = bysquareHeaderDecoder(bysquareHeader);
221
- if ((version > 1 /* Version["1.1.0"] */)) {
179
+ if ((bysquareHeaderDecoder(bysquareHeader).version > 1 /* Version["1.1.0"] */)) {
222
180
  throw new Error("Unsupported Bysquare version");
223
181
  }
224
182
  /**
@@ -233,14 +191,16 @@ function parse(qr) {
233
191
  * | Properties | Dictionary Size | Uncompressed Size |
234
192
  * +------------+----+----+----+----+--+--+--+--+--+--+--+--+
235
193
  */
236
- const lzmaProperties = bytes.slice(2, 3);
237
- const decodedProps = LzmaPropertiesDecoder(lzmaProperties);
238
- const dictSize = calcLzmaDictionarySize(decodedProps);
194
+ const defaultProperties = [0x5D]; // lc=3, lp=0, pb=2
195
+ const defaultDictionarySize = [0x00, 0x02, 0x00, 0x00]; // 2^17
196
+ const dataLengthView = new DataView(bytes.slice(2, 4).buffer);
197
+ const dataLength = dataLengthView.getUint16(0);
198
+ const uncompressedSize = new ArrayBuffer(8);
199
+ new DataView(uncompressedSize).setBigUint64(0, BigInt(dataLength), true);
239
200
  const header = new Uint8Array([
240
- lzmaProperties[0],
241
- ...dictSize,
242
- /** Uncompressed size, this value indicates that size is unknown */
243
- ...[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]
201
+ ...defaultProperties,
202
+ ...defaultDictionarySize,
203
+ ...new Uint8Array(uncompressedSize)
244
204
  ]);
245
205
  const payload = bytes.slice(4);
246
206
  const body = new Uint8Array([
@@ -248,15 +208,11 @@ function parse(qr) {
248
208
  ...payload
249
209
  ]);
250
210
  try {
251
- var decompressed = new Uint8Array(lzma.decompress(body));
211
+ var decompressed = new Uint8Array((0, lzma1_1.decompress)(body));
252
212
  }
253
213
  catch (error) {
254
214
  throw new DecodeError(error, "LZMA decompression failed");
255
215
  }
256
- const dataLength = bytes.slice(3, 4);
257
- if (dataLength[0] !== decompressed.length) {
258
- throw new Error("The length of the data after decompression is not as expected.");
259
- }
260
216
  const _checksum = decompressed.slice(0, 4);
261
217
  const decompressedBody = decompressed.slice(4);
262
218
  const decoded = new TextDecoder("utf-8").decode(decompressedBody);
@@ -1,6 +1,6 @@
1
1
  import crc32 from "crc-32";
2
2
  import deburr from "lodash.deburr";
3
- import * as lzma from "lzma1";
3
+ import { compress } from "lzma1";
4
4
  import { base32hex } from "rfc4648";
5
5
  import { PaymentOptions } from "./types.js";
6
6
  /**
@@ -36,33 +36,16 @@ header = [
36
36
  ]);
37
37
  return mergedNibbles;
38
38
  }
39
- /**
40
- * The function first sets default values for the lc, lp, and pb properties,
41
- * which represent the number of literal context bits, literal position bits,
42
- * and position bits, respectively. These values are then used to calculate the
43
- * properties value, which is a single byte that encodes all three properties.
44
- *
45
- * @see 3.11.
46
- */
47
- function headerLzmaProps() {
48
- const lc = 3;
49
- const lp = 0;
50
- const pb = 2;
51
- const properties = (((pb * 5) + lp) * 9) + lc;
52
- const header = new ArrayBuffer(1);
53
- new DataView(header).setUint8(0, properties);
54
- return new Uint8Array(header);
55
- }
56
39
  /**
57
40
  * Creates a one-byte array that represents the length of compressed data in
58
41
  * combination with CRC32 in bytes.
59
42
  */
60
43
  export function headerDataLength(length) {
61
- if (length >= 2 ** 16) {
44
+ if (length >= 131072 /** 2^17 */) {
62
45
  throw new Error("The maximum compressed data size has been reached");
63
46
  }
64
- const header = new ArrayBuffer(1);
65
- new DataView(header).setUint8(0, length);
47
+ const header = new ArrayBuffer(2);
48
+ new DataView(header).setUint16(0, length);
66
49
  return new Uint8Array(header);
67
50
  }
68
51
  /**
@@ -163,15 +146,17 @@ export function generate(model, options = { deburr: true }) {
163
146
  }
164
147
  const payload = serialize(model);
165
148
  const withChecksum = addChecksum(payload);
166
- const compressed = Uint8Array.from(lzma.compress(withChecksum));
167
- /** Exclude the LZMA header and retain raw compressed data */
168
- const _headerLzma = Uint8Array.from(compressed.subarray(0, 13));
169
- const compressedPayload = Uint8Array.from(compressed.subarray(13));
149
+ const compressed = Uint8Array.from(compress(withChecksum));
150
+ const _lzmaHeader = Uint8Array.from(compressed.subarray(0, 13));
151
+ const lzmaBody = Uint8Array.from(compressed.subarray(13));
170
152
  const output = Uint8Array.from([
171
- ...headerBysquare([0x00, 1 /* Version["1.1.0"] */, 0x00, 0x00]),
172
- ...headerLzmaProps(),
153
+ // FIXME:
154
+ // for now other implementation of bysquare doesn't recognize header if
155
+ // version is specified like TatraBanka
156
+ // ...headerBysquare([0x00, Version["1.1.0"], 0x00, 0x00]),
157
+ ...headerBysquare([0x00, 0x00, 0x00, 0x00]),
173
158
  ...headerDataLength(withChecksum.byteLength),
174
- ...compressedPayload
159
+ ...lzmaBody
175
160
  ]);
176
161
  return base32hex.stringify(output, {
177
162
  pad: false
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bysquare",
3
3
  "description": "It's a national standard for payment QR codes adopted by Slovak Banking Association (SBA)",
4
- "version": "2.2.0",
4
+ "version": "2.3.0",
5
5
  "license": "Apache-2.0",
6
6
  "funding": "https://github.com/sponsors/xseman",
7
7
  "homepage": "https://github.com/xseman/bysquare#readme",
package/lib/mjs/parse.js CHANGED
@@ -1,4 +1,4 @@
1
- import * as lzma from "lzma1";
1
+ import { decompress } from "lzma1";
2
2
  import { base32hex } from "rfc4648";
3
3
  import { PaymentOptions } from "./index.js";
4
4
  function cleanEmptyProps(obj) {
@@ -128,24 +128,6 @@ export function deserialize(qr) {
128
128
  }
129
129
  return output;
130
130
  }
131
- /**
132
- * LZMA compression properties from the byte
133
- *
134
- * @param props 1-byte size
135
- */
136
- function LzmaPropertiesDecoder(props) {
137
- const byte = props[0];
138
- return {
139
- lc: byte >> 5,
140
- lp: byte >> 2 & 0b0111,
141
- pb: byte & 0b0011
142
- };
143
- }
144
- function calcLzmaDictionarySize(props) {
145
- const dictionarySize = new ArrayBuffer(4);
146
- new DataView(dictionarySize).setUint32(0, Math.pow(2, props.pb + props.lp));
147
- return new Uint8Array(dictionarySize);
148
- }
149
131
  /**
150
132
  * The function uses bit-shifting and masking to convert the first two bytes of
151
133
  * the input header array into four nibbles representing the bysquare header
@@ -156,9 +138,9 @@ function calcLzmaDictionarySize(props) {
156
138
  function bysquareHeaderDecoder(header) {
157
139
  const bytes = (header[0] << 8) | header[1];
158
140
  const bysquareType = bytes >> 12;
159
- const version = (bytes >> 8) & 0b1111;
160
- const documentType = (bytes >> 4) & 0b1111;
161
- const reserved = bytes & 0b1111;
141
+ const version = (bytes >> 8) & 15;
142
+ const documentType = (bytes >> 4) & 15;
143
+ const reserved = bytes & 15;
162
144
  return {
163
145
  bysquareType,
164
146
  version,
@@ -189,8 +171,7 @@ export function parse(qr) {
189
171
  throw new DecodeError(error, "Unable to decode QR string base32hex encoding");
190
172
  }
191
173
  const bysquareHeader = bytes.slice(0, 2);
192
- const { version } = bysquareHeaderDecoder(bysquareHeader);
193
- if ((version > 1 /* Version["1.1.0"] */)) {
174
+ if ((bysquareHeaderDecoder(bysquareHeader).version > 1 /* Version["1.1.0"] */)) {
194
175
  throw new Error("Unsupported Bysquare version");
195
176
  }
196
177
  /**
@@ -205,14 +186,16 @@ export function parse(qr) {
205
186
  * | Properties | Dictionary Size | Uncompressed Size |
206
187
  * +------------+----+----+----+----+--+--+--+--+--+--+--+--+
207
188
  */
208
- const lzmaProperties = bytes.slice(2, 3);
209
- const decodedProps = LzmaPropertiesDecoder(lzmaProperties);
210
- const dictSize = calcLzmaDictionarySize(decodedProps);
189
+ const defaultProperties = [0x5D]; // lc=3, lp=0, pb=2
190
+ const defaultDictionarySize = [0x00, 0x02, 0x00, 0x00]; // 2^17
191
+ const dataLengthView = new DataView(bytes.slice(2, 4).buffer);
192
+ const dataLength = dataLengthView.getUint16(0);
193
+ const uncompressedSize = new ArrayBuffer(8);
194
+ new DataView(uncompressedSize).setBigUint64(0, BigInt(dataLength), true);
211
195
  const header = new Uint8Array([
212
- lzmaProperties[0],
213
- ...dictSize,
214
- /** Uncompressed size, this value indicates that size is unknown */
215
- ...[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]
196
+ ...defaultProperties,
197
+ ...defaultDictionarySize,
198
+ ...new Uint8Array(uncompressedSize)
216
199
  ]);
217
200
  const payload = bytes.slice(4);
218
201
  const body = new Uint8Array([
@@ -220,15 +203,11 @@ export function parse(qr) {
220
203
  ...payload
221
204
  ]);
222
205
  try {
223
- var decompressed = new Uint8Array(lzma.decompress(body));
206
+ var decompressed = new Uint8Array(decompress(body));
224
207
  }
225
208
  catch (error) {
226
209
  throw new DecodeError(error, "LZMA decompression failed");
227
210
  }
228
- const dataLength = bytes.slice(3, 4);
229
- if (dataLength[0] !== decompressed.length) {
230
- throw new Error("The length of the data after decompression is not as expected.");
231
- }
232
211
  const _checksum = decompressed.slice(0, 4);
233
212
  const decompressedBody = decompressed.slice(4);
234
213
  const decoded = new TextDecoder("utf-8").decode(decompressedBody);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bysquare",
3
3
  "description": "It's a national standard for payment QR codes adopted by Slovak Banking Association (SBA)",
4
- "version": "2.2.0",
4
+ "version": "2.3.0",
5
5
  "license": "Apache-2.0",
6
6
  "funding": "https://github.com/sponsors/xseman",
7
7
  "homepage": "https://github.com/xseman/bysquare#readme",