Refactor without changing the public API.
The kind of refactor you can actually merge on a Tuesday — internal cleanup, external contract preserved.
You have code that works but is a mess internally. You'd love to rewrite it. You can't afford to touch every caller. This prompt does the safe version: refactor the internals while preserving the public API exactly, so nothing downstream has to change.
THE PROMPT
Refactor the following code with one strict constraint: the public API cannot change. Any function, class, or export that is imported by other files stays with the same name, same signature, same return shape. Internal helpers and implementation are yours to change. I'll paste the code below. Return: **Refactored code** — the new implementation, in a single code block. Add a brief comment above any non-obvious internal helper. **What changed** — bullet list of the internal changes. Keep it concise; anyone reviewing this should understand the intent in 30 seconds. **What didn't change** — bullet list of the public API surface, so I can grep and confirm nothing external needs updating. **Test recommendation** — one line: "Existing tests should pass with no changes" (if so), or "Existing tests need updating in [file/way]" (if the public behavior did shift in a subtle way and you noticed). If the refactor would meaningfully improve things only by changing the API, name that at the top and I'll decide whether to lift the constraint. Code: [PASTE CODE]
**Refactored code**
```ts
// unchanged export
export function calculateShipping(order: Order): ShippingQuote { ... }
// internal — was a 90-line inline calculation
function selectCarrier(order: Order): Carrier { ... }
function computeWeight(items: Item[]): Weight { ... }
function baseFor(carrier: Carrier, weight: Weight, zone: Zone): USD { ... }
```
**What changed**
- Extracted three named helpers from what was previously an inline switch statement, so the code documents its own logic.
- Replaced the manual weight loop with a reduce, which surfaced a bug: fractional weights were being rounded to integers per-item instead of once at the end.
- Dropped the unused `Region` parameter that had been threaded through three functions.
**What didn't change**
- `calculateShipping(order: Order): ShippingQuote` — same name, same signature, same return.
- All types exported from this module are unchanged.
**Test recommendation**
Existing tests should pass with no changes, but the fractional-weight bug means at least one existing test may have been asserting the wrong number. Run the suite; if a test fails, verify the new answer is correct before "fixing" the test.