# data-to-jsonschema-to-ts

Convert plain javascript objects to JSON Schema and TypeScript typings.

> **Requirements:** Node.js 20 or newer. This package is ESM-only as of v2.0.0 — `import` only, no `require`.

## Installation

```
npm install data-to-jsonschema-to-ts
```

## Example

### Convert data to JSON Schema

```typescript
import {
  convertJsonSchemaToTs,
  createJsonSchemaValidator,
  generateJsonSchemaFromData,
} from "data-to-jsonschema-to-ts";

const TEST_DATA = [
  {
    id: 1,
    name: "John Doe",
    age: 30,
    email: "email@email.com",
  },
  {
    id: 1,
    name: "John Doe",
    age: 30,
    email: "email@email.com",
    address: {
      street: "123 Main St",
      city: "Anytown",
      state: "NY",
      zip: "12345",
    },
  },
  {
    id: 1,
    name: "John Doe",
    age: 30,
    email: null,
    preferences: [{ name: "pref1", value: "value1" }],
  },
];

const jsonSchema = generateJsonSchemaFromData(TEST_DATA, "TestData", {
  additionalProperties: false,
});

console.log(JSON.stringify(jsonSchema, null, 2));
```

### Create a validator function from the generated schema

```typescript
const validator = createJsonSchemaValidator(jsonSchema)

console.log(validator({id: 1, name: "John Doe", age: 30, email: "something@email.com"})); // valid
console.log(validator({id: 1, name: "John Doe", age: 30 })); // invalid, missing email
```

### Convert the generated schema to TypeScript

```typescript
const generatedTs = convertJsonSchemaToTs(jsonSchema);

console.log(generatedTs);
// export type TestData = { id: number; name: string; ... };
```

`convertJsonSchemaToTs` is a thin wrapper over [`ajsc`](https://www.npmjs.com/package/ajsc)'s `TypescriptConverter`. Pass the same options it accepts (`inlineTypes`, `enumStyle`, `arrayItemNaming`, `depluralize`, `uncountableWords`, `jsdoc`).

## Subpath imports

You can import individual functions from per-feature subpaths if you only need one piece of the library:

```typescript
import { generateJsonSchemaFromData } from "data-to-jsonschema-to-ts/generate-schema";
import { convertJsonSchemaToTs } from "data-to-jsonschema-to-ts/convert-to-ts";
import { createJsonSchemaValidator } from "data-to-jsonschema-to-ts/validator";
import { traverseObject } from "data-to-jsonschema-to-ts/traverse";

import type { JsonSchema, JsonType } from "data-to-jsonschema-to-ts/generate-schema";
```

The bundled barrel (`import { ... } from "data-to-jsonschema-to-ts"`) continues to work and re-exports everything.

## Utilities

### createJsonSchemaValidator(schema)

Generate a function that validates an object against a JSON Schema.

```typescript
import { createJsonSchemaValidator } from "data-to-jsonschema-to-ts";

const validator = createJsonSchemaValidator({
    type: "object",
    properties: {
        id: { type: "number" },
        name: { type: "string" },
        age: { type: "number" },
        email: { type: "string" }
    },
    required: ["id", "name", "age", "email"]
});

validator({
    id: 1,
    name: "John Doe",
    age: 30,
    email: "myemail.com"
}); // { valid: true, errors: undefined }

validator({
    id: 1,
    age: null
}); // { valid: false, errors: [{...}] }
```

### traverseObject(obj, callback)

Walk a plain javascript object and call a callback for each primitive leaf value, with its JSON-dot/bracket path and parent metadata.

```typescript
import { traverseObject } from "data-to-jsonschema-to-ts";

const obj = {
    id: 1,
    profile: {
        name: "John Doe",
    },
    tags: ["admin", "owner"],
};

traverseObject(obj, (value, jsonPath, meta) => {
    console.log(value, jsonPath, meta);
});

// console output (one line per primitive leaf):
// 1                 'id'             { key: 'id',      parent: { path: '',        type: 'object' } }
// 'John Doe'        'profile.name'   { key: 'name',    parent: { path: 'profile', type: 'object' } }
// 'admin'           'tags[0]'        { key: 0,         parent: { path: 'tags',    type: 'array'  } }
// 'owner'           'tags[1]'        { key: 1,         parent: { path: 'tags',    type: 'array'  } }
```

The third callback argument `meta` is optional — drop it if you only need the value and path.
