object-reduce-by-map
v3.3.0
Published
Recursively reduce an object to match a given map.
Downloads
843
Readme
object-reduce-by-map aka OBR-M
Recursively reduce an object to match a given map (Map, JSON Schema, TypeScript Interface). Perfect for filtering API responses and preventing data leakage.
Table of Contents generated with DocToc
- Full Documentation
- Quick Start
- Features
- Map-Based Filtering Example
- JSON Schema Support
- TypeScript Interface String Parsing
- Documentation
Full Documentation
Quick Start
npm install object-reduce-by-mapimport reduceByMap from 'object-reduce-by-map';
const input = {
name: 'John',
email: '[email protected]',
password: 'secret123', // Will be removed
internalId: 'xyz' // Will be removed
};
const map = { name: String, email: String };
const result = reduceByMap(input, map);
// { name: 'John', email: '[email protected]' }Three Ways to Define Your Schema
1. Direct Map (Fastest ⚡)
const map = { name: String, email: String, age: Number };
const result = reduceByMap(input, map);This is the fastest way to use object-reduce-by-map. Use this when you already have a map or can generate one.
2. JSON Schema (Convenient)
const schema = {
type: 'object',
properties: {
name: { type: 'string' },
email: { type: 'string' }
}
};
const result = reducer.fromJsonSchema(input, schema);Converts JSON Schema to a map. Slightly slower due to parsing overhead.
3. TypeScript Interface (Convenient, Async)
const interfaceString = `
interface User {
name: string;
email: string;
}
`;
const result = await reducer.fromInterface(input, interfaceString);Parses TypeScript interfaces. Slowest option (~600ms first call, <1ms cached) but very convenient.
Performance Comparison:
- Direct map: <1ms ⚡ (recommended for production)
- JSON Schema: ~1-2ms (parsing overhead)
- TypeScript Interface: ~600ms first call, <1ms cached (requires TypeScript peer dependency)
Features
✅ Map-based object reduction - Define schemas using JavaScript constructors (fastest)
✅ JSON Schema support - Use JSON Schema objects as input (NEW!)
✅ TypeScript interface parsing - Use TypeScript interfaces directly as schemas
✅ Nested object support - Handle deeply nested structures
✅ Array handling - Process arrays of objects
✅ Type validation - Ensure correct types
✅ Flexible options - Control behavior with various configuration options
✅ Zero dependencies - Core functionality has no dependencies
✅ TypeScript support - Full type definitions included
✅ Tiny bundle size - ~10 KB (core), TypeScript optional
Map-Based Filtering Example
A real world use case here is as a middleware in ExpressJS, the middleware would ensure the output does not contain data it should not output.
It can be considered an accidental safety net.
// A map using JavaScript type constructors (typically auto generated from an OpenAPI spec):
const map = {
starts: Number,
wins: Number,
secondPlaces: Number,
thirdPlaces: Number,
topFives: Number,
topFiveRatio: Number,
mostRecentRank: {
event: {
locations: [{ country: String, city: String, timezone: String }],
},
rank: Number
},
bestRank: Number
};
// A payload generated from a database query or similar
const input = {
This_Should_Not_Be_In_The_Output: 'the api should not deliver this content',
starts: 0,
wins: 0,
secondPlaces: 0,
thirdPlaces: 0,
topFives: 0,
topFiveRatio: null,
mostRecentRank: {
event: {
locations: [{
country: null
}]
}
},
bestRank: null
};
// The test case here is asserting that the "This_Should_Not_Be_In_The_Output" attribute in the object is stripped
// When used in an output transformer for an API this is a safety net preventing accidental data leakage
it('Should handle null leaf values ie remove them', () => {
expect(reducer(input, map)).toEqual({
starts: 0,
wins: 0,
secondPlaces: 0,
thirdPlaces: 0,
topFives: 0,
mostRecentRank: {
event: {
locations: [{}]
}
},
});
});
JSON Schema Support
Use dereferenced JSON Schema objects as input:
import reducer from 'object-reduce-by-map';
const schema = {
type: 'object',
properties: {
name: { type: 'string' },
email: { type: 'string' },
age: { type: 'number' }
}
};
const input = {
name: 'John Doe',
email: '[email protected]',
age: 30,
password: 'secret123', // Will be removed
internalId: 'xyz' // Will be removed
};
const result = reducer.fromJsonSchema(input, schema);
// { name: 'John Doe', email: '[email protected]', age: 30 }Note: Schema must be dereferenced (no $ref). This is a synchronous operation with minimal overhead (~1-2ms).
Perfect for:
- OpenAPI/Swagger schemas
- Existing JSON Schema validation
- API contract enforcement
TypeScript Interface String Parsing
Use TypeScript interfaces directly as schemas:
import reducer from 'object-reduce-by-map';
const interfaceString = `
interface User {
name: string;
email: string;
age: number;
}
`;
const input = {
name: 'John Doe',
email: '[email protected]',
age: 30,
password: 'secret123', // Will be removed
internalId: 'xyz' // Will be removed
};
const result = await reducer.fromInterface(input, interfaceString);
// { name: 'John Doe', email: '[email protected]', age: 30 }Requires: npm install typescript (optional peer dependency)
Perfect for LLM Output Sanitization
A powerful use case is cleaning up LLM (Large Language Model) responses. LLMs often hallucinate and add extra fields to their JSON output. Use interface parsing to strip out hallucinated fields and ensure the output strictly matches your expected schema:
// LLM returns extra fields like 'confidence', 'reasoning', 'metadata'
const llmOutput = await callLLM('Generate a product...');
// Strip hallucinated fields to match interface exactly
const cleanOutput = await reducer.fromInterface(llmOutput, productInterface);Learn more about TypeScript Interface Parsing & LLM Sanitization →
Documentation
- Installation & Basic Usage - Get started with all three input methods
- JSON Schema Support - Use JSON Schema objects (NEW!)
- TypeScript Interface Parsing - Use TS interfaces as schemas
- Configuration Options - All available options
- Examples - Real-world examples
- API Reference - Complete API docs
- Migration Guide - Upgrading guide
- Testing & Distribution - How it's tested
