.md

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 section names its own packages and is documented only here.

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.

DcuplInitOptions

The options object of new Dcupl(options). See DcuplInitOptions.

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.

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)

DcuplInitConfig

The project a loader added with dcupl.loaders.add() reads from: its projectId, apiKey and version variables. See DcuplInitConfig.

// 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.

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.

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 and Limiting stored errors.

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

DcuplInitLoggingConfig

Logging options; typed, but not applied to the SDK core's logs. See DcuplInitLoggingConfig.

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.

type DcuplUpdateOptions = { autoUpdateLists?: boolean };

Model types

Field-by-field reference with defaults and examples: Models API → Type definitions.

ModelDefinition

A data model: its key, properties, references, key settings and quality defaults. See ModelDefinition.

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.

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.

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.

RawItem

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

type RawItem = any;

ListItem

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

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.

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.

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. @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.

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.

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.

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.

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().

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.

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

DcuplGlobalItemOptions

The options of dcupl.query.one() and dcupl.query.many(). See Global queries.

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.

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.

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.

DcuplListOptions

The options for creating a list: its model, key, scope and auto-update. See DcuplListOptions.

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.

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().

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. The list.catalog.fn.* functions take the options below; the dcupl.fn.* functions take them wrapped with a model key and an optional query:

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().

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().

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().

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().

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().

// 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().

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().

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().

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().

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().

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.

CallbackFunction

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

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

DcuplUpdateMessage

The message an event callback receives (abridged). See Event message structure.

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 for when each one fires.

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.

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.

AttributeQualityConfig

Validation rules for a property or reference (quality on the attribute). Defaults and validators: AttributeQualityConfig.

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.

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.

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 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.

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.

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.

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.

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.

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.

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.

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