An order note fits a character-count limit but exceeds a downstream byte budget. Cutting its encoded bytes at an arbitrary position can split a multibyte sequence. For a Shopify 3PL review screen, build an explicitly shortened preview while preserving the complete original instruction.
The TextEncoder encode() method returns UTF-8 bytes. The example below counts those bytes one Unicode code point at a time. It rejects ill-formed input using isWellFormed(), which detects lone surrogates.
Return the shortened state with the preview
This is a local display helper. It must not replace the original packing instruction or silently shorten an outbound message. It returns the full byte count and a flag so the interface can offer the complete text separately.
'use strict';
const assert = require('node:assert/strict');
const encoder = new TextEncoder();
function notePreview(text, maxBytes) {
if (typeof text !== 'string' || !text.isWellFormed()) {
throw new Error('Well-formed text required');
}
if (!Number.isSafeInteger(maxBytes) || maxBytes < 0) {
throw new Error('Nonnegative safe byte budget required');
}
let preview = '', used = 0;
for (const point of text) {
const size = encoder.encode(point).length;
if (used + size > maxBytes) break;
preview += point;
used += size;
}
return { preview, shortened: preview !== text,
fullBytes: encoder.encode(text).length };
}
const text = 'A📦ä¸Z';
const expected = ['', 'A', 'A', 'A', 'A', 'A📦', 'A📦',
'A📦', 'A📦ä¸', text];
for (let budget = 0; budget <= 9; budget++) {
const result = notePreview(text, budget);
const bytes = encoder.encode(result.preview);
assert.equal(result.preview, expected[budget]);
assert.ok(bytes.length <= budget);
assert.equal(new TextDecoder('utf-8', { fatal: true }).decode(bytes),
result.preview);
assert.equal(result.shortened, budget < 9);
assert.equal(result.fullBytes, 9);
}
assert.equal(text, 'A📦ä¸Z');
assert.deepEqual(notePreview('', 0),
{ preview: '', shortened: false, fullBytes: 0 });
for (const budget of [-1, 1.5, NaN, '4']) {
assert.throws(() => notePreview(text, budget));
}
assert.throws(() => notePreview('\uD800', 4));
console.log('UTF-8 preview boundary checks passed');
Save as note-preview.cjs and run node note-preview.cjs with Node.js 24. The checks exercise every byte boundary of ASCII, an emoji and a Chinese code point, plus invalid budgets and malformed input. No request is sent.
Preserve the operational text
A drop shipping review may show a supplier instruction, while a shopify fulfillment screen may show a seller-approved packing note. Keep the original value available and mark a shortened display clearly. If a real receiving API rejects an overlong field, resolve that error through its documented contract instead of sending this preview.
For China fulfillment, agree whether a limit counts bytes, code points or another unit. A China 3PL interface should also specify the encoding. This helper does not preserve whole grapheme clusters: combining marks and joined emoji can span multiple code points. It is unsuitable when those display boundaries must remain intact.
In a hypothetical brief named “International Fulfillment for Folligen,” document the actual field contract before using a display helper. I work with YX Fulfillment; its Shopify handover guide provides related business context. This executable example is not a deployed connector and does not establish a tested store integration.
Warehouse workstations and equipment.

Top comments (1)
Keeping the shortened flag separate from the original packing instruction is the important bit here; a preview must never become the warehouse payload by accident. For a Hebrew/English hardware store on Next.js, I'd also include Hebrew with niqqud in the boundary tests, since valid UTF-8 can still leave a visually incomplete character. Your grapheme-cluster caveat is a useful distinction: byte-safe and display-safe aren't the same requirement.