Data Def™️

Data Def™️ is a specification for declaratively indicating how blocks of data are utilized.

Data Def Fields

The following section outlines a comprehensive list of currently supported Data Def fields.

Identity Fields


type: string

A unique identifier used to reference the definition. This identifier must be unique within the data block it is defined in.

An id must conform to the regular expression [a-zA-Z_][a-zA-Z0-9_-]* or the reserved id *

* {

dataId-1 {

dataId-n {


type: string\ default: undefined

An optional namespace to use. Namespaces are used to resolve ids within multiple data block instances and declarations. Namespaces may be used by a provider to partition data regions.

User Interface Fields


type: string\ default: undefined

A human readable name used in reports and user interfaces. A variant of the id will be used if not specified.


type: string\ default: undefined

A brief description of the property. The description is used in tooltips, detail sections, and documentation.


type: string\ default: undefined

A description of the property to be displaying in user interface hint areas.


type: string\ default: undefined

The type of data. This can be inferred from the default value or the schema.


type: string\ default: undefined

The subtype of data.

For example

  type: string;
  type2: password;

State Management Fields

Value fields affect how a value is loaded or saved


type: string\ default: undefined

Specifies the resource provider that manages the data.


type: object\ default: undefined

Provider specific properties


type: string \ default: undefined

Specifies the accounts, applications, sessions, and devices that share the data. Scope is meant to augment provider settings with universal parameters. See [[Data Language Block Scopes]]

Scope does not define persistence


Indicates how data is stored and loaded between instantiations


type: any | function\ default: undefined

The default value of the data. This value will be used in several circumstances:

  • to initialize a provider
  • when resetting the data
  • when a provider cannot be reached
  • to determine if a value is not the default
  • generating a schema


type: function\ default: undefined

A function to validate data integrity when initializing it from an external source. This function can modify the incoming value or properties on the incoming value.

The signature the function is:

(value:T, context:Context) => T | undefined

A validate function can return a new or replaced value. It can also throw an exception.

If the validate function returns undefined, the value is considered valid.


type: selector-string | element | (selector-string | element)[] | function\ default: undefined

Targets to use when autobinding data to elements. Multiple targets may be set for the same dataId.


type: object\ default: undefined

Determines the schema to use for a property


type: true | false | number\ default: undefined

Determines the exclusivity of a field. This may be configured to allow a field to be modified by only a single peer over a period of time. For instance, the system may be configured to a single peer to scroll, with a mandatory timeout before allowing another peer to scroll.

  type: 'none' | 'default' | 'json'
  value: any


type: event | group | user\ default: undefined

Determines how the value is distributed and persisted.


type: TBD\ default: undefined

Determines how the value is handled during loading and errors.

Security Fields


type: boolean\ default: undefined

Indicates if the field should be enumerated in user interfaces


type: object\ default: undefined

Indicates if the field should be encrypted when storing or transmitting

Data Shaping Fields


type: object\ default: undefined

The following fields may be set in the shaping object. They are all optional.


type: boolean

Only persist the value when commit is called. This operation may be attached to an element blur (losing focus), to an enter keypress on a text field, user interface side shaping, or by pressing a commit button, etc.

When commit is enabled, no other shaping parameters are considered.1


type: number

Delays sending updates until time based conditions are met.


type: number

Limits the frequency of updates sent. Throttling does not alter content.


type: boolean

Indicates if the value is sent immediately, before and timeouts.


type: number

Indicates the change between 2 set values required to trigger an immediate send.


Indicates if, when, and how data is compressed before transfering or storing. Also indicates compression parameters and protocol.


Indicates if and how cached updates are combined or replaced before sending them.

Developer Tools Fields


type: true | false\ default: undefined

Indicates if the data should be debugged. This includes tracing operations such as lifecycle, initialization, validation, reads, writes, and errors.


type: true | false | (read | write | permission|error)[]\ default: undefined

Indicates if data access (reads, writes, permissions, errors) of the data should be logged.

Unfiled Fields


Data Language Block

URM uses a declarative approach for working with data.

URM defines a data language block specification that allows the platform to manage boilerplate functionality The language block also allows developers to manage the granularity of data functionality from a centralized location. The declarative approach also facilitates code reuse.

Data can be defined using many data block fields that configure features such as persistence, groups, network shaping, debugging, etc. Data definitions may be referenced using their ID from multiple places within a codebase.

The Data Block API provides methods to interact with data definitions, the client, and providers.

Data Language Block features can be leveraged by simply creating data block value from a data block definition or a plain object.

const animal = {
  name: 'Woolly',
  type: 'dog'

// Equivalent conversions

const animal = dlb({
  name: 'Woolly',
  type: 'dog'

const animal = dlb({
  name: ()=> 'Woolly',
  type: ()=> 'dog',

const animal = dlb({
  name: { default: ()=> 'Woolly', displayName: 'Name' },
  type: { default:()=> 'dog', displayName: 'Type' },

// Default field values can be set for all fields. 
const animal = dlb({
  name: 'Woolly',
  type: 'dog'
}, {provider:’local.shared’})

Data Management

Data Block can automatically manage many application concerns. Here is a comprehensive list.

[todo descriptions and categories]

  • Availability
  • Structure
  • Schema Generation
  • Validation
    • manual validation
    • automatic validation
    • phases
    • field validation
    • block validation
    • local validation
    • remote validation
  • Searchable Options
  • Field Mapping
  • Initialization
  • External Change Notification
  • Persistence
  • Error Handling
  • Synchronization
  • Exclusivity And Locks
  • Sharing
  • Shaping
    • throttling
    • debouncing
    • aggregation
    • summation
    • averaging
    • merging
    • filtering
  • Binding (To UI and other data sources)
  • Security
  • Plugin / Tapping
  • Monitoring
  • Identification / Organization
  • Reusability
  • UI Generation
  • Conflict Resolution
  • Undo/Redo
  • Loading State
  • Error State
  • Transactions
  • Dirty state
    • detect if the local and remote state are out of sync
  • SAS (Selective Aspect Synchronization)
  • Hysteresis
  • Reset
  • Creation factories
  • Memory and object tracking
  • i8n - internationalization for language strings
  • Documentation
  • Context sensitive help
  • Composable definitions
  • Language independent specifications
  • Field Mapping
    • Field Flattening
  • Enumerable
  • Security
    • Encryption
    • Transmission
    • Storage
    • Visibility
    • Salt

The <data> block

The current approach used by modern web technologies is to combine three types of language blocks into one or more files. This structure follows the "separation of concerns" principle. For an example, see

<!-- structure and content (typically HTML) -->

<!-- logic, executable code and data declarations (typically Javascript) -->

<!-- style directives (typically CSS) -->

URM adds an additional Data Language Block type to the standard language blocks.

<!-- data binding, persistence, shaping, flow control, validation, provider, ui hints, etc.  -->

Data Block Syntax

The syntax of a data block resembles CSS and Javascript. Whereas CSS defines selectors, a data block defines data block definitions. Each data block definition is comprised of a dataId, followed by data block definition fields.

<dataId> { 
  <field-name>: <field-value>;
  <field-name-n>: <field-value-n>;

<dataId-n> { 
  <field-name>: <field-value>;
  <field-name-n>: <field-value-n>;

Whitespace is optional.

name{displayName:Name;description:Your full name;}age{type:number;}

DataId and Field Names

This regular expression describes valid id and field names: [a-zA-Z_][a-zA-Z_0-9\-]*

Examples of valid values


Examples of invalid values


Field Values

A field value is always interpreted as a string, with any surrounding whitespace trimmed.

If the field name is prefixed with a :, the field value will be evaluated using either eval(...) or JSON.parse(...). If the evaluated value returns a function, the function will invoked to resolve the actual value.

name_eval {
  displayName: () => "Some" + " Person"
name_json {
  displayName: "Some Person"

Field values terminate with a ;. If a field value uses a ; or \ character, the character must be escaped with a \ character. This applies to strings, parsed strings, and evaluated strings

name {
  description: I have a \; and a \\ in my description;

Default Field Values

Default field values may be defined using the reserved DataId *. These field values apply to any definition in the Data Block that omits the field.

* {
  provider: some_provider;
  namespace: some_namespace;


An example Data Block with options.

* {
  provider: LocalStorage;

my-string {
 scope: workspace;
 :debounce: 100;
 :validate: myValidateFunction;
 bind: #some-element
 default: () => {message: 'Hello World'}

// get the provided value
const myString = await dataBlock.get('my-string')

// 2-way bind
await dataBlock.bind('my-string', '#my-element')

// autobind definitions that use the bind field
await dataBlock.autobind();

Preprocessing Existing Source Code

Until the data block becomes a web standard, the data block content can be added via a script. Furthermore, an HTML preprocessor can replace the data block with a script.

window.urm_data_block_string = `
my-text-area {
 scope: workspace;
 debounce: 100;
 validate: myValidateFunction;
 default: () => {message: 'Hello World'}
window.urm_data_block = parseDataBlock(wi dow.urm_data_block_string)

Data Def Fields

See Data Def Fields

Data Block Object

A data block can also be created directly.

Data Block declaration using Javascript

const defs = {
  name: {
    default: User;
  age: {
    :default: null;

Data Block API

The Data Block API provides functionality to manage data, data definition fields, and interactive services.

Standard API methods


Retrieve the data associated with a data definition


Set the data associated with a data definition


Retrieve a data definition


Retrieve all data definitions


Retrive a data definition fields (not the realized field value)


Retrive a data definition field (not the realized field value)



getRef (todo)



Standard API Messages



Syntactic Sugar

To allow for terse code, several shortcut macros have been added to the other three language block sections. As with the data language block, a preprocessor can replace the shortcut macros with valid code.


const myTextArea = ^description // getDataRef('description')
const myTextArea = ^^description // getDataValue('description')
^description = 'Some description' // setDataValue('description', 'Some description')
const debounce = ^description.debounce // getDataProperty('description', 'debounce') 
const debounce = ^description.* // getDataProperties('description')
const defaultValue = ^description?.default() // getDataProperty('description', 'default')?.()


  <div ^description /> <!-- v-model="getDataRef('description')" -->
  <div ^^description /> <!-- v-model="getDataValue('description')" -->


.some-class::before {
  content: ^description
.another-class::before {