# Type definitions

An index of the SDK's TypeScript types: for each type its signature, one sentence, and a link to the page that documents its fields, defaults and examples. `@dcupl/core` exports only the `Dcupl` and `DcuplList` classes; import the types from `@dcupl/common`. A few names on this page only describe a shape and are not exported (`DcuplQueryBase`, `DcuplQueryOptions`, `DcuplUpdateOptions`, the `Pivot*` option types, the `SuggestionOptions*` variants); their sections show how to derive them from an exported type. The [Script types](#script-types) section names its own packages and is documented only here.

```typescript
import { Dcupl } from '@dcupl/core';
import type { DcuplQuery, DcuplQueryGroup, ModelDefinition } from '@dcupl/common';
```

---

## Configuration types

The options of `new Dcupl()` and `dcupl.update()`. Fields, defaults and examples: [Dcupl class → Configuration types](/sdk/api/dcupl#configuration-types).

### DcuplInitOptions

The options object of `new Dcupl(options)`. See [DcuplInitOptions](/sdk/api/dcupl#dcuplinitoptions).

```typescript
type DcuplInitOptions = {
  config?: DcuplInitConfig;
  errorTracking?: DcuplInitErrorTrackingConfig;
  quality?: DcuplInitQualityConfig;
  performance?: DcuplInitPerformanceConfig;
  analytics?: DcuplInitErrorAnalyticsConfig;
  referenceMetadata?: DcuplInitReferenceMetadataConfig;
  logging?: DcuplInitLoggingConfig;
  scripting?: DcuplInitScriptingConfig;
};

// DcuplInitErrorTrackingConfig, DcuplInitErrorAnalyticsConfig and
// DcuplInitReferenceMetadataConfig are all { enabled: boolean }
```

### DcuplInitScriptingConfig

Controls the scripts, custom operators and loader transformers of an instance.

```typescript
type DcuplInitScriptingConfig = { enabled?: boolean; compile?: ScriptCompiler };

type ScriptCompiler = (source: string, params: string[]) => (...args: any[]) => any;
```

| Property  | Type             | Default                      | Description                                                                                                                                                                                                                                          |
| --------- | ---------------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enabled` | `boolean`        | `true`                       | `false` runs none of your scripts: `dcupl.scripts.execute*` throws `Scripting is disabled for this dcupl instance` and the loader skips `script`, `operator` and `transformer` resources with a `ScriptingDisabled` quality error                    |
| `compile` | `ScriptCompiler` | `new Function` in your realm | Turns script text into a function. Pass your own compiler, for example a sandboxed one, when the scripts come from a source you don't trust. Scripts on an app runner instance always run sandboxed ([The sandbox](/sdk/guides/scripts#the-sandbox)) |

### DcuplInitConfig

The project a loader added with `dcupl.loaders.add()` reads from: its `projectId`, `apiKey` and `version` variables. See [DcuplInitConfig](/sdk/api/dcupl#dcuplinitconfig).

```typescript
// version: 'draft' (default), 'production' or a version name such as 'v1.0.0'
type DcuplInitConfig = { projectId?: string; apiKey?: string; version?: string };
```

### DcuplInitPerformanceConfig

Cache, clone, partial-update and list auto-update settings. See [DcuplInitPerformanceConfig](/sdk/api/dcupl#dcuplinitperformanceconfig).

```typescript
type DcuplInitPerformanceConfig = {
  cache?: {
    enabled: boolean;
    maxSize?: number; // estimated bytes, default 64 MiB; Infinity = no limit
    maxProjectionSize?: number; // estimated bytes per list, default 256 MiB; Infinity = no limit
  };
  clone?: { enabled: boolean };
  partialUpdates?: DcuplPartialUpdateConfig;
  containerBatchSize?: number;
  autoUpdateLists?: { enabled: boolean };
  retainStagedData?: boolean; // default true; false seals the instance after init()
};
```

### DcuplPartialUpdateConfig

When `update()` applies a partial update instead of a full rebuild. See [DcuplPartialUpdateConfig](/sdk/api/dcupl#dcuplpartialupdateconfig).

```typescript
type DcuplPartialUpdateConfig = {
  modelRatioThreshold?: number;
  itemRatioThreshold?: number;
  enableDetailedLogging?: boolean;
};
```

### DcuplInitQualityConfig

Turns the data quality checks on or off and caps the stored errors per group. See [DcuplInitQualityConfig](/sdk/api/dcupl#dcuplinitqualityconfig) and [Limiting stored errors](/sdk/advanced/quality-validation#limiting-stored-errors).

```typescript
type DcuplInitQualityConfig = { enabled: boolean; maxErrorsPerGroup?: number };
```

### DcuplInitLoggingConfig

Logging options; typed, but not applied to the SDK core's logs. See [DcuplInitLoggingConfig](/sdk/api/dcupl#dcuplinitloggingconfig).

```typescript
type DcuplInitLoggingConfig = {
  level?: LogLevel;
  format?: 'json' | 'pretty';
  onLog?: (entry: LogEntry) => void;
  modules?: Record<string, LogLevel>;
};

type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug';
```

### DcuplUpdateOptions

The options of `dcupl.update()`. Not exported; use `Parameters<Dcupl['update']>[0]`. See [DcuplUpdateOptions](/sdk/api/dcupl#dcuplupdateoptions).

```typescript
type DcuplUpdateOptions = { autoUpdateLists?: boolean };
```

---

## Model types

Field-by-field reference with defaults and examples: [Models API → Type definitions](/sdk/api/models#type-definitions).

### ModelDefinition

A data model: its key, properties, references, key settings and quality defaults. See [ModelDefinition](/sdk/api/models#modeldefinition).

```typescript
type ModelDefinition<ModelNames extends string = string> = {
  key: ModelNames;
  keyProperty?: string | readonly string[];
  keyPropertySeparator?: string;
  properties?: Property[];
  references?: Reference[];
  quality?: ModelQualityConfig;
  data?: RawItem[];
  autoGenerateKey?: boolean;
  autoGenerateProperties?: boolean | { deep?: boolean; sampleSize?: number };
  supportsAutoCreation?: boolean;
  valueMappings?: ValueMappingConfig[];
  meta?: ModelMetadata; // { name: string; description?: string; [key: string]: any }
};

type ValueMappingConfig = {
  attributes: string[]; // properties and references the mapping applies to
  values: { from: (string | '$dcupl_falsy')[]; to: any }[];
};
```

### Property

One property of a model. `Property` is a union of one variant per `type` (`PropertyString`, `PropertyInt`, `PropertyDate`, …); the fields marked below exist only on some variants. See [Property](/sdk/api/models#property).

```typescript
type Property = {
  key: string;
  type: PropertyType;
  quality?: AttributeQualityConfig;
  expression?: string;
  derive?: { localReference: string; remoteProperty: string; separator?: string };
  filter?: boolean | FilterStringSingle | FilterStringArray[]; // object forms: string and Array<string> only
  aggregate?: boolean | Omit<AggregationOptions, 'attribute'>;
  index?: boolean;
  origin?: string; // source field to read the value from, e.g. a CSV column header
  meta?: ModelMetadata;
  separator?: string; // Array<…> types: splits a string value
  fractionDigits?: number; // float, Array<float>
  inputFormat?: string; // date, Array<date>
  UTC?: boolean; // date, Array<date>
};

type FilterStringSingle = { comparisonType?: FilterComparisonType };
type FilterStringArray = { key: string; comparisonType: FilterComparisonType };
type FilterComparisonType =
  | 'equal'
  | 'equalIgnoreCase'
  | 'contains'
  | 'containsIgnoreCase'
  | 'containsIgnoreCaseAndWhitespace';

type PropertyType =
  | 'string'
  | 'int'
  | 'float'
  | 'boolean'
  | 'date'
  | 'json'
  | 'any'
  | 'Array<string>'
  | 'Array<int>'
  | 'Array<float>'
  | 'Array<date>';
```

### Reference

A link to another model; a computed reference sets exactly one of `resolve`, `derive`, `groupBy` or `query`. See [Reference](/sdk/api/models#reference).

```typescript
type Reference = {
  key: string;
  model: string;
  type: ReferenceType;
  separator?: string;
  filter?: boolean | ReferenceFilterDefinition;
  aggregate?: boolean | Omit<AggregationOptions, 'attribute'>;
  index?: boolean;
  validity?: ReferenceValidity;
  quality?: AttributeQualityConfig;
  origin?: string; // source field to read the key(s) from
  meta?: ModelMetadata;
  // computed references (one of):
  resolve?: { reference: string; model: string };
  derive?: { localReference: string; remoteReference: string };
  groupBy?: { reference: string; includeSelfInGroup?: boolean };
  query?: DcuplGlobalQueryOptions<any> | DcuplQuery | DcuplQueryGroup | DcuplQuery[] | DcuplQueryGroup[];
};

type ReferenceType = 'singleValued' | 'multiValued';
type ReferenceValidity = 'loose' | 'strict';
type ReferenceFilterDefinition = { calculateFacets?: boolean; excludeZeros?: boolean; excludeUndefineds?: boolean };
```

---

## Data types

How data goes in and comes out. Data methods and their options: [Data API](/sdk/api/data).

### RawItem

A plain object as you pass it to `dcupl.data.set()` or `model.data`; its key is read from `keyProperty` (default `'key'`).

```typescript
type RawItem = any;
```

### ListItem

An item as dcupl returns it from queries and functions: it always carries its `key`.

```typescript
type ListItem = { key: string; [id: string]: any };
```

### DataOptions

The options of `data.set()`, `update()`, `upsert()` and `remove()`; omitted key options fall back to the model definition. See [DataOptions](/sdk/api/data#dataoptions).

```typescript
type DataOptions<ModelNames extends string = string> = {
  model: ModelNames;
  keyProperty?: string | readonly string[];
  keyPropertySeparator?: string;
  autoGenerateKey?: boolean;
};
```

### DataContainer

One staged data operation, as `data.apply()` takes it. See [DataContainer](/sdk/api/data#datacontainer).

```typescript
type DataContainer = {
  model: string;
  type?: DataContainerType;
  data: RawItem[];
  keyProperty?: string | readonly string[];
  keyPropertySeparator?: string;
  autoGenerateKey?: boolean;
  autoGenerateProperties?: boolean | { deep?: boolean; sampleSize?: number };
  placeholderUid?: string;
};

type DataContainerType = 'upsert' | 'update' | 'set' | 'remove';
```

---

## Query types

Operators, options and query structure: [Query operators](/sdk/api/query-operators). `@dcupl/common` also exports these under readable alias names: `QueryCondition` (`DcuplQuery`), `QueryConditionGroup` (`DcuplQueryGroup`), `QueryExecutionContext` (`DcuplGlobalQueryOptions`), `ListQueryOptions` (`DcuplListQueryOptions`) and `ItemDataOptions` (`DcuplItemsOptions`: `start`, `count`, `sort`, `projection`). A custom operator registered with `dcupl.query.registerCustomOperator()` has the type `CustomOperatorFn = (query: DcuplQuery, listItem: ListItem) => boolean`.

### DcuplQuery

One condition on one attribute, a union discriminated by `operator`. See [DcuplQuery](/sdk/api/query-operators#dcuplquery).

```typescript
type DcuplQuery =
  | DcuplQueryEq // operator: 'eq'; value: any
  | DcuplQueryIn // operator: 'in'; value: unknown[]
  | DcuplQueryNumbers // operator: 'gt' | 'lt' | 'gte' | 'lte'; value: string | number | Date
  | DcuplQueryTypeOf // operator: 'typeof'; value: string
  | DcuplQueryIsTruthy // operator: 'isTruthy'; value: boolean
  | DcuplQuerySize // operator: 'size'; value: number
  | DcuplQueryFind; // operator: 'find'; value: string | Record<string, unknown>

// Shared by every variant; not exported
type DcuplQueryBase = {
  attribute: string; // dot notation for nested values, e.g. 'user.email'
  queryKey?: any;
  options?: DcuplQueryOptions;
};
```

### DcuplQueryOperator

The ten operator names. Each one's rules and examples: [Query operators](/sdk/api/query-operators#quick-reference).

```typescript
type DcuplQueryOperator = 'eq' | 'in' | 'find' | 'gt' | 'gte' | 'lt' | 'lte' | 'typeof' | 'isTruthy' | 'size';
```

### DcuplQueryOptions

Modifiers of one condition. Not exported: `DcuplQuery` declares its `options` inline; use `NonNullable<DcuplQuery['options']>`. See [Operator options](/sdk/api/query-operators#operator-options).

```typescript
type DcuplQueryOptions = {
  transform?: DcuplQueryTransformOptions[];
  invert?: boolean;
  arrayValueHandling?: 'some' | 'every';
  regexFlags?: string; // find only
};

type DcuplQueryTransformOptions = 'lowercase' | 'trim' | 'removeWhitespace';
```

### DcuplQueryGroup

Combines conditions and nested groups with `'and'` or `'or'`. Set `groupType` explicitly: the default differs between the query builder and evaluation, see [DcuplQueryGroup](/sdk/api/query-operators#dcuplquerygroup).

```typescript
type DcuplQueryGroup<ChildQuery extends DcuplQuery | DcuplQueryGroup = any> = {
  groupType?: 'and' | 'or';
  groupKey?: string;
  queries: Array<ChildQuery>;
};
```

### DcuplListQueryOptions

The options of `list.catalog.query.execute()`: optional extra conditions on top of the list's query, plus paging, projection and sorting. See [execute()](/sdk/api/catalog#execute).

```typescript
type DcuplListQueryOptions<T> = DcuplItemsOptions<T> & Partial<DcuplQueryGroup>;

type DcuplItemsOptions<T> = { start?: number; count?: number; projection?: Projection<T>; sort?: SortingProjection<T> };
```

### DcuplGlobalQueryOptions

A full query on one model, as `dcupl.query.execute()`, `lists.create({ query })` and the `query` of `dcupl.fn.*` take it. See [Global queries](/sdk/api/dcupl#query).

```typescript
type DcuplGlobalQueryOptions<T> = { modelKey: string } & DcuplItemsOptions<T> & DcuplQueryGroup;
```

### DcuplGlobalItemOptions

The options of `dcupl.query.one()` and `dcupl.query.many()`. See [Global queries](/sdk/api/dcupl#query).

```typescript
type DcuplGlobalItemOptions<T> = { modelKey: string; itemKey: string; projection?: Projection<T> };
type DcuplGlobalManyItemOptions<T> = { modelKey: string; itemKeys: string[]; projection?: Projection<T> };
```

### SortingProjection

Sort order of a result: one direction per attribute, or a sort script. `order` values are uppercase; a sort with `'asc'`/`'desc'` (or another invalid shape) is ignored as a whole and logs a warning naming the expected shape. Examples: [Query results](/sdk/queries/query-results).

```typescript
type SortingProjection<T> = {
  attributes: Array<keyof T>;
  order: Array<'ASC' | 'DESC'>;
  script?: { key: string; options: any };
};
```

### Projection

Which fields a returned item carries. Without a projection you get `{ $: true }`. Examples: [Query results](/sdk/queries/query-results).

```typescript
type Projection<T> = WildCard | ProjectionAdvanced<T>;

type WildCard = { $?: boolean; $$?: boolean }; // not exported

type ProjectionAdvanced<T> = {
  [P in keyof T]?: boolean | WildCard | ProjectionAdvanced<T[P]>;
};
```

| Entry                  | Effect                                                                        |
| ---------------------- | ----------------------------------------------------------------------------- |
| `$: true`              | Every own field; references stay as stored (`{ key }`)                        |
| `$$: true`             | Every own field, and every reference resolved to its item's own fields        |
| `name: true` / `false` | Include or leave out one field. Without `$`, only `key` and the listed fields |
| `category: { … }`      | Resolve the reference and project the referenced item with the nested object  |

---

## List types

Creating and updating lists: [Lists API](/sdk/api/lists).

### DcuplListOptions

The options for creating a list: its model, key, scope and auto-update. See [DcuplListOptions](/sdk/api/lists#dcupllistoptions).

```typescript
type DcuplListOptions<ModelNames extends string = string> = {
  modelKey: ModelNames;
  listKey?: string;
  listItemKeys?: string[];
  query?: DcuplGlobalQueryOptions<ListItem>;
  autoUpdate?: boolean;
};
```

`autoUpdate` works at runtime, but the parameter type of `dcupl.lists.create()` does not declare it, so passing it in an object literal is a TypeScript error.

### DcuplList

The list class exported by `@dcupl/core` (abridged). See [DcuplList class](/sdk/api/lists#dcupllist-class).

```typescript
class DcuplList<ListType = any> {
  key: string;
  modelKey: string;
  catalog: Catalog<ListType & ListItem>;

  update(options?: { reprocessData?: boolean }): void;
  invalidate(): void;
  destroy(): void;
  on(callback: CallbackFunction): () => void;
  onResultChange(callback: CallbackFunction): () => void;
}
```

### ListMetadata

What `list.catalog.fn.metadata()` and `dcupl.fn.metadata()` return. See [metadata()](/sdk/fn/metadata).

```typescript
type ListMetadata = {
  key: string;
  currentSize: number;
  initialSize: number;
  appliedQuery: DcuplGlobalQueryOptions<any>;
  attributes: ModelAttribute[]; // ModelAttribute = Property | Reference
  views: ViewDefinition[];
};
```

---

## Function types

Options, semantics, return shapes and examples of each function live on its `/sdk/fn/*` page; the global form, the `query` rule and the errors on [Functions API](/sdk/api/functions). The `list.catalog.fn.*` functions take the options below; the `dcupl.fn.*` functions take them wrapped with a model key and an optional query:

```typescript
type DcuplGlobalFacetOptions = { modelKey: string; options: DcuplFacetOptions; query?: DcuplGlobalQueryOptions<any> };
// Same shape: DcuplGlobalAggregateOptions (AggregationOptions), DcuplGlobalSuggestionOptions (SuggestionOptions),
// DcuplGlobalGroupByOptions (DcuplGroupByOptions<any>), DcuplGlobalPivotOptions (PivotOptions)
type DcuplGlobalMetadataOptions = { modelKey: string; query?: DcuplGlobalQueryOptions<any> };
```

### DcuplFacetOptions

The options of `facets()`: the attribute, limits, exclusions, sort and the excluded query group. See [facets()](/sdk/fn/facets).

```typescript
type DcuplFacetOptions = {
  attribute: string;
  count?: number;
  excludeZeros?: boolean;
  excludeUndefineds?: boolean;
  excludeUnresolved?: boolean;
  calculateResults?: boolean;
  sort?: 'size-desc' | 'size-asc' | 'value-asc' | 'value-desc';
  excludeGroup?: string;
};
```

### DcuplFacet

One facet value with its count and result keys. `dcupl.fn.facets()` declares the same shape as `FilterItemEntry`. See [facets()](/sdk/fn/facets).

```typescript
type DcuplFacet = {
  key: string;
  enabled: boolean;
  selected: boolean;
  size: number;
  value: boolean | string | null | undefined;
  entry: ListItem;
  resultKeys: string[];
  children?: Array<DcuplFacet>; // declared, but never set
};
```

### AggregationOptions

The options of `aggregate()`, and of each entry of `groupBy({ aggregates })` and `pivot({ values })`. See [aggregate()](/sdk/fn/aggregate).

```typescript
type AggregationOptions = {
  attribute: string;
  types: AggregationType[];
  distinctOptions?: { limit?: number; skipKeys?: boolean };
  groupOptions?: { calculateNotFound?: boolean; groups?: AggregationGroupOption[] };
  excludeUndefineds?: boolean;
};

type AggregationType = 'sum' | 'avg' | 'count' | 'min' | 'max' | 'distinct' | 'group';

type AggregationGroupOption = { from?: any; to?: any; value?: any[] };
```

`excludeZeros`, `excludeUnresolved` and `groupOptions.limit` are not part of `AggregationOptions`: passing one is a type error. `DcuplFacetOptions` keeps `excludeZeros` and `excludeUnresolved`.

### Aggregation

What `aggregate()` returns: only the requested types are set. See [aggregate()](/sdk/fn/aggregate).

```typescript
type Aggregation = {
  attribute: string;
  types: AggregationType[];
  sum?: number;
  avg?: number;
  count?: number;
  min?: number;
  max?: number;
  distinct?: AggregationDistinctValue[];
  group?: AggregationGroupValue[];
};

type AggregationDistinctValue = { value: string; count: number; keys?: string[] };
type AggregationGroupValue = { option: AggregationGroupOption; count: number; keys: string[] };
```

### SuggestionOptions

The options of `suggest()`: the attribute, the search value, limits and which data to search. See [suggest()](/sdk/fn/suggest).

```typescript
// Only SuggestionOptions is exported; narrow it with
// Extract<SuggestionOptions, { relevantData: 'excludeQuery' }> if you need one variant
type SuggestionOptions = SuggestionOptionsFiltered | SuggestionOptionsAll | SuggestionOptionsExcludeQuery;

type SuggestionOptionsBase = {
  attribute: string;
  value: any;
  max?: number;
  calculateResultKeys?: boolean;
  excludeUndefineds?: boolean;
  excludeNulls?: boolean;
  transform?: DcuplQueryTransformOptions[];
  regexFlags?: string;
};

type SuggestionOptionsFiltered = SuggestionOptionsBase & { relevantData?: 'filtered'; excludeQuery?: never };
type SuggestionOptionsAll = SuggestionOptionsBase & { relevantData?: 'all'; excludeQuery?: never };
type SuggestionOptionsExcludeQuery = SuggestionOptionsBase & {
  relevantData: 'excludeQuery';
  excludeQuery: Partial<DcuplQuery | DcuplQueryGroup>;
};
```

### Suggestion

One suggestion: the matched value and the keys of the items that carry it. See [suggest()](/sdk/fn/suggest).

```typescript
type Suggestion = {
  value: string; // typed string; at runtime numbers and booleans keep their type, a date (or Array<date>) value comes back as its ISO string
  keys: string[];
};
```

### DcuplGroupByOptions

The options of `groupBy()`: the grouping attribute, per-group aggregates, which groups return their items, and paging of the groups. See [groupBy()](/sdk/fn/group-by).

```typescript
type DcuplGroupByOptions<T> = DcuplItemsOptions<T> & {
  attribute: string;
  aggregates?: AggregationOptions[];
  items?: DcuplSectionItemOption<T>[];
};

type DcuplSectionItemOption<T> = DcuplItemsOptions<T> & {
  key: string; // a group key, or '*' for every group
};
```

`excludeZeros`, `excludeUndefineds` and `excludeUnresolved` are not part of `DcuplGroupByOptions`: passing one is a type error.

### GroupByResponse

What `groupBy()` returns: the groups, each with its size, aggregates and (if requested) items. See [groupBy()](/sdk/fn/group-by).

```typescript
type GroupByResponse = {
  _meta: { currentSize: number; initialSize: number };
  items: SectionItem[];
};

type SectionItem = ListItem & {
  _meta: { size: number }; // items in this group
  _aggregates: Aggregation[]; // one per entry of options.aggregates
  _items: ListItem[]; // filled only for groups named in options.items
};
```

`key` is the raw attribute value, so a numeric attribute gives number keys although `ListItem` types `key` as a `string`.

### PivotOptions

The options of `pivot()`: row and column dimensions and the aggregations per cell. Only `PivotOptions` is exported; derive the others with e.g. `PivotOptions['rows'][number]`. See [pivot()](/sdk/fn/pivot).

```typescript
type PivotOptions = {
  rows: PivotRowOption[];
  columns: PivotColumnOption[];
  values: PivotValueOption[];
  options?: { calculateTotals?: boolean };
};

type PivotRowOption = { attribute: string; calculateTotals?: boolean };
type PivotColumnOption = { attribute: string; calculateTotals?: boolean };
type PivotValueOption = AggregationOptions;
```

### PivotResponse

What `pivot()` returns: a tree of dimension items and cells. See [pivot()](/sdk/fn/pivot).

```typescript
type PivotResponse = PivotResponseItem;

// Not exported; same shape as PivotResponse
type PivotResponseItem = {
  key: string;
  value?: any;
  values?: Aggregation[];
  columns?: Omit<PivotResponseItem, 'rows'>[];
  rows?: PivotResponseItem[];
};
```

---

## Event types

Subscribing and when each event fires: [Events](/sdk/api/events).

### CallbackFunction

The callback of `dcupl.on()`, `list.on()` and `list.onResultChange()`; each returns an unsubscribe function.

```typescript
type CallbackFunction = (message: DcuplUpdateMessage) => void;
```

### DcuplUpdateMessage

The message an event callback receives (abridged). See [Event message structure](/sdk/api/events#event-message-structure).

```typescript
type DcuplUpdateMessage = {
  type: DcuplUpdateType;
  scope: 'all' | 'global' | 'list' | 'list$';
  action?: 'update';
  origin?: 'user' | 'loader';
  listKey?: string;
  modelKey?: string;
  method?: string; // the operation that triggered the event, as the SDK names it
  args?: any;
  result?: any;
  start?: number;
  end?: number;
  duration?: number;
  key?: number;
};
```

### DcuplUpdateType

The event names. See [All event types](/sdk/api/events#all-event-types) for when each one fires.

```typescript
type DcuplUpdateType =
  | 'data_change'
  | 'dcupl_destroyed'
  | 'dcupl_handle_datacontainer'
  | 'dcupl_initialized'
  | 'dcupl_updated_manually'
  | 'dcupl_partial_update'
  | 'filter_many'
  | 'filter_one'
  | 'fn_aggregate'
  | 'fn_facets'
  | 'fn_groupBy'
  | 'fn_metadata'
  | 'fn_pivot'
  | 'fn_suggest'
  | 'list_created'
  | 'list_destroyed'
  | 'list_updated'
  | 'loader_added'
  | 'loader_config_fetched'
  | 'loader_data_fetched'
  | 'loader_models_fetched'
  | 'loader_scripts_fetched'
  | 'loader_processed'
  | 'loader_removed'
  | 'model_add'
  | 'query_apply_options'
  | 'query_apply'
  | 'query_execute'
  | 'query_get'
  | 'query_has'
  | 'query_many'
  | 'query_one'
  | 'query_remove'
  | 'query_reset'
  | 'result_updated'
  | 'view_add';
```

---

## View types

### ViewDefinition

A stored `section` (groupBy) or `pivot` view on a model, managed with `dcupl.views`. See [views](/sdk/api/dcupl#views).

```typescript
type ViewDefinition = ViewDefinitionSection | ViewDefinitionPivot;

type ViewDefinitionSection = {
  key: string;
  model: string;
  type: 'section';
  primaryAttribute: string;
  aggregates: AggregationOptions[];
  meta?: ModelMetadata;
};

type ViewDefinitionPivot = {
  key: string;
  model: string;
  type: 'pivot';
  options: PivotOptions;
  meta?: ModelMetadata;
};
```

---

## Quality types

What each check and error type means: [Quality & validation](/sdk/advanced/quality-validation).

### AttributeQualityConfig

Validation rules for a property or reference (`quality` on the attribute). Defaults and validators: [AttributeQualityConfig](/sdk/api/models#attributequalityconfig).

```typescript
type AttributeQualityConfig = {
  required?: boolean; // default true
  nullable?: boolean; // default false
  forceStrictDataType?: boolean; // default false
  validators?: {
    email?: { value?: any };
    endsWith?: { value?: any };
    enum?: { value?: any };
    includes?: { value?: any };
    max?: { value?: any };
    maxLength?: { value?: any };
    min?: { value?: any };
    minLength?: { value?: any };
    pattern?: { value?: any };
    unique?: { value?: any };
    startsWith?: { value?: any };
  };
  validatorHandling?: 'loose' | 'strict'; // default 'loose'
};
```

### ModelQualityConfig

Model-level quality settings and the defaults for every attribute of the model; its checks run only while `DcuplInitOptions.quality.enabled` is on as well. See [ModelQualityConfig](/sdk/api/models#modelqualityconfig).

```typescript
type ModelQualityConfig = {
  enabled?: boolean; // default true
  attributes?: Omit<AttributeQualityConfig, 'validators'>;
};
```

### QualityAnalyzer.ErrorGroupSummary

One entry of `dcupl.quality.errors.summary()` (`QualityAnalyzer` is a namespace exported from `@dcupl/common`). After `dcupl.update()` the summary equals what `init()` reports on the same data. See [Error summary](/sdk/advanced/quality-validation#error-summary).

```typescript
type ErrorGroupSummary = {
  key: string; // `model::attribute::errorType`
  model?: string;
  attribute?: string;
  errorGroup: string;
  errorType: string; // QualityAnalyzer.ModelErrorType | QualityAnalyzer.LoaderErrorType
  type: 'model' | 'loader';
  totalCount: number; // also counts beyond maxErrorsPerGroup
  storedCount: number; // records kept (<= maxErrorsPerGroup)
  truncated: boolean; // totalCount > storedCount
};

type ModelErrorType =
  | 'UndefinedAttribute'
  | 'InvalidValidator'
  | 'UndefinedValue'
  | 'NullValue'
  | 'WrongDataType'
  | 'NonUniqueKey'
  | 'MissingKey'
  | 'DuplicatePropertyKey'
  | 'MissingModel'
  | 'MissingProperty'
  | 'MissingReference'
  | 'UnknownExpressionVariable'
  | 'RemoteReferenceKeyNotFound'
  | 'InvalidModelDefinition'
  | 'UnknownColumn';

type LoaderErrorType =
  | 'InvalidConfig'
  | 'InvalidResource'
  | 'ScriptingDisabled'
  | 'TransformerError'
  | 'EndpointScriptMissing'
  | 'EndpointDuplicate';
```

---

## Script types

Exported from `@dcupl/common` (`RestApi.TemplateEndpoint` included). See [Scripts and script modes](/sdk/guides/scripts) for the contract behind them.

### ScriptType

The mode a script runs in. The first parameter of every script, `script_type`, holds one of these values.

```typescript
type ScriptType = 'script' | 'async_script' | 'sort' | 'operator' | 'validator' | 'endpoint';
```

`validator` is reserved; no call site dispatches it.

### EndpointScriptRequest

The `request` an `endpoint` script receives: plain data built from the HTTP request, without methods.

```typescript
type EndpointScriptMethod = 'GET' | 'POST';

type EndpointScriptRequest = {
  method: EndpointScriptMethod;
  path: string;
  params: Record<string, string>;
  query: Record<string, string | string[]>;
  body: unknown;
  headers: Record<string, string>;
};
```

| Property  | Type                                 | Description                                                                                                              |
| --------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ |
| `method`  | `'GET' \| 'POST'`                    | HTTP method                                                                                                              |
| `path`    | `string`                             | Path relative to the instance's `endpoints/` prefix, no leading slash, no query string, e.g. `orders/42`                 |
| `params`  | `Record<string, string>`             | Values of the matched endpoint's `:name` segments, e.g. `{ id: '42' }` for `orders/:id`                                  |
| `query`   | `Record<string, string \| string[]>` | Query string, repeated keys as arrays. The host removes its own keys (`api-key` spellings, `v`)                          |
| `body`    | `unknown`                            | Parsed JSON body for `POST`, `undefined` for `GET`                                                                       |
| `headers` | `Record<string, string>`             | Lower-cased header names. The host removes credentials: `api-key`, `apikey`, `x-api-key`, `authorization`, `cookie`, `v` |

### EndpointScriptContext

Everything an `endpoint` script sees besides `script_type`.

```typescript
type EndpointScriptContext = { dcupl: ReadOnlyDcupl; request: EndpointScriptRequest; options: Record<string, unknown> };
```

| Property  | Type                      | Description                                                                                                              |
| --------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `dcupl`   | `ReadOnlyDcupl`           | The read-only facade of the instance                                                                                     |
| `request` | `EndpointScriptRequest`   | The request                                                                                                              |
| `options` | `Record<string, unknown>` | Host-provided; the app runner passes the endpoint's template entry (`path`, `scriptKey`, `description`). `{}` by default |

### ReadOnlyDcupl

What an `endpoint` script may call. Everything reads; nothing stages data, registers scripts or operators, or re-initialises. One frozen object per instance; every result is a deep copy.

```typescript
type ReadOnlyDcupl = {
  query: {
    one: <T extends ListItem = ListItem>(options: DcuplGlobalItemOptions<T>) => T | null;
    many: <T extends ListItem = ListItem>(options: DcuplGlobalManyItemOptions<T>) => T[];
    execute: <T extends ListItem = ListItem>(options: DcuplGlobalQueryOptions<T>) => T[];
    generate: (
      modelKey: string,
      query: DcuplQueryGroup | DcuplQuery | DcuplQuery[] | DcuplQueryGroup[],
    ) => DcuplGlobalQueryOptions<any>;
  };
  fn: {
    pivot: (options: DcuplGlobalPivotOptions) => PivotResponse;
    aggregate: (options: DcuplGlobalAggregateOptions) => Aggregation;
    suggest: (options: DcuplGlobalSuggestionOptions) => Suggestion[];
    groupBy: (options: DcuplGlobalGroupByOptions) => GroupByResponse;
    facets: (options: DcuplGlobalFacetOptions) => FilterItemEntry[];
    metadata: (options: DcuplGlobalMetadataOptions) => ListMetadata;
  };
  models: { get: (modelKey: string) => ModelDefinition | undefined; keys: () => string[] };
  views: { get: (viewKey: string) => ViewDefinition | undefined; keys: (options?: { modelKey: string }) => string[] };
  scripts: { keys: () => string[] };
};
```

Absent on purpose: `data`, `lists`, `init`, `update`, `scripts.set`/`remove`, `query.registerCustomOperator`. They are `undefined`, so calling one (`dcupl.data.update(...)`) is a `TypeError` inside the script.

### ScriptNotFoundError

Thrown by `scripts.execute` and rejected by `scripts.executeAsync`/`scripts.executeEndpoint` when the key is not registered.

```typescript
class ScriptNotFoundError extends Error {
  readonly name = 'ScriptNotFound';
  readonly key: string;
  // message: `Script ${key} not found`
}
```

Check `error.name === 'ScriptNotFound'`, not `instanceof`: `@dcupl/core` bundles its own copy of `@dcupl/common`.

### RestApi.TemplateEndpoint

One scripted endpoint in a REST API template. See [Scripted endpoints](/console/rapi/scripted-endpoints).

```typescript
type TemplateEndpoint = { path: string; method: 'GET' | 'POST'; scriptKey: string; description?: string };

// on RestApi.Template
endpoints?: TemplateEndpoint[];
```

| Property      | Type              | Description                                                                                                                                                   |
| ------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `path`        | `string`          | URL-safe segments separated by `/`, no leading slash; a segment starting with `:` is a path parameter. Pattern `^(:?[A-Za-z0-9_.~-]+)(/:?[A-Za-z0-9_.~-]+)*$` |
| `method`      | `'GET' \| 'POST'` | HTTP method                                                                                                                                                   |
| `scriptKey`   | `string`          | `scriptKey` of a `type: 'script'` loader resource. Only listed scripts are callable                                                                           |
| `description` | `string`          | Shown as the operation summary in the instance's OpenAPI document                                                                                             |

`method + path` must be unique per template; the Console form and the runner (quality error `EndpointDuplicate`) check this, the schema does not.

### endpointScriptContextTypes

A `string` holding the declarations above as one global `.d.ts` — `script_type`, `dcupl`, `request`, `options`, `context`, `query`, `item`, `items`, `resolve` and `reject` as `declare const` globals plus the types. Load it as an extra lib in an editor such as Monaco to get completions in script files.

---

## Classes

### Dcupl

The public surface of the `Dcupl` class from `@dcupl/core` (abridged; the namespaces are plain object members, not named types). Every member is documented on [Dcupl class](/sdk/api/dcupl).

```typescript
class Dcupl {
  constructor(options?: DcuplInitOptions);

  models: {
    get(modelKey: string): ModelDefinition | undefined;
    set(model: ModelDefinition): void;
    update(model: ModelDefinition): void;
    remove(modelKey: string): void;
    keys(): string[];
  };
  data: {
    // Staged; applied by the next dcupl.update() (or init())
    set(data: RawItem[], options: DataOptions): void;
    update(data: RawItem[], options: DataOptions): void;
    upsert(data: RawItem[], options: DataOptions): void;
    remove(data: RawItem[], options: DataOptions): void;
    reset(options: { model: string }): void;
    apply(container: DataContainer): void;
  };
  lists: {
    create<T extends RawItem = RawItem>(options: {
      modelKey: string;
      listKey?: string;
      listItemKeys?: string[];
      query?: DcuplGlobalQueryOptions<ListItem>;
    }): DcuplList<T>;
    get(listKey: string): DcuplList | undefined;
    getAll(options?: { modelKey: string }): DcuplList[];
    destroy(options?: { listKey?: string; modelKey?: string }): void;
  };
  query: {
    one<T extends ListItem = ListItem>(options: DcuplGlobalItemOptions<T>): T | null;
    many<T extends ListItem = ListItem>(options: DcuplGlobalManyItemOptions<T>): T[];
    execute<T extends ListItem = ListItem>(options: DcuplGlobalQueryOptions<T>): T[];
    generate(
      modelKey: string,
      query: DcuplQueryGroup | DcuplQuery | DcuplQuery[] | DcuplQueryGroup[],
    ): DcuplGlobalQueryOptions<any>;
    registerCustomOperator(operator: string, fn: CustomOperatorFn): void; // deprecated: use a custom script
  };
  fn: {
    pivot(options: DcuplGlobalPivotOptions): PivotResponse;
    aggregate(options: DcuplGlobalAggregateOptions): Aggregation;
    suggest(options: DcuplGlobalSuggestionOptions): Suggestion[];
    groupBy(options: DcuplGlobalGroupByOptions): GroupByResponse;
    facets(options: DcuplGlobalFacetOptions): FilterItemEntry[];
    metadata(options: DcuplGlobalMetadataOptions): ListMetadata;
  };
  views: {
    get(viewKey: string): ViewDefinition | undefined;
    keys(options?: { modelKey: string }): string[];
    set(view: ViewDefinition): void;
    remove(viewKey: string): void;
  };
  scripts: {
    set(key: string, script: string): void;
    remove(key: string): void;
    get(key: string): string | undefined;
    keys(): string[];
    execute(key: string, options?: any): any;
    executeAsync(key: string, options?: any): any;
    executeEndpoint(key: string, request: EndpointScriptRequest, options?: Record<string, unknown>): Promise<unknown>;
  };
  loaders: {
    add(loader: any, key?: string): void; // a DcuplAppLoader from @dcupl/loader
    remove(key: string): void;
    get(key: string): any;
  };
  quality: { errors: { summary(): QualityAnalyzer.ErrorGroupSummary[] } };
  initOptions: DcuplInitOptions;
  version: string; // the installed @dcupl/core version
  readonly sealed: boolean;

  init(): Promise<boolean>;
  update(options?: { autoUpdateLists?: boolean }): Promise<boolean>;
  seal(): void;
  destroy(): void;
  on(callback: CallbackFunction): () => void;
}
```

---

## See also

- [Dcupl class API](/sdk/api/dcupl) - Main class reference
- [Functions API](/sdk/api/functions) - The global `dcupl.fn.*` form and its errors
- [DcuplAppLoader API](/sdk/api/loader) - The loader's types (`AppLoaderConfiguration`: resources, applications, process options)
- [Query Operators](/sdk/api/query-operators) - Operator reference
