bysquare 2.4.0 → 2.6.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
@@ -14,7 +14,7 @@ reminders and other payment regulations.
14
14
 
15
15
  This library doesn't have a specific opinion and how the QR code string is
16
16
  transformed into images depends on how you implement it. See
17
- [examples](examples).
17
+ [examples](./docs/examples/).
18
18
 
19
19
  ## Install
20
20
 
@@ -24,38 +24,33 @@ transformed into images depends on how you implement it. See
24
24
  npm install bysquare
25
25
  ```
26
26
 
27
- **GitHub**
27
+ **Browser**
28
28
 
29
- ```sh
30
- # same as latest released npm registry version
31
- npm install xseman/bysquare#master
29
+ ```html
30
+ <script type="module">
31
+ import { generate, parse } from "https://esm.sh/bysquare@2.4.0/";
32
+ </script>
33
+ ```
32
34
 
33
- # latest unreleased changes
34
- npm install xseman/bysquare#develop
35
+ **Deno** `v1.28+`, just import `npm:bysquare` `v2.1.0+`
35
36
 
36
- # specific tag version, e.g. v2.1.0
37
- npm install xseman/bysquare#v2.1.0
37
+ ```ts
38
+ import { generate, parse } from "npm:bysquare@2.1.0"
38
39
  ```
39
40
 
40
- **CLI**
41
+ **CLI** (Node.JS `v18`+)
41
42
 
42
43
  ```sh
43
44
  npm install --global bysquare
44
45
  ```
45
46
 
46
- **Deno** `v1.28+`, just import `npm:bysquare` `v2.1.0+`
47
+ # How it works
47
48
 
48
- ```
49
- import { generate, parse } from "npm:bysquare@2.1.0"
50
- ```
51
-
52
- ## How it works
49
+ ## Encoding sequence
53
50
 
54
- ### Encoding sequence
51
+ ![logic](./docs/uml/logic.svg)
55
52
 
56
- ![logic](./doc/uml/logic.svg)
57
-
58
- ## API
53
+ # API
59
54
 
60
55
  ```ts
61
56
  generate(model: DataModel, options?: Options): string
@@ -63,14 +58,14 @@ parse(qr: string): DataModel
63
58
  detect(qr: string): Boolean
64
59
  ```
65
60
 
66
- ## Usage
61
+ # Usage
67
62
 
68
- Generate
63
+ ## Generate
69
64
 
70
65
  ```ts
71
- import { DataModel, generate, PaymentOptions } from "bysquare"
66
+ import { CurrencyCode, DataModel, generate, PaymentOptions } from "bysquare"
72
67
 
73
- // long string ready to be encoded to QR
68
+ // string ready to be encoded to QR
74
69
  const qrString = generate({
75
70
  invoiceId: "random-id",
76
71
  payments: [
@@ -80,14 +75,14 @@ const qrString = generate({
80
75
  bankAccounts: [
81
76
  { iban: "SK9611000000002918599669" }
82
77
  ],
83
- currencyCode: "EUR",
78
+ currencyCode: CurrencyCode.EUR,
84
79
  variableSymbol: "123"
85
80
  }
86
81
  ]
87
82
  })
88
83
  ```
89
84
 
90
- Parse
85
+ ## Parse
91
86
 
92
87
  ```ts
93
88
  import { parse } from "bysquare"
@@ -112,44 +107,20 @@ const model =
112
107
  //
113
108
  ```
114
109
 
115
- You can use json file with valid model to generate qr-string.
110
+ ## CLI
111
+
112
+ Encode JSON data from a file and print the corresponding QR code. The file
113
+ argument should be a path to a JSON file.
116
114
 
117
115
  ```sh
118
- # example.json
119
- # {
120
- # "invoiceId": "random-id",
121
- # "payments": [
122
- # {
123
- # "type": 1,
124
- # "amount": 100.0,
125
- # "bankAccounts": [{ "iban": "SK9611000000002918599669" }],
126
- # "currencyCode": "EUR",
127
- # "variableSymbol": "123"
128
- # }
129
- # ]
130
- # }
131
-
132
- $ npx bysquare ./example.json
133
- $ 0405QH8090IFU27IV0J6HGGLIOTIBVHNQQJQ6LAVGNBT363HR13JC6CB54HSI0KH9FCRASHNQBSKAQD2LJ4AU400UVKDNDPFRKLOBEVVVU0QJ000
116
+ npx bysquare --encode <file>
134
117
  ```
135
118
 
136
- You can also use stdin.
119
+ Decode the specified QR code string and print the corresponding JSON data. The
120
+ qrstring argument should be a valid QR code string.
137
121
 
138
122
  ```sh
139
- $ npx bysquare <<< '{
140
- "invoiceId": "random-id",
141
- "payments": [
142
- {
143
- "type": 1,
144
- "amount": 100.0,
145
- "bankAccounts": [{ "iban": "SK9611000000002918599669" }],
146
- "currencyCode": "EUR",
147
- "variableSymbol": "123"
148
- }
149
- ]
150
- }'
151
-
152
- $ 0405QH8090IFU27IV0J6HGGLIOTIBVHNQQJQ6LAVGNBT363HR13JC6CB54HSI0KH9FCRASHNQBSKAQD2LJ4AU400UVKDNDPFRKLOBEVVVU0QJ000
123
+ npx bysquare --decode <qrstring>
153
124
  ```
154
125
 
155
126
  ## Related
@@ -161,23 +132,5 @@ $ 0405QH8090IFU27IV0J6HGGLIOTIBVHNQQJQ6LAVGNBT363HR13JC6CB54HSI0KH9FCRASHNQBSKAQ
161
132
  - <https://www.sbaonline.sk/wp-content/uploads/2020/03/pay-by-square-specifications-1_1_0.pdf>
162
133
  - <https://www.vutbr.cz/studenti/zav-prace/detail/78439>
163
134
 
164
- <!--
165
- Versioning
166
- ----------
167
-
168
- https://github.com/dherges/npm-version-git-flow
169
-
170
- - Stash unfinished work
171
- - Run `npm test`
172
- - Run `npm version <patch, minor, major>`
173
- - Commit and push
174
- - Follow git-flow instructions
175
- - Checkout to master
176
- - Build artefacts
177
- - Push commits and tag, git push && git push --tags
178
- - Validate with `npm publish --dry-run`
179
- - Publish to npm, `npm publish`
180
- -->
181
-
182
135
  [build]: https://img.shields.io/github/actions/workflow/status/xseman/bysquare/tests.yml
183
136
  [version]: https://img.shields.io/npm/v/bysquare
package/dist/cli.js ADDED
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { parseArgs } from "node:util";
4
+ import { generate } from "./generate.js";
5
+ import { parse } from "./parse.js";
6
+ const args = parseArgs({
7
+ allowPositionals: true,
8
+ options: {
9
+ decode: {
10
+ type: "string",
11
+ short: "d"
12
+ },
13
+ encode: {
14
+ type: "string",
15
+ short: "e"
16
+ },
17
+ help: {
18
+ type: "boolean",
19
+ short: "h"
20
+ }
21
+ }
22
+ });
23
+ if (process.stdin.isTTY) {
24
+ /** json file */
25
+ if (args.values.encode) {
26
+ const file = args.values.encode;
27
+ if (existsSync(file)) {
28
+ const data = readFileSync(file, "utf8");
29
+ console.log(generate(JSON.parse(data)));
30
+ }
31
+ else {
32
+ console.error(`File ${file} doesn't exists`);
33
+ process.exit(1);
34
+ }
35
+ }
36
+ /** input string */
37
+ if (args.values.decode) {
38
+ const qrstring = args.values.decode;
39
+ console.log(JSON.stringify(parse(qrstring), null, 4));
40
+ }
41
+ if (args.values.help || Object.keys(args.values).length === 0) {
42
+ console.log([
43
+ "NAME",
44
+ " bysquare - Simple Node.js library to generate and parse PAY bysquare standard",
45
+ "",
46
+ "SYNOPSIS",
47
+ " bysquare [OPTIONS]",
48
+ "",
49
+ "DESCRIPTION",
50
+ " bysquare is a command-line tool that provides a simple Node.js library to generate ",
51
+ " and parse PAY bysquare standard. It offers functionality to encode JSON data into a ",
52
+ " corresponding QR code and decode a QR code string to obtain the associated JSON data.",
53
+ "",
54
+ "OPTIONS",
55
+ " -d, --decode <qrstring>",
56
+ " Decode the specified QR code string and print the corresponding JSON data.",
57
+ " The qrstring argument should be a valid QR code string.",
58
+ "",
59
+ " -e, --encode <file>",
60
+ " Encode JSON data from a file and print the corresponding QR code.",
61
+ " The file argument should be a path to a JSON file.",
62
+ "",
63
+ " -h, --help",
64
+ " Display the help message and exit.",
65
+ "",
66
+ "USAGE",
67
+ " Encoding JSON data from a file",
68
+ "",
69
+ ` ${process.argv[1]} --encode <file>`,
70
+ " The <file> argument should be the path to the JSON file you want to encode.",
71
+ " The tool will read the file, generate a QR code representing the JSON data",
72
+ "",
73
+ " Decoding a QR code string",
74
+ "",
75
+ ` ${process.argv[1]} --decode <qrstring>`,
76
+ " Replace qrstring with the QR code string you want to decode.",
77
+ " The program will parse the QR code string and print the resulting JSON data.",
78
+ ""
79
+ ].join("\n"));
80
+ }
81
+ }
@@ -45,7 +45,7 @@ export function headerDataLength(length) {
45
45
  throw new Error("The maximum compressed data size has been reached");
46
46
  }
47
47
  const header = new ArrayBuffer(2);
48
- new DataView(header).setUint16(0, length);
48
+ new DataView(header).setUint16(0, length, true);
49
49
  return new Uint8Array(header);
50
50
  }
51
51
  /**
@@ -80,7 +80,7 @@ export function serialize(data) {
80
80
  serialized.push(p.variableSymbol);
81
81
  serialized.push(p.constantSymbol);
82
82
  serialized.push(p.specificSymbol);
83
- serialized.push(p.originatorRefInfo);
83
+ serialized.push(p.originatorsReferenceInformation);
84
84
  serialized.push(p.paymentNote);
85
85
  serialized.push(p.bankAccounts.length.toString());
86
86
  for (const ba of p.bankAccounts) {
@@ -103,7 +103,7 @@ export function serialize(data) {
103
103
  serialized.push(p.directDebitType?.toString());
104
104
  serialized.push(p.variableSymbol?.toString());
105
105
  serialized.push(p.specificSymbol?.toString());
106
- serialized.push(p.originatorRefInfo?.toString());
106
+ serialized.push(p.originatorsReferenceInformation?.toString());
107
107
  serialized.push(p.mandateId?.toString());
108
108
  serialized.push(p.creditorId?.toString());
109
109
  serialized.push(p.contractId?.toString());
@@ -1,7 +1,7 @@
1
1
  import { decompress } from "lzma1";
2
2
  import { base32hex } from "rfc4648";
3
3
  import { PaymentOptions } from "./index.js";
4
- function cleanEmptyProps(obj) {
4
+ function cleanUndefined(obj) {
5
5
  Object.keys(obj).forEach((key) => {
6
6
  if (typeof obj[key] === "undefined") {
7
7
  delete obj[key];
@@ -50,7 +50,7 @@ export function deserialize(qr) {
50
50
  specificSymbol: specifics?.length
51
51
  ? specifics
52
52
  : undefined,
53
- originatorRefInfo: originatorRefInfo?.length
53
+ originatorsReferenceInformation: originatorRefInfo?.length
54
54
  ? originatorRefInfo
55
55
  : undefined,
56
56
  paymentNote: paymentNote?.length
@@ -70,7 +70,7 @@ export function deserialize(qr) {
70
70
  ? bic
71
71
  : undefined
72
72
  };
73
- cleanEmptyProps(account);
73
+ cleanUndefined(account);
74
74
  payment.bankAccounts.push(account);
75
75
  }
76
76
  serialized.shift(); // StandingOrderExt
@@ -103,7 +103,7 @@ export function deserialize(qr) {
103
103
  default:
104
104
  break;
105
105
  }
106
- cleanEmptyProps(payment);
106
+ cleanUndefined(payment);
107
107
  output.payments.push(payment);
108
108
  }
109
109
  for (let i = 0; i < paymentslen; i++) {
@@ -122,7 +122,7 @@ export function deserialize(qr) {
122
122
  ? addressLine2
123
123
  : undefined
124
124
  };
125
- cleanEmptyProps(beneficiary);
125
+ cleanUndefined(beneficiary);
126
126
  output.payments[i].beneficiary = beneficiary;
127
127
  }
128
128
  }
@@ -149,11 +149,10 @@ function bysquareHeaderDecoder(header) {
149
149
  };
150
150
  }
151
151
  export class DecodeError extends Error {
152
- cause;
153
- name = "DecodeError";
154
152
  constructor(cause, msg) {
155
153
  super(msg);
156
154
  this.cause = cause;
155
+ this.name = "DecodeError";
157
156
  }
158
157
  }
159
158
  /**
@@ -188,14 +187,12 @@ export function parse(qr) {
188
187
  */
189
188
  const defaultProperties = [0x5D]; // lc=3, lp=0, pb=2
190
189
  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);
190
+ const uncompressedSize = new Uint8Array(8);
191
+ uncompressedSize.set(bytes.slice(2, 4));
195
192
  const header = new Uint8Array([
196
193
  ...defaultProperties,
197
194
  ...defaultDictionarySize,
198
- ...new Uint8Array(uncompressedSize)
195
+ ...uncompressedSize
199
196
  ]);
200
197
  const payload = bytes.slice(4);
201
198
  const body = new Uint8Array([