2.4.1 • Published 4 months ago

resolve-schema-values v2.4.1

Weekly downloads
-
License
-
Repository
github
Last release
4 months ago

resolve-schema-values NPM version NPM monthly downloads NPM total downloads

Resolve values based on a JSON schema. Supports conditionals and composition. Useful for configuration, preferences, LLM chat completions, etc.

Please consider following this project's author, Jon Schlinkert, and consider starring the project to show your :heart: and support.

Install

Install with npm:

$ npm install --save resolve-schema-values

What is this?

A JSON Schema resolver and validator that transforms and verifies data based on a provided JSON Schema. It combines value resolution (providing defaults, handling conditionals, and managing complex compositions) with strict validation (enforcing types, formats, and constraints) to ensure data consistency and correctness.

Why another JSON Schema library?

This library focuses on resolution of data, versus validation only. You can use any validation library, then use this one to resolve values.

Note that this library is not a full JSON Schema validator and does not resolve $refs, but rather a value resolver that can be used in conjunction with a validator to provide a more complete solution.

Usage and Examples

import { resolveValues } from 'resolve-schema-values';

const schema = {
  type: 'object',
  properties: {
    username: {
      type: 'string',
      default: 'jonschlinkert'
    },
    company: {
      type: 'string'
    }
  }
};

const data = { company: 'Sellside' };
const result = await resolveValues(schema, data);
console.log(result.value); // { username: 'jonschlinkert', company: 'Sellside' }

Conditional Schema Resolution

const schema = {
  type: 'object',
  properties: {
    userType: { type: 'string' }
  },
  if: {
    properties: { userType: { const: 'business' } }
  },
  then: {
    properties: {
      taxId: { type: 'string', default: 'REQUIRED' },
      employees: { type: 'number', default: 0 }
    }
  },
  else: {
    properties: {
      personalId: { type: 'string', default: 'REQUIRED' }
    }
  }
};

const data = { userType: 'business' };
const result = await resolveValues(schema, data);
console.log(result.value);
// {
//   userType: 'business',
//   taxId: 'REQUIRED',
//   employees: 0
// }

Composition with allOf

const schema = {
  type: 'object',
  allOf: [
    {
      properties: {
        name: { type: 'string', default: 'Unnamed' }
      }
    },
    {
      properties: {
        age: { type: 'number', default: 0 }
      }
    }
  ]
};

const data = {};
const result = await resolveValues(schema, data);
console.log(result.value); // { name: 'Unnamed', age: 0 }

Pattern Properties

const schema = {
  type: 'object',
  patternProperties: {
    '^field\\d+$': {
      type: 'string',
      default: 'empty'
    }
  }
};

const data = {
  field1: undefined,
  field2: undefined,
  otherField: undefined
};

const result = await resolveValues(schema, data);
console.log(result.value);
// {
//   field1: 'empty',
//   field2: 'empty',
//   otherField: undefined
// }

Dependent Schemas

const schema = {
  type: 'object',
  properties: {
    creditCard: { type: 'string' }
  },
  dependentSchemas: {
    creditCard: {
      properties: {
        billingAddress: { type: 'string', default: 'REQUIRED' },
        securityCode: { type: 'string', default: 'REQUIRED' }
      }
    }
  }
};

const data = { creditCard: '1234-5678-9012-3456' };
const result = await resolveValues(schema, data);
console.log(result.value);
// {
//   creditCard: '1234-5678-9012-3456',
//   billingAddress: 'REQUIRED',
//   securityCode: 'REQUIRED'
// }

Array Items Resolution

const schema = {
  type: 'array',
  items: {
    type: 'object',
    properties: {
      id: { type: 'number' },
      status: { type: 'string', default: 'pending' }
    }
  }
};

const data = [
  { id: 1 },
  { id: 2 },
  { id: 3 }
];
const result = await resolveValues(schema, data);
console.log(result.value);
// [
//   { id: 1, status: 'pending' },
//   { id: 2, status: 'pending' },
//   { id: 3, status: 'pending' }
// ]

OneOf with Type Validation

const schema = {
  type: 'object',
  properties: {
    value: {
      oneOf: [
        { type: 'number' },
        { type: 'string', pattern: '^\\d+$' }
      ],
      default: 0
    }
  }
};

const data = { value: '123' };
const result = await resolveValues(schema, data);
console.log(result.value);
// { value: '123' }  // Validates as it matches the string pattern

const invalidData = { value: 'abc' };
const invalidResult = await resolveValues(schema, invalidData);
if (!invalidResult.ok) {
  console.log('Validation failed:', invalidResult.errors);
} else {
  console.log(invalidResult.value);
  // { value: 0 }  // Falls back to default as it matches neither schema
}

Additional Properties with Schema

const schema = {
  type: 'object',
  properties: {
    name: { type: 'string' }
  },
  additionalProperties: {
    type: 'string',
    default: 'additional'
  }
};

const data = {
  name: 'John',
  customField1: undefined,
  customField2: undefined
};
const result = await resolveValues(schema, data);
console.log(result.value);
// {
//   name: 'John',
//   customField1: 'additional',
//   customField2: 'additional'
// }

Example Validation

import util from 'node:util';
import { resolveValues } from 'resolve-schema-values';

const inspect = (obj: any) => util.inspect(obj, { depth: null, colors: true });

async function runExample() {
  // Example 1: Basic type validation
  console.log('\n=== Example 1: Number type validation ===');
  const numberSchem = {
    type: 'number',
    minimum: 0,
    maximum: 100
  };

  console.log('Testing with string input:');
  let result = await resolveValues(numberSchema, 'not a number');
  console.log(inspect(result));

  console.log('\nTesting with valid number:');
  result = await resolveValues(numberSchema, 50);
  console.log(inspect(result));

  console.log('\nTesting with out of range number:');
  result = await resolveValues(numberSchema, 150);
  console.log(inspect(result));

  // Example 2: Object validation
  console.log('\n=== Example 2: Object validation ===');
  const userSchema: JSONSchema = {
    type: 'object',
    properties: {
      name: { type: 'string', minLength: 1 },
      age: { type: 'number' }
    },
    required: ['name', 'age']
  };

  console.log('Testing with invalid types:');
  result = await resolveValues(userSchema, {
    name: 123,
    age: 'invalid'
  });
  console.log(inspect(result));

  // Example 2: Object validation
  console.log('\n=== Example 3: Object validation ===');
  const nestedSchema: JSONSchema = {
    type: 'object',
    properties: {
      person: {
        type: 'object',
        properties: {
          name: { type: 'string', minLength: 1 },
          age: { type: 'number' }
        },
        required: ['name', 'age']
      }
    },
    required: ['person']
  };

  console.log('Testing with invalid types:');
  result = await resolveValues(nestedSchema, {
    person: {
      name: 123,
      age: 'invalid'
    }
  });

  console.log(inspect(result));
}

runExample();

About

Pull requests and stars are always welcome. For bugs and feature requests, please create an issue.

Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:

$ npm install && npm test

(This project's readme.md is generated by verb, please don't edit the readme directly. Any changes to the readme must be made in the .verb.md readme template.)

To generate the readme, run the following command:

$ npm install -g verbose/verb#dev verb-generate-readme && verb

Related projects

You might also be interested in these projects:

  • clone-deep: Recursively (deep) clone JavaScript native types, like Object, Array, RegExp, Date as well as primitives. | homepage
  • kind-of: Get the native type of a value. | homepage

Author

Jon Schlinkert

License

Copyright © 2025, Jon Schlinkert. Released under the MIT License.


This file was generated by verb-generate-readme, v0.8.0, on March 06, 2025.

2.4.1

4 months ago

2.4.0

4 months ago

2.3.1

8 months ago

2.3.0

8 months ago

2.2.0

8 months ago

2.1.2

8 months ago

2.1.1

8 months ago

2.1.0

8 months ago

2.0.2

8 months ago

2.0.1

8 months ago

2.0.0

8 months ago

1.0.0

8 months ago