Skip to content

Schema ​

The schema describes one logical table. It drives autocomplete, the deterministic parser, the model prompt, validation and execution. Only this metadata is ever sent to a model, never rows.

ts
import { defineSchema } from '@avinash-baraiya/pragma-core';

export const customersSchema = defineSchema({
  schemaVersion: '1',
  resource: 'customers',
  label: 'Customers',
  aliases: ['users', 'accounts'],
  fields: [
    { id: 'name', label: 'Name', type: 'string' },
    { id: 'age', label: 'Age', type: 'number' },
    {
      id: 'status',
      label: 'Status',
      type: 'enum',
      values: [
        { value: 'active', label: 'Active' },
        { value: 'churned', label: 'Churned', aliases: ['cancelled', 'lost'] },
      ],
    },
    {
      id: 'revenue',
      label: 'Lifetime Revenue',
      type: 'number',
      format: 'currency',
      currency: 'INR',
      aliases: ['ltv'],
    },
    { id: 'createdAt', label: 'Signed Up', type: 'datetime', aliases: ['joined', 'signup date'] },
    { id: 'phone', label: 'Phone', type: 'string', sortable: false },
    { id: 'internalNotes', label: 'Internal Notes', type: 'string', hidden: true },
  ],
  defaults: {
    pageSize: 20,
    recencyField: 'createdAt',
    sort: [{ field: 'createdAt', direction: 'desc' }],
  },
  capabilities: { search: true, pagination: ['page', 'cursor'], maxPageSize: 100, maxSorts: 3 },
});

defineSchema validates everything at startup and throws one PragmaConfigError (SCHEMA_ERROR) listing every problem. It returns a frozen ResolvedSchema with defaults applied, lookup indexes and a stable hash.

Fields ​

PropertyMeaning
idStable key used in queries: letters, digits, _; dot-separated segments allowed (address.city).
labelHuman name, used in explanations and matching.
typestring · number · boolean · date · datetime · enum
aliasesOther names users may type ("joined", "signup date"). Must be unique across fields.
descriptionSemantic hint for the model (e.g. "revenue excluding refunds, INR").
formatcurrency · percent · duration · rating (numbers), email · url · phone (strings).
currencyISO 4217 code for format: 'currency'.
percentScalewhole (20 means 20%, default) or fraction (0.2). "20%" is converted accordingly.
valuesEnum values { value, label?, aliases? }; required for enums. Synonyms ("completed" → "approved") belong here. The engine never invents mappings.
operatorsNarrow the type's operators for this field.
filterable / sortableDefault true.
searchableIncluded in global search. Default true for strings.
hiddenNever sent to a model, never suggested, and rejected with the same error as a non-existent field.

Defaults and capabilities ​

PropertyDefaultMeaning
defaults.pageSize20Page size of the initial query
defaults.sort[]Sort applied on reset
defaults.recencyField—Date field for "newest", "oldest", "recent" and standalone "this week". Without it, Pragma asks which date is meant (unless there is only one).
capabilities.searchtrueWhether global search is allowed
capabilities.pagination['page']Supported styles; the first is the default
capabilities.maxPageSize500Larger requests are LIMIT_EXCEEDED (or clamped under bestGuess)
capabilities.maxSorts5Maximum sort keys

Rules checked by defineSchema ​

  • Duplicate field ids, invalid ids, and names or aliases shared by two fields (after normalizing case and camelCase/snake_case).
  • An enum without values, or enum values whose labels or aliases collide.
  • values on non-enum fields; a format that doesn't fit the type; currency without the currency format; percentScale without the percent format.
  • Searchable non-text fields; operators that aren't valid for the type; an empty operator list.
  • A recencyField that is missing, not a date or not sortable; default sorts on unknown or non-sortable fields; a page size above the maximum.
  • A schema with no visible fields; a resource name that collides with a field name.

Deriving a schema from table columns ​

@avinash-baraiya/pragma-tanstack can build a schema from TanStack column definitions that carry meta.pragma:

ts
const columns = [
  { accessorKey: 'age', header: 'Age', meta: { pragma: { type: 'number' } } },
  {
    accessorKey: 'status',
    header: 'Status',
    meta: { pragma: { type: 'enum', values: [{ value: 'active' }] } },
  },
];
const schema = schemaFromColumns(columns, { resource: 'customers' });

Released under the MIT License.