@reactionary/fake 0.10.23 → 0.10.25

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.
@@ -16,6 +16,7 @@ import {
16
16
  Reactionary,
17
17
  success
18
18
  } from "@reactionary/core";
19
+ import { calcSeed } from "../utilities/seed.js";
19
20
  class FakeInventoryCapability extends InventoryCapability {
20
21
  config;
21
22
  factory;
@@ -25,16 +26,14 @@ class FakeInventoryCapability extends InventoryCapability {
25
26
  this.factory = factory;
26
27
  }
27
28
  async getBySKU(payload) {
28
- let hash = 0;
29
- for (let i = 0; i < payload.variant.sku.length; i++) {
30
- hash = (hash << 5) - hash + payload.variant.sku.charCodeAt(i);
31
- hash &= hash;
32
- }
29
+ const seedString = payload.variant.sku + (payload.fulfilmentCenter?.key ?? "");
30
+ const seed = calcSeed(seedString);
33
31
  const generator = new Faker({
34
- seed: hash || 42,
32
+ seed,
35
33
  locale: [en, base]
36
34
  });
37
- const quantity = generator.number.int({ min: 0, max: 100 });
35
+ const isOutOfStock = generator.datatype.boolean({ probability: 0.1 });
36
+ const quantity = isOutOfStock ? 0 : generator.number.int({ min: 1, max: 100 });
38
37
  const status = quantity > 0 ? "inStock" : "outOfStock";
39
38
  const result = {
40
39
  identifier: {
@@ -22,6 +22,47 @@ class FakePriceCapability extends PriceCapability {
22
22
  config;
23
23
  faker;
24
24
  factory;
25
+ EXCHANGE_RATES = {
26
+ USD: 1,
27
+ // USD-base rates published on 2026-09-28.
28
+ ALL: 80.77663447,
29
+ AMD: 364.40085393,
30
+ AZN: 1.70002087,
31
+ BAM: 1.71729191,
32
+ BYN: 3.02436738,
33
+ CHF: 0.82937207,
34
+ CZK: 21.40268821,
35
+ DKK: 6.56376981,
36
+ EUR: 0.87803741,
37
+ FOK: 6.56376981,
38
+ GBP: 0.75495717,
39
+ GEL: 2.59828739,
40
+ GGP: 0.75495717,
41
+ GIP: 0.75495717,
42
+ HUF: 321.3111657,
43
+ IMP: 0.75495717,
44
+ ISK: 120.29041481,
45
+ JEP: 0.75495717,
46
+ MDL: 17.7583979,
47
+ MKD: 54.07860616,
48
+ NOK: 9.51139889,
49
+ PLN: 3.83998104,
50
+ RON: 4.6300027,
51
+ RSD: 103.15758559,
52
+ RUB: 84.38052987,
53
+ SEK: 9.92541411,
54
+ TRY: 48.97845183,
55
+ UAH: 44.79455454
56
+ };
57
+ CURRENCY_DECIMAL_PLACES = {
58
+ ISK: 0
59
+ };
60
+ CURRENCY_PRICE_ENDINGS = {
61
+ DKK: [0, 50, 95],
62
+ EUR: [0, 90, 95],
63
+ NOK: [0, 90],
64
+ SEK: [0, 90]
65
+ };
25
66
  constructor(config, cache, context, factory) {
26
67
  super(cache, context);
27
68
  this.config = config;
@@ -41,20 +82,22 @@ class FakePriceCapability extends PriceCapability {
41
82
  price = price * this.faker.number.float({ min: 0.5, max: 0.9 });
42
83
  }
43
84
  }
85
+ const currency = this.context.languageContext.currencyCode;
86
+ price = this.roundCurrencyAmount(price * (this.EXCHANGE_RATES[currency] ?? 1), currency);
44
87
  const tiers = [];
45
88
  if (variantSku.includes("with-tiers")) {
46
89
  tiers.push({
47
90
  minimumQuantity: this.faker.number.int({ min: 2, max: 5 }),
48
91
  price: {
49
- value: price * 0.8,
50
- currency: this.context.languageContext.currencyCode
92
+ value: this.roundCurrencyAmount(price * 0.8, currency),
93
+ currency
51
94
  }
52
95
  });
53
96
  tiers.push({
54
97
  minimumQuantity: this.faker.number.int({ min: 6, max: 10 }),
55
98
  price: {
56
- value: price * 0.6,
57
- currency: this.context.languageContext.currencyCode
99
+ value: this.roundCurrencyAmount(price * 0.6, currency),
100
+ currency
58
101
  }
59
102
  });
60
103
  }
@@ -66,12 +109,27 @@ class FakePriceCapability extends PriceCapability {
66
109
  },
67
110
  unitPrice: {
68
111
  value: price,
69
- currency: this.context.languageContext.currencyCode
112
+ currency
70
113
  },
71
114
  onSale,
72
115
  tieredPrices: tiers
73
116
  };
74
117
  }
118
+ roundCurrencyAmount(amount, currency) {
119
+ const endings = this.CURRENCY_PRICE_ENDINGS[currency];
120
+ if (endings) {
121
+ const wholeAmount = Math.floor(amount);
122
+ const candidates = [wholeAmount, wholeAmount + 1].flatMap(
123
+ (whole) => endings.map((ending) => whole + ending / 100)
124
+ );
125
+ return candidates.reduce(
126
+ (closest, candidate) => Math.abs(candidate - amount) < Math.abs(closest - amount) ? candidate : closest
127
+ );
128
+ }
129
+ const decimalPlaces = this.CURRENCY_DECIMAL_PLACES[currency] ?? 2;
130
+ const multiplier = 10 ** decimalPlaces;
131
+ return Math.round((amount + Number.EPSILON) * multiplier) / multiplier;
132
+ }
75
133
  async getListPrice(payload) {
76
134
  const base2 = payload.variant.sku === "unknown-sku" ? this.createEmptyPriceResult(payload.variant.sku) : this.createPrice(payload.variant.sku, "list");
77
135
  return success(this.factory.parsePrice(this.context, base2));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reactionary/fake",
3
- "version": "0.10.23",
3
+ "version": "0.10.25",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "types": "./src/index.d.ts",
@@ -9,7 +9,7 @@
9
9
  "url": "git+https://github.com/Solteq/reactionary.git"
10
10
  },
11
11
  "dependencies": {
12
- "@reactionary/core": "0.10.23",
12
+ "@reactionary/core": "0.10.25",
13
13
  "zod": "4.1.9",
14
14
  "@faker-js/faker": "^9.8.0"
15
15
  },
@@ -6,8 +6,12 @@ export declare class FakePriceCapability<TFactory extends PriceFactory = FakePri
6
6
  protected config: FakeConfiguration;
7
7
  protected faker: Faker;
8
8
  protected factory: PriceFactoryWithOutput<TFactory>;
9
+ protected EXCHANGE_RATES: Record<string, number>;
10
+ protected CURRENCY_DECIMAL_PLACES: Record<string, number>;
11
+ protected CURRENCY_PRICE_ENDINGS: Record<string, number[]>;
9
12
  constructor(config: FakeConfiguration, cache: Cache, context: RequestContext, factory: PriceFactoryWithOutput<TFactory>);
10
13
  protected createPrice(variantSku: string, mode: 'list' | 'customer'): Price;
14
+ protected roundCurrencyAmount(amount: number, currency: string): number;
11
15
  getListPrice(payload: ListPriceQuery): Promise<Result<PriceFactoryOutput<TFactory>>>;
12
16
  getCustomerPrice(payload: CustomerPriceQuery): Promise<Result<PriceFactoryOutput<TFactory>>>;
13
17
  }