Overview
OpenAI-powered mapping generator for morphos. Given a source schema, a
destination schema, and an OpenAI API token, returns a RootMapping JSON that
transforms data of the source shape into data of the destination shape.
This entry is published as a subpath of morphos. It is not loaded unless
imported, so consumers of the main package pay nothing for the OpenAI SDK.
Installation
openai is declared as an optional peer dependency. Install it in your app:
npm install openai
Usage
import { generateMapping } from 'morphos/openai';
import type { JsonSchema } from 'morphos';
const sourceSchema: JsonSchema = {
type: 'object',
properties: {
UPC: { type: 'string' },
QTY: { type: 'number' },
PRICE: { type: 'number' },
CUSTOMER: {
type: 'object',
properties: {
NAME: { type: 'string' },
EMAIL: { type: 'string' }
}
}
}
};
const destinationSchema: JsonSchema = {
type: 'object',
properties: {
code: { type: 'string' },
qty: { type: 'number' },
amount: { type: 'number' },
customer: {
type: 'object',
properties: {
name: { type: 'string' },
email: { type: 'string' }
}
}
}
};
const mapping = await generateMapping(
sourceSchema,
destinationSchema,
process.env.OPENAI_API_KEY!,
{
instructions: 'Truncate UPC to 5 characters for the destination code field.',
model: 'gpt-5.5',
reasoningEffort: 'low',
generateMappingTemplate: true,
generateRequiredFields: true
}
);
console.log(mapping);
// {
// code: 'UPC.substring(0, 5)',
// qty: 'QTY',
// amount: 'QTY * PRICE',
// customer: { from: 'CUSTOMER', map: { name: 'NAME', email: 'EMAIL' } }
// }
The returned value is a RootMapping that can be fed directly into createMapper from
the main package, or used as the initial value of the MappingEditor.
Options
| Option | Type | Description |
|---|---|---|
sourceSchema |
JsonSchema |
JSON-schema-like description of input data. Required. |
destinationSchema |
JsonSchema |
JSON-schema-like description of desired output. Required. |
apiKey |
string |
OpenAI API key. Required. |
options.instructions |
string |
Optional free-form text appended to the user prompt (e.g. naming conventions, edge cases). |
options.mappingTemplate |
RootMapping |
Optional mapping shape for the model to preserve and fill when confident. |
options.generateMappingTemplate |
boolean |
Generate a mapping template from the destination schema before calling OpenAI. Defaults to false. |
options.model |
string |
Optional OpenAI model identifier. Defaults to gpt-5.5. |
options.dangerouslyAllowBrowser |
boolean |
Passed to the OpenAI client for browser usage. Defaults to false. |
options.generateRequiredFields |
boolean |
Add placeholders for unmapped required destination fields after generation. Defaults to false. |
When mappingTemplate is provided, it is sent with the schemas as the preferred
output shape. When generateMappingTemplate is enabled and mappingTemplate is
not provided, a template is generated from the destination schema first. Blank
values are treated as fields the model may fill when it finds a confident source
mapping, literal, or JavaScript expression. This is useful when you already have
an editor-generated mapping skeleton or want the model to preserve object, array,
conditional, or concatenation structure.
When generateRequiredFields is enabled, unmapped required scalar fields are set to "", required objects are expanded as { "map": { ... } }, homogeneous arrays are expanded as { "forEach": "", "map": { ... } }, and tuple arrays are expanded as positional object mappings such as { "0": "", "1": { "map": { ... } } }. Generated nested maps contain only required child fields.
How it works
The function instantiates an OpenAI client with the supplied API key and calls
chat.completions.create with:
- A system prompt describing the
morphosmapping format (expression strings,forEach/fromwrappers, plain nested objects, type-conversion conventions). - A user message that includes both schemas, your
mappingTemplate, and yourinstructionsif provided. response_format: { type: 'json_schema', json_schema: { schema, strict: false } }whereschemais the project’s ownschemas/mapping.json— the canonical grammar for any valid mapping (expression string,forEachiterator,fromcontext switch, plain nested object, tuple, etc.). It is passed as a guidance schema (strict: false) rather than enforced, because the mapping grammar usesoneOf/patternPropertiesconstructs that aren’t part of OpenAI’s strict subset, and because the same destination can legitimately be expressed in multiple shapes (e.g. an array destination can be mapped viaforEach/mapor via a single JS expression that returns the array).
The response is parsed and returned. If the model returns an empty content or invalid JSON, the function throws.
Notes
- The returned mapping is not validated against the
morphosmapping schema. Pass it throughcreateMapper(which performs its own validation) or wrap the call in your own validator if strict guarantees are required. - For browser usage, instantiate your own
OpenAIclient withdangerouslyAllowBrowser: trueand use the OpenAI SDK directly — this helper assumes Node-like environments by default. Exposing API tokens in browser code is generally a bad idea. - The system prompt biases the model toward the simplest valid mapping (single expression
string when possible,
forEachfor arrays,fromfor context switches). You can override behavior withinstructions.