Nuvira is a structured data format that combines schema definitions, validation rules, records, and relationships. It provides a way to define complex data relationships and structures while ensuring data integrity through validation and strict mode enforcement.
- Overview
- Nuvira File Structure
- File Rules
- Schema Section
- Relations Section
- Validation Section
- Records Section
- Key Features of Nuvira
- Example Usage
- Advantages of Nuvira Format
Overview
Nuvira is a structured data format that combines schema definitions, validation rules, records, and relationships. It supports strict mode, which ensures data consistency by enforcing type restrictions and validation rules. The format is designed to make it easier to define complex data structures and their interrelationships while maintaining data integrity.
File Structure
A Nuvira file consists of several key sections, each serving a specific purpose to ensure data consistency, validation, and relationships between records. The structure includes:
-
File Rules (`STRICT`, `SIZE`, `TYPE`, `LOCKED`): Specifies the rules governing the behavior of the file and its schema:
- STRICT: Controls the strictness of data adherence to the schema structure (e.g., `STRICT=TRUE` for strict compliance).
- SIZE: Defines the maximum number of records allowed in the file (e.g., `SIZE=100`).
- TYPE: Specifies the schema type, such as `ROOT`, `NODE`, `LEAF`, etc. (e.g., `TYPE=NODE`).
- LOCKED: Defines whether the schema is locked for modification (e.g., `LOCKED=TRUE`).
- Schema Definition (`@schema`): Defines the structure of the data, specifying fields, data types, and relationships between them. The schema can also include nested structures and arrays.
- Relations Definition (`@relations`): Defines the relationships between different schemas, such as one-to-one, one-to-many, and many-to-many, along with behaviors on delete, update, and create operations.
- Validation Rules (`@validations`): Specifies the validation rules for each field, including constraints like `required`, `minLength`, `maxLength`, `isDate`, `isUnique`, and more, to ensure data integrity.
- Records (`@records`): Contains the actual data entries, following the schema and validation rules defined earlier. The records section is where the main dataset is stored.
Each section in the Nuvira file is marked by specific tags (`@schema`, `@relations`, `@validations`, `@records`) and is closed with `@end`. The structure ensures that the data is well-organized, validated, and linked according to the rules defined in the schema and relations sections.
File Rules Explanation
The File Rules section at the top of the Nuvira file configures how data is validated, structured, and whether schema modifications are allowed. This section includes the following parameters:
-
*STRICT: Controls the strictness of the data.
- TRUE: Data must strictly follow the schema structure, types, and order.
- FALSE: Data can have more flexibility in types and order.
*STRICT=FALSE
-
*SIZE: Defines the number of records allowed in the file. This sets the maximum document count within the records section.
Example:
*SIZE=100
-
*TYPE: Specifies the schema type for the dataset. Valid values are:
- ROOT: The top-most schema.
- NODE: A mid-level schema that can connect other schemas.
- LEAF: A terminal schema with no children.
- ISOLATED: A schema that doesn’t connect with any other schema.
- REFERENCE: A schema that points to other data, but doesn’t hold it.
*TYPE=NODE
-
*LOCKED: When TRUE, the file is locked and cannot be modified. When FALSE, the file is open for changes.
Example:
*LOCKED=TRUE
These rules are defined at the top of the Nuvira file and help configure how data will be handled, validated, and structured.
Schema Section
The schema section defines the fields and their data types. Each schema is named and can include complex structures such as objects and arrays. A schema is defined using the `@schema` directive followed by the schema name.
The following data types can be used in a schema field definition:- Number: Represents numerical values.
- String: Represents textual data.
- Binary: Represents binary data.
- Date: Represents date values.
- Boolean: Represents true/false values.
- Uint8Array: Represents an array of unsigned 8-bit integers.
- Object: Represents an object with key-value pairs.
- Any[]: Represents an array of any type of data.
- StringArray: Represents an array of strings.
- String[]: Another way to define an array of strings.
- ObjectArray: Represents an array of objects.
- NumberArray: Represents an array of numbers.
- Number[]: Another way to define an array of numbers.
- Null: Represents a null value (used when a field can be null).
- undefined: Represents an undefined value (used when a field can be undefined).
- Array: A general array type.
-
[]: Another way to define an array (equivalent to
Array
). - Any: Represents any data type (used when the field type is flexible).
- AnyArray: Represents an array of any data type.
@schema: Users-Info
Users -> Object[] {
name -> String
age -> Number
friends -> StringArray | Null | undefined
isStudent -> Boolean
image -> Binary
birthDate -> Date | Number
nationality -> Object {
countries -> String[]
city -> String | Null
postcode -> String | undefined
}
}
@end
In this example, the schema `Users-Info` defines an array of `Object[]` with various field types. Nested structures are included, such as an `Object` for the `nationality` field. Additionally, it demonstrates how to specify optional (`Null`, `undefined`) or multiple valid types for a field, like `birthDate` which can be either `Date` or `Number`.
Relations Section
The relations section defines relationships between different schemas. You can specify one-to-one, one-to-many, or many-to-many relationships. Additionally, you can define the behavior on delete, update, and other operations such as cascading, restricting, or setting defaults.
The following valid relation types and behaviors can be used in the relations section:Metadata Field | Valid Values | Description |
---|---|---|
type | one-to-one, one-to-many, many-to-one, many-to-many | Specifies the type of relationship between two schemas. For example, "one-to-one" means one instance of the source schema is related to exactly one instance of the target schema. |
onDelete | cascade, restrict, set-null, no-action | Defines the behavior when a record is deleted in the source schema. Options include:
|
onUpdate | cascade, restrict, set-null, no-action | Defines the behavior when a record is updated in the source schema. Similar to onDelete , options include cascading, restricting, setting to null, or doing nothing. |
onCreate | set-default, restrict, no-action | Defines what happens when a new record is created in the target schema. Options include setting default values, restricting creation, or taking no action. |
unique | true, false | Indicates whether the relation should be unique. If set to true , the related field must be unique in the target schema. |
nullable | true, false | Indicates whether the related field can be null. If set to true , the relation allows null values. |
index | true, false | Specifies whether the relation should be indexed for faster lookup. |
cascade | true, false | Indicates whether cascading behavior is applied to the relation. |
reverse | true, false | Specifies if the reverse of the relation should be created. For example, if a one-to-many relation is defined, the reverse relation will be a "many-to-one". |
uniqueConstraint | true, false | Indicates whether a unique constraint should be enforced on the relation. |
@relations
Employee(Salary) -> Users(name) {
type = "one-to-many";
onDelete = "cascade";
onUpdate = "restrict";
}
Company(age) -> Users(age) {
type = "one-to-one";
onDelete = "cascade";
onUpdate = "restrict";
}
@end
In this example:
- The relation between `Employee` and `Users` is one-to-many, meaning one employee can have many associated users. Deleting an employee will cascade and delete the related user records, but updates to the employee record will be restricted if there are related users.
- The relation between `Company` and `Users` is one-to-one, meaning each company is linked to a single user. Deleting a company will cascade and delete the related user, and updates to the company record are restricted if there is a related user.
Validation Section
The validation section specifies rules for each field to ensure data integrity. These rules can include constraints like `required`, `minLength`, `isDate`, `maxLength`, `isUnique`, and more. Validation rules are set on schema fields to ensure the data conforms to the expected structure and values.
The following validation keywords can be used, with the respective valid types for each rule:Validation Keyword | Description | Valid Types |
---|---|---|
minLength | Specifies the minimum length of a string, array, or object. | String, StringArray, String[], ObjectArray, Object[], Array, Any[], [], Object, NumberArray, Number[], Uint8Array |
maxLength | Specifies the maximum length of a string, array, or object. | String, StringArray, String[], ObjectArray, Object[], Array, Any[], [], Object, NumberArray, Number[], Uint8Array |
isDate | Ensures the field value is a valid date. | Date, StringArray, String[], NumberArray, Number[] |
minDate | Specifies the minimum date allowed. | Date, StringArray, String[], NumberArray, Number[] |
maxDate | Specifies the maximum date allowed. | Date, StringArray, String[], NumberArray, Number[] |
isBoolean | Ensures the field value is a boolean. | Boolean, Array, Any[], [] |
hasProperties | Ensures the object has specified properties. | Object, ObjectArray, Object[] |
enum | Ensures the field value is one of the specified values. | Any |
notNull | Ensures the field is not null. | Any |
pattern | Ensures the field matches a specified pattern (usually a regex). | Any |
isUnique | Ensures the field values are unique within the dataset. | Any |
required | Ensures the field is required and cannot be empty. | Any |
isNull | Ensures the field value is null. | Any |
min | Specifies the minimum numeric value. | Number, NumberArray, Number[], Uint8Array |
max | Specifies the maximum numeric value. | Number, NumberArray, Number[], Uint8Array |
isPositive | Ensures the field value is positive. | Number, NumberArray, Number[], Uint8Array |
isNegative | Ensures the field value is negative. | Number, NumberArray, Number[], Uint8Array |
isNumeric | Ensures the field value is numeric. | NumberArray, Number[], Number |
isInteger | Ensures the field value is an integer. | Number, NumberArray, Number[] |
isFloat | Ensures the field value is a float. | Number, NumberArray, Number[] |
isEmail | Ensures the field value is a valid email address. | String, StringArray, String[] |
isURL | Ensures the field value is a valid URL. | String, String[], StringArray |
isAlpha | Ensures the field value contains only alphabetic characters. | String, String[], StringArray |
isAlphanumeric | Ensures the field value contains only alphanumeric characters. | String, String[], StringArray |
isIP | Ensures the field value is a valid IP address. | String, String[], StringArray |
trim | Ensures the field value is trimmed of whitespace. | String, String[], StringArray |
lowercase | Ensures the field value is converted to lowercase. | String, String[], StringArray |
uppercase | Ensures the field value is converted to uppercase. | String, String[], StringArray |
@validations
Users -> required=true; maxLength=50; isUnique=true
Users.name -> required=true; minLength=3; uppercase=true
@end
In this example, the `Users` field is required, must have a maximum length of 50 characters, and must contain unique values. Additionally, the `name` field under `Users` is required, must have a minimum length of 3, and must be converted to uppercase.
Records Section
The records section contains actual data entries. Each record is prefixed with a unique document number (`#0`, `#1`, etc.). These entries represent real data and follow the schema and validation rules.
@records
#0 -> Users[
_0{
name("Elias"); age(20); friends[ _0("Marco"); _1("Kmosha"); _2("Abdullah"); ];
iSstudent(TRUE); image(); birthDate(05/04/2004);
nationality{ countries[ _0("Egypt"); _1("Poland"); ]; city(NULL); postcode(); };
};
];
#1 -> Users[....];
@end
Example Usage
You can find usage examples in the `example` folder of the installed package. See:
Nuvira Validation Example
This example demonstrates:
- How to define nested schemas for objects and arrays.
- How to apply validation rules to nested schemas.
- Use all types (`String`, `Number`, `Date`, `Boolean`, `StringArray`, `Object`, `ObjectArray`).
import { Validator, ValidateParams, ValidationResult, SchemaDefinition, ValidationRules } from './Validator';
// Example Schema Definition
const schema: Record<string, SchemaDefinition> = {
username: { type: ['String'] },
age: { type: ['Number'] },
birthdate: { type: ['Date'] },
isVerified: { type: ['Boolean'] },
friends: { type: ['StringArray'] },
preferences: { type: ['Object'], properties: { theme: { type: ['String'] }, notifications: { type: ['Boolean'] } } },
activities: { type: ['ObjectArray'], items: {
type: ['String'] } }
};
// Example Validation Rule
const validation: Record<string, ValidationRules> = {
username: { required: true, minLength: 3, maxLength: 20, isUnique: true },
age: { required: true, min: 18, max: 99 },
birthdate: { required: true, isDate: true },
isVerified: { required: true },
friends: { minLength: 1 },
preferences: { required: true }
};
// Example Validation Request
const params: ValidateParams = {
username: "JohnDoe",
age: 30,
birthdate: new Date(),
isVerified: true,
friends: ["Jane", "Doe"],
preferences: { theme: "dark", notifications: true }
};
const validationResult: ValidationResult = Validator.validate(schema, validation, params);
if (validationResult.isValid) {
console.log("Validation passed.");
} else {
console.error("Validation failed.");
}
Key Features
-
Document Numbers:
Each record is identified by a unique document number (#0
,#1
,#2
, etc.). These document numbers are essential for referencing specific records, ensuring easy tracking, error resolution, and quick lookups. This helps organize large datasets and allows for efficient querying and validation. -
Indexed Arrays:
Arrays in Nuvira are indexed with unique keys like_0
,_1
,_2
, etc. This provides clarity and structure for managing array elements and ensures consistency when accessing or modifying individual elements. It is particularly useful for data where elements are ordered and need to be referenced directly. -
Strict Mode:
The strict mode (*STRICT=TRUE
) ensures that the data strictly follows the schema structure, types, and the order of elements. When strict mode is enabled, any deviation from the schema, such as missing fields, wrong data types, or extra fields, will lead to validation errors. In non-strict mode (*STRICT=FALSE
), the format allows for more flexible data input and can accommodate deviations from the strict schema, giving you more freedom when working with the data. -
Schema Definition Flexibility:
The Nuvira format supports various schema types—ROOT, NODE, LEAF, ISOLATED, and REFERENCE—giving users flexibility to define complex relationships between data fields and structure. This ensures that your data models can range from simple flat structures to deeply nested or interconnected schemas. -
Validation Rules:
Validation is a built-in feature in Nuvira, ensuring that data adheres to predefined rules. Rules can be applied to fields, specifying things likerequired
,minLength
,maxLength
,isDate
,unique
, and more. This allows for automatic validation during data insertion or modification, ensuring that the data stays consistent and valid. -
File Integrity:
The File Rules (*STRICT
,*SIZE
,*TYPE
,*LOCKED
) at the top of the Nuvira file define global settings for how the data is structured and validated. These settings also specify whether the schema is locked or can be modified, and how strict the validation should be across the entire file. -
Nested and Complex Data Types:
Nuvira allows for the definition of complex data types like Objects, Arrays, and even Arrays of Objects, allowing for multi-level data modeling. It’s possible to nest objects within objects, as well as create arrays of multiple types, making it suitable for complex, real-world data structures. -
Human-Readable Format:
The Nuvira file format is designed to be easily readable by humans, with clear definitions and a structured, organized layout. This makes it simple to write, debug, and maintain, even for non-programmers or users unfamiliar with the technical details. -
Document Locking:
The*LOCKED
setting in the file rules allows you to lock file, preventing any further modifications. This feature ensures that once a file is finalized, it cannot be changed, maintaining data integrity over time. -
Support for Relationships:
Nuvira supports complex relationships between different schemas. With the @relations section, you can define one-to-one, one-to-many, or many-to-many relationships between schemas, as well as actions to be taken on delete or update (e.g., cascading or restricting).
These features ensure that Nuvira is a highly flexible, robust, and efficient data format for managing structured, validated data, making it ideal for use in applications where data integrity, flexibility, and complex relationships are important.
Advantages
- Enforces Data Integrity: Nuvira ensures that your data adheres strictly to predefined schemas, preventing inconsistencies and errors through robust validation rules.
- Supports Complex Data Structures and Relationships: With support for arrays, nested objects, and various data types, Nuvira can model intricate relationships between different entities in your data.
- Flexible Validation and Strict Mode: Customize validation settings to match your project's requirements. Whether you need strict data structure adherence or more flexibility, Nuvira allows you to choose the right balance for your needs.
- Easy Integration with JavaScript (Node.js) Environments: Nuvira is optimized for seamless integration with Node.js and other JavaScript frameworks, ensuring quick setup and easy use in modern web and backend applications.
- Improved Performance: Nuvira’s lightweight format ensures fast processing speeds, even when working with large datasets or complex schema structures.
- Enhanced Security and Data Consistency: By leveraging strong validation mechanisms, Nuvira helps secure data by preventing the introduction of invalid or harmful data.