Semaphor
Data Apps

SDK Reference

Public Data App SDK builders, hooks, and common result fields.

This is a compact reference for the public Data App SDK surface.

Imports

import {
  SemaphorDataAppProvider,
  defineSemaphorDataApp,
  defineSemaphorInput,
  semaphor,
  useClearInvalidSemaphorInputValue,
  useSemaphorInput,
  useSemaphorInputs,
  useSemaphorSelection,
  useSemaphorQuery,
} from 'react-semaphor/data-app-sdk';

Provider

<SemaphorDataAppProvider token={token} apiBaseUrl={apiBaseUrl}>
  <App />
</SemaphorDataAppProvider>

Props:

PropRequiredMeaning
tokenLocal developmentScoped Semaphor access token.
apiBaseUrlOptionalAPI base URL for local or self-hosted environments.
executorOptionalCustom query executor, usually for tests.

Source Builders

semaphor.source.semantic({
  domainId: 'commerce',
  datasetName: 'fact_orders',
  datasetId: 'ds_orders',
  connectionId: 'conn_123',
  label: 'Orders',
});

semaphor.source.sql({
  connectionId: 'conn_123',
  dialect: 'postgres',
  label: 'Analytics warehouse',
});

For semantic sources, provide domainId and datasetName; include datasetId when available to strengthen identity. connectionId is execution metadata, not the semantic identity.

Field Builders

semaphor.field.measure('revenue', { source: orders, aggregate: 'SUM' });
semaphor.field.dimension('campaign_name', { source: campaign });
semaphor.field.date('order_date', { source: orders });
semaphor.field.id('campaign_id', { source: campaign });

Query Builders

semaphor.metric({
  source,
  measures,
  primaryMeasure,
});

semaphor.records({
  source,
  fields,
  dateField,
  orderBy,
  limit,
  pagination,
});

semaphor.matrix({
  source,
  rows,
  columns,
  values,
  totals,
});

semaphor.analysis({
  source,
  measures,
  primaryMeasure,
  dimensions,
  analysis,
});

semaphor.inputOptions({
  inputId,
  source,
  labelField,
  valueField,
  searchField,
  population,
  dependencies,
  limit,
});

semaphor.sql({
  source,
  sql,
  rationale,
  limit,
  pagination,
});

Input Builders

semaphor.filter({
  id: 'campaign',
  label: 'Campaign',
  field: campaignId,
  operator: 'in',
  multi: true,
});

semaphor.control({
  id: 'grain',
  label: 'Grain',
  role: 'grain',
  defaultValue: 'month',
});

With the current React SDK, apps usually call useSemaphorInput directly:

const campaignInput = useSemaphorInput({
  id: 'campaign',
  label: 'Campaign',
  kind: 'filter',
  field: campaignId,
  operator: 'in',
  multi: true,
});

Hooks

const input = useSemaphorInput(spec);
const inputs = useSemaphorInputs([campaignSpec, dateSpec]);
const result = useSemaphorQuery(query, { inputs: [input] });
const selection = useSemaphorSelection(
  semaphor.selection({ id: 'campaign-chart', fields: [campaignId] }),
);
const selectedResult = useSemaphorQuery(query, {
  inputs: [input],
  selections: [selection],
});
useClearInvalidSemaphorInputValue(input, optionsResult);

useSemaphorQuery is overloaded by query kind, so the result shape follows the builder you pass. Selection handles stay separate from scalar input handles and do not expose toAnalyticsInput().

Common Result Fields

All results:

result.status;
result.isLoading;
result.error;
result.executionResult;

Metric:

result.primaryValue;
result.measures;
result.delta;
result.deltaPercent;

Records and SQL:

result.records;
result.columns;
result.rowCount;
result.pagination;

Input options:

result.options;

Matrix:

result.matrixResult;
result.grid;

Analysis:

result.answerSummary;
result.resultSets?.records?.records;
result.resultSets?.changes?.records;
result.resultSets?.drivers?.records;
result.analysisWarnings;

executionResult is the authoritative governed result contract. Top-level analysis fields such as records, drivers, changes, or fieldsUsed are convenience projections for display. In particular, top-level fieldsUsed is compact display metadata; full derived-field lineage belongs in executionResult.fieldsUsed.

Option Population

population: {
  kind: 'related_population',
  baseSource: inventory,
}

Use related_population when the option source should be limited by a related fact or bridge population.

Option Dependencies

Option queries are independent unless dependencies are declared.

const stateOptions = semaphor.inputOptions({
  inputId: 'state',
  source: geo,
  labelField: stateName,
  valueField: stateId,
});

Use explicit dependencies only when a relationship path has been proven:

dependencies: {
  mode: 'explicit',
  includeInputIds: ['region'],
}

Use independent dependencies when an option list should ignore active filters:

dependencies: {
  mode: 'independent',
}

Relationship Hint

Use only when Semaphor reports an ambiguous relationship and the user or planner selects one modeled path.

relationshipHint: {
  relationshipIds: ['rel_orders_buyer_customer'],
}

Do not use free-form role aliases as hints.

On this page