Skip to main content

Data Sources

Shared data infrastructure​

The Data Source Engine is shared infrastructure. It is not exclusive to DyonaForm: any application code can use executeDyonaDataSource with a DyonaDataSourceExecutor to execute and validate a typed request/result exchange.

DYONA validates and transports requests and results. The consuming application owns HTTP, fetch or Axios, URLs, authentication, tokens, and response transformations. DYONA does not fetch data automatically.

Public contract​

sourceId identifies a source in the consuming application. DyonaDataSourceExecutor receives a typed request and returns a matching typed result, synchronously or as a promise. executeDyonaDataSource validates both sides of that exchange before returning the result.

The current operations are only:

  • options.search
  • options.resolve

options.search receives input.searchText and returns an array of {label, value, secondaryLabel?} options. options.resolve receives input.value and returns one option or null.

An option value is a string, number, or boolean. Its type is preserved strictly: a resolve result must return exactly the requested value, and 102 is different from '102'. result.operation must match the requested operation.

When present, secondaryLabel is a string used only to provide secondary presentation in the RemoteAutocomplete dropdown. The selected input continues to show label, and value is unchanged.

request.context is an optional object supplied by the caller for application context, such as a field name or current values. request.signal is an AbortSignal; pass it to cancellable work such as fetch so a superseded request can be cancelled.

Complete example​

import {
executeDyonaDataSource,
type DyonaDataSourceExecutor,
} from '@typhonsoftware/dyona-form';

const customers = [
{value: 102, label: 'Taylor Reed'},
{value: 103, label: 'Jordan Lee'},
];

const dataSourceExecutor: DyonaDataSourceExecutor = async (request) => {
if (request.operation === 'options.search') {
const searchText = request.input.searchText.toLowerCase();
return {
operation: 'options.search',
data: customers.filter((customer) =>
customer.label.toLowerCase().includes(searchText),
),
};
}

return {
operation: 'options.resolve',
data: customers.find((customer) =>
customer.value === request.input.value,
) ?? null,
};
};

const controller = new AbortController();
const result = await executeDyonaDataSource({
sourceId: 'customers',
operation: 'options.search',
input: {searchText: 'tay'},
context: {fieldName: 'customerId', values: {}},
signal: controller.signal,
}, dataSourceExecutor);

In a real application, replace the local lookup inside the executor with your own transport and response mapping while preserving the request and result contract.

See it in DyonaForm​

Try it outside DyonaForm​