Models API
The Models API (dcupl.models) provides methods for managing data model definitions in dcupl. Models define the structure, types, and relationships of your data.
Methods
set()
Sets or replaces a model definition. If a model with the same key exists, it will be replaced.
Signature:
set(model: ModelDefinition): voidParameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
model |
ModelDefinition |
Yes | The model definition to set |
Examples:
dcupl.models.set({
key: 'Product',
properties: [
{ key: 'name', type: 'string' },
{ key: 'price', type: 'float' },
],
});dcupl.models.set({
key: 'Product',
properties: [
{ key: 'name', type: 'string' },
{ key: 'price', type: 'float' },
],
references: [{ key: 'category', type: 'singleValued', model: 'Category' }],
});dcupl.models.set({
key: 'Product',
keyProperty: 'id',
autoGenerateKey: false,
properties: [
{ key: 'name', type: 'string' },
{ key: 'price', type: 'float' },
{ key: 'tags', type: 'Array<string>', separator: ',' },
],
references: [{ key: 'category', type: 'singleValued', model: 'Category' }],
quality: {
enabled: true,
attributes: {
required: true,
},
},
});update()
Updates an existing model definition, merging with existing properties.
Signature:
update(model: ModelDefinition): voidParameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
model |
ModelDefinition |
Yes | The model definition to merge |
Examples:
dcupl.models.update({
key: 'Product',
properties: [{ key: 'description', type: 'string' }],
});dcupl.models.update({
key: 'Product',
references: [{ key: 'manufacturer', type: 'singleValued', model: 'Manufacturer' }],
});get()
Retrieves a model definition by key.
Signature:
get(modelKey: string): ModelDefinition | undefinedParameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
modelKey |
string |
Yes | The key of the model to retrieve |
Returns: ModelDefinition | undefined - The model definition or undefined if not found
Examples:
const model = dcupl.models.get('Product');
if (model) {
console.log(model.properties);
console.log(model.references);
}const exists = dcupl.models.get('Product') !== undefined;const model = dcupl.models.get('Product');
if (model) {
const properties = model.properties || [];
const references = model.references || [];
}remove()
Removes a model definition by key.
Signature:
remove(modelKey: string): voidParameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
modelKey |
string |
Yes | The key of the model to remove |
Examples:
dcupl.models.remove('Product');['Product', 'Category', 'Tag'].forEach((key) => {
dcupl.models.remove(key);
});keys()
Returns an array of all model keys.
Signature:
keys(): string[]Returns: string[] - Array of model keys
Examples:
const modelKeys = dcupl.models.keys();
console.log(modelKeys); // ['Product', 'Category', 'Tag']const hasProduct = dcupl.models.keys().includes('Product');const modelCount = dcupl.models.keys().length;Type Definitions
ModelDefinition
Defines the structure of a data model.
Type Definition:
type ModelDefinition<ModelNames extends string = string> = {
key: ModelNames;
properties?: Property[];
references?: Reference[];
data?: RawItem[];
keyProperty?: string;
autoGenerateKey?: boolean;
autoGenerateProperties?: boolean;
supportsAutoCreation?: boolean;
valueMappings?: ValueMappingConfig[];
meta?: ModelMetadata;
quality?: ModelQualityConfig;
};Properties:
| Property | Type | Description |
|---|---|---|
key |
string |
Unique model identifier |
properties |
Property[] |
Array of property definitions |
references |
Reference[] |
Array of reference definitions |
data |
RawItem[] |
Optional inline data for the model |
keyProperty |
string |
Property to use as item key (default: 'key') |
autoGenerateKey |
boolean |
Auto-generate unique keys for items without one (default: false) |
autoGenerateProperties |
boolean |
Infer property definitions from data structure (default: false) |
supportsAutoCreation |
boolean |
Allow automatic item creation when referenced by other models (default: false) |
valueMappings |
ValueMappingConfig[] |
Transform values during data loading |
meta |
ModelMetadata |
Arbitrary metadata attached to the model |
quality |
ModelQualityConfig |
Quality validation configuration |
Examples:
const model: ModelDefinition = {
key: 'Product',
properties: [{ key: 'name', type: 'string' }],
};const model: ModelDefinition = {
key: 'Product',
keyProperty: 'productId',
autoGenerateKey: false,
properties: [
{ key: 'name', type: 'string' },
{ key: 'price', type: 'float' },
{ key: 'createdAt', type: 'date', inputFormat: 'yyyy-MM-dd' },
],
references: [
{ key: 'category', type: 'singleValued', model: 'Category' },
{ key: 'tags', type: 'multiValued', model: 'Tag' },
],
quality: {
enabled: true,
attributes: {
required: true,
},
},
};Model Options
keyProperty
Specifies which property in your data should be used as the unique item identifier. By default, dcupl looks for a property named key.
const model: ModelDefinition = {
key: 'Product',
keyProperty: 'productId', // Use 'productId' instead of 'key'
properties: [
{ key: 'productId', type: 'string' },
{ key: 'name', type: 'string' },
],
};
// Data can now use 'productId' as the identifier
dcupl.data.set(
[
{ productId: 'SKU-001', name: 'Widget' },
{ productId: 'SKU-002', name: 'Gadget' },
],
{ model: 'Product' }
);autoGenerateKey
When true, dcupl generates a unique 10-character key for items that don't have one. Useful when your data doesn't have natural identifiers.
const model: ModelDefinition = {
key: 'LogEntry',
autoGenerateKey: true,
properties: [
{ key: 'message', type: 'string' },
{ key: 'timestamp', type: 'date' },
],
};
// Data without keys - dcupl generates them automatically
dcupl.data.set(
[
{ message: 'User logged in', timestamp: '2025-01-15' },
{ message: 'User logged out', timestamp: '2025-01-15' },
],
{ model: 'LogEntry' }
);
// Items will have auto-generated keys like 'a8f3k2m9x1'autoGenerateProperties
When true, dcupl infers property definitions from the data structure. Useful for quick prototyping or when working with dynamic data.
const model: ModelDefinition = {
key: 'DynamicData',
autoGenerateProperties: true,
// No properties defined - they will be inferred from data
};
dcupl.data.set([{ key: 'item1', name: 'Test', count: 42, active: true }], { model: 'DynamicData' });
// Properties 'name', 'count', 'active' are automatically createdsupportsAutoCreation
When true, items are automatically created in this model when referenced by other models. This is useful for lookup tables or reference data that might be incomplete.
const productModel: ModelDefinition = {
key: 'Product',
references: [{ key: 'category', type: 'singleValued', model: 'Category' }],
data: [
{ key: 'p1', category: 'electronics' },
{ key: 'p2', category: 'books' },
],
};
const categoryModel: ModelDefinition = {
key: 'Category',
supportsAutoCreation: true, // Categories created automatically
properties: [{ key: 'name', type: 'string' }],
};
// After init, 'electronics' and 'books' exist in Category model
// even though no Category data was explicitly providedvalueMappings
Transform values during data loading. Useful for normalizing data, handling special values, or converting between formats.
Type Definition:
type ValueMappingConfig = {
attributes: string[]; // Properties/references to apply mapping to
values: {
from: (string | '$dcupl_falsy')[]; // Values to match
to: any; // Replacement value
}[];
};const model: ModelDefinition = {
key: 'Product',
valueMappings: [
{
attributes: ['category', 'brand'],
values: [
{
from: ['$dcupl_falsy'], // Matches undefined, null, empty string
to: 'uncategorized',
},
],
},
],
references: [
{ key: 'category', type: 'singleValued', model: 'Category' },
{ key: 'brand', type: 'singleValued', model: 'Brand' },
],
};const model: ModelDefinition = {
key: 'Product',
valueMappings: [
{
attributes: ['inStock'],
values: [
{ from: ['Yes', 'yes', 'Y', '1'], to: true },
{ from: ['No', 'no', 'N', '0'], to: false },
],
},
],
properties: [{ key: 'inStock', type: 'boolean' }],
};meta
Attach arbitrary metadata to the model for documentation or application-specific purposes.
const model: ModelDefinition = {
key: 'Product',
meta: {
name: 'Product Catalog',
description: 'All products available for sale',
version: '2.0',
maintainer: 'catalog-team@example.com',
},
properties: [{ key: 'name', type: 'string' }],
};
// Access metadata
const productModel = dcupl.models.get('Product');
console.log(productModel?.meta?.description);Property
Defines a property (field) in a model.
Type Definition:
type Property =
| PropertyString
| PropertyStringArray
| PropertyInt
| PropertyIntArray
| PropertyFloat
| PropertyFloatArray
| PropertyDate
| PropertyDateArray
| PropertyJson
| PropertyBoolean
| PropertyAny;Common Properties:
| Property | Type | Description |
|---|---|---|
key |
string |
Unique property identifier |
type |
PropertyType |
Data type of the property |
index |
boolean |
Create index for this property |
expression |
string |
Computed property expression |
derive |
DeriveConfig |
Derive value from reference |
quality |
AttributeQualityConfig |
Validation rules |
Property Types:
| Type | Description |
|---|---|
'string' |
Text values |
'Array |
Array of text values |
'int' |
Integer numbers |
'Array |
Array of integers |
'float' |
Floating point numbers |
'Array |
Array of floats |
'date' |
Date/time values |
'Array |
Array of dates |
'boolean' |
Boolean values |
'json' |
JSON objects |
'any' |
Any type |
Examples:
{
key: 'name',
type: 'string'
}{
key: 'price',
type: 'float',
fractionDigits: 2
}{
key: 'tags',
type: 'Array<string>',
separator: ','
}{
key: 'createdAt',
type: 'date',
inputFormat: 'yyyy-MM-dd',
UTC: true
}{
key: 'categoryName',
type: 'string',
derive: {
localReference: 'category',
remoteProperty: 'name'
}
}{
key: 'discountedPrice',
type: 'float',
expression: 'price * (1 - discount)'
}{
key: 'email',
type: 'string',
quality: {
required: true,
validators: {
email: { value: true }
}
}
}Reference
Defines a relationship to another model.
Type Definition:
type Reference =
| ReferenceBase
| ResolvedReference
| DerivedReference
| GroupedReference
| QueryReference;Common Properties:
| Property | Type | Description |
|---|---|---|
key |
string |
Unique reference identifier |
type |
'singleValued' | 'multiValued' |
Single or multiple items |
model |
string |
Target model key |
separator |
string |
Separator for multi-valued references |
validity |
'loose' | 'strict' |
Validation strictness |
Reference Types:
1. Basic Reference
{
key: 'category',
type: 'singleValued',
model: 'Category'
}
{
key: 'tags',
type: 'multiValued',
model: 'Tag',
separator: ','
}2. Resolved Reference
{
key: 'relatedProducts',
type: 'multiValued',
model: 'Product',
resolve: {
reference: 'productId',
model: 'ProductRelation'
}
}3. Derived Reference
{
key: 'similarProducts',
type: 'multiValued',
model: 'Product',
derive: {
localReference: 'category',
remoteReference: 'products'
}
}4. Grouped Reference
{
key: 'categoryGroup',
type: 'multiValued',
model: 'Product',
groupBy: {
reference: 'category',
includeSelfInGroup: false
}
}5. Query Reference
{
key: 'activeProducts',
type: 'multiValued',
model: 'Product',
query: {
modelKey: 'Product',
queries: [
{ operator: 'eq', attribute: 'status', value: 'active' }
]
}
}Property Options
derive
Derives a property value from a referenced model.
Type: { localReference: string; remoteProperty: string; separator?: string }
Examples:
{
key: 'categoryName',
type: 'string',
derive: {
localReference: 'category',
remoteProperty: 'name'
}
}{
key: 'tagNames',
type: 'Array<string>',
derive: {
localReference: 'tags',
remoteProperty: 'name',
separator: ', '
}
}expression
Defines a computed property using an expression.
Type: string
Examples:
{
key: 'total',
type: 'float',
expression: 'price * quantity'
}{
key: 'discountedPrice',
type: 'float',
expression: 'price * (1 - discount) * (taxRate + 1)'
}{
key: 'status',
type: 'string',
expression: 'quantity > 0 ? "available" : "out of stock"'
}quality
Defines validation rules for a property.
Type: AttributeQualityConfig
Examples:
{
key: 'name',
type: 'string',
quality: {
required: true
}
}{
key: 'email',
type: 'string',
quality: {
required: true,
validators: {
email: { value: true }
}
}
}{
key: 'age',
type: 'int',
quality: {
required: true,
validators: {
min: { value: 0 },
max: { value: 120 }
}
}
}{
key: 'zipCode',
type: 'string',
quality: {
validators: {
pattern: { value: '^[0-9]{5} }
}
}
}{
key: 'username',
type: 'string',
quality: {
required: true,
validators: {
unique: { value: true }
}
}
}ModelQualityConfig
Quality validation configuration for a model.
Type Definition:
type ModelQualityConfig = {
enabled?: boolean;
attributes?: AttributeQualityConfig;
};Example:
{
key: 'Product',
properties: [...],
quality: {
enabled: true,
attributes: {
required: true,
nullable: false
}
}
}AttributeQualityConfig
Quality validation configuration for properties.
Type Definition:
type AttributeQualityConfig = {
required?: boolean;
nullable?: boolean;
forceStrictDataType?: boolean;
validators?: AttributeValidatorConfig;
validatorHandling?: 'loose' | 'strict';
};Properties:
| Property | Type | Description |
|---|---|---|
required |
boolean |
Property must have a value |
nullable |
boolean |
Property can be null |
forceStrictDataType |
boolean |
Enforce strict type checking |
validators |
AttributeValidatorConfig |
Validation rules |
validatorHandling |
'loose' | 'strict' |
Error handling mode |
AttributeValidatorConfig
Validator configuration for properties.
Type Definition:
type AttributeValidatorConfig = {
email?: ValidatorConfig;
endsWith?: ValidatorConfig;
enum?: ValidatorConfig;
includes?: ValidatorConfig;
max?: ValidatorConfig;
maxLength?: ValidatorConfig;
min?: ValidatorConfig;
minLength?: ValidatorConfig;
pattern?: ValidatorConfig;
unique?: ValidatorConfig;
startsWith?: ValidatorConfig;
};Available Validators:
| Validator | Description | Value Type |
|---|---|---|
email |
Email format validation | boolean |
endsWith |
String ends with value | string |
enum |
Value must be in list | any[] |
includes |
String contains value | string |
max |
Maximum value | number |
maxLength |
Maximum string length | number |
min |
Minimum value | number |
minLength |
Minimum string length | number |
pattern |
Regex pattern match | string |
unique |
Unique across all items | boolean |
startsWith |
String starts with value | string |
Examples:
validators: {
email: { value: true },
minLength: { value: 5 },
maxLength: { value: 100 },
pattern: { value: '^[a-zA-Z0-9]+ }
}
validators: {
min: { value: 0 },
max: { value: 1000 },
unique: { value: true }
}
validators: {
enum: { value: ['active', 'inactive', 'pending'] },
startsWith: { value: 'PRD-' }
}Complete Examples
Product Model
dcupl.models.set({
key: 'Product',
keyProperty: 'productId',
properties: [
{
key: 'name',
type: 'string',
quality: {
required: true,
validators: {
minLength: { value: 3 },
maxLength: { value: 100 },
},
},
},
{
key: 'price',
type: 'float',
fractionDigits: 2,
quality: {
required: true,
validators: {
min: { value: 0 },
},
},
},
{
key: 'description',
type: 'string',
},
{
key: 'tags',
type: 'Array<string>',
separator: ',',
},
{
key: 'createdAt',
type: 'date',
inputFormat: 'yyyy-MM-dd',
UTC: true,
},
],
references: [
{
key: 'category',
type: 'singleValued',
model: 'Category',
},
{
key: 'manufacturer',
type: 'singleValued',
model: 'Manufacturer',
},
],
quality: {
enabled: true,
},
});Model with Derived Properties
dcupl.models.set({
key: 'Product',
properties: [
{ key: 'name', type: 'string' },
{ key: 'price', type: 'float' },
{ key: 'discount', type: 'float' },
{
key: 'finalPrice',
type: 'float',
expression: 'price * (1 - discount)',
fractionDigits: 2,
},
{
key: 'categoryName',
type: 'string',
derive: {
localReference: 'category',
remoteProperty: 'name',
},
},
],
references: [{ key: 'category', type: 'singleValued', model: 'Category' }],
});Model with Quality Checks
dcupl.models.set({
key: 'User',
properties: [
{
key: 'username',
type: 'string',
quality: {
required: true,
validators: {
minLength: { value: 3 },
maxLength: { value: 20 },
pattern: { value: '^[a-zA-Z0-9_]+ },
unique: { value: true },
},
},
},
{
key: 'email',
type: 'string',
quality: {
required: true,
validators: {
email: { value: true },
unique: { value: true },
},
},
},
{
key: 'age',
type: 'int',
quality: {
validators: {
min: { value: 18 },
max: { value: 120 },
},
},
},
{
key: 'status',
type: 'string',
quality: {
required: true,
validators: {
enum: { value: ['active', 'inactive', 'pending'] },
},
},
},
],
quality: {
enabled: true,
attributes: {
required: true,
nullable: false,
forceStrictDataType: true,
},
},
});Complex References
// Product model with various reference types
dcupl.models.set({
key: 'Product',
properties: [
{ key: 'name', type: 'string' },
{ key: 'price', type: 'float' },
],
references: [
// Basic reference
{
key: 'category',
type: 'singleValued',
model: 'Category',
},
// Multi-valued reference
{
key: 'tags',
type: 'multiValued',
model: 'Tag',
separator: ',',
},
// Resolved reference
{
key: 'relatedProducts',
type: 'multiValued',
model: 'Product',
resolve: {
reference: 'productId',
model: 'ProductRelation',
},
},
// Query reference
{
key: 'similarProducts',
type: 'multiValued',
model: 'Product',
query: {
modelKey: 'Product',
queries: [{ operator: 'eq', attribute: 'category', value: { key: '$self.category' } }],
},
},
],
});