@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,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NbuExchangeRateSource = void 0;
4
+ const core_1 = require("@vendure/core");
5
+ const constants_1 = require("../constants");
6
+ const fetch_body_1 = require("./fetch-body");
7
+ /**
8
+ * @description
9
+ * The National Bank of Ukraine's official rates, set once per business day. The list also carries
10
+ * metals and the SDR, which are dropped because they are not Vendure currencies.
11
+ */
12
+ class NbuExchangeRateSource {
13
+ constructor(options = {}) {
14
+ this.name = 'nbu';
15
+ this.apiUrl = options.apiUrl ?? 'https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?json';
16
+ this.timeout = options.timeout ?? constants_1.DEFAULT_SOURCE_TIMEOUT;
17
+ }
18
+ async fetchRates() {
19
+ const rows = await (0, fetch_body_1.fetchJsonArray)(this.name, this.apiUrl, this.timeout);
20
+ const quotes = rows.map((row) => ({ currencyCode: row.cc, rate: row.rate }));
21
+ return { base: core_1.CurrencyCode.UAH, quotes };
22
+ }
23
+ }
24
+ exports.NbuExchangeRateSource = NbuExchangeRateSource;
25
+ //# sourceMappingURL=nbu-exchange-rate-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nbu-exchange-rate-source.js","sourceRoot":"","sources":["../../src/sources/nbu-exchange-rate-source.ts"],"names":[],"mappings":";;;AAAA,wCAA6C;AAC7C,4CAAsD;AAEtD,6CAA8C;AAe9C;;;;GAIG;AACH,MAAa,qBAAqB;IAKhC,YAAY,UAAwC,EAAE;QAJ7C,SAAI,GAAG,KAAK,CAAC;QAKpB,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,mEAAmE,CAAC;QACpG,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,kCAAsB,CAAC;IAC3D,CAAC;IAED,KAAK,CAAC,UAAU;QACd,MAAM,IAAI,GAAG,MAAM,IAAA,2BAAc,EAAU,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACjF,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,YAAY,EAAE,GAAG,CAAC,EAAkB,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC7F,OAAO,EAAE,IAAI,EAAE,mBAAY,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC;IAC5C,CAAC;CACF;AAfD,sDAeC"}
@@ -0,0 +1,20 @@
1
+ import { CurrencyCode } from '@vendure/core';
2
+ import { ExchangeRateSource, ExchangeRateSourceResult } from '../types';
3
+ export interface StaticExchangeRateSourceOptions {
4
+ /** The currency `rates` are expressed in. */
5
+ base: CurrencyCode;
6
+ /** Units of `base` per one unit of each currency. */
7
+ rates: Partial<Record<CurrencyCode, number>>;
8
+ }
9
+ /**
10
+ * @description
11
+ * Fixed rates, for a shop that keys them in by hand, for development and for tests:
12
+ * `new StaticExchangeRateSource({ base: CurrencyCode.USD, rates: { EUR: 1.12, GBP: 1.32 } })`.
13
+ */
14
+ export declare class StaticExchangeRateSource implements ExchangeRateSource {
15
+ config: StaticExchangeRateSourceOptions;
16
+ readonly name = "static";
17
+ constructor(config: StaticExchangeRateSourceOptions);
18
+ fetchRates(): Promise<ExchangeRateSourceResult>;
19
+ }
20
+ //# sourceMappingURL=static-exchange-rate-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static-exchange-rate-source.d.ts","sourceRoot":"","sources":["../../src/sources/static-exchange-rate-source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAExE,MAAM,WAAW,+BAA+B;IAC9C,6CAA6C;IAC7C,IAAI,EAAE,YAAY,CAAC;IACnB,qDAAqD;IACrD,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;CAC9C;AAED;;;;GAIG;AACH,qBAAa,wBAAyB,YAAW,kBAAkB;IAG9C,MAAM,EAAE,+BAA+B;IAF1D,QAAQ,CAAC,IAAI,YAAY;gBAEN,MAAM,EAAE,+BAA+B;IAE1D,UAAU,IAAI,OAAO,CAAC,wBAAwB,CAAC;CAOhD"}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StaticExchangeRateSource = void 0;
4
+ /**
5
+ * @description
6
+ * Fixed rates, for a shop that keys them in by hand, for development and for tests:
7
+ * `new StaticExchangeRateSource({ base: CurrencyCode.USD, rates: { EUR: 1.12, GBP: 1.32 } })`.
8
+ */
9
+ class StaticExchangeRateSource {
10
+ constructor(config) {
11
+ this.config = config;
12
+ this.name = 'static';
13
+ }
14
+ fetchRates() {
15
+ const quotes = Object.entries(this.config.rates).map(([currencyCode, rate]) => ({
16
+ currencyCode: currencyCode,
17
+ rate: rate,
18
+ }));
19
+ return Promise.resolve({ base: this.config.base, quotes });
20
+ }
21
+ }
22
+ exports.StaticExchangeRateSource = StaticExchangeRateSource;
23
+ //# sourceMappingURL=static-exchange-rate-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static-exchange-rate-source.js","sourceRoot":"","sources":["../../src/sources/static-exchange-rate-source.ts"],"names":[],"mappings":";;;AAUA;;;;GAIG;AACH,MAAa,wBAAwB;IAGnC,YAAmB,MAAuC;QAAvC,WAAM,GAAN,MAAM,CAAiC;QAFjD,SAAI,GAAG,QAAQ,CAAC;IAEoC,CAAC;IAE9D,UAAU;QACR,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;YAC9E,YAAY,EAAE,YAA4B;YAC1C,IAAI,EAAE,IAAc;SACrB,CAAC,CAAC,CAAC;QACJ,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7D,CAAC;CACF;AAZD,4DAYC"}
@@ -0,0 +1,64 @@
1
+ import type { CurrencyCode, ID, InjectableStrategy, RequestContext, ScheduledTaskConfig } from '@vendure/core';
2
+ /** One fetched rate: `rate` units of the source's base currency buy one unit of `currencyCode`. */
3
+ export interface ExchangeRateQuote {
4
+ currencyCode: CurrencyCode;
5
+ rate: number;
6
+ }
7
+ /** What a source fetched: its quotes, and the base currency they are expressed in. */
8
+ export interface ExchangeRateSourceResult {
9
+ base: CurrencyCode;
10
+ quotes: ExchangeRateQuote[];
11
+ }
12
+ /**
13
+ * @description
14
+ * Where the rates come from. `fetchRates` returns every pair the source has, in whatever base it quotes
15
+ * in; the plugin re-bases them onto the shop's base currency, drops unusable quotes and upserts the rest
16
+ * by code. An admin's custom rate is kept unless the base currency changes.
17
+ *
18
+ * Throw (ideally an {@link ExchangeRateSourceError}) when the source cannot be read — never return no
19
+ * quotes to mean "failed" — and bound the request with a timeout: the API server waits for the first
20
+ * fetch on boot. The plugin calls `init(injector)` on bootstrap and `destroy()` on shutdown.
21
+ */
22
+ export interface ExchangeRateSource extends InjectableStrategy {
23
+ /** Short name for logs, e.g. `'ecb'`. */
24
+ readonly name: string;
25
+ fetchRates(ctx: RequestContext): Promise<ExchangeRateSourceResult>;
26
+ }
27
+ export interface ExchangeRatesPluginOptions {
28
+ /** Where the rates come from: `EcbExchangeRateSource`, `FrankfurterExchangeRateSource`, … or your own. */
29
+ source: ExchangeRateSource;
30
+ /**
31
+ * The currency rates are expressed in: `rate` = units of it per one unit of a currency.
32
+ *
33
+ * @default the default channel's `defaultCurrencyCode`
34
+ */
35
+ baseCurrency?: CurrencyCode;
36
+ /**
37
+ * The scheduled refresh. `false` leaves the task out; `CurrencyExchangeRateSyncService` can still
38
+ * be called.
39
+ *
40
+ * @default { schedule: '40 2-23/3 * * *' } — every 3 hours
41
+ */
42
+ sync?: {
43
+ schedule?: ScheduledTaskConfig['schedule'];
44
+ } | false;
45
+ }
46
+ /** {@link ExchangeRatesPluginOptions} with every default applied. */
47
+ export interface ResolvedExchangeRatesPluginOptions {
48
+ source: ExchangeRateSource;
49
+ baseCurrency?: CurrencyCode;
50
+ sync: {
51
+ schedule: ScheduledTaskConfig['schedule'];
52
+ } | false;
53
+ }
54
+ /** Mirrors `UpdateCurrencyExchangeRateInput` in `api-extensions.ts`. */
55
+ export interface UpdateCurrencyExchangeRateInput {
56
+ id: ID;
57
+ enabled: boolean;
58
+ useCustomRate: boolean;
59
+ customRate?: number | null;
60
+ }
61
+ export interface MutationUpdateCurrencyExchangeRateArgs {
62
+ input: UpdateCurrencyExchangeRateInput;
63
+ }
64
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,EAAE,EAAE,kBAAkB,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAE/G,mGAAmG;AACnG,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,YAAY,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,sFAAsF;AACtF,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,EAAE,iBAAiB,EAAE,CAAC;CAC7B;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,kBAAmB,SAAQ,kBAAkB;IAC5D,yCAAyC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;CACpE;AAED,MAAM,WAAW,0BAA0B;IACzC,0GAA0G;IAC1G,MAAM,EAAE,kBAAkB,CAAC;IAC3B;;;;OAIG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;;;OAKG;IACH,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,mBAAmB,CAAC,UAAU,CAAC,CAAA;KAAE,GAAG,KAAK,CAAC;CAC/D;AAED,qEAAqE;AACrE,MAAM,WAAW,kCAAkC;IACjD,MAAM,EAAE,kBAAkB,CAAC;IAC3B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,IAAI,EAAE;QAAE,QAAQ,EAAE,mBAAmB,CAAC,UAAU,CAAC,CAAA;KAAE,GAAG,KAAK,CAAC;CAC7D;AAED,wEAAwE;AACxE,MAAM,WAAW,+BAA+B;IAC9C,EAAE,EAAE,EAAE,CAAC;IACP,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,sCAAsC;IACrD,KAAK,EAAE,+BAA+B,CAAC;CACxC"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,96 @@
1
+ {
2
+ "name": "@uplab/vendure-plugin-exchange-rates",
3
+ "version": "0.1.0",
4
+ "description": "Exchange rates for Vendure in any base currency, from the ECB, Frankfurter, Monobank, the NBU or your own source, overridable per currency in the dashboard",
5
+ "license": "MIT",
6
+ "author": "Uplab",
7
+ "homepage": "https://github.com/Uplab/uplab-vendure-plugins/tree/main/packages/vendure-plugin-exchange-rates#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/Uplab/uplab-vendure-plugins.git",
11
+ "directory": "packages/vendure-plugin-exchange-rates"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/Uplab/uplab-vendure-plugins/issues"
15
+ },
16
+ "keywords": [
17
+ "vendure",
18
+ "vendure-plugin",
19
+ "currency",
20
+ "exchange-rates",
21
+ "multi-currency",
22
+ "ecb",
23
+ "frankfurter",
24
+ "monobank",
25
+ "nbu"
26
+ ],
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "type": "commonjs",
31
+ "main": "./dist/index.js",
32
+ "types": "./dist/index.d.ts",
33
+ "exports": {
34
+ ".": {
35
+ "types": "./dist/index.d.ts",
36
+ "default": "./dist/index.js"
37
+ },
38
+ "./package.json": "./package.json"
39
+ },
40
+ "files": [
41
+ "dist",
42
+ "README.md",
43
+ "CHANGELOG.md"
44
+ ],
45
+ "scripts": {
46
+ "build": "rimraf dist && tsc -p tsconfig.build.json && node ../../scripts/copy-dashboard.mjs",
47
+ "typecheck": "tsc -p tsconfig.json --noEmit && node ../../scripts/typecheck-dashboard.mjs",
48
+ "test": "vitest run"
49
+ },
50
+ "dependencies": {
51
+ "currency-codes": "^2.2.0",
52
+ "graphql-tag": "^2.12.6"
53
+ },
54
+ "peerDependencies": {
55
+ "@lingui/react": "^5.0.0",
56
+ "@nestjs/common": "^11.0.0",
57
+ "@nestjs/core": "^11.0.0",
58
+ "@nestjs/graphql": "^13.0.0",
59
+ "@vendure/core": "^3.7.0",
60
+ "@vendure/dashboard": "^3.7.0",
61
+ "react": "^19.0.0",
62
+ "typeorm": "^0.3.21"
63
+ },
64
+ "peerDependenciesMeta": {
65
+ "@lingui/react": {
66
+ "optional": true
67
+ },
68
+ "@vendure/dashboard": {
69
+ "optional": true
70
+ },
71
+ "react": {
72
+ "optional": true
73
+ }
74
+ },
75
+ "devDependencies": {
76
+ "@lingui/react": "^5.9.5",
77
+ "@nestjs/common": "^11.0.12",
78
+ "@nestjs/core": "^11.2.1",
79
+ "@nestjs/graphql": "^13.0.0",
80
+ "@types/react": "^19.0.0",
81
+ "@vendure/core": "3.7.2",
82
+ "@vendure/dashboard": "3.7.2",
83
+ "@vendure/testing": "3.7.2",
84
+ "graphql": "^16.11.0",
85
+ "react": "^19.0.0",
86
+ "rimraf": "^6.0.1",
87
+ "rxjs": "^7.8.1",
88
+ "typeorm": "^0.3.21",
89
+ "typescript": "^5.8.3",
90
+ "unplugin-swc": "^1.5.7",
91
+ "vitest": "^4.0.0"
92
+ },
93
+ "engines": {
94
+ "node": ">=20.0.0"
95
+ }
96
+ }