mirror of
https://github.com/InvoiceShelf/InvoiceShelf.git
synced 2026-08-04 15:12:12 +00:00
crypto.randomUUID() and navigator.clipboard are both [SecureContext]- gated, so neither exists on a plain-HTTP origin that isn't localhost. That covers the dev host (http://invoiceshelf.test) and any self-hosted install reached over a hostname or LAN IP — a large share of them. generateClientId() called crypto.randomUUID() unguarded. It runs during Pinia store construction via the invoice, estimate and recurring-invoice stub factories, so on those origins it threw a TypeError before the store existed and took the document screens down with it. The value is only a placeholder identity for a row that has no server id yet — the server assigns the real one on save, which is why DocumentItem and DocumentTax type it `number | string`. It never needed randomness, so it is now a session counter: no crypto, no fallback branch, works everywhere. PaymentDropdown.copyPdfUrl() had a textarea fallback attached with .catch(), which cannot fire — on a non-secure origin navigator.clipboard is undefined, so `.writeText` throws on property access before any promise exists. Test up front instead, matching the guard the invoice and estimate dropdowns already use.
18 lines
820 B
TypeScript
18 lines
820 B
TypeScript
let counter = 0
|
|
|
|
/**
|
|
* Local identity for a row that does not exist server-side yet — a new invoice
|
|
* item, a new tax line. The server assigns the real numeric id on save (hence
|
|
* `id: number | string` on DocumentItem/DocumentTax), so this only has to stay
|
|
* unique within the page session, which a counter guarantees outright.
|
|
*
|
|
* Deliberately not `crypto.randomUUID()`: that is `[SecureContext]`-gated, so it
|
|
* is undefined on any plain-HTTP origin that isn't localhost. That covers the
|
|
* dev host (`http://invoiceshelf.test`) and self-hosted installs reached over a
|
|
* hostname or LAN IP — where calling it threw during Pinia store construction
|
|
* and took the document screens down with it. Nothing here needs randomness.
|
|
*/
|
|
export function generateClientId(): string {
|
|
return `client-${++counter}`
|
|
}
|