@rvboris/sberparse 1.0.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.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +42 -0
  3. package/dist/balance-checker.d.ts +17 -0
  4. package/dist/balance-checker.d.ts.map +1 -0
  5. package/dist/balance-checker.js +34 -0
  6. package/dist/balance-checker.js.map +1 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +31 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/commands/index.d.ts +17 -0
  12. package/dist/commands/index.d.ts.map +1 -0
  13. package/dist/commands/index.js +70 -0
  14. package/dist/commands/index.js.map +1 -0
  15. package/dist/converter.d.ts +9 -0
  16. package/dist/converter.d.ts.map +1 -0
  17. package/dist/converter.js +101 -0
  18. package/dist/converter.js.map +1 -0
  19. package/dist/csv-writer.d.ts +10 -0
  20. package/dist/csv-writer.d.ts.map +1 -0
  21. package/dist/csv-writer.js +71 -0
  22. package/dist/csv-writer.js.map +1 -0
  23. package/dist/exceptions.d.ts +31 -0
  24. package/dist/exceptions.d.ts.map +1 -0
  25. package/dist/exceptions.js +46 -0
  26. package/dist/exceptions.js.map +1 -0
  27. package/dist/extractor-selector.d.ts +16 -0
  28. package/dist/extractor-selector.d.ts.map +1 -0
  29. package/dist/extractor-selector.js +48 -0
  30. package/dist/extractor-selector.js.map +1 -0
  31. package/dist/extractor.d.ts +58 -0
  32. package/dist/extractor.d.ts.map +1 -0
  33. package/dist/extractor.js +65 -0
  34. package/dist/extractor.js.map +1 -0
  35. package/dist/extractors/index.d.ts +10 -0
  36. package/dist/extractors/index.d.ts.map +1 -0
  37. package/dist/extractors/index.js +14 -0
  38. package/dist/extractors/index.js.map +1 -0
  39. package/dist/extractors/sber-debit-2510.d.ts +15 -0
  40. package/dist/extractors/sber-debit-2510.d.ts.map +1 -0
  41. package/dist/extractors/sber-debit-2510.js +157 -0
  42. package/dist/extractors/sber-debit-2510.js.map +1 -0
  43. package/dist/extractors/sber-debit-2603.d.ts +16 -0
  44. package/dist/extractors/sber-debit-2603.d.ts.map +1 -0
  45. package/dist/extractors/sber-debit-2603.js +161 -0
  46. package/dist/extractors/sber-debit-2603.js.map +1 -0
  47. package/dist/index.d.ts +5 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +4 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/json-writer.d.ts +11 -0
  52. package/dist/json-writer.d.ts.map +1 -0
  53. package/dist/json-writer.js +38 -0
  54. package/dist/json-writer.js.map +1 -0
  55. package/dist/logger.d.ts +2 -0
  56. package/dist/logger.d.ts.map +1 -0
  57. package/dist/logger.js +21 -0
  58. package/dist/logger.js.map +1 -0
  59. package/dist/pdf-parser.d.ts +14 -0
  60. package/dist/pdf-parser.d.ts.map +1 -0
  61. package/dist/pdf-parser.js +31 -0
  62. package/dist/pdf-parser.js.map +1 -0
  63. package/dist/types.d.ts +58 -0
  64. package/dist/types.d.ts.map +1 -0
  65. package/dist/types.js +2 -0
  66. package/dist/types.js.map +1 -0
  67. package/dist/unidecode.d.ts +6 -0
  68. package/dist/unidecode.d.ts.map +1 -0
  69. package/dist/unidecode.js +92 -0
  70. package/dist/unidecode.js.map +1 -0
  71. package/dist/utils.d.ts +27 -0
  72. package/dist/utils.d.ts.map +1 -0
  73. package/dist/utils.js +65 -0
  74. package/dist/utils.js.map +1 -0
  75. package/package.json +72 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 sbertoactual contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # sberparse
2
+
3
+ Конвертация выписок Сбербанка из PDF в JSON/CSV формат.
4
+
5
+ ## Установка
6
+
7
+ ```bash
8
+ pnpm add -g @rvboris/sberparse
9
+ ```
10
+
11
+ ## Использование
12
+
13
+ ```bash
14
+ # Конвертация в CSV (по умолчанию)
15
+ sberparse ./vypiska.pdf
16
+
17
+ # Конвертация в JSON
18
+ sberparse ./vypiska.pdf -t json
19
+
20
+ # Указать конкретный выходной файл
21
+ sberparse ./vypiska.pdf -o ./output/my-extract
22
+
23
+ # Принудительный формат (skip auto-detect)
24
+ sberparse ./vypiska.pdf -f SBER_DEBIT_2603
25
+
26
+ # Обратный порядок транзакций
27
+ sberparse ./vypiska.pdf -r
28
+
29
+ # Без проверки баланса
30
+ sberparse ./vypiska.pdf -b
31
+
32
+ # Сохранить промежуточный текстовый файл
33
+ sberparse ./vypiska.pdf --interm
34
+ ```
35
+
36
+ ## Поддерживаемые форматы
37
+
38
+ - SBER_DEBIT_2603 - Дебетовая карта образца марта 2026
39
+
40
+ ## Лицензия
41
+
42
+ MIT
@@ -0,0 +1,17 @@
1
+ import { Decimal } from "decimal.js";
2
+ import type { Transaction } from "./types.js";
3
+ /**
4
+ * Проверяет баланс транзакций
5
+ * @param transactions Список транзакций
6
+ * @param balance Баланс из шапки выписки
7
+ * @param columnNameForBalance Название колонки для расчёта
8
+ * @throws {BalanceVerificationError} если баланс не совпадает
9
+ */
10
+ export declare function checkTransactionsBalance(transactions: Transaction[], balance: Decimal, columnNameForBalance: string): void;
11
+ /**
12
+ * Переворачивает порядок транзакций
13
+ * @param transactions Список транзакций
14
+ * @returns Перевёрнутый список
15
+ */
16
+ export declare function reverseTransactions(transactions: Transaction[]): Transaction[];
17
+ //# sourceMappingURL=balance-checker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"balance-checker.d.ts","sourceRoot":"","sources":["../src/balance-checker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,YAAY,EAAE,WAAW,EAAE,EAC3B,OAAO,EAAE,OAAO,EAChB,oBAAoB,EAAE,MAAM,GAC3B,IAAI,CAoBN;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAE9E"}
@@ -0,0 +1,34 @@
1
+ import { Decimal } from "decimal.js";
2
+ import { BalanceVerificationError } from "./exceptions.js";
3
+ /**
4
+ * Проверяет баланс транзакций
5
+ * @param transactions Список транзакций
6
+ * @param balance Баланс из шапки выписки
7
+ * @param columnNameForBalance Название колонки для расчёта
8
+ * @throws {BalanceVerificationError} если баланс не совпадает
9
+ */
10
+ export function checkTransactionsBalance(transactions, balance, columnNameForBalance) {
11
+ let calculatedBalance = new Decimal(0);
12
+ for (const transaction of transactions) {
13
+ const value = transaction[columnNameForBalance];
14
+ if (typeof value === "number") {
15
+ calculatedBalance = calculatedBalance.plus(value);
16
+ }
17
+ }
18
+ const difference = balance.minus(calculatedBalance).abs();
19
+ if (difference.greaterThan(0.01)) {
20
+ throw new BalanceVerificationError(`Ошибка проверки баланса по транзакциям:\n` +
21
+ ` Вычисленный баланс по информации в шапке выписки = ${balance.toFixed(2)}\n` +
22
+ ` Вычисленный баланс по всем транзакциям = ${calculatedBalance.toFixed(2)}\n` +
23
+ ` Разница = ${difference.toFixed(2)}`);
24
+ }
25
+ }
26
+ /**
27
+ * Переворачивает порядок транзакций
28
+ * @param transactions Список транзакций
29
+ * @returns Перевёрнутый список
30
+ */
31
+ export function reverseTransactions(transactions) {
32
+ return [...transactions].reverse();
33
+ }
34
+ //# sourceMappingURL=balance-checker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"balance-checker.js","sourceRoot":"","sources":["../src/balance-checker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAG3D;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CACtC,YAA2B,EAC3B,OAAgB,EAChB,oBAA4B;IAE5B,IAAI,iBAAiB,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;IAEvC,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACvC,MAAM,KAAK,GAAI,WAAiD,CAAC,oBAAoB,CAAC,CAAC;QACvF,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,iBAAiB,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,GAAG,EAAE,CAAC;IAE1D,IAAI,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,wBAAwB,CAChC,2CAA2C;YACzC,wDAAwD,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;YAC9E,8CAA8C,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;YAC9E,eAAe,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CACzC,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,YAA2B;IAC7D,OAAO,CAAC,GAAG,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;AACrC,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { run } from "@oclif/core";
5
+ import packageJson from "../package.json" with { type: "json" };
6
+ import { logger } from "./logger.js";
7
+ const currentFile = fileURLToPath(import.meta.url);
8
+ const root = path.resolve(path.dirname(currentFile), "..");
9
+ const isSource = currentFile.endsWith(`${path.sep}src${path.sep}cli.ts`);
10
+ const commandsTarget = isSource ? "./src/commands/index.ts" : "./dist/commands/index.js";
11
+ const pjson = {
12
+ ...packageJson,
13
+ oclif: {
14
+ ...packageJson.oclif,
15
+ commands: {
16
+ strategy: "single",
17
+ target: commandsTarget,
18
+ },
19
+ },
20
+ };
21
+ await run(process.argv.slice(2), { root, pjson }).catch((error) => {
22
+ const hasOclif = typeof error === "object" &&
23
+ error !== null &&
24
+ "oclif" in error &&
25
+ typeof error.oclif === "object";
26
+ if (!hasOclif) {
27
+ logger.error `Неожиданная ошибка: ${error}`;
28
+ }
29
+ process.exitCode = 1;
30
+ });
31
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,WAAW,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACnD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC,CAAC;AAC3D,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;AACzE,MAAM,cAAc,GAAG,QAAQ,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,0BAA0B,CAAC;AAEzF,MAAM,KAAK,GAAG;IACZ,GAAG,WAAW;IACd,KAAK,EAAE;QACL,GAAG,WAAW,CAAC,KAAK;QACpB,QAAQ,EAAE;YACR,QAAQ,EAAE,QAAiB;YAC3B,MAAM,EAAE,cAAc;SACvB;KACF;CACF,CAAC;AAEF,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IACzE,MAAM,QAAQ,GACZ,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,OAAO,IAAI,KAAK;QAChB,OAAQ,KAAuC,CAAC,KAAK,KAAK,QAAQ,CAAC;IAErE,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,CAAC,KAAK,CAAA,uBAAuB,KAAK,EAAE,CAAC;IAC7C,CAAC;IAED,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { Command } from "@oclif/core";
2
+ export default class Convert extends Command {
3
+ static description: string;
4
+ static args: {
5
+ inputFile: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static flags: {
8
+ output: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ format: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ type: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
+ reverse: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
+ balanceCheck: import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
+ interm: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
+ };
15
+ run(): Promise<void>;
16
+ }
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,OAAO,EAAS,MAAM,aAAa,CAAC;AAMnD,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,OAAO;IAC1C,MAAM,CAAC,WAAW,SAAqD;IAEvE,MAAM,CAAC,IAAI;;MAKT;IAEF,MAAM,CAAC,KAAK;;;;;;;MA+BV;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAsB3B"}
@@ -0,0 +1,70 @@
1
+ import { Args, Command, Flags } from "@oclif/core";
2
+ import { convertPdf } from "../converter.js";
3
+ import { SberParseError } from "../exceptions.js";
4
+ import { extractorsList } from "../extractors/index.js";
5
+ import { logger } from "../logger.js";
6
+ export default class Convert extends Command {
7
+ static description = "Конвертация выписок Сбербанка из PDF в JSON/CSV";
8
+ static args = {
9
+ inputFile: Args.string({
10
+ description: "Входной PDF файл",
11
+ required: true,
12
+ }),
13
+ };
14
+ static flags = {
15
+ output: Flags.string({
16
+ char: "o",
17
+ description: "Имя выходного файла (без расширения)",
18
+ }),
19
+ format: Flags.string({
20
+ char: "f",
21
+ description: `Принудительно использовать формат (${extractorsList
22
+ .map((e) => e.name)
23
+ .join(", ")})`,
24
+ }),
25
+ type: Flags.string({
26
+ char: "t",
27
+ description: "Тип выходного файла: json или csv",
28
+ options: ["json", "csv"],
29
+ default: "csv",
30
+ }),
31
+ reverse: Flags.boolean({
32
+ char: "r",
33
+ description: "Изменить порядок транзакций на обратный",
34
+ default: false,
35
+ }),
36
+ balanceCheck: Flags.boolean({
37
+ description: "Игнорировать результаты сверки баланса",
38
+ allowNo: true,
39
+ default: true,
40
+ }),
41
+ interm: Flags.boolean({
42
+ description: "Сохранить промежуточный текстовый файл",
43
+ default: false,
44
+ }),
45
+ };
46
+ async run() {
47
+ const { args, flags } = await this.parse(Convert);
48
+ try {
49
+ await convertPdf(args.inputFile, {
50
+ output: flags.output,
51
+ format: flags.format,
52
+ type: flags.type,
53
+ reverse: flags.reverse,
54
+ balance_check: flags.balanceCheck,
55
+ interm: flags.interm,
56
+ });
57
+ }
58
+ catch (error) {
59
+ if (error instanceof SberParseError) {
60
+ logger.error `Ошибка: ${error.message}`;
61
+ this.error(error.message, { exit: 1 });
62
+ }
63
+ else {
64
+ logger.error `Неожиданная ошибка: ${error}`;
65
+ this.error("Unexpected error", { exit: 1 });
66
+ }
67
+ }
68
+ }
69
+ }
70
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,OAAO;IAC1C,MAAM,CAAC,WAAW,GAAG,iDAAiD,CAAC;IAEvE,MAAM,CAAC,IAAI,GAAG;QACZ,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC;YACrB,WAAW,EAAE,kBAAkB;YAC/B,QAAQ,EAAE,IAAI;SACf,CAAC;KACH,CAAC;IAEF,MAAM,CAAC,KAAK,GAAG;QACb,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;YACnB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,sCAAsC;SACpD,CAAC;QACF,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;YACnB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,sCAAsC,cAAc;iBAC9D,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;iBAClB,IAAI,CAAC,IAAI,CAAC,GAAG;SACjB,CAAC;QACF,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;YACjB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,mCAAmC;YAChD,OAAO,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC;YACxB,OAAO,EAAE,KAAK;SACf,CAAC;QACF,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC;YACrB,IAAI,EAAE,GAAG;YACT,WAAW,EAAE,yCAAyC;YACtD,OAAO,EAAE,KAAK;SACf,CAAC;QACF,YAAY,EAAE,KAAK,CAAC,OAAO,CAAC;YAC1B,WAAW,EAAE,wCAAwC;YACrD,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,IAAI;SACd,CAAC;QACF,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC;YACpB,WAAW,EAAE,wCAAwC;YACrD,OAAO,EAAE,KAAK;SACf,CAAC;KACH,CAAC;IAEF,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAElD,IAAI,CAAC;YACH,MAAM,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE;gBAC/B,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,IAAI,EAAE,KAAK,CAAC,IAAsB;gBAClC,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,aAAa,EAAE,KAAK,CAAC,YAAY;gBACjC,MAAM,EAAE,KAAK,CAAC,MAAM;aACrB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,cAAc,EAAE,CAAC;gBACpC,MAAM,CAAC,KAAK,CAAA,WAAW,KAAK,CAAC,OAAO,EAAE,CAAC;gBACvC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YACzC,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,KAAK,CAAA,uBAAuB,KAAK,EAAE,CAAC;gBAC3C,IAAI,CAAC,KAAK,CAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;IACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { CLIOptions, ExtractorResult } from "./types.js";
2
+ /**
3
+ * Конвертирует PDF файл в JSON/CSV
4
+ * @param inputFileName Путь к входному PDF файлу
5
+ * @param options Опции CLI
6
+ * @returns Информация о результате
7
+ */
8
+ export declare function convertPdf(inputFileName: string, options: CLIOptions): Promise<ExtractorResult>;
9
+ //# sourceMappingURL=converter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converter.d.ts","sourceRoot":"","sources":["../src/converter.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE9D;;;;;GAKG;AACH,wBAAsB,UAAU,CAC9B,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,eAAe,CAAC,CAoG1B"}
@@ -0,0 +1,101 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { checkTransactionsBalance, reverseTransactions } from "./balance-checker.js";
4
+ import { writeTransactionsToCsv } from "./csv-writer.js";
5
+ import { BalanceVerificationError, UserInputError } from "./exceptions.js";
6
+ import { determineExtractorAuto, determineExtractorByName } from "./extractor-selector.js";
7
+ import { writeTransactionsToJson } from "./json-writer.js";
8
+ import { logger } from "./logger.js";
9
+ import { pdfToText } from "./pdf-parser.js";
10
+ /**
11
+ * Конвертирует PDF файл в JSON/CSV
12
+ * @param inputFileName Путь к входному PDF файлу
13
+ * @param options Опции CLI
14
+ * @returns Информация о результате
15
+ */
16
+ export async function convertPdf(inputFileName, options) {
17
+ logger.info `${"*".repeat(30)}`;
18
+ logger.info `Конвертируем файл ${inputFileName}`;
19
+ // Проверяем расширение
20
+ const ext = path.extname(inputFileName).toLowerCase();
21
+ if (ext !== ".pdf") {
22
+ throw new UserInputError(`Неподдерживаемое расширение файла: ${ext}`);
23
+ }
24
+ // Конвертируем PDF в текст
25
+ const bankText = await pdfToText(inputFileName);
26
+ // Сохраняем промежуточный файл, если запрошено
27
+ if (options.interm) {
28
+ const txtFileName = inputFileName.replace(/\.pdf$/i, ".txt");
29
+ await fs.writeFile(txtFileName, bankText, "utf-8");
30
+ logger.info `Сохранён промежуточный файл: ${txtFileName}`;
31
+ }
32
+ // Определяем экстрактор
33
+ let extractorClass;
34
+ if (options.format) {
35
+ extractorClass = determineExtractorByName(options.format);
36
+ logger.info `Конвертируем файл как формат ${options.format}`;
37
+ }
38
+ else {
39
+ extractorClass = determineExtractorAuto(bankText);
40
+ logger.info `Формат файла определён как ${extractorClass.name}`;
41
+ }
42
+ // Создаём экземпляр экстрактора
43
+ const extractor = new extractorClass(bankText);
44
+ // Получаем транзакции
45
+ const transactions = extractor.getEntries();
46
+ logger.info `Найдено транзакций: ${transactions.length}`;
47
+ // Получаем баланс из шапки
48
+ const periodBalance = extractor.getPeriodBalance();
49
+ // Получаем информацию о колонках
50
+ const columnsInfo = extractor.getColumnsInfo();
51
+ // Проверяем баланс
52
+ let error = "";
53
+ try {
54
+ checkTransactionsBalance(transactions, periodBalance, extractor.getColumnNameForBalanceCalculation());
55
+ }
56
+ catch (e) {
57
+ if (e instanceof BalanceVerificationError) {
58
+ if (options.balance_check) {
59
+ throw e;
60
+ }
61
+ else {
62
+ logger.warn `${e.message}`;
63
+ error = e.message;
64
+ }
65
+ }
66
+ else {
67
+ throw e;
68
+ }
69
+ }
70
+ // Переворачиваем порядок, если запрошено
71
+ let finalTransactions = transactions;
72
+ if (options.reverse) {
73
+ finalTransactions = reverseTransactions(transactions);
74
+ }
75
+ // Определяем выходной файл
76
+ let outputFileName;
77
+ if (options.output) {
78
+ outputFileName = options.output;
79
+ }
80
+ else {
81
+ outputFileName = inputFileName.replace(/\.pdf$/i, "");
82
+ }
83
+ // Записываем результат
84
+ if (options.type === "json") {
85
+ const filename = await writeTransactionsToJson(finalTransactions, outputFileName, extractorClass.name, error);
86
+ logger.info `Создан файл ${filename}`;
87
+ }
88
+ else {
89
+ const filename = await writeTransactionsToCsv(finalTransactions, outputFileName, columnsInfo);
90
+ logger.info `Создан файл ${filename}`;
91
+ }
92
+ return {
93
+ extractor_name: extractorClass.name,
94
+ transactions: finalTransactions,
95
+ period_balance: periodBalance.toNumber(),
96
+ balance_column: extractor.getColumnNameForBalanceCalculation(),
97
+ columns_info: columnsInfo,
98
+ errors: error,
99
+ };
100
+ }
101
+ //# sourceMappingURL=converter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converter.js","sourceRoot":"","sources":["../src/converter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { Transaction } from "./types.js";
2
+ /**
3
+ * Записывает транзакции в CSV файл
4
+ * @param transactions Список транзакций
5
+ * @param filename Имя файла (без расширения)
6
+ * @param columnsInfo Информация о колонках
7
+ * @returns Имя созданного файла
8
+ */
9
+ export declare function writeTransactionsToCsv(transactions: Transaction[], filename: string, columnsInfo: Record<string, string>): Promise<string>;
10
+ //# sourceMappingURL=csv-writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csv-writer.d.ts","sourceRoot":"","sources":["../src/csv-writer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AA2B9C;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAC1C,YAAY,EAAE,WAAW,EAAE,EAC3B,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAClC,OAAO,CAAC,MAAM,CAAC,CA4CjB"}
@@ -0,0 +1,71 @@
1
+ import fs from "node:fs/promises";
2
+ /**
3
+ * Экранирует значение для CSV
4
+ * @param value Значение
5
+ * @returns Экранированное значение
6
+ */
7
+ function escapeCsvValue(value) {
8
+ if (value === undefined || value === null) {
9
+ return "";
10
+ }
11
+ let strValue;
12
+ if (value instanceof Date) {
13
+ strValue = value.toISOString();
14
+ }
15
+ else {
16
+ strValue = String(value);
17
+ }
18
+ // Экранируем кавычки и оборачиваем в кавычки если нужно
19
+ if (strValue.includes(";") || strValue.includes('"') || strValue.includes("\n")) {
20
+ return `"${strValue.replace(/"/g, '""')}"`;
21
+ }
22
+ return strValue;
23
+ }
24
+ /**
25
+ * Записывает транзакции в CSV файл
26
+ * @param transactions Список транзакций
27
+ * @param filename Имя файла (без расширения)
28
+ * @param columnsInfo Информация о колонках
29
+ * @returns Имя созданного файла
30
+ */
31
+ export async function writeTransactionsToCsv(transactions, filename, columnsInfo) {
32
+ const outputFilename = filename.endsWith(".csv") ? filename : `${filename}.csv`;
33
+ // Заголовки
34
+ const headers = Object.keys(columnsInfo);
35
+ const headerRow = headers.map((key) => columnsInfo[key]).join(";");
36
+ // Данные
37
+ const dataRows = [];
38
+ for (const transaction of transactions) {
39
+ const rowValues = headers.map((key) => {
40
+ const value = transaction[key];
41
+ let formattedValue;
42
+ if (value instanceof Date) {
43
+ // Форматируем дату
44
+ if (key === "operation_date") {
45
+ formattedValue = value.toLocaleString("ru-RU", {
46
+ day: "2-digit",
47
+ month: "2-digit",
48
+ year: "numeric",
49
+ hour: "2-digit",
50
+ minute: "2-digit",
51
+ });
52
+ }
53
+ else {
54
+ formattedValue = value.toLocaleDateString("ru-RU");
55
+ }
56
+ }
57
+ else {
58
+ formattedValue = value;
59
+ }
60
+ return escapeCsvValue(formattedValue);
61
+ });
62
+ dataRows.push(rowValues.join(";"));
63
+ }
64
+ // Собираем CSV
65
+ const csvContent = [headerRow, ...dataRows].join("\n");
66
+ // Добавляем BOM для Excel
67
+ const bom = "\uFEFF";
68
+ await fs.writeFile(outputFilename, `${bom + csvContent}\n`, "utf-8");
69
+ return outputFilename;
70
+ }
71
+ //# sourceMappingURL=csv-writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csv-writer.js","sourceRoot":"","sources":["../src/csv-writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAGlC;;;;GAIG;AACH,SAAS,cAAc,CAAC,KAAyC;IAC/D,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC1C,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,QAAgB,CAAC;IACrB,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;QAC1B,QAAQ,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IACjC,CAAC;SAAM,CAAC;QACN,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAED,wDAAwD;IACxD,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAChF,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;IAC7C,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,YAA2B,EAC3B,QAAgB,EAChB,WAAmC;IAEnC,MAAM,cAAc,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,MAAM,CAAC;IAEhF,YAAY;IACZ,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACzC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEnE,SAAS;IACT,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACvC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YACpC,MAAM,KAAK,GAAI,WAAkD,CAAC,GAAG,CAAC,CAAC;YACvE,IAAI,cAAkD,CAAC;YAEvD,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;gBAC1B,mBAAmB;gBACnB,IAAI,GAAG,KAAK,gBAAgB,EAAE,CAAC;oBAC7B,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE;wBAC7C,GAAG,EAAE,SAAS;wBACd,KAAK,EAAE,SAAS;wBAChB,IAAI,EAAE,SAAS;wBACf,IAAI,EAAE,SAAS;wBACf,MAAM,EAAE,SAAS;qBAClB,CAAC,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACN,cAAc,GAAG,KAAK,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;gBACrD,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,cAAc,GAAG,KAAoC,CAAC;YACxD,CAAC;YAED,OAAO,cAAc,CAAC,cAAc,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;QACH,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrC,CAAC;IAED,eAAe;IACf,MAAM,UAAU,GAAG,CAAC,SAAS,EAAE,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEvD,0BAA0B;IAC1B,MAAM,GAAG,GAAG,QAAQ,CAAC;IACrB,MAAM,EAAE,CAAC,SAAS,CAAC,cAAc,EAAE,GAAG,GAAG,GAAG,UAAU,IAAI,EAAE,OAAO,CAAC,CAAC;IAErE,OAAO,cAAc,CAAC;AACxB,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Базовый класс для всех ошибок sberparse
3
+ */
4
+ export declare class SberParseError extends Error {
5
+ constructor(message: string);
6
+ }
7
+ /**
8
+ * Ошибка структуры входного файла
9
+ */
10
+ export declare class InputFileStructureError extends SberParseError {
11
+ constructor(message: string);
12
+ }
13
+ /**
14
+ * Ошибка проверки баланса
15
+ */
16
+ export declare class BalanceVerificationError extends SberParseError {
17
+ constructor(message: string);
18
+ }
19
+ /**
20
+ * Ошибка пользовательского ввода
21
+ */
22
+ export declare class UserInputError extends SberParseError {
23
+ constructor(message: string);
24
+ }
25
+ /**
26
+ * Ошибка тестирования
27
+ */
28
+ export declare class TestingError extends SberParseError {
29
+ constructor(message: string);
30
+ }
31
+ //# sourceMappingURL=exceptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exceptions.d.ts","sourceRoot":"","sources":["../src/exceptions.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,cAAc;gBAC7C,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,wBAAyB,SAAQ,cAAc;gBAC9C,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,cAAc;gBACpC,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,cAAc;gBAClC,OAAO,EAAE,MAAM;CAI5B"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Базовый класс для всех ошибок sberparse
3
+ */
4
+ export class SberParseError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = "SberParseError";
8
+ }
9
+ }
10
+ /**
11
+ * Ошибка структуры входного файла
12
+ */
13
+ export class InputFileStructureError extends SberParseError {
14
+ constructor(message) {
15
+ super(message);
16
+ this.name = "InputFileStructureError";
17
+ }
18
+ }
19
+ /**
20
+ * Ошибка проверки баланса
21
+ */
22
+ export class BalanceVerificationError extends SberParseError {
23
+ constructor(message) {
24
+ super(message);
25
+ this.name = "BalanceVerificationError";
26
+ }
27
+ }
28
+ /**
29
+ * Ошибка пользовательского ввода
30
+ */
31
+ export class UserInputError extends SberParseError {
32
+ constructor(message) {
33
+ super(message);
34
+ this.name = "UserInputError";
35
+ }
36
+ }
37
+ /**
38
+ * Ошибка тестирования
39
+ */
40
+ export class TestingError extends SberParseError {
41
+ constructor(message) {
42
+ super(message);
43
+ this.name = "TestingError";
44
+ }
45
+ }
46
+ //# sourceMappingURL=exceptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exceptions.js","sourceRoot":"","sources":["../src/exceptions.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,uBAAwB,SAAQ,cAAc;IACzD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,wBAAyB,SAAQ,cAAc;IAC1D,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;IACzC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,cAAe,SAAQ,cAAc;IAChD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,YAAa,SAAQ,cAAc;IAC9C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF"}
@@ -0,0 +1,16 @@
1
+ import type { Extractor } from "./extractor.js";
2
+ /**
3
+ * Определяет подходящий экстрактор для текста выписки автоматически
4
+ * @param bankText Текст выписки
5
+ * @returns Класс экстрактора
6
+ * @throws {InputFileStructureError} если ни один экстрактор не подходит
7
+ */
8
+ export declare function determineExtractorAuto(bankText: string): new (bank_text: string) => Extractor;
9
+ /**
10
+ * Возвращает экстрактор по имени
11
+ * @param extractorName Имя экстрактора
12
+ * @returns Класс экстрактора
13
+ * @throws {UserInputError} если экстрактор не найден
14
+ */
15
+ export declare function determineExtractorByName(extractorName: string): new (bank_text: string) => Extractor;
16
+ //# sourceMappingURL=extractor-selector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor-selector.d.ts","sourceRoot":"","sources":["../src/extractor-selector.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGhD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,SAAS,EAAE,MAAM,KAAK,SAAS,CAmC7F;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,MAAM,GACpB,KACD,SAAS,EAAE,MAAM,KACd,SAAS,CAWb"}
@@ -0,0 +1,48 @@
1
+ import { InputFileStructureError, UserInputError } from "./exceptions.js";
2
+ import { extractorsList } from "./extractors/index.js";
3
+ /**
4
+ * Определяет подходящий экстрактор для текста выписки автоматически
5
+ * @param bankText Текст выписки
6
+ * @returns Класс экстрактора
7
+ * @throws {InputFileStructureError} если ни один экстрактор не подходит
8
+ */
9
+ export function determineExtractorAuto(bankText) {
10
+ const supportedExtractors = extractorsList.filter((ExtractorClass) => {
11
+ try {
12
+ const quickCheck = ExtractorClass.quickCheck;
13
+ if (quickCheck && !quickCheck(bankText)) {
14
+ return false;
15
+ }
16
+ const extractor = new ExtractorClass(bankText);
17
+ return extractor.checkSupport();
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ });
23
+ if (supportedExtractors.length === 0) {
24
+ throw new InputFileStructureError("Неизвестный формат выписки, ни один из экстракторов не подходят");
25
+ }
26
+ if (supportedExtractors.length > 1) {
27
+ throw new InputFileStructureError(`Непонятный формат выписки. Больше чем один экстрактор говорят, что понимают его: ${supportedExtractors
28
+ .map((e) => e.name)
29
+ .join(", ")}`);
30
+ }
31
+ return supportedExtractors[0];
32
+ }
33
+ /**
34
+ * Возвращает экстрактор по имени
35
+ * @param extractorName Имя экстрактора
36
+ * @returns Класс экстрактора
37
+ * @throws {UserInputError} если экстрактор не найден
38
+ */
39
+ export function determineExtractorByName(extractorName) {
40
+ for (const ExtractorClass of extractorsList) {
41
+ if (ExtractorClass.name === extractorName) {
42
+ return ExtractorClass;
43
+ }
44
+ }
45
+ const availableNames = extractorsList.map((e) => e.name).join(", ");
46
+ throw new UserInputError(`Указанный формат файла "${extractorName}" неизвестен. Доступные форматы: ${availableNames}`);
47
+ }
48
+ //# sourceMappingURL=extractor-selector.js.map