@uplab/vendure-plugin-exchange-rates 0.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.
Files changed (94) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +369 -0
  3. package/dist/api/admin.resolver.d.ts +16 -0
  4. package/dist/api/admin.resolver.d.ts.map +1 -0
  5. package/dist/api/admin.resolver.js +66 -0
  6. package/dist/api/admin.resolver.js.map +1 -0
  7. package/dist/api/api-extensions.d.ts +6 -0
  8. package/dist/api/api-extensions.d.ts.map +1 -0
  9. package/dist/api/api-extensions.js +57 -0
  10. package/dist/api/api-extensions.js.map +1 -0
  11. package/dist/api/shop.resolver.d.ts +15 -0
  12. package/dist/api/shop.resolver.d.ts.map +1 -0
  13. package/dist/api/shop.resolver.js +63 -0
  14. package/dist/api/shop.resolver.js.map +1 -0
  15. package/dist/constants.d.ts +10 -0
  16. package/dist/constants.d.ts.map +1 -0
  17. package/dist/constants.js +13 -0
  18. package/dist/constants.js.map +1 -0
  19. package/dist/dashboard/format-rate.ts +8 -0
  20. package/dist/dashboard/graphql.ts +74 -0
  21. package/dist/dashboard/i18n/en.po +109 -0
  22. package/dist/dashboard/i18n/uk.po +109 -0
  23. package/dist/dashboard/index.tsx +7 -0
  24. package/dist/dashboard/routes/currency-exchange-rate-detail.tsx +194 -0
  25. package/dist/dashboard/routes/currency-exchange-rate-list.tsx +105 -0
  26. package/dist/derive-rates.d.ts +13 -0
  27. package/dist/derive-rates.d.ts.map +1 -0
  28. package/dist/derive-rates.js +40 -0
  29. package/dist/derive-rates.js.map +1 -0
  30. package/dist/effective-rate.d.ts +8 -0
  31. package/dist/effective-rate.d.ts.map +1 -0
  32. package/dist/effective-rate.js +13 -0
  33. package/dist/effective-rate.js.map +1 -0
  34. package/dist/entities/currency-exchange-rate.entity.d.ts +13 -0
  35. package/dist/entities/currency-exchange-rate.entity.d.ts.map +1 -0
  36. package/dist/entities/currency-exchange-rate.entity.js +55 -0
  37. package/dist/entities/currency-exchange-rate.entity.js.map +1 -0
  38. package/dist/events/currency-exchange-rate.event.d.ts +18 -0
  39. package/dist/events/currency-exchange-rate.event.d.ts.map +1 -0
  40. package/dist/events/currency-exchange-rate.event.js +18 -0
  41. package/dist/events/currency-exchange-rate.event.js.map +1 -0
  42. package/dist/exchange-rate-source-error.d.ts +16 -0
  43. package/dist/exchange-rate-source-error.d.ts.map +1 -0
  44. package/dist/exchange-rate-source-error.js +18 -0
  45. package/dist/exchange-rate-source-error.js.map +1 -0
  46. package/dist/exchange-rate-sync.task.d.ts +3 -0
  47. package/dist/exchange-rate-sync.task.d.ts.map +1 -0
  48. package/dist/exchange-rate-sync.task.js +18 -0
  49. package/dist/exchange-rate-sync.task.js.map +1 -0
  50. package/dist/exchange-rates.plugin.d.ts +24 -0
  51. package/dist/exchange-rates.plugin.d.ts.map +1 -0
  52. package/dist/exchange-rates.plugin.js +101 -0
  53. package/dist/exchange-rates.plugin.js.map +1 -0
  54. package/dist/index.d.ts +15 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +31 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/services/currency-exchange-rate-sync.service.d.ts +30 -0
  59. package/dist/services/currency-exchange-rate-sync.service.d.ts.map +1 -0
  60. package/dist/services/currency-exchange-rate-sync.service.js +145 -0
  61. package/dist/services/currency-exchange-rate-sync.service.js.map +1 -0
  62. package/dist/services/currency-exchange-rate.service.d.ts +30 -0
  63. package/dist/services/currency-exchange-rate.service.d.ts.map +1 -0
  64. package/dist/services/currency-exchange-rate.service.js +93 -0
  65. package/dist/services/currency-exchange-rate.service.js.map +1 -0
  66. package/dist/sources/ecb-exchange-rate-source.d.ts +20 -0
  67. package/dist/sources/ecb-exchange-rate-source.d.ts.map +1 -0
  68. package/dist/sources/ecb-exchange-rate-source.js +33 -0
  69. package/dist/sources/ecb-exchange-rate-source.js.map +1 -0
  70. package/dist/sources/fetch-body.d.ts +9 -0
  71. package/dist/sources/fetch-body.d.ts.map +1 -0
  72. package/dist/sources/fetch-body.js +59 -0
  73. package/dist/sources/fetch-body.js.map +1 -0
  74. package/dist/sources/frankfurter-exchange-rate-source.d.ts +23 -0
  75. package/dist/sources/frankfurter-exchange-rate-source.d.ts.map +1 -0
  76. package/dist/sources/frankfurter-exchange-rate-source.js +35 -0
  77. package/dist/sources/frankfurter-exchange-rate-source.js.map +1 -0
  78. package/dist/sources/monobank-exchange-rate-source.d.ts +29 -0
  79. package/dist/sources/monobank-exchange-rate-source.d.ts.map +1 -0
  80. package/dist/sources/monobank-exchange-rate-source.js +46 -0
  81. package/dist/sources/monobank-exchange-rate-source.js.map +1 -0
  82. package/dist/sources/nbu-exchange-rate-source.d.ts +20 -0
  83. package/dist/sources/nbu-exchange-rate-source.d.ts.map +1 -0
  84. package/dist/sources/nbu-exchange-rate-source.js +25 -0
  85. package/dist/sources/nbu-exchange-rate-source.js.map +1 -0
  86. package/dist/sources/static-exchange-rate-source.d.ts +20 -0
  87. package/dist/sources/static-exchange-rate-source.d.ts.map +1 -0
  88. package/dist/sources/static-exchange-rate-source.js +23 -0
  89. package/dist/sources/static-exchange-rate-source.js.map +1 -0
  90. package/dist/types.d.ts +64 -0
  91. package/dist/types.d.ts.map +1 -0
  92. package/dist/types.js +3 -0
  93. package/dist/types.js.map +1 -0
  94. package/package.json +96 -0
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.CurrencyExchangeRateSyncService = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const core_1 = require("@vendure/core");
18
+ const typeorm_1 = require("typeorm");
19
+ const currency_exchange_rate_service_1 = require("./currency-exchange-rate.service");
20
+ const constants_1 = require("../constants");
21
+ const derive_rates_1 = require("../derive-rates");
22
+ const currency_exchange_rate_entity_1 = require("../entities/currency-exchange-rate.entity");
23
+ const currency_exchange_rate_event_1 = require("../events/currency-exchange-rate.event");
24
+ const vendureCurrencyCodes = new Set(Object.values(core_1.CurrencyCode));
25
+ function isUsable(quote) {
26
+ return vendureCurrencyCodes.has(quote.currencyCode) && Number.isFinite(quote.rate) && quote.rate > 0;
27
+ }
28
+ /** One quote per code: the last one wins, so a combining source can override another. */
29
+ function lastPerCode(quotes) {
30
+ return [...new Map(quotes.map((q) => [q.currencyCode, q]))].map(([, q]) => q);
31
+ }
32
+ /**
33
+ * @description
34
+ * Pulls rates from the configured {@link ExchangeRateSource} into the `CurrencyExchangeRate` table,
35
+ * re-based onto the shop's base currency. A fetched rate only replaces `rate`: whether a currency is
36
+ * enabled and its custom rate stay as the admin left them, unless the base changed. New currencies arrive
37
+ * disabled.
38
+ */
39
+ let CurrencyExchangeRateSyncService = class CurrencyExchangeRateSyncService {
40
+ constructor(options, connection, eventBus, rateService) {
41
+ this.options = options;
42
+ this.connection = connection;
43
+ this.eventBus = eventBus;
44
+ this.rateService = rateService;
45
+ }
46
+ /**
47
+ * Returns every rate stored in the current base afterwards, and publishes a `synced` event with them when
48
+ * anything changed — or `[]` when the source returned nothing usable, the stored rates left untouched. Throws when the source cannot be read or cannot be re-based; the stored rates are then
49
+ * left as they were.
50
+ */
51
+ async syncRates(ctx) {
52
+ const { source } = this.options;
53
+ const baseCurrency = await this.rateService.getBaseCurrency(ctx);
54
+ const { base, quotes } = await source.fetchRates(ctx);
55
+ const usable = lastPerCode(quotes.filter(isUsable));
56
+ if (usable.length < quotes.length) {
57
+ core_1.Logger.verbose(`Dropped ${quotes.length - usable.length} ${source.name} rates that are not usable`, constants_1.loggerCtx);
58
+ }
59
+ const derived = usable.length ? (0, derive_rates_1.deriveRates)(source.name, baseCurrency, base, usable) : [];
60
+ if (!derived.length) {
61
+ core_1.Logger.warn(`${source.name} returned no usable rates; keeping the stored ones`, constants_1.loggerCtx);
62
+ return [];
63
+ }
64
+ // One transaction: a failure part-way leaves every rate as it was, not half of them refreshed.
65
+ const { rows, changed } = await this.connection.withTransaction(ctx, async (txCtx) => {
66
+ const repository = this.connection.getRepository(txCtx, currency_exchange_rate_entity_1.CurrencyExchangeRate);
67
+ const stored = await repository.find();
68
+ const storedByCode = new Map(stored.map((r) => [r.code, r]));
69
+ const rebased = [];
70
+ const created = [];
71
+ let updated = 0;
72
+ for (const { currencyCode, rate } of derived) {
73
+ const existing = storedByCode.get(currencyCode);
74
+ if (!existing) {
75
+ created.push(new currency_exchange_rate_entity_1.CurrencyExchangeRate({ code: currencyCode, baseCurrency, rate }));
76
+ continue;
77
+ }
78
+ let changes = {};
79
+ if (existing.baseCurrency !== baseCurrency) {
80
+ // A custom rate in the old base means nothing in the new one.
81
+ changes = { baseCurrency, rate, useCustomRate: false, customRate: null };
82
+ rebased.push(currencyCode);
83
+ }
84
+ else if (existing.rate !== rate) {
85
+ changes = { rate };
86
+ }
87
+ // Only the columns the sync owns, and only when they change: an admin edit made meanwhile stays.
88
+ if (Object.keys(changes).length) {
89
+ await repository.update({ id: existing.id }, changes);
90
+ updated++;
91
+ }
92
+ }
93
+ await repository.save(created);
94
+ // Rows the new base did not re-quote, the old row for the new base currency itself among them.
95
+ await repository.delete({ baseCurrency: (0, typeorm_1.Not)(baseCurrency) });
96
+ if (rebased.length) {
97
+ core_1.Logger.warn(`Rates are now in ${baseCurrency}: dropped the custom rates of ${rebased.join(', ')}`, constants_1.loggerCtx);
98
+ }
99
+ const quoted = new Set(derived.map((q) => q.currencyCode));
100
+ const dropped = stored.filter((r) => r.enabled && r.baseCurrency === baseCurrency && !quoted.has(r.code));
101
+ if (dropped.length) {
102
+ const codes = dropped.map((r) => r.code).join(', ');
103
+ core_1.Logger.warn(`${source.name} no longer quotes ${codes}; they keep their last rate`, constants_1.loggerCtx);
104
+ }
105
+ const deleted = stored.some((r) => r.baseCurrency !== baseCurrency);
106
+ return {
107
+ // Read back, so `updatedAt` and the rest are what the database now holds.
108
+ rows: await repository.find({ where: { baseCurrency }, order: { code: 'ASC' } }),
109
+ changed: created.length > 0 || updated > 0 || deleted,
110
+ };
111
+ });
112
+ core_1.Logger.verbose(`Synced ${rows.length} rates in ${baseCurrency} from ${source.name} (base ${base})`, constants_1.loggerCtx);
113
+ if (changed) {
114
+ await this.eventBus.publish(new currency_exchange_rate_event_1.CurrencyExchangeRateEvent(ctx, rows, 'synced'));
115
+ }
116
+ return rows;
117
+ }
118
+ /**
119
+ * Syncs when no rate is stored in the current base: on the first boot, and after a restart that changed
120
+ * the base. Never throws: a source outage must not stop the server.
121
+ */
122
+ async backfillIfEmpty(ctx) {
123
+ const baseCurrency = await this.rateService.getBaseCurrency(ctx);
124
+ if ((await this.connection.getRepository(ctx, currency_exchange_rate_entity_1.CurrencyExchangeRate).count({ where: { baseCurrency } })) > 0) {
125
+ return;
126
+ }
127
+ try {
128
+ const persisted = await this.syncRates(ctx);
129
+ core_1.Logger.info(`Loaded ${persisted.length} exchange rates from ${this.options.source.name}`, constants_1.loggerCtx);
130
+ }
131
+ catch (e) {
132
+ // Also what a second instance booting at the same time sees: the first one already inserted them.
133
+ core_1.Logger.warn(`Could not load the initial exchange rates: ${e.message}`, constants_1.loggerCtx);
134
+ }
135
+ }
136
+ };
137
+ exports.CurrencyExchangeRateSyncService = CurrencyExchangeRateSyncService;
138
+ exports.CurrencyExchangeRateSyncService = CurrencyExchangeRateSyncService = __decorate([
139
+ (0, common_1.Injectable)(),
140
+ __param(0, (0, common_1.Inject)(constants_1.EXCHANGE_RATES_PLUGIN_OPTIONS)),
141
+ __metadata("design:paramtypes", [Object, core_1.TransactionalConnection,
142
+ core_1.EventBus,
143
+ currency_exchange_rate_service_1.CurrencyExchangeRateService])
144
+ ], CurrencyExchangeRateSyncService);
145
+ //# sourceMappingURL=currency-exchange-rate-sync.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currency-exchange-rate-sync.service.js","sourceRoot":"","sources":["../../src/services/currency-exchange-rate-sync.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { FindOptionsWhere } from 'typeorm';
2
+ import { ChannelService, CurrencyCode, EventBus, ListQueryBuilder, ID, ListQueryOptions, PaginatedList, RequestContext, TransactionalConnection } from '@vendure/core';
3
+ import { CurrencyExchangeRate } from '../entities/currency-exchange-rate.entity';
4
+ import { ResolvedExchangeRatesPluginOptions, UpdateCurrencyExchangeRateInput } from '../types';
5
+ export declare class CurrencyExchangeRateService {
6
+ private readonly options;
7
+ private connection;
8
+ private listQueryBuilder;
9
+ private eventBus;
10
+ private channelService;
11
+ constructor(options: ResolvedExchangeRatesPluginOptions, connection: TransactionalConnection, listQueryBuilder: ListQueryBuilder, eventBus: EventBus, channelService: ChannelService);
12
+ /**
13
+ * The currency every rate is expressed in: the `baseCurrency` option, otherwise the default channel's
14
+ * currency — read on each call, so a change to the channel applies from the next sync.
15
+ */
16
+ getBaseCurrency(ctx: RequestContext): Promise<CurrencyCode>;
17
+ /** `where` is applied beneath the list options, so no `filter` or `filterOperator` can widen it. */
18
+ findAll(ctx: RequestContext, options?: ListQueryOptions<CurrencyExchangeRate>, where?: FindOptionsWhere<CurrencyExchangeRate>): Promise<PaginatedList<CurrencyExchangeRate>>;
19
+ findOne(ctx: RequestContext, id: ID): Promise<CurrencyExchangeRate | null>;
20
+ /**
21
+ * The {@link effectiveRate} of `currencyCode` — units of the base currency per one unit — or
22
+ * `undefined` when no usable rate in the current base is stored. `requireEnabled` is the caller's policy: whether a currency the admin switched off still
23
+ * counts (`true` for anything a customer is billed in).
24
+ */
25
+ getRate(ctx: RequestContext, currencyCode: CurrencyCode, { requireEnabled }: {
26
+ requireEnabled: boolean;
27
+ }): Promise<number | undefined>;
28
+ update(ctx: RequestContext, input: UpdateCurrencyExchangeRateInput): Promise<CurrencyExchangeRate>;
29
+ }
30
+ //# sourceMappingURL=currency-exchange-rate.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currency-exchange-rate.service.d.ts","sourceRoot":"","sources":["../../src/services/currency-exchange-rate.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EACL,cAAc,EACd,YAAY,EACZ,QAAQ,EACR,gBAAgB,EAChB,EAAE,EACF,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,uBAAuB,EAExB,MAAM,eAAe,CAAC;AAIvB,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,kCAAkC,EAAE,+BAA+B,EAAE,MAAM,UAAU,CAAC;AAE/F,qBACa,2BAA2B;IAEG,OAAO,CAAC,QAAQ,CAAC,OAAO;IAC/D,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,gBAAgB;IACxB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,cAAc;gBAJkC,OAAO,EAAE,kCAAkC,EAC3F,UAAU,EAAE,uBAAuB,EACnC,gBAAgB,EAAE,gBAAgB,EAClC,QAAQ,EAAE,QAAQ,EAClB,cAAc,EAAE,cAAc;IAGxC;;;OAGG;IACG,eAAe,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC;IAIjE,oGAAoG;IAC9F,OAAO,CACX,GAAG,EAAE,cAAc,EACnB,OAAO,CAAC,EAAE,gBAAgB,CAAC,oBAAoB,CAAC,EAChD,KAAK,CAAC,EAAE,gBAAgB,CAAC,oBAAoB,CAAC,GAC7C,OAAO,CAAC,aAAa,CAAC,oBAAoB,CAAC,CAAC;IAUzC,OAAO,CAAC,GAAG,EAAE,cAAc,EAAE,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAIhF;;;;OAIG;IACG,OAAO,CACX,GAAG,EAAE,cAAc,EACnB,YAAY,EAAE,YAAY,EAC1B,EAAE,cAAc,EAAE,EAAE;QAAE,cAAc,EAAE,OAAO,CAAA;KAAE,GAC9C,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAUxB,MAAM,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,+BAA+B,GAAG,OAAO,CAAC,oBAAoB,CAAC;CAsBzG"}
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.CurrencyExchangeRateService = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const core_1 = require("@vendure/core");
18
+ const constants_1 = require("../constants");
19
+ const derive_rates_1 = require("../derive-rates");
20
+ const effective_rate_1 = require("../effective-rate");
21
+ const currency_exchange_rate_entity_1 = require("../entities/currency-exchange-rate.entity");
22
+ const currency_exchange_rate_event_1 = require("../events/currency-exchange-rate.event");
23
+ let CurrencyExchangeRateService = class CurrencyExchangeRateService {
24
+ constructor(options, connection, listQueryBuilder, eventBus, channelService) {
25
+ this.options = options;
26
+ this.connection = connection;
27
+ this.listQueryBuilder = listQueryBuilder;
28
+ this.eventBus = eventBus;
29
+ this.channelService = channelService;
30
+ }
31
+ /**
32
+ * The currency every rate is expressed in: the `baseCurrency` option, otherwise the default channel's
33
+ * currency — read on each call, so a change to the channel applies from the next sync.
34
+ */
35
+ async getBaseCurrency(ctx) {
36
+ return this.options.baseCurrency ?? (await this.channelService.getDefaultChannel(ctx)).defaultCurrencyCode;
37
+ }
38
+ /** `where` is applied beneath the list options, so no `filter` or `filterOperator` can widen it. */
39
+ async findAll(ctx, options, where) {
40
+ return this.listQueryBuilder
41
+ .build(currency_exchange_rate_entity_1.CurrencyExchangeRate, options, { ctx, where })
42
+ .getManyAndCount()
43
+ .then(([items, totalItems]) => ({
44
+ items,
45
+ totalItems,
46
+ }));
47
+ }
48
+ async findOne(ctx, id) {
49
+ return this.connection.getRepository(ctx, currency_exchange_rate_entity_1.CurrencyExchangeRate).findOne({ where: { id } });
50
+ }
51
+ /**
52
+ * The {@link effectiveRate} of `currencyCode` — units of the base currency per one unit — or
53
+ * `undefined` when no usable rate in the current base is stored. `requireEnabled` is the caller's policy: whether a currency the admin switched off still
54
+ * counts (`true` for anything a customer is billed in).
55
+ */
56
+ async getRate(ctx, currencyCode, { requireEnabled }) {
57
+ const row = await this.connection
58
+ .getRepository(ctx, currency_exchange_rate_entity_1.CurrencyExchangeRate)
59
+ .findOne({ where: { code: currencyCode, baseCurrency: await this.getBaseCurrency(ctx) } });
60
+ if (!row || (requireEnabled && !row.enabled)) {
61
+ return undefined;
62
+ }
63
+ return (0, effective_rate_1.effectiveRate)(row);
64
+ }
65
+ async update(ctx, input) {
66
+ if (input.useCustomRate && input.customRate == null) {
67
+ throw new core_1.UserInputError('A custom rate must be a positive number when useCustomRate is on');
68
+ }
69
+ // Stored with 8 decimals: anything that rounds to 0 there would silently stop being a rate.
70
+ const customRate = input.customRate == null ? input.customRate : (0, derive_rates_1.round8)(input.customRate);
71
+ if (customRate != null && !(Number.isFinite(customRate) && customRate > 0 && customRate < constants_1.MAX_RATE)) {
72
+ throw new core_1.UserInputError('A custom rate must be at least 0.00000001 and below 100000000000');
73
+ }
74
+ await this.connection.getEntityOrThrow(ctx, currency_exchange_rate_entity_1.CurrencyExchangeRate, input.id);
75
+ const repository = this.connection.getRepository(ctx, currency_exchange_rate_entity_1.CurrencyExchangeRate);
76
+ // Only the admin's columns: a sync committed meanwhile keeps its rate and base.
77
+ const changes = Object.fromEntries(Object.entries({ enabled: input.enabled, useCustomRate: input.useCustomRate, customRate }).filter(([, value]) => value !== undefined));
78
+ await repository.update({ id: input.id }, changes);
79
+ const saved = await this.connection.getEntityOrThrow(ctx, currency_exchange_rate_entity_1.CurrencyExchangeRate, input.id);
80
+ await this.eventBus.publish(new currency_exchange_rate_event_1.CurrencyExchangeRateEvent(ctx, [saved], 'updated'));
81
+ return saved;
82
+ }
83
+ };
84
+ exports.CurrencyExchangeRateService = CurrencyExchangeRateService;
85
+ exports.CurrencyExchangeRateService = CurrencyExchangeRateService = __decorate([
86
+ (0, common_1.Injectable)(),
87
+ __param(0, (0, common_1.Inject)(constants_1.EXCHANGE_RATES_PLUGIN_OPTIONS)),
88
+ __metadata("design:paramtypes", [Object, core_1.TransactionalConnection,
89
+ core_1.ListQueryBuilder,
90
+ core_1.EventBus,
91
+ core_1.ChannelService])
92
+ ], CurrencyExchangeRateService);
93
+ //# sourceMappingURL=currency-exchange-rate.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currency-exchange-rate.service.js","sourceRoot":"","sources":["../../src/services/currency-exchange-rate.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { ExchangeRateSource, ExchangeRateSourceResult } from '../types';
2
+ export interface EcbExchangeRateSourceOptions {
3
+ /** @default 'https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml' */
4
+ apiUrl?: string;
5
+ /** @default 10000 */
6
+ timeout?: number;
7
+ }
8
+ /**
9
+ * @description
10
+ * The European Central Bank's euro reference rates: about 30 currencies, published every working day
11
+ * around 16:00 CET. Free, no key. Base EUR.
12
+ */
13
+ export declare class EcbExchangeRateSource implements ExchangeRateSource {
14
+ readonly name = "ecb";
15
+ private readonly apiUrl;
16
+ private readonly timeout;
17
+ constructor(options?: EcbExchangeRateSourceOptions);
18
+ fetchRates(): Promise<ExchangeRateSourceResult>;
19
+ }
20
+ //# sourceMappingURL=ecb-exchange-rate-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ecb-exchange-rate-source.d.ts","sourceRoot":"","sources":["../../src/sources/ecb-exchange-rate-source.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAGxE,MAAM,WAAW,4BAA4B;IAC3C,+EAA+E;IAC/E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAKD;;;;GAIG;AACH,qBAAa,qBAAsB,YAAW,kBAAkB;IAC9D,QAAQ,CAAC,IAAI,SAAS;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,OAAO,GAAE,4BAAiC;IAKhD,UAAU,IAAI,OAAO,CAAC,wBAAwB,CAAC;CAUtD"}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EcbExchangeRateSource = void 0;
4
+ const core_1 = require("@vendure/core");
5
+ const constants_1 = require("../constants");
6
+ const fetch_body_1 = require("./fetch-body");
7
+ /** `<Cube currency='USD' rate='1.1225'/>`, tolerant of quoting, attribute order and a closing tag. */
8
+ const CUBE = /<Cube\b(?=[^>]*\bcurrency=['"]([A-Z]{3})['"])(?=[^>]*\brate=['"]([\d.]+)['"])[^>]*>/g;
9
+ /**
10
+ * @description
11
+ * The European Central Bank's euro reference rates: about 30 currencies, published every working day
12
+ * around 16:00 CET. Free, no key. Base EUR.
13
+ */
14
+ class EcbExchangeRateSource {
15
+ constructor(options = {}) {
16
+ this.name = 'ecb';
17
+ this.apiUrl = options.apiUrl ?? 'https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml';
18
+ this.timeout = options.timeout ?? constants_1.DEFAULT_SOURCE_TIMEOUT;
19
+ }
20
+ async fetchRates() {
21
+ const xml = await (0, fetch_body_1.fetchText)(this.name, this.apiUrl, this.timeout);
22
+ // `rate` is "1 EUR = rate units", the inverse of a quote.
23
+ const quotes = [...xml.matchAll(CUBE)].map(([, code, rate]) => ({
24
+ currencyCode: code,
25
+ rate: 1 / Number(rate),
26
+ }));
27
+ if (!quotes.length)
28
+ throw (0, fetch_body_1.unexpectedBody)(this.name);
29
+ return { base: core_1.CurrencyCode.EUR, quotes };
30
+ }
31
+ }
32
+ exports.EcbExchangeRateSource = EcbExchangeRateSource;
33
+ //# sourceMappingURL=ecb-exchange-rate-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ecb-exchange-rate-source.js","sourceRoot":"","sources":["../../src/sources/ecb-exchange-rate-source.ts"],"names":[],"mappings":";;;AAAA,wCAA6C;AAC7C,4CAAsD;AAEtD,6CAAyD;AASzD,sGAAsG;AACtG,MAAM,IAAI,GAAG,sFAAsF,CAAC;AAEpG;;;;GAIG;AACH,MAAa,qBAAqB;IAKhC,YAAY,UAAwC,EAAE;QAJ7C,SAAI,GAAG,KAAK,CAAC;QAKpB,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,+DAA+D,CAAC;QAChG,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,kCAAsB,CAAC;IAC3D,CAAC;IAED,KAAK,CAAC,UAAU;QACd,MAAM,GAAG,GAAG,MAAM,IAAA,sBAAS,EAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAClE,0DAA0D;QAC1D,MAAM,MAAM,GAAG,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;YAC9D,YAAY,EAAE,IAAoB;YAClC,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC;SACvB,CAAC,CAAC,CAAC;QACJ,IAAI,CAAC,MAAM,CAAC,MAAM;YAAE,MAAM,IAAA,2BAAc,EAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpD,OAAO,EAAE,IAAI,EAAE,mBAAY,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC;IAC5C,CAAC;CACF;AApBD,sDAoBC"}
@@ -0,0 +1,9 @@
1
+ import { ExchangeRateSourceError } from '../exchange-rate-source-error';
2
+ export declare function unexpectedBody(source: string): ExchangeRateSourceError;
3
+ /** GETs a JSON array. Monobank, for one, answers some errors with a 200 and `{ errorDescription }`. */
4
+ export declare function fetchJsonArray<T>(source: string, url: string, timeout: number): Promise<T[]>;
5
+ /** GETs a JSON object. */
6
+ export declare function fetchJsonObject<T>(source: string, url: string, timeout: number): Promise<T>;
7
+ /** GETs a text body, e.g. XML. */
8
+ export declare function fetchText(source: string, url: string, timeout: number): Promise<string>;
9
+ //# sourceMappingURL=fetch-body.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-body.d.ts","sourceRoot":"","sources":["../../src/sources/fetch-body.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAgCxE,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,uBAAuB,CAEtE;AAED,uGAAuG;AACvG,wBAAsB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAIlG;AAED,0BAA0B;AAC1B,wBAAsB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAIjG;AAED,kCAAkC;AAClC,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE7F"}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.unexpectedBody = unexpectedBody;
4
+ exports.fetchJsonArray = fetchJsonArray;
5
+ exports.fetchJsonObject = fetchJsonObject;
6
+ exports.fetchText = fetchText;
7
+ const exchange_rate_source_error_1 = require("../exchange-rate-source-error");
8
+ async function request(source, url, timeout) {
9
+ let response;
10
+ try {
11
+ response = await fetch(url, { signal: AbortSignal.timeout(timeout) });
12
+ }
13
+ catch (cause) {
14
+ const reason = !(cause instanceof Error)
15
+ ? String(cause)
16
+ : cause.name === 'TimeoutError'
17
+ ? `timed out after ${timeout} ms`
18
+ : cause.message;
19
+ throw new exchange_rate_source_error_1.ExchangeRateSourceError(`${source} rates request failed: ${reason}`, { source, cause });
20
+ }
21
+ if (!response.ok) {
22
+ throw new exchange_rate_source_error_1.ExchangeRateSourceError(`${source} rates request failed: HTTP ${response.status}`, {
23
+ source,
24
+ status: response.status,
25
+ });
26
+ }
27
+ return response;
28
+ }
29
+ async function fetchJson(source, url, timeout) {
30
+ const response = await request(source, url, timeout);
31
+ try {
32
+ return await response.json();
33
+ }
34
+ catch (cause) {
35
+ throw new exchange_rate_source_error_1.ExchangeRateSourceError(`${source} answered with invalid JSON`, { source, cause });
36
+ }
37
+ }
38
+ function unexpectedBody(source) {
39
+ return new exchange_rate_source_error_1.ExchangeRateSourceError(`${source} answered with an unexpected body`, { source });
40
+ }
41
+ /** GETs a JSON array. Monobank, for one, answers some errors with a 200 and `{ errorDescription }`. */
42
+ async function fetchJsonArray(source, url, timeout) {
43
+ const body = await fetchJson(source, url, timeout);
44
+ if (!Array.isArray(body))
45
+ throw unexpectedBody(source);
46
+ return body;
47
+ }
48
+ /** GETs a JSON object. */
49
+ async function fetchJsonObject(source, url, timeout) {
50
+ const body = await fetchJson(source, url, timeout);
51
+ if (body === null || typeof body !== 'object' || Array.isArray(body))
52
+ throw unexpectedBody(source);
53
+ return body;
54
+ }
55
+ /** GETs a text body, e.g. XML. */
56
+ async function fetchText(source, url, timeout) {
57
+ return (await request(source, url, timeout)).text();
58
+ }
59
+ //# sourceMappingURL=fetch-body.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-body.js","sourceRoot":"","sources":["../../src/sources/fetch-body.ts"],"names":[],"mappings":";;AAgCA,wCAEC;AAGD,wCAIC;AAGD,0CAIC;AAGD,8BAEC;AArDD,8EAAwE;AAExE,KAAK,UAAU,OAAO,CAAC,MAAc,EAAE,GAAW,EAAE,OAAe;IACjE,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACxE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC;YACtC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YACf,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,cAAc;gBAC7B,CAAC,CAAC,mBAAmB,OAAO,KAAK;gBACjC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC;QACpB,MAAM,IAAI,oDAAuB,CAAC,GAAG,MAAM,0BAA0B,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACpG,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,oDAAuB,CAAC,GAAG,MAAM,+BAA+B,QAAQ,CAAC,MAAM,EAAE,EAAE;YAC3F,MAAM;YACN,MAAM,EAAE,QAAQ,CAAC,MAAM;SACxB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,MAAc,EAAE,GAAW,EAAE,OAAe;IACnE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IACrD,IAAI,CAAC;QACH,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,oDAAuB,CAAC,GAAG,MAAM,6BAA6B,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/F,CAAC;AACH,CAAC;AAED,SAAgB,cAAc,CAAC,MAAc;IAC3C,OAAO,IAAI,oDAAuB,CAAC,GAAG,MAAM,mCAAmC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;AAC/F,CAAC;AAED,uGAAuG;AAChG,KAAK,UAAU,cAAc,CAAI,MAAc,EAAE,GAAW,EAAE,OAAe;IAClF,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IACnD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;IACvD,OAAO,IAAW,CAAC;AACrB,CAAC;AAED,0BAA0B;AACnB,KAAK,UAAU,eAAe,CAAI,MAAc,EAAE,GAAW,EAAE,OAAe;IACnF,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IACnD,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;IACnG,OAAO,IAAS,CAAC;AACnB,CAAC;AAED,kCAAkC;AAC3B,KAAK,UAAU,SAAS,CAAC,MAAc,EAAE,GAAW,EAAE,OAAe;IAC1E,OAAO,CAAC,MAAM,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AACtD,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { CurrencyCode } from '@vendure/core';
2
+ import { ExchangeRateSource, ExchangeRateSourceResult } from '../types';
3
+ export interface FrankfurterExchangeRateSourceOptions {
4
+ /** @default 'https://api.frankfurter.dev/v1/latest' */
5
+ apiUrl?: string;
6
+ /** @default 10000 */
7
+ timeout?: number;
8
+ /** The base to ask for. The plugin re-bases either way; this only saves it a division. @default EUR */
9
+ base?: CurrencyCode;
10
+ }
11
+ /**
12
+ * @description
13
+ * [Frankfurter](https://frankfurter.dev): the ECB reference rates as JSON, in any of its currencies as
14
+ * the base. Free, no key; can be self-hosted (`apiUrl`).
15
+ */
16
+ export declare class FrankfurterExchangeRateSource implements ExchangeRateSource {
17
+ readonly name = "frankfurter";
18
+ private readonly url;
19
+ private readonly timeout;
20
+ constructor(options?: FrankfurterExchangeRateSourceOptions);
21
+ fetchRates(): Promise<ExchangeRateSourceResult>;
22
+ }
23
+ //# sourceMappingURL=frankfurter-exchange-rate-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frankfurter-exchange-rate-source.d.ts","sourceRoot":"","sources":["../../src/sources/frankfurter-exchange-rate-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAGxE,MAAM,WAAW,oCAAoC;IACnD,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uGAAuG;IACvG,IAAI,CAAC,EAAE,YAAY,CAAC;CACrB;AAQD;;;;GAIG;AACH,qBAAa,6BAA8B,YAAW,kBAAkB;IACtE,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,OAAO,GAAE,oCAAyC;IAOxD,UAAU,IAAI,OAAO,CAAC,wBAAwB,CAAC;CAatD"}
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FrankfurterExchangeRateSource = void 0;
4
+ const constants_1 = require("../constants");
5
+ const fetch_body_1 = require("./fetch-body");
6
+ /**
7
+ * @description
8
+ * [Frankfurter](https://frankfurter.dev): the ECB reference rates as JSON, in any of its currencies as
9
+ * the base. Free, no key; can be self-hosted (`apiUrl`).
10
+ */
11
+ class FrankfurterExchangeRateSource {
12
+ constructor(options = {}) {
13
+ this.name = 'frankfurter';
14
+ const url = new URL(options.apiUrl ?? 'https://api.frankfurter.dev/v1/latest');
15
+ if (options.base)
16
+ url.searchParams.set('base', options.base);
17
+ this.url = url.toString();
18
+ this.timeout = options.timeout ?? constants_1.DEFAULT_SOURCE_TIMEOUT;
19
+ }
20
+ async fetchRates() {
21
+ const body = await (0, fetch_body_1.fetchJsonObject)(this.name, this.url, this.timeout);
22
+ if (typeof body.base !== 'string' || !/^[A-Z]{3}$/.test(body.base) || !body.rates) {
23
+ throw (0, fetch_body_1.unexpectedBody)(this.name);
24
+ }
25
+ const amount = body.amount ?? 1;
26
+ // `rates[c]` is "amount base = rates[c] c", the inverse of a quote.
27
+ const quotes = Object.entries(body.rates).map(([code, rate]) => ({
28
+ currencyCode: code,
29
+ rate: amount / rate,
30
+ }));
31
+ return { base: body.base, quotes };
32
+ }
33
+ }
34
+ exports.FrankfurterExchangeRateSource = FrankfurterExchangeRateSource;
35
+ //# sourceMappingURL=frankfurter-exchange-rate-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frankfurter-exchange-rate-source.js","sourceRoot":"","sources":["../../src/sources/frankfurter-exchange-rate-source.ts"],"names":[],"mappings":";;;AACA,4CAAsD;AAEtD,6CAA+D;AAiB/D;;;;GAIG;AACH,MAAa,6BAA6B;IAKxC,YAAY,UAAgD,EAAE;QAJrD,SAAI,GAAG,aAAa,CAAC;QAK5B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,uCAAuC,CAAC,CAAC;QAC/E,IAAI,OAAO,CAAC,IAAI;YAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7D,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC1B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,kCAAsB,CAAC;IAC3D,CAAC;IAED,KAAK,CAAC,UAAU;QACd,MAAM,IAAI,GAAG,MAAM,IAAA,4BAAe,EAAkB,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACvF,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAClF,MAAM,IAAA,2BAAc,EAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;QAChC,oEAAoE;QACpE,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;YAC/D,YAAY,EAAE,IAAoB;YAClC,IAAI,EAAE,MAAM,GAAG,IAAI;SACpB,CAAC,CAAC,CAAC;QACJ,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAoB,EAAE,MAAM,EAAE,CAAC;IACrD,CAAC;CACF;AAzBD,sEAyBC"}
@@ -0,0 +1,29 @@
1
+ import { ExchangeRateSource, ExchangeRateSourceResult } from '../types';
2
+ export interface MonobankExchangeRateSourceOptions {
3
+ /** @default 'https://api.monobank.ua/bank/currency' */
4
+ apiUrl?: string;
5
+ /** @default 10000 */
6
+ timeout?: number;
7
+ /**
8
+ * Which of Monobank's rates to store: `'buy'` is what the bank pays for the currency (the lower),
9
+ * `'sell'` what it charges, `'mid'` their average. Pairs quoted only as a cross rate use that.
10
+ *
11
+ * @default 'buy'
12
+ */
13
+ side?: 'buy' | 'sell' | 'mid';
14
+ }
15
+ /**
16
+ * @description
17
+ * Monobank's public rates against the hryvnia — the bank's own buy/sell rates, refreshed through the
18
+ * day. Free, no key; cached 5 minutes and rate-limited. Base UAH.
19
+ */
20
+ export declare class MonobankExchangeRateSource implements ExchangeRateSource {
21
+ readonly name = "monobank";
22
+ private readonly apiUrl;
23
+ private readonly timeout;
24
+ private readonly side;
25
+ constructor(options?: MonobankExchangeRateSourceOptions);
26
+ fetchRates(): Promise<ExchangeRateSourceResult>;
27
+ private pick;
28
+ }
29
+ //# sourceMappingURL=monobank-exchange-rate-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monobank-exchange-rate-source.d.ts","sourceRoot":"","sources":["../../src/sources/monobank-exchange-rate-source.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAcxE,MAAM,WAAW,iCAAiC;IAChD,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;CAC/B;AAED;;;;GAIG;AACH,qBAAa,0BAA2B,YAAW,kBAAkB;IACnE,QAAQ,CAAC,IAAI,cAAc;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyB;gBAElC,OAAO,GAAE,iCAAsC;IAMrD,UAAU,IAAI,OAAO,CAAC,wBAAwB,CAAC;IAYrD,OAAO,CAAC,IAAI;CAMb"}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MonobankExchangeRateSource = void 0;
7
+ const core_1 = require("@vendure/core");
8
+ const currency_codes_1 = __importDefault(require("currency-codes"));
9
+ const constants_1 = require("../constants");
10
+ const fetch_body_1 = require("./fetch-body");
11
+ const UAH_NUMERIC_CODE = 980;
12
+ /**
13
+ * @description
14
+ * Monobank's public rates against the hryvnia — the bank's own buy/sell rates, refreshed through the
15
+ * day. Free, no key; cached 5 minutes and rate-limited. Base UAH.
16
+ */
17
+ class MonobankExchangeRateSource {
18
+ constructor(options = {}) {
19
+ this.name = 'monobank';
20
+ this.apiUrl = options.apiUrl ?? 'https://api.monobank.ua/bank/currency';
21
+ this.timeout = options.timeout ?? constants_1.DEFAULT_SOURCE_TIMEOUT;
22
+ this.side = options.side ?? 'buy';
23
+ }
24
+ async fetchRates() {
25
+ const pairs = await (0, fetch_body_1.fetchJsonArray)(this.name, this.apiUrl, this.timeout);
26
+ const quotes = pairs.flatMap((pair) => {
27
+ const currencyCode = currency_codes_1.default.number(String(pair.currencyCodeA).padStart(3, '0'))?.code;
28
+ if (pair.currencyCodeB !== UAH_NUMERIC_CODE || !currencyCode) {
29
+ return [];
30
+ }
31
+ return [{ currencyCode: currencyCode, rate: this.pick(pair) }];
32
+ });
33
+ return { base: core_1.CurrencyCode.UAH, quotes };
34
+ }
35
+ pick({ rateBuy, rateSell, rateCross }) {
36
+ if (rateBuy === undefined || rateSell === undefined)
37
+ return rateCross ?? NaN;
38
+ if (this.side === 'sell')
39
+ return rateSell;
40
+ if (this.side === 'mid')
41
+ return (rateBuy + rateSell) / 2;
42
+ return rateBuy;
43
+ }
44
+ }
45
+ exports.MonobankExchangeRateSource = MonobankExchangeRateSource;
46
+ //# sourceMappingURL=monobank-exchange-rate-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monobank-exchange-rate-source.js","sourceRoot":"","sources":["../../src/sources/monobank-exchange-rate-source.ts"],"names":[],"mappings":";;;;;;AAAA,wCAA6C;AAC7C,oEAA2C;AAC3C,4CAAsD;AAEtD,6CAA8C;AAE9C,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAyB7B;;;;GAIG;AACH,MAAa,0BAA0B;IAMrC,YAAY,UAA6C,EAAE;QALlD,SAAI,GAAG,UAAU,CAAC;QAMzB,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,uCAAuC,CAAC;QACxE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,kCAAsB,CAAC;QACzD,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,KAAK,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,UAAU;QACd,MAAM,KAAK,GAAG,MAAM,IAAA,2BAAc,EAAe,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACvF,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YACpC,MAAM,YAAY,GAAG,wBAAa,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC;YAC7F,IAAI,IAAI,CAAC,aAAa,KAAK,gBAAgB,IAAI,CAAC,YAAY,EAAE,CAAC;gBAC7D,OAAO,EAAE,CAAC;YACZ,CAAC;YACD,OAAO,CAAC,EAAE,YAAY,EAAE,YAA4B,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjF,CAAC,CAAC,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,mBAAY,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC;IAC5C,CAAC;IAEO,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAgB;QACzD,IAAI,OAAO,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,SAAS,IAAI,GAAG,CAAC;QAC7E,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,QAAQ,CAAC;QAC1C,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK;YAAE,OAAO,CAAC,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QACzD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AA9BD,gEA8BC"}
@@ -0,0 +1,20 @@
1
+ import { ExchangeRateSource, ExchangeRateSourceResult } from '../types';
2
+ export interface NbuExchangeRateSourceOptions {
3
+ /** @default 'https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?json' */
4
+ apiUrl?: string;
5
+ /** @default 10000 */
6
+ timeout?: number;
7
+ }
8
+ /**
9
+ * @description
10
+ * The National Bank of Ukraine's official rates, set once per business day. The list also carries
11
+ * metals and the SDR, which are dropped because they are not Vendure currencies.
12
+ */
13
+ export declare class NbuExchangeRateSource implements ExchangeRateSource {
14
+ readonly name = "nbu";
15
+ private readonly apiUrl;
16
+ private readonly timeout;
17
+ constructor(options?: NbuExchangeRateSourceOptions);
18
+ fetchRates(): Promise<ExchangeRateSourceResult>;
19
+ }
20
+ //# sourceMappingURL=nbu-exchange-rate-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nbu-exchange-rate-source.d.ts","sourceRoot":"","sources":["../../src/sources/nbu-exchange-rate-source.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AASxE,MAAM,WAAW,4BAA4B;IAC3C,mFAAmF;IACnF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,qBAAa,qBAAsB,YAAW,kBAAkB;IAC9D,QAAQ,CAAC,IAAI,SAAS;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,OAAO,GAAE,4BAAiC;IAKhD,UAAU,IAAI,OAAO,CAAC,wBAAwB,CAAC;CAKtD"}