Skip to content
Astera Technology

Expand a kit definition into component quantities

Multiply declared components while retaining the per-kit basis.

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 local contract accepts a nonnegative safe whole-number kit count. Component part labels must be unique; perKit is a positive safe integer. Multiply kits by perKit and reject an unsafe product. Output retains kits, perKit and each resulting requirement. Zero kits retains the definition with zero requirements.

Editable synthetic mapping cases
CaseInput record (JSON)Expected output (JSON)
Expand component quantities{"kits":2,"components":[{"part":"P","perKit":3},{"part":"Q","perKit":1}]}{"ok":true,"value":{"kits":2,"requirements":[{"part":"P","units":6,"perKit":3},{"part":"Q","units":2,"perKit":1}]}}
Reject duplicate component{"kits":1,"components":[{"part":"P","perKit":3},{"part":"P","perKit":1}]}{"ok":false,"error":"KIT_COMPONENT"}
Preserve zero-kit definitions{"kits":0,"components":[{"part":"P","perKit":3}]}{"ok":true,"value":{"kits":0,"requirements":[{"part":"P","units":0,"perKit":3}]}}
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 kitRequirements(i){
  const fail=error=>({ok:false,error});if(!i||!Number.isSafeInteger(i.kits)||i.kits<0||!Array.isArray(i.components))return fail('KIT_SHAPE');
  const parts=new Set(),requirements=[];
  for(const c of i.components){
    if(!c||typeof c.part!=='string'||!c.part||parts.has(c.part)||!Number.isSafeInteger(c.perKit)||c.perKit<=0)return fail('KIT_COMPONENT');
    const units=i.kits*c.perKit;if(!Number.isSafeInteger(units))return fail('KIT_RANGE');parts.add(c.part);requirements.push({part:c.part,units,perKit:c.perKit});
  }
  return {ok:true,value:{kits:i.kits,requirements}};
}

// Original synthetic cases; expected outputs are literal records.
const cases = [
  {
    "label": "Expand component quantities",
    "input": {
      "kits": 2,
      "components": [
        {
          "part": "P",
          "perKit": 3
        },
        {
          "part": "Q",
          "perKit": 1
        }
      ]
    },
    "expected": {
      "ok": true,
      "value": {
        "kits": 2,
        "requirements": [
          {
            "part": "P",
            "units": 6,
            "perKit": 3
          },
          {
            "part": "Q",
            "units": 2,
            "perKit": 1
          }
        ]
      }
    }
  },
  {
    "label": "Reject duplicate component",
    "input": {
      "kits": 1,
      "components": [
        {
          "part": "P",
          "perKit": 3
        },
        {
          "part": "P",
          "perKit": 1
        }
      ]
    },
    "expected": {
      "ok": false,
      "error": "KIT_COMPONENT"
    }
  },
  {
    "label": "Preserve zero-kit definitions",
    "input": {
      "kits": 0,
      "components": [
        {
          "part": "P",
          "perKit": 3
        }
      ]
    },
    "expected": {
      "ok": true,
      "value": {
        "kits": 0,
        "requirements": [
          {
            "part": "P",
            "units": 0,
            "perKit": 3
          }
        ]
      }
    }
  }
];
for (const sample of cases) {
  const actual = kitRequirements(sample.input);
  assert.deepEqual(actual, sample.expected);
  console.log(sample.label, JSON.stringify(actual));
}
Download runnable example ↓

Work through the boundary

Two kits use P=3 and Q=1 each. What component record is produced?

Show the worked answer

P requires 2×3=6 and Q requires 2×1=2. Each row retains its perKit value. These are computed requirements; this function does not consume stock.

Related resources