From 281cb3989dd1e0fca29c2887df2fceccdd0e2d6c Mon Sep 17 00:00:00 2001 From: Mattsson <111893710+mattssonn@users.noreply.github.com> Date: Mon, 3 Aug 2026 19:28:15 +0200 Subject: [PATCH] fix(build): break Turbopack chunk-name hash collision from #1385's import edge (#1394) Since the #1385 squash-merge every production build failed with 'Two or more assets with different content were emitted to the same output path' on [root-of-the-server]__1ge0sz5._.js: two distinct server chunk groups (an AWS smithy helper chunk and the withRouteContext auth chunk) hash to the same chunk name. The graph change that tipped the chunk layout into the colliding state was entity-mapper.ts (arcim-migration extension entry graph) importing lib/vat/supplier-invoice-line-checks, which drags lib/money into the extension root. Move normalizeVatRateToFraction into an import-free leaf module (lib/vat/vat-rate-unit.ts), re-export it from supplier-invoice-line-checks for all existing callers, and point entity-mapper at the leaf. Behavior is unchanged (511 targeted tests pass); the server chunk graph returns to the pre-#1385 shape that builds cleanly. Verified: npm run build fails on ff864ad3d and passes with this change. Co-authored-by: Claude Fable 5 --- .../arcim-migration/lib/entity-mapper.ts | 2 +- lib/vat/supplier-invoice-line-checks.ts | 20 ++++++------------ lib/vat/vat-rate-unit.ts | 21 +++++++++++++++++++ 3 files changed, 28 insertions(+), 15 deletions(-) create mode 100644 lib/vat/vat-rate-unit.ts diff --git a/extensions/general/arcim-migration/lib/entity-mapper.ts b/extensions/general/arcim-migration/lib/entity-mapper.ts index 815de490..2b12a770 100644 --- a/extensions/general/arcim-migration/lib/entity-mapper.ts +++ b/extensions/general/arcim-migration/lib/entity-mapper.ts @@ -8,7 +8,7 @@ import type { SupabaseClient } from '@supabase/supabase-js' import { fetchExchangeRate } from '@/lib/currency/riksbanken' import { encryptCustomerPersonalNumber } from '@/lib/customers/protect-personal-number' -import { normalizeVatRateToFraction } from '@/lib/vat/supplier-invoice-line-checks' +import { normalizeVatRateToFraction } from '@/lib/vat/vat-rate-unit' import type { Currency, CustomerType, ExchangeRate, SupplierType, VatTreatment } from '@/types' import type { CustomerDto, diff --git a/lib/vat/supplier-invoice-line-checks.ts b/lib/vat/supplier-invoice-line-checks.ts index 29119416..1a6c013c 100644 --- a/lib/vat/supplier-invoice-line-checks.ts +++ b/lib/vat/supplier-invoice-line-checks.ts @@ -2,6 +2,7 @@ // Kept free of React so the rules can be unit-tested and reused. import { roundOre } from '@/lib/money' +import { normalizeVatRateToFraction } from './vat-rate-unit' // Only 25/12/6/0 % are legal Swedish VAT rates (ML 2023:200). The supplier // invoice form stores rates as decimal fractions (0.25 = 25 %); this list is @@ -17,20 +18,11 @@ export function isLegalVatRate(rate: number): boolean { return LEGAL_VAT_RATES.includes(rate) } -/** - * Convert a supplier-invoice VAT rate to the database's decimal-fraction - * unit without changing the underlying rate. Values above 1 are interpreted - * as percentages, while values already between 0 and 1 pass through. This is - * intentionally a unit normalizer, not a Swedish-rate validator: imported - * foreign VAT such as 19 % must remain 0.19 instead of being rewritten. - */ -export function normalizeVatRateToFraction(rate: unknown): number { - const n = Number(rate) - if (!Number.isFinite(n) || n < 0) return 0 - - const fraction = n > 1 ? n / 100 : n - return fraction <= 1 ? fraction : 0 -} +// normalizeVatRateToFraction lives in the import-free leaf module +// vat-rate-unit.ts so extension entry graphs can use it without pulling in +// this file's lib/money dependency; re-exported here so existing callers +// keep their import path. +export { normalizeVatRateToFraction } /** * Normalize a VAT rate that may arrive percent-shaped (25, 12, 6: the AI diff --git a/lib/vat/vat-rate-unit.ts b/lib/vat/vat-rate-unit.ts new file mode 100644 index 00000000..ce5d3141 --- /dev/null +++ b/lib/vat/vat-rate-unit.ts @@ -0,0 +1,21 @@ +// Leaf module on purpose: imported by extension entry graphs (arcim-migration +// entity mapper) where pulling in supplier-invoice-line-checks' dependencies +// (lib/money) shifted the server chunk graph into a Turbopack chunk-name hash +// collision ("Two or more assets with different content were emitted to the +// same output path", first seen on the #1385 merge). Keep this file free of +// imports; supplier-invoice-line-checks re-exports it for all other callers. + +/** + * Convert a supplier-invoice VAT rate to the database's decimal-fraction + * unit without changing the underlying rate. Values above 1 are interpreted + * as percentages, while values already between 0 and 1 pass through. This is + * intentionally a unit normalizer, not a Swedish-rate validator: imported + * foreign VAT such as 19 % must remain 0.19 instead of being rewritten. + */ +export function normalizeVatRateToFraction(rate: unknown): number { + const n = Number(rate) + if (!Number.isFinite(n) || n < 0) return 0 + + const fraction = n > 1 ? n / 100 : n + return fraction <= 1 ? fraction : 0 +}