Skip to content
Astera Technology

Build display names from declared person or company parts

Retain name components instead of guessing them from one string.

Download complete case notes and answer keys ↓

Source contract and expected records

This is an original, fully synthetic mapping example. Inputs are plain, acyclic JSON-shaped records with the fields shown; the canonical shape and rejection codes belong to this example. Adapt the contract before using a different source.

The source explicitly declares person or company. Persons require nonblank given and family names; honorific is optional text. Compose the display in the local order honorific, given, family, trimming display parts only. Companies use organisation text. Preserve original parts, including whitespace. Other kinds are rejected.

Editable synthetic mapping cases
CaseInput record (JSON)Expected output (JSON)
Compose supplied person parts{"kind":"person","given":"Ada","family":"Chan","honorific":"Ms"}{"ok":true,"value":{"kind":"person","display":"Ms Ada Chan","parts":{"honorific":"Ms","given":"Ada","family":"Chan"}}}
Reject unknown name kind{"kind":"nickname","given":"Ada"}{"ok":false,"error":"NAME_KIND"}
Preserve company kind{"kind":"company","organisation":"Demo Co"}{"ok":true,"value":{"kind":"company","display":"Demo Co","parts":{"organisation":"Demo Co"}}}
Download editable CSV ↓

Run the local transformation

Run the complete example as a JavaScript module in Node.js. It contains the pure mapping function, all three inputs and literal expected outputs; assertions stop on a mismatch. A rejected case returns ok=false with an error code, rather than a partial canonical record.

Complete function and executable cases
import assert from 'node:assert/strict';

function nameParts(i){
  const fail=error=>({ok:false,error});if(!i)return fail('NAME_KIND');
  if(i.kind==='company'){
    if(typeof i.organisation!=='string'||!i.organisation.trim())return fail('NAME_PART');
    return {ok:true,value:{kind:'company',display:i.organisation.trim(),parts:{organisation:i.organisation}}};
  }
  if(i.kind!=='person')return fail('NAME_KIND');
  if(typeof i.given!=='string'||!i.given.trim()||typeof i.family!=='string'||!i.family.trim()||(i.honorific!==undefined&&typeof i.honorific!=='string'))return fail('NAME_PART');
  const honorific=i.honorific??'';
  return {ok:true,value:{kind:'person',display:[honorific.trim(),i.given.trim(),i.family.trim()].filter(Boolean).join(' '),parts:{honorific,given:i.given,family:i.family}}};
}

// Original synthetic cases; expected outputs are literal records.
const cases = [
  {
    "label": "Compose supplied person parts",
    "input": {
      "kind": "person",
      "given": "Ada",
      "family": "Chan",
      "honorific": "Ms"
    },
    "expected": {
      "ok": true,
      "value": {
        "kind": "person",
        "display": "Ms Ada Chan",
        "parts": {
          "honorific": "Ms",
          "given": "Ada",
          "family": "Chan"
        }
      }
    }
  },
  {
    "label": "Reject unknown name kind",
    "input": {
      "kind": "nickname",
      "given": "Ada"
    },
    "expected": {
      "ok": false,
      "error": "NAME_KIND"
    }
  },
  {
    "label": "Preserve company kind",
    "input": {
      "kind": "company",
      "organisation": "Demo Co"
    },
    "expected": {
      "ok": true,
      "value": {
        "kind": "company",
        "display": "Demo Co",
        "parts": {
          "organisation": "Demo Co"
        }
      }
    }
  }
];
for (const sample of cases) {
  const actual = nameParts(sample.input);
  assert.deepEqual(actual, sample.expected);
  console.log(sample.label, JSON.stringify(actual));
}
Download runnable example ↓

Work through the boundary

Why does Ms Ada Chan retain three name parts?

Show the worked answer

The display is composed from Ms, Ada and Chan, but the parts remain independently available. Company Demo Co instead retains organisation; the mapper never guesses that it is a person.

Related resources