bysquare 1.0.6 → 1.1.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
@@ -9,13 +9,17 @@ Simple `Node.js` library to generate "PAY by square" `QR` string.
9
9
  **What is `PAY by square`?**
10
10
 
11
11
  It's a national standard for payment QR codes adopted by Slovak Banking
12
- Association (SBA) in 2013. It is part of a large number of invoices, reminders
13
- and other payment regulations.
12
+ Association in 2013. It is part of a large number of invoices, reminders and
13
+ other payment regulations.
14
14
 
15
15
  **Can I generate an image?**
16
16
 
17
- This library is un-opinionated about generating images. Image generation from
18
- qr-code string depends on your implementation. See the [examples](examples).
17
+ This library is un-opinionated. Image generation from qr-code string depends on
18
+ your implementation. See [examples](examples).
19
+
20
+ ## How it works
21
+
22
+ ![diagram](./uml/logic.svg)
19
23
 
20
24
  ## Install
21
25
 
@@ -25,17 +29,21 @@ Node.js
25
29
  npm install bysquare
26
30
  ```
27
31
 
28
- ## API
32
+ CLI, global
33
+
34
+ ```sh
35
+ npm install --global bysquare
36
+ ```
29
37
 
30
- **Available functions**
38
+ ## API
31
39
 
32
- ### `generate(model: Model): Promise<string>`
40
+ ### **generate(model: Model): Promise<string>**
33
41
 
34
42
  ```typescript
35
- import { generate, Model } from 'bysquare';
43
+ import { generate, parse, Model } from "bysquare";
36
44
 
37
45
  const model: Model = {
38
- IBAN: 'SK9611000000002918599669',
46
+ IBAN: "SK9611000000002918599669",
39
47
  Amount: 100.0,
40
48
  CurrencyCode: "EUR",
41
49
  VariableSymbol: "123",
@@ -44,55 +52,48 @@ const model: Model = {
44
52
  BankAccounts: 1,
45
53
  };
46
54
 
47
- generate(model).then((qrString) => {
55
+ generate(model).then((qrString: string) => {
56
+ // "0004G0005ES17OQ09C98Q7ME34TCR3V71LVKD2AE6EGHKR82DKS5NBJ3331VUFQIV0JGMR743UJCKSAKEM9QGVVVOIVH000"
48
57
  // your logic...
49
- })
58
+ });
50
59
  ```
51
60
 
52
- ### `parse(qrString: string): Promise<Model>`
61
+ ### **parse(qrString: string): Promise<Model>**
53
62
 
54
63
  ```typescript
55
- import { parse } from 'bysquare';
64
+ import { parse, Model } from "bysquare";
56
65
 
57
- const qr: string = '0005FO5V6G02NE0JSD04M4KD3R71IEMDHVJGQVQ6H573788QDK16QE2RLPHHHGVV7T9FG9OBDJI1V9MAE5A7B4T8FVVS9FOG00';
66
+ const qrString = "0004G0005ES17OQ09C98Q7ME34TCR3V71LVKD2AE6EGHKR82DKS5NBJ3331VUFQIV0JGMR743UJCKSAKEM9QGVVVOIVH000"
58
67
 
59
- parse(qrString).then((parsed) => {
68
+ parse(qrString).then((model: Model) => {
60
69
  // your logic...
61
70
  });
62
71
  ```
63
72
 
64
- <!-- ## How it works -->
65
- <!-- TODO: diagram -->
66
-
67
73
  ## CLI
68
74
 
69
- Local executable install
70
-
71
- ```sh
72
- npm install --global bysquare
73
- bysquare ./example.json
74
- ```
75
-
76
- Executable without installation
77
-
78
- ```sh
79
- npx bysquare ./example.json
80
- ```
81
-
82
- **file**
83
-
84
- ```sh
85
- bysquare ./example.json
86
- ```
75
+ You can use json file with valid model to generate qr-string.
87
76
 
88
77
  ```sh
89
- $ 0005FO5V6G02NE0JSD04M4KD3R71IEMDHVJGQVQ6H573788QDK16QE2RLPHHHGVV7T9FG9OBDJI1V9MAE5A7B4T8FVVS9FOG00
78
+ # example.json
79
+ # {
80
+ # "IBAN": "SK9611000000002918599669",
81
+ # "Amount": 100.0,
82
+ # "CurrencyCode": "EUR",
83
+ # "VariableSymbol": "123",
84
+ # "Payments": 1,
85
+ # "PaymentOptions": 1,
86
+ # "BankAccounts": 1
87
+ # }
88
+
89
+ > npx bysquare ./example.json
90
+ > 0004G0005ES17OQ09C98Q7ME34TCR3V71LVKD2AE6EGHKR82DKS5NBJ3331VUFQIV0JGMR743UJCKSAKEM9QGVVVOIVH000
90
91
  ```
91
92
 
92
- **standard input**
93
+ You can also use stdin.
93
94
 
94
95
  ```sh
95
- $ echo '
96
+ > echo '
96
97
  {
97
98
  "IBAN": "SK9611000000002918599669",
98
99
  "Amount": 100.0,
@@ -103,19 +104,56 @@ $ echo '
103
104
  "BankAccounts": 1
104
105
  }' \
105
106
  | bysquare
107
+ > 0004G0005ES17OQ09C98Q7ME34TCR3V71LVKD2AE6EGHKR82DKS5NBJ3331VUFQIV0JGMR743UJCKSAKEM9QGVVVOIVH000
106
108
  ```
107
109
 
108
- ```sh
109
- $ 0005FO5V6G02NE0JSD04M4KD3R71IEMDHVJGQVQ6H573788QDK16QE2RLPHHHGVV7T9FG9OBDJI1V9MAE5A7B4T8FVVS9FOG00
110
- ```
111
-
112
- ## License
110
+ ## Model
111
+
112
+ | Option | Type | Required |
113
+ | -------------------------------- | -------- | -------- |
114
+ | InvoiceID | `string` | no |
115
+ | Payments | `number` | yes |
116
+ | PaymentOptions | `number` | yes |
117
+ | Amount | `number` | no |
118
+ | CurrencyCode | `string` | yes |
119
+ | PaymentDueDate | `string` | no |
120
+ | VariableSymbol | `string` | no |
121
+ | ConstantSymbol | `string` | no |
122
+ | SpecificSymbol | `string` | no |
123
+ | OriginatorsReferenceInformation | `string` | no |
124
+ | PaymentNote | `string` | no |
125
+ | BankAccounts | `number` | yes |
126
+ | IBAN | `string` | yes |
127
+ | BIC | `string` | no |
128
+ | StandingOrderExt | `number` | no |
129
+ | Day | `number` | no |
130
+ | Month | `number` | no |
131
+ | Periodicity | `string` | no |
132
+ | LastDate | `string` | no |
133
+ | LastDate | `string` | no |
134
+ | DirectDebitExt | `number` | no |
135
+ | DirectDebitScheme | `number` | no |
136
+ | DirectDebitType | `number` | no |
137
+ | VariableSymbol_ | `string` | no |
138
+ | SpecificSymbol_ | `string` | no |
139
+ | OriginatorsReferenceInformation_ | `string` | no |
140
+ | MandateID | `string` | no |
141
+ | CreditorID | `string` | no |
142
+ | ContractID | `string` | no |
143
+ | MaxAmount | `number` | no |
144
+ | ValidTillDate | `string` | no |
145
+ | BeneficiaryName | `string` | no |
146
+ | BeneficiaryAddressLine1 | `string` | no |
147
+ | BeneficiaryAddressLine2 | `string` | no |
113
148
 
114
- Distributed under the MIT License. See [LICENSE](LICENSE) for more information.
115
-
116
- ## Contributors
149
+ ## Resources
117
150
 
118
- ![Contributors](https://contrib.rocks/image?repo=xseman/bysquare)
151
+ - <https://bysquare.com/>
152
+ - <https://devel.cz/otazka/qr-kod-pay-by-square>
153
+ - <https://github.com/matusf/pay-by-square>
154
+ - <https://www.bsqr.co/schema/>
155
+ - <https://www.sbaonline.sk/wp-content/uploads/2020/03/pay-by-square-specifications-1_1_0.pdf>
156
+ - <https://www.vutbr.cz/studenti/zav-prace/detail/78439>
119
157
 
120
158
  <!-- Links -->
121
159
 
@@ -123,15 +161,7 @@ Distributed under the MIT License. See [LICENSE](LICENSE) for more information.
123
161
  [version]: https://img.shields.io/npm/v/bysquare
124
162
  [license]: https://img.shields.io/github/license/xseman/bysquare
125
163
 
126
- ## Resources
127
-
128
- - <https://bysquare.com/>
129
- - <https://github.com/matusf/pay-by-square>
130
- - <https://www.vutbr.cz/studenti/zav-prace/detail/78439>
131
- - <https://www.sbaonline.sk/wp-content/uploads/2020/03/pay-by-square-specifications-1_1_0.pdf>
132
-
133
164
  <!--
134
-
135
165
  Versioning
136
166
  ----------
137
167
 
@@ -145,5 +175,4 @@ Versioning
145
175
  - Checkout to master
146
176
  - Push commits and tag, git push, git push --tags
147
177
  - Publish to npm, npm publish
148
-
149
178
  -->
package/lib/cli.js CHANGED
@@ -1,24 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
- if (k2 === undefined) k2 = k;
5
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
6
- }) : (function(o, m, k, k2) {
7
- if (k2 === undefined) k2 = k;
8
- o[k2] = m[k];
9
- }));
10
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
11
- Object.defineProperty(o, "default", { enumerable: true, value: v });
12
- }) : function(o, v) {
13
- o["default"] = v;
14
- });
15
- var __importStar = (this && this.__importStar) || function (mod) {
16
- if (mod && mod.__esModule) return mod;
17
- var result = {};
18
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
19
- __setModuleDefault(result, mod);
20
- return result;
21
- };
22
3
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
23
4
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
24
5
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -60,11 +41,12 @@ var fs_1 = require("fs");
60
41
  var readline_1 = require("readline");
61
42
  var main_1 = require("./main");
62
43
  if (process.stdin.isTTY) {
63
- // bysquare "file"
44
+ /** bysquare "file" */
64
45
  handleInput(process.argv[2]);
65
46
  }
66
47
  else {
67
- // echo "data" | bysquare
48
+ /** echo "data" | bysquare */
49
+ ;
68
50
  (function () { return __awaiter(void 0, void 0, void 0, function () {
69
51
  var stdin, qrString;
70
52
  return __generator(this, function (_a) {
@@ -85,22 +67,9 @@ else {
85
67
  });
86
68
  }); })();
87
69
  }
88
- function version() {
89
- return __awaiter(this, void 0, void 0, function () {
90
- var version;
91
- return __generator(this, function (_a) {
92
- switch (_a.label) {
93
- case 0: return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("./package.json")); })];
94
- case 1:
95
- version = (_a.sent()).version;
96
- return [2 /*return*/, "bysquare v".concat(version)];
97
- }
98
- });
99
- });
100
- }
101
70
  function handleInput(input) {
102
71
  return __awaiter(this, void 0, void 0, function () {
103
- var v, file, qrString;
72
+ var file, qrString;
104
73
  return __generator(this, function (_a) {
105
74
  switch (_a.label) {
106
75
  case 0:
@@ -108,29 +77,21 @@ function handleInput(input) {
108
77
  console.log(help());
109
78
  process.exit(0);
110
79
  }
111
- if (!(input === "-v" || input === "--version")) return [3 /*break*/, 2];
112
- return [4 /*yield*/, version()];
113
- case 1:
114
- v = _a.sent();
115
- console.log(v);
116
- process.exit(0);
117
- _a.label = 2;
118
- case 2:
119
- if (!(0, fs_1.existsSync)(process.argv[2])) return [3 /*break*/, 4];
80
+ if (!(0, fs_1.existsSync)(process.argv[2])) return [3 /*break*/, 2];
120
81
  file = (0, fs_1.readFileSync)(process.argv[2], "utf8");
121
82
  return [4 /*yield*/, jsonStringToQrString(file).catch(function (e) {
122
83
  console.error(e);
123
84
  process.exit(1);
124
85
  })];
125
- case 3:
86
+ case 1:
126
87
  qrString = _a.sent();
127
88
  console.log(qrString);
128
- return [3 /*break*/, 5];
129
- case 4:
89
+ return [3 /*break*/, 3];
90
+ case 2:
130
91
  console.error("File ".concat(process.argv[2], " doesn't exists"));
131
92
  process.exit(1);
132
- _a.label = 5;
133
- case 5: return [2 /*return*/];
93
+ _a.label = 3;
94
+ case 3: return [2 /*return*/];
134
95
  }
135
96
  });
136
97
  });
@@ -141,9 +102,8 @@ function jsonStringToQrString(stdin) {
141
102
  return [2 /*return*/, new Promise(function (resolve, reject) {
142
103
  try {
143
104
  var data = JSON.parse(stdin);
144
- (0, main_1.generate)(data).then(function (qrString) {
145
- resolve(qrString);
146
- });
105
+ var qrString = (0, main_1.generate)(data);
106
+ resolve(qrString);
147
107
  }
148
108
  catch (e) {
149
109
  reject(e);
@@ -159,7 +119,7 @@ function handleStdin() {
159
119
  readline = (0, readline_1.createInterface)({
160
120
  input: process.stdin,
161
121
  output: process.stdout,
162
- terminal: false,
122
+ terminal: false
163
123
  });
164
124
  lines = [];
165
125
  return [2 /*return*/, new Promise(function (resolve, reject) {
@@ -186,7 +146,6 @@ function help() {
186
146
  "",
187
147
  "Flags:",
188
148
  " -h, --help display this help and exit",
189
- " -v, --version display actual version",
190
149
  "",
191
150
  "If <file> is omitted, reads from stdin.",
192
151
  "",
@@ -194,7 +153,7 @@ function help() {
194
153
  " bysquare ./example.json",
195
154
  "",
196
155
  " echo ",
197
- ' {',
156
+ " {",
198
157
  ' "IBAN": "SK9611000000002918599669"',
199
158
  ' "Amount": 100.0',
200
159
  ' "CurrencyCode": "EUR"',
@@ -203,6 +162,6 @@ function help() {
203
162
  ' "PaymentOptions": 1',
204
163
  ' "BankAccounts": 1',
205
164
  " }'",
206
- " | bysquare",
165
+ " | bysquare"
207
166
  ].join("\n");
208
167
  }
package/lib/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  export * from './main';
2
- export * from './model';
2
+ export * from './schema';
package/lib/index.js CHANGED
@@ -11,4 +11,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
11
11
  };
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
13
  __exportStar(require("./main"), exports);
14
- __exportStar(require("./model"), exports);
14
+ __exportStar(require("./schema"), exports);
package/lib/main.d.ts CHANGED
@@ -1,24 +1,24 @@
1
1
  /// <reference types="node" />
2
- import { Model } from './model';
3
- export declare function generate(model: Model): Promise<string>;
2
+ import { Model } from "./schema";
4
3
  /**
5
4
  * ```
6
- * Attribute | Number of bits | Possible values | Note
5
+ * | Attribute | Number of bits | Possible values | Note
7
6
  * --------------------------------------------------------------------------------------------
8
- * BySquareType | 4 | 0-15 | by square type
9
- * Version | 4 | 0-15 | version 4 0­15 version of the by sq
10
- * DocumentType | 4 | 0-15 | document type within given by square type
11
- * Reserved | 4 | 0-15 | bits reserved for future needs
7
+ * | BySquareType | 4 | 0-15 | by square type
8
+ * | Version | 4 | 0-15 | version 4 0­15 version of the by sq
9
+ * | DocumentType | 4 | 0-15 | document type within given by square type
10
+ * | Reserved | 4 | 0-15 | bits reserved for future needs
12
11
  * ```
13
12
  */
14
- export declare function createBysquareHeader(header?: [
13
+ export declare function createHeader(header?: [
15
14
  BySquareType: number,
16
15
  Version: number,
17
16
  DocumentType: number,
18
17
  Reserved: number
19
18
  ]): Buffer;
20
- export declare function createDataBuffer(tabbedString: string): Buffer;
21
- export declare function checksumFromTabbedString(tabbedString: string): string;
19
+ export declare function createChecksum(tabbedInput: string): Buffer;
20
+ export declare function dataWithChecksum(model: Model): Buffer;
21
+ export declare function generate(model: Model): Promise<string>;
22
22
  export declare function createTabbedString(model: Model): string;
23
- export declare function createModelFromTabbedString(tabbedModel: string): Model;
24
- export declare function parse(qrString: string): Promise<Model>;
23
+ export declare function createModel(tabbedString: string): Model;
24
+ export declare function parse(qr: string): Promise<Model>;
package/lib/main.js CHANGED
@@ -24,138 +24,165 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
24
24
  }
25
25
  return to.concat(ar || Array.prototype.slice.call(from));
26
26
  };
27
+ var __importDefault = (this && this.__importDefault) || function (mod) {
28
+ return (mod && mod.__esModule) ? mod : { "default": mod };
29
+ };
27
30
  Object.defineProperty(exports, "__esModule", { value: true });
28
- exports.parse = exports.createModelFromTabbedString = exports.createTabbedString = exports.checksumFromTabbedString = exports.createDataBuffer = exports.createBysquareHeader = exports.generate = void 0;
29
- var model_1 = require("./model");
30
- var lzma = require('lzma-native');
31
- function generate(model) {
31
+ exports.parse = exports.createModel = exports.createTabbedString = exports.generate = exports.dataWithChecksum = exports.createChecksum = exports.createHeader = void 0;
32
+ var lzma_native_1 = __importDefault(require("lzma-native"));
33
+ var schema_1 = require("./schema");
34
+ /**
35
+ * ```
36
+ * | Attribute | Number of bits | Possible values | Note
37
+ * --------------------------------------------------------------------------------------------
38
+ * | BySquareType | 4 | 0-15 | by square type
39
+ * | Version | 4 | 0-15 | version 4 0­15 version of the by sq
40
+ * | DocumentType | 4 | 0-15 | document type within given by square type
41
+ * | Reserved | 4 | 0-15 | bits reserved for future needs
42
+ * ```
43
+ */
44
+ function createHeader(
45
+ // prettier-ignore
46
+ header) {
47
+ if (header === void 0) { header = [
48
+ 0,
49
+ 0,
50
+ 0,
51
+ 0
52
+ ]; }
53
+ var isValid = header.every(function (nibble) { return 0 <= nibble && nibble <= 15; });
54
+ if (!isValid)
55
+ throw new Error();
56
+ var _a = __read(header, 4), BySquareType = _a[0], Version = _a[1], DocumentType = _a[2], Reserved = _a[3];
57
+ /** Combine 4-nibbles to 2-bytes */
58
+ var headerBuffer = Buffer.from([
59
+ (BySquareType << 4) | (Version << 0),
60
+ (DocumentType << 4) | (Reserved << 0)
61
+ ]);
62
+ return headerBuffer;
63
+ }
64
+ exports.createHeader = createHeader;
65
+ function createChecksum(tabbedInput) {
66
+ // @ts-ignore: Wrong return type
67
+ var data = lzma_native_1.default.crc32(tabbedInput);
68
+ var crc32 = Buffer.alloc(4);
69
+ crc32.writeUInt32LE(data);
70
+ return crc32;
71
+ }
72
+ exports.createChecksum = createChecksum;
73
+ function dataWithChecksum(model) {
32
74
  var tabbedString = createTabbedString(model);
33
- var dataWithChecksum = createDataBuffer(tabbedString);
34
- var encoder = lzma.createStream('rawEncoder', {
35
- synchronous: true,
36
- filters: [{ id: lzma.FILTER_LZMA1 }],
37
- });
38
- var data = [];
39
- encoder.on('data', function (chunk) {
40
- data.push(chunk);
41
- });
42
- function compress(resolve, reject) {
43
- encoder.on('error', reject);
44
- encoder.on('end', function () {
45
- var header = createBysquareHeader();
46
- var checksum = Buffer.from(checksumFromTabbedString(tabbedString), 'hex').reverse();
47
- /** Merged binary data (specification 3.15.) */
75
+ var checksum = createChecksum(tabbedString);
76
+ var merged = Buffer.concat([
77
+ checksum,
78
+ Buffer.from(tabbedString, "utf-8")
79
+ ]);
80
+ return merged;
81
+ }
82
+ exports.dataWithChecksum = dataWithChecksum;
83
+ /**
84
+ * spec 3.13 (Table 9 – Encoding table)
85
+ */
86
+ var SUBST = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
87
+ function generate(model) {
88
+ var dataBuffer = dataWithChecksum(model);
89
+ var dataChunks = [];
90
+ return new Promise(function (resolve, reject) {
91
+ var encoder = lzma_native_1.default.createStream("rawEncoder", {
92
+ synchronous: true,
93
+ // @ts-ignore: Missing filter types
94
+ filters: [{ id: lzma_native_1.default.FILTER_LZMA1 }]
95
+ });
96
+ encoder
97
+ .on("data", function (chunk) {
98
+ dataChunks.push(chunk);
99
+ })
100
+ .on("error", Promise.reject)
101
+ .on("end", function () {
102
+ /**
103
+ * The header of compressed data is 2 bytes long and contains only
104
+ * one 16­bit unsigned integer (word, little­endian), which is the
105
+ * size of the decompressed data (spec 3.11)
106
+ */
107
+ var size = Buffer.alloc(2);
108
+ size.writeInt16LE(dataBuffer.byteLength, 0);
109
+ /** (spec 3.5) */
110
+ var header = createHeader();
111
+ /** Merged binary data (spec 3.15.) */
48
112
  var merged = Buffer.concat([
49
113
  header,
50
- checksum,
51
- Buffer.concat(data),
114
+ size,
115
+ Buffer.concat(dataChunks)
52
116
  ]);
53
- var paddedBinString = merged.reduce(function (acc, byte) { return (acc += byte.toString(2).padStart(8, '0')); }, '');
117
+ var paddedBinString = merged.reduce(function (acc, byte) { return acc + byte.toString(2).padStart(8, "0"); }, "");
54
118
  var paddedBinLength = paddedBinString.length;
55
119
  var remainder = paddedBinLength % 5;
56
120
  if (remainder) {
57
- paddedBinString += Array(5 - remainder).fill('0').join('');
121
+ paddedBinString += Array(5 - remainder)
122
+ .fill("0")
123
+ .join("");
58
124
  paddedBinLength += 5 - remainder;
59
125
  }
60
126
  /**
61
127
  * Map a binary number of 5 bits to a string representation 2^5
62
128
  * '0123456789ABCDEFGHIJKLMNOPQRSTUV'[0...32] represents char
63
129
  */
64
- var subst = '0123456789ABCDEFGHIJKLMNOPQRSTUV';
65
- var output = '';
66
- for (var i = 0; i < (paddedBinLength / 5); i++) {
130
+ var output = "";
131
+ for (var i = 0; i < paddedBinLength / 5; i++) {
67
132
  var binStart = 5 * i;
68
133
  var binEnd = 5 * i + 5;
69
134
  var slice = paddedBinString.slice(binStart, binEnd);
70
135
  var key = parseInt(slice, 2);
71
- output += subst[key];
136
+ output += SUBST[key];
72
137
  }
73
- resolve(output);
74
- });
75
- encoder.write(dataWithChecksum, function () {
138
+ return resolve(output);
139
+ })
140
+ .write(dataBuffer, function (err) {
141
+ err && reject(err);
76
142
  encoder.end();
77
143
  });
78
- }
79
- return new Promise(compress);
144
+ });
80
145
  }
81
146
  exports.generate = generate;
82
- /**
83
- * ```
84
- * Attribute | Number of bits | Possible values | Note
85
- * --------------------------------------------------------------------------------------------
86
- * BySquareType | 4 | 0-15 | by square type
87
- * Version | 4 | 0-15 | version 4 0­15 version of the by sq
88
- * DocumentType | 4 | 0-15 | document type within given by square type
89
- * Reserved | 4 | 0-15 | bits reserved for future needs
90
- * ```
91
- */
92
- function createBysquareHeader(header) {
93
- if (header === void 0) { header = [0, 0, 0, 0]; }
94
- var isValid = header.every(function (nibble) { return 0 <= nibble && nibble <= 15; });
95
- if (!isValid)
96
- throw new Error();
97
- var _a = __read(header, 4), BySquareType = _a[0], Version = _a[1], DocumentType = _a[2], Reserved = _a[3];
98
- /** Combine 4-nibbles to 2-bytes */
99
- var headerBuffer = Buffer.from([
100
- (BySquareType << 4) | Version,
101
- (DocumentType << 4) | Reserved,
102
- ]);
103
- return headerBuffer;
104
- }
105
- exports.createBysquareHeader = createBysquareHeader;
106
- function createDataBuffer(tabbedString) {
107
- var checksum = checksumFromTabbedString(tabbedString);
108
- var buffer = Buffer.concat([
109
- /** Little-endian, reverse */
110
- Buffer.from(checksum, 'hex').reverse(),
111
- Buffer.from(tabbedString, 'utf-8'),
112
- ]);
113
- return buffer;
114
- }
115
- exports.createDataBuffer = createDataBuffer;
116
- function checksumFromTabbedString(tabbedString) {
117
- var checksum = lzma.crc32(tabbedString, 'utf-8');
118
- var hexString = checksum.toString(16);
119
- return hexString;
120
- }
121
- exports.checksumFromTabbedString = checksumFromTabbedString;
122
147
  function createTabbedString(model) {
123
148
  /**
124
- * - Order keys by specification
125
- * - Fill empty values
126
- * - Create tabbed string
149
+ * Order keys by specification
150
+ * Fill empty values
151
+ * Transform to tabbed string
127
152
  */
128
153
  var tabbedModel = Object.keys(model)
129
154
  .reduce(function (acc, key) {
130
155
  var _a;
131
- acc[model_1.MODEL_INDEXED[key]] = String((_a = model[key]) !== null && _a !== void 0 ? _a : '');
156
+ acc[schema_1.ModelOrdered[key]] = String((_a = model[key]) !== null && _a !== void 0 ? _a : "");
132
157
  return acc;
133
- }, Array(33).fill(''))
134
- .join('\t');
158
+ }, Array(33).fill(""))
159
+ .join("\t");
135
160
  return tabbedModel;
136
161
  }
137
162
  exports.createTabbedString = createTabbedString;
138
- function createModelFromTabbedString(tabbedModel) {
139
- var model = tabbedModel
140
- .split('\t')
163
+ function createModel(tabbedString) {
164
+ var model = tabbedString
165
+ .split("\t")
166
+ .filter(function (ch) { return !(ch === "\x00"); })
141
167
  .reduce(function (acc, value, i) {
142
- var key = model_1.MODEL_INDEXED[i];
143
- /** empty value, continue */
144
- if (value === '') {
168
+ var key = schema_1.ModelOrdered[i];
169
+ if (value === "") {
145
170
  return acc;
146
171
  }
147
- if (!!Number(value) &&
148
- key === 'Payments' ||
149
- key === 'PaymentOptions' ||
150
- key === 'Amount' ||
151
- key === 'BankAccounts' ||
152
- key === 'StandingOrderExt' ||
153
- key === 'Day' ||
154
- key === 'Month' ||
155
- key === 'DirectDebitExt' ||
156
- key === 'DirectDebitScheme' ||
157
- key === 'DirectDebitType' ||
158
- key === 'MaxAmount') {
172
+ var numericKeys = [
173
+ "Payments",
174
+ "PaymentOptions",
175
+ "Amount",
176
+ "BankAccounts",
177
+ "StandingOrderExt",
178
+ "Day",
179
+ "Month",
180
+ "DirectDebitExt",
181
+ "DirectDebitScheme",
182
+ "DirectDebitType",
183
+ "MaxAmount"
184
+ ];
185
+ if (numericKeys.includes(key)) {
159
186
  acc[key] = Number(value);
160
187
  return acc;
161
188
  }
@@ -164,45 +191,44 @@ function createModelFromTabbedString(tabbedModel) {
164
191
  }, {});
165
192
  return model;
166
193
  }
167
- exports.createModelFromTabbedString = createModelFromTabbedString;
168
- function parse(qrString) {
169
- var subst = '0123456789ABCDEFGHIJKLMNOPQRSTUV';
170
- var paddedBinString = __spreadArray([], __read(qrString), false).reduce(function (acc, char) {
171
- acc += subst.indexOf(char).toString(2).padStart(5, '0');
194
+ exports.createModel = createModel;
195
+ function parse(qr) {
196
+ var binary = __spreadArray([], __read(qr), false).reduce(function (acc, char) {
197
+ acc += SUBST.indexOf(char).toString(2).padStart(5, "0");
172
198
  return acc;
173
- }, '');
199
+ }, "");
174
200
  var bytes = [];
175
- for (var count = 0, leftCount = 0; paddedBinString.length > leftCount; count++) {
176
- var byte = parseInt(paddedBinString.slice(leftCount, (leftCount += 8)), 2)
177
- .toString(16)
178
- .padStart(2, '0');
179
- bytes[count] = byte;
201
+ for (var nth = 0, leftCount = 0; binary.length > leftCount; nth++) {
202
+ var byte = parseInt(binary.slice(leftCount, (leftCount += 8)), 2);
203
+ bytes[nth] = byte;
180
204
  }
181
- var binaryData = Buffer.from(bytes.join(''), 'hex');
182
- var header = binaryData.slice(0, 2);
183
- var checksum = binaryData.slice(2, 6);
184
- var data = binaryData.slice(6, binaryData.length);
185
- var decoder = lzma.createStream('rawDecoder', {
205
+ var input = Buffer.from(bytes);
206
+ // const header = input.slice(0, 2)
207
+ // const size = input.slice(2, 4)
208
+ var data = input.slice(4);
209
+ // @ts-ignore: Missing decored types
210
+ var decoder = lzma_native_1.default.createStream("rawDecoder", {
186
211
  synchronous: true,
187
- filters: [{ id: lzma.FILTER_LZMA1 }],
188
- });
189
- decoder.write(data, undefined, function () {
190
- decoder.end();
212
+ // @ts-ignore: Missing filter types
213
+ filters: [{ id: lzma_native_1.default.FILTER_LZMA1 }]
191
214
  });
192
- function compress(resolve, reject) {
193
- decoder.on('error', reject);
194
- decoder.on('data', function (res) {
195
- var checksumFromData = res.slice(0, 4);
196
- var data = res.slice(4, res.length);
197
- if (checksum.equals(checksumFromData) === false) {
198
- reject('Checksum conflict');
199
- }
200
- var decoded = data.toString();
201
- var model = createModelFromTabbedString(decoded);
215
+ return new Promise(function (resolve, reject) {
216
+ decoder
217
+ .on("error", reject)
218
+ .on("data", function (decompress) {
219
+ var checksum = decompress.slice(0, 4);
220
+ var data = decompress.slice(4).toString();
221
+ // TODO: Not neccesary to validate, but data can be corrupted
222
+ // if (!createChecksum(data).equals(checksum)) {
223
+ // reject("Checksum conflict")
224
+ // }
225
+ var model = createModel(data);
202
226
  resolve(model);
227
+ })
228
+ .write(data, function (err) {
229
+ err && reject(err);
230
+ decoder.end();
203
231
  });
204
- }
205
- ;
206
- return new Promise(compress);
232
+ });
207
233
  }
208
234
  exports.parse = parse;
@@ -1,4 +1,6 @@
1
1
  /**
2
+ * TODO: yup schema, infer interface
3
+ *
2
4
  * Data model
3
5
  * (Appendix D, table)
4
6
  */
@@ -100,7 +102,7 @@ export interface Model {
100
102
  /** Max length 1 */
101
103
  DirectDebitExt?: number;
102
104
  /**
103
- * Tthis field can have “SEPA” value, if direct debit is using SEPA direct
105
+ * This field can have “SEPA” value, if direct debit is using SEPA direct
104
106
  * debit scheme or “other” when an ordinary direct debit is defined
105
107
  *
106
108
  * Max length 1
@@ -151,7 +153,7 @@ export interface Model {
151
153
  * Atributes must follow specific order
152
154
  * (Apendix D - data model overview)
153
155
  */
154
- export declare enum MODEL_INDEXED {
156
+ export declare enum ModelOrdered {
155
157
  InvoiceID = 0,
156
158
  Payments = 1,
157
159
  PaymentOptions = 2,
@@ -1,46 +1,46 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CurrencyCode = exports.MODEL_INDEXED = void 0;
3
+ exports.CurrencyCode = exports.ModelOrdered = void 0;
4
4
  /**
5
5
  * Atributes must follow specific order
6
6
  * (Apendix D - data model overview)
7
7
  */
8
- var MODEL_INDEXED;
9
- (function (MODEL_INDEXED) {
10
- MODEL_INDEXED[MODEL_INDEXED["InvoiceID"] = 0] = "InvoiceID";
11
- MODEL_INDEXED[MODEL_INDEXED["Payments"] = 1] = "Payments";
12
- MODEL_INDEXED[MODEL_INDEXED["PaymentOptions"] = 2] = "PaymentOptions";
13
- MODEL_INDEXED[MODEL_INDEXED["Amount"] = 3] = "Amount";
14
- MODEL_INDEXED[MODEL_INDEXED["CurrencyCode"] = 4] = "CurrencyCode";
15
- MODEL_INDEXED[MODEL_INDEXED["PaymentDueDate"] = 5] = "PaymentDueDate";
16
- MODEL_INDEXED[MODEL_INDEXED["VariableSymbol"] = 6] = "VariableSymbol";
17
- MODEL_INDEXED[MODEL_INDEXED["ConstantSymbol"] = 7] = "ConstantSymbol";
18
- MODEL_INDEXED[MODEL_INDEXED["SpecificSymbol"] = 8] = "SpecificSymbol";
19
- MODEL_INDEXED[MODEL_INDEXED["OriginatorsReferenceInformation"] = 9] = "OriginatorsReferenceInformation";
20
- MODEL_INDEXED[MODEL_INDEXED["PaymentNote"] = 10] = "PaymentNote";
21
- MODEL_INDEXED[MODEL_INDEXED["BankAccounts"] = 11] = "BankAccounts";
22
- MODEL_INDEXED[MODEL_INDEXED["IBAN"] = 12] = "IBAN";
23
- MODEL_INDEXED[MODEL_INDEXED["BIC"] = 13] = "BIC";
24
- MODEL_INDEXED[MODEL_INDEXED["StandingOrderExt"] = 14] = "StandingOrderExt";
25
- MODEL_INDEXED[MODEL_INDEXED["Day"] = 15] = "Day";
26
- MODEL_INDEXED[MODEL_INDEXED["Month"] = 16] = "Month";
27
- MODEL_INDEXED[MODEL_INDEXED["Periodicity"] = 17] = "Periodicity";
28
- MODEL_INDEXED[MODEL_INDEXED["LastDate"] = 18] = "LastDate";
29
- MODEL_INDEXED[MODEL_INDEXED["DirectDebitExt"] = 19] = "DirectDebitExt";
30
- MODEL_INDEXED[MODEL_INDEXED["DirectDebitScheme"] = 20] = "DirectDebitScheme";
31
- MODEL_INDEXED[MODEL_INDEXED["DirectDebitType"] = 21] = "DirectDebitType";
32
- MODEL_INDEXED[MODEL_INDEXED["VariableSymbol_"] = 22] = "VariableSymbol_";
33
- MODEL_INDEXED[MODEL_INDEXED["SpecificSymbol_"] = 23] = "SpecificSymbol_";
34
- MODEL_INDEXED[MODEL_INDEXED["OriginatorsReferenceInformation_"] = 24] = "OriginatorsReferenceInformation_";
35
- MODEL_INDEXED[MODEL_INDEXED["MandateID"] = 25] = "MandateID";
36
- MODEL_INDEXED[MODEL_INDEXED["CreditorID"] = 26] = "CreditorID";
37
- MODEL_INDEXED[MODEL_INDEXED["ContractID"] = 27] = "ContractID";
38
- MODEL_INDEXED[MODEL_INDEXED["MaxAmount"] = 28] = "MaxAmount";
39
- MODEL_INDEXED[MODEL_INDEXED["ValidTillDate"] = 29] = "ValidTillDate";
40
- MODEL_INDEXED[MODEL_INDEXED["BeneficiaryName"] = 30] = "BeneficiaryName";
41
- MODEL_INDEXED[MODEL_INDEXED["BeneficiaryAddressLine1"] = 31] = "BeneficiaryAddressLine1";
42
- MODEL_INDEXED[MODEL_INDEXED["BeneficiaryAddressLine2"] = 32] = "BeneficiaryAddressLine2";
43
- })(MODEL_INDEXED = exports.MODEL_INDEXED || (exports.MODEL_INDEXED = {}));
8
+ var ModelOrdered;
9
+ (function (ModelOrdered) {
10
+ ModelOrdered[ModelOrdered["InvoiceID"] = 0] = "InvoiceID";
11
+ ModelOrdered[ModelOrdered["Payments"] = 1] = "Payments";
12
+ ModelOrdered[ModelOrdered["PaymentOptions"] = 2] = "PaymentOptions";
13
+ ModelOrdered[ModelOrdered["Amount"] = 3] = "Amount";
14
+ ModelOrdered[ModelOrdered["CurrencyCode"] = 4] = "CurrencyCode";
15
+ ModelOrdered[ModelOrdered["PaymentDueDate"] = 5] = "PaymentDueDate";
16
+ ModelOrdered[ModelOrdered["VariableSymbol"] = 6] = "VariableSymbol";
17
+ ModelOrdered[ModelOrdered["ConstantSymbol"] = 7] = "ConstantSymbol";
18
+ ModelOrdered[ModelOrdered["SpecificSymbol"] = 8] = "SpecificSymbol";
19
+ ModelOrdered[ModelOrdered["OriginatorsReferenceInformation"] = 9] = "OriginatorsReferenceInformation";
20
+ ModelOrdered[ModelOrdered["PaymentNote"] = 10] = "PaymentNote";
21
+ ModelOrdered[ModelOrdered["BankAccounts"] = 11] = "BankAccounts";
22
+ ModelOrdered[ModelOrdered["IBAN"] = 12] = "IBAN";
23
+ ModelOrdered[ModelOrdered["BIC"] = 13] = "BIC";
24
+ ModelOrdered[ModelOrdered["StandingOrderExt"] = 14] = "StandingOrderExt";
25
+ ModelOrdered[ModelOrdered["Day"] = 15] = "Day";
26
+ ModelOrdered[ModelOrdered["Month"] = 16] = "Month";
27
+ ModelOrdered[ModelOrdered["Periodicity"] = 17] = "Periodicity";
28
+ ModelOrdered[ModelOrdered["LastDate"] = 18] = "LastDate";
29
+ ModelOrdered[ModelOrdered["DirectDebitExt"] = 19] = "DirectDebitExt";
30
+ ModelOrdered[ModelOrdered["DirectDebitScheme"] = 20] = "DirectDebitScheme";
31
+ ModelOrdered[ModelOrdered["DirectDebitType"] = 21] = "DirectDebitType";
32
+ ModelOrdered[ModelOrdered["VariableSymbol_"] = 22] = "VariableSymbol_";
33
+ ModelOrdered[ModelOrdered["SpecificSymbol_"] = 23] = "SpecificSymbol_";
34
+ ModelOrdered[ModelOrdered["OriginatorsReferenceInformation_"] = 24] = "OriginatorsReferenceInformation_";
35
+ ModelOrdered[ModelOrdered["MandateID"] = 25] = "MandateID";
36
+ ModelOrdered[ModelOrdered["CreditorID"] = 26] = "CreditorID";
37
+ ModelOrdered[ModelOrdered["ContractID"] = 27] = "ContractID";
38
+ ModelOrdered[ModelOrdered["MaxAmount"] = 28] = "MaxAmount";
39
+ ModelOrdered[ModelOrdered["ValidTillDate"] = 29] = "ValidTillDate";
40
+ ModelOrdered[ModelOrdered["BeneficiaryName"] = 30] = "BeneficiaryName";
41
+ ModelOrdered[ModelOrdered["BeneficiaryAddressLine1"] = 31] = "BeneficiaryAddressLine1";
42
+ ModelOrdered[ModelOrdered["BeneficiaryAddressLine2"] = 32] = "BeneficiaryAddressLine2";
43
+ })(ModelOrdered = exports.ModelOrdered || (exports.ModelOrdered = {}));
44
44
  /* Active ISO 4217 */
45
45
  var CurrencyCode;
46
46
  (function (CurrencyCode) {
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": "1.0.6",
4
+ "version": "1.1.0",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Filip Seman <filip.seman@protonmail.com>",
7
7
  "keywords": [
@@ -21,9 +21,9 @@
21
21
  "homepage": "https://github.com/xseman/bysquare#readme",
22
22
  "funding": "https://github.com/sponsors/xseman",
23
23
  "scripts": {
24
- "build": "rm -rf ./lib; tsc",
24
+ "build": "rm -rf ./lib; tsc && chmod +x ./lib/cli.js",
25
25
  "test": "npm run build && xv ./lib",
26
- "cli:local": "npm link",
26
+ "cli:local": "npm link bysquare",
27
27
  "version": "git flow release start v$npm_package_version",
28
28
  "prepare": "",
29
29
  "prepublishOnly": "npm run build",
@@ -31,21 +31,27 @@
31
31
  "postversion": ""
32
32
  },
33
33
  "dependencies": {
34
- "lzma-native": "8.0.5"
34
+ "lzma-native": "8.0.6"
35
35
  },
36
36
  "devDependencies": {
37
+ "@types/lzma-native": "^4.0.1",
37
38
  "@types/node": "14.14.20",
38
- "typescript": "4.5.4",
39
+ "typescript": "4.5.5",
39
40
  "xv": "1.1.1"
40
41
  },
41
- "engines": {
42
- "node": ">=10.0.0"
43
- },
44
42
  "files": [
45
43
  "lib",
46
44
  "!lib/*.test.*"
47
45
  ],
48
46
  "bin": "lib/cli.js",
49
47
  "main": "lib/index.js",
50
- "types": "lib/index.d.ts"
48
+ "types": "lib/index.d.ts",
49
+ "engines": {
50
+ "node": ">=14.14.x",
51
+ "npm": ">= 7.0"
52
+ },
53
+ "os": [
54
+ "darwin",
55
+ "linux"
56
+ ]
51
57
  }
package/lib/package.json DELETED
@@ -1,51 +0,0 @@
1
- {
2
- "name": "bysquare",
3
- "description": "It's a national standard for payment QR codes adopted by Slovak Banking Association (SBA)",
4
- "version": "1.0.6",
5
- "license": "Apache-2.0",
6
- "author": "Filip Seman <filip.seman@protonmail.com>",
7
- "keywords": [
8
- "pay by square",
9
- "by square",
10
- "paybysquare",
11
- "bysquare",
12
- "payments",
13
- "qr-string",
14
- "qr",
15
- "cli"
16
- ],
17
- "repository": {
18
- "type": "git",
19
- "url": "git+https://github.com/xseman/bysquare.git"
20
- },
21
- "homepage": "https://github.com/xseman/bysquare#readme",
22
- "funding": "https://github.com/sponsors/xseman",
23
- "scripts": {
24
- "build": "rm -rf ./lib; tsc",
25
- "test": "npm run build && xv ./lib",
26
- "cli:local": "npm link",
27
- "version": "git flow release start v$npm_package_version",
28
- "prepare": "",
29
- "prepublishOnly": "npm run build",
30
- "preversion": "git checkout develop",
31
- "postversion": ""
32
- },
33
- "dependencies": {
34
- "lzma-native": "8.0.5"
35
- },
36
- "devDependencies": {
37
- "@types/node": "14.14.20",
38
- "typescript": "4.5.4",
39
- "xv": "1.1.1"
40
- },
41
- "engines": {
42
- "node": ">=10.0.0"
43
- },
44
- "files": [
45
- "lib",
46
- "!lib/*.test.*"
47
- ],
48
- "bin": "lib/cli.js",
49
- "main": "lib/index.js",
50
- "types": "lib/index.d.ts"
51
- }