BEJSON JS library Guide
Introduction to the BEJSON JavaScript Library
The BEJSON (Boehnen's Enterprise JSON) format is a strict, self-describing tabular data format built on JSON. Its core design principles emphasize positional integrity, meaning the order of fields declared in the Fields array precisely dictates the order of values within each record in the Values array. This fundamental characteristic enables efficient index-based access to data, fast parsing, strong typing, and embedded schema validation without the need for external schema files. BEJSON documents are defined by a set of mandatory top-level keys, including Format, Format_Version, Format_Creator, Records_Type, Fields, and Values.
The BEJSON specification includes several versions, such as BEJSON 104 for homogeneous, high-throughput data like logs, BEJSON 104a for configuration files and simple metrics with custom metadata, and BEJSON 104db for multi-entity lightweight databases requiring record type discrimination. Each version introduces specific rules and capabilities, allowing BEJSON to adapt to diverse data storage and exchange needs while maintaining its strict structural integrity.
Purpose of the BEJSON JavaScript Library
The official BEJSON JavaScript Library serves as a comprehensive toolkit for developers working with BEJSON documents in Node.js and browser environments. It provides a robust and reliable API to interact with BEJSON data, ensuring that documents adhere to the specification and simplifying common data management tasks. The library's primary role can be broken down into three key areas:
- Creating BEJSON Documents: The library offers helper functions to programmatically construct new BEJSON documents for each version (104, 104a, 104db). These functions abstract away the complexity of assembling the correct top-level keys and array structures, allowing developers to focus on defining their data.
- Validating BEJSON Documents: A critical feature of the library is its powerful validator module. This module can check the JSON syntax and, more importantly, the structural and data integrity of any BEJSON document against its strict specification. It identifies missing mandatory keys, incorrect data types, length mismatches, and version-specific rule violations, ensuring that only compliant BEJSON data is processed.
-
Manipulating BEJSON Documents: Beyond creation and validation, the library provides extensive capabilities for programmatically interacting with BEJSON data. This includes:
- Loading existing documents from files or strings.
- Accessing document-level metadata, field definitions, and individual record values.
- Modifying data by adding, removing, or updating records and field values.
- Performing advanced data operations such as querying records based on specific criteria, filtering documents using custom predicates, and sorting records by field values.
- Managing the document's schema by adding, removing, or renaming columns (fields).
- Ensuring data integrity and safety through atomic file write operations, including automatic backups.
By leveraging the BEJSON JavaScript Library, developers can streamline their workflows, reduce the likelihood of data corruption due to malformed documents, and build applications that reliably interact with BEJSON data. This guide will walk you through each aspect of the library, demonstrating how to effectively use its features to manage your BEJSON documents.
Installation and Core Validation
Before diving into the features of the BEJSON JavaScript Library, you first need to install it in your project. The library is primarily designed for Node.js environments, leveraging file system operations for document handling.
Installation
The BEJSON JavaScript Library can be installed using npm or yarn, the standard package managers for JavaScript.
-
Using npm: Open your terminal or command prompt in your project's root directory and run:
npm install bejson-js-library -
Using yarn: Alternatively, if you prefer yarn, run:
yarn add bejson-js-library
Once installed, you can import the necessary modules into your JavaScript files. The library exposes two main components: the validator module for document validation and the core manipulation functions.
const { validator, BEJSONValidationError } = require('bejson-js-library').validator; // For validator module
const bejsonCore = require('bejson-js-library').core; // For core manipulation functions
For the purpose of validation, we will focus on the validator module.
Core Validation with the validator Module
The validator module is crucial for ensuring that your BEJSON documents adhere to the strict specification. It provides functions to check both the fundamental JSON syntax and the specific structural and data integrity rules of BEJSON. This module can validate BEJSON data from either a raw JSON string or a file path.
Checking JSON Syntax
The first step in validating any BEJSON document is to ensure it is valid JSON. The validator module automatically performs this check. If the input is not well-formed JSON, it will throw a BEJSONValidationError with an E_INVALID_JSON code.
Checking BEJSON Structural Integrity
Beyond basic JSON validity, the validator module enforces all BEJSON-specific rules, including:
- Presence and correctness of all mandatory top-level keys (Format, Format_Version, Format_Creator, Records_Type, Fields, Values).
- Correctness of Format_Version (must be "104", "104a", or "104db").
- Proper structure of the Fields array, including unique field names and valid field types.
- Version-specific rules for Records_Type (e.g., single string for 104/104a, array of 2+ unique strings for 104db).
- Consistency between the number of fields in Fields and the number of values in each record within Values.
- Type matching for each value against its declared field type (with null being universally allowed).
- BEJSON 104a specific checks for primitive field types only and PascalCase custom headers.
- BEJSON 104db specific checks for the Record_Type_Parent discriminator field and strict null enforcement for non-applicable fields.
Validation Functions
The validator module provides two primary functions for initiating validation:
-
validateString(jsonString):
Use this function to validate a BEJSON document provided as a JavaScript string. It parses the string and applies all validation rules.
const { validator } = require('bejson-js-library').validator; const validBejsonString = `{ "Format": "BEJSON", "Format_Version": "104", "Format_Creator": "Elton Boehnen", "Records_Type": ["SensorReading"], "Fields": [ {"name": "sensor_id", "type": "string"}, {"name": "temperature", "type": "number"} ], "Values": [ ["S001", 23.5], ["S002", 19.8] ] }`; const invalidBejsonString = `{ "Format": "BEJSON", "Format_Version": "999", // Invalid version "Format_Creator": "Elton Boehnen", "Records_Type": ["SensorReading"], "Fields": [ {"name": "sensor_id", "type": "string"} ], "Values": [ ["S001", 23.5] // Too many values for fields ] }`; try { validator.validateString(validBejsonString); console.log("Valid BEJSON string."); } catch (e) { if (e instanceof BEJSONValidationError) { console.error(`Validation Error (${e.code}): ${e.message}`); } else { console.error(`Unexpected error: ${e.message}`); } } try { validator.validateString(invalidBejsonString); console.log("This should not be reached."); } catch (e) { if (e instanceof BEJSONValidationError) { console.error(`Validation Error (${e.code}): ${e.message}`); // Example: E_INVALID_VERSION (4), E_RECORD_LENGTH_MISMATCH (9) } } -
validateFile(filePath):
This function is used to validate a BEJSON document stored in a file. It reads the file content, parses it, and then applies all validation rules. It will throw an error if the file does not exist or cannot be read.
const { validator } = require('bejson-js-library').validator; const fs = require('fs'); // Required for file system operations in Node.js const exampleFilePath = './my_data.bejson'; const invalidFilePath = './invalid_data.bejson'; // Create a dummy valid BEJSON file for demonstration fs.writeFileSync(exampleFilePath, JSON.stringify({ "Format": "BEJSON", "Format_Version": "104", "Format_Creator": "Elton Boehnen", "Records_Type": ["LogEntry"], "Fields": [ {"name": "timestamp", "type": "string"}, {"name": "message", "type": "string"} ], "Values": [ ["2026-03-01T10:00:00Z", "System started"], ["2026-03-01T10:01:00Z", "User logged in"] ] }, null, 2)); // Create a dummy invalid BEJSON file for demonstration fs.writeFileSync(invalidFilePath, JSON.stringify({ "Format": "BEJSON", "Format_Version": "104a", // 104a does not allow 'object' type "Format_Creator": "Elton Boehnen", "Records_Type": ["Config"], "Fields": [ {"name": "setting", "type": "string"}, {"name": "details", "type": "object"} ], "Values": [ ["foo", {"key": "value"}] ] }, null, 2)); try { validator.validateFile(exampleFilePath); console.log(`File '${exampleFilePath}' is a valid BEJSON document.`); } catch (e) { if (e instanceof BEJSONValidationError) { console.error(`Validation Error for '${exampleFilePath}' (${e.code}): ${e.message}`); } else { console.error(`Unexpected error for '${exampleFilePath}': ${e.message}`); } } try { validator.validateFile(invalidFilePath); console.log(`File '${invalidFilePath}' is valid (this should not happen).`); } catch (e) { if (e instanceof BEJSONValidationError) { console.error(`Validation Error for '${invalidFilePath}' (${e.code}): ${e.message}`); // Example: E_INVALID_FIELDS (6) due to disallowed type for 104a } } // Clean up dummy files fs.unlinkSync(exampleFilePath); fs.unlinkSync(invalidFilePath);
Detailed Validation Reports
Instead of catching exceptions, you can use the getReport() function to receive a human-readable summary of the validation status, including all errors and warnings. This can be useful for logging or presenting validation results to users.
const { validator } = require('bejson-js-library').validator;
const invalidBejsonString = `{
"Format": "BEJSON",
"Format_Version": "104a",
"Format_Creator": "Elton Boehnen",
"Records_Type": ["Config"],
"CustomHeader": "Value", // Warning for PascalCase
"Fields": [
{"name": "setting", "type": "string"},
{"name": "details", "type": "object"} // Error: object not allowed in 104a
],
"Values": [
["foo", {"key": "value"}],
["bar"] // Error: length mismatch
]
}`;
const report = validator.getReport(invalidBejsonString);
console.log(report);
// Example output:
// === BEJSON Validation Report ===
// Status: INVALID
//
// Errors: 2
// ---
// ERROR | Location: Fields | Message: Field 'details' (index 1): Type 'object' not allowed in 104a. | Context:
// ERROR | Location: Values | Message: Record at 'Values' index 1 has 1 elements, expected 2. | Context:
//
// Warnings: 1
// ---
// WARNING | Location: Top-Level Keys/CustomHeader | Message: Custom top-level key 'CustomHeader' does not follow recommended PascalCase naming.
The validator module also provides helper methods to query the validation state after an attempt:
- validator.hasErrors(): Returns true if any errors were found.
- validator.errorCount(): Returns the number of errors.
- validator.getErrors(): Returns an array of error messages.
- validator.hasWarnings(): Returns true if any warnings were found.
- validator.warningCount(): Returns the number of warnings.
- validator.getWarnings(): Returns an array of warning messages.
- validator.resetState(): Clears all errors and warnings from the internal state, useful before validating a new document.
Understanding and utilizing the validator module is fundamental to working with the BEJSON JavaScript Library, as it ensures the integrity and correctness of your BEJSON data throughout its lifecycle.
Creating BEJSON Documents
The BEJSON JavaScript Library simplifies the programmatic creation of new BEJSON documents by providing dedicated helper functions for each version: create104(), create104a(), and create104db(). These functions handle the boilerplate of setting mandatory top-level keys like Format, Format_Version, and Format_Creator, allowing you to focus on defining your data schema and records.
All creation functions are exposed via the core module of the library.
const bejsonCore = require('bejson-js-library').core;
Creating BEJSON 104 Documents
The create104() function is used for generating BEJSON 104 documents. This version is designed for homogeneous, high-throughput data and supports complex data types (arrays and objects) within its fields. It does not allow custom top-level keys, with the single exception of Parent_Hierarchy.
Function Signature:
bejsonCore.create104(recordsType, fields, values)
- recordsType (string): A single string representing the type of records stored in the document. This will be wrapped in an array for the Records_Type key.
- fields (array of objects): An array defining the schema of your records. Each object must have a name (string) and type (string, e.g., "string", "integer", "number", "boolean", "array", "object") property.
- values (array of arrays): An array where each inner array represents a single record, with values ordered according to the fields array. Missing or optional values should be represented by null.
Example:
Let's create a BEJSON 104 document to store sensor readings, including complex types like arrays for tags.
const bejsonCore = require('bejson-js-library').core;
const recordsType104 = "SensorReading";
const fields104 = [
{"name": "sensor_id", "type": "string"},
{"name": "timestamp", "type": "string"},
{"name": "temperature", "type": "number"},
{"name": "tags", "type": "array"}
];
const values104 = [
["S001", "2026-01-10T12:00:00Z", 23.5, ["indoor", "ground"]],
["S002", "2026-01-10T12:00:00Z", 19.8, null],
["S003", "2026-01-10T12:01:00Z", 24.1, ["outdoor"]]
];
const doc104 = bejsonCore.create104(recordsType104, fields104, values104);
console.log("BEJSON 104 Document:");
console.log(bejsonCore.prettyPrint(doc104));
The output will be a valid BEJSON 104 object, ready for further manipulation or storage.
Creating BEJSON 104a Documents
The create104a() function is designed for BEJSON 104a documents, which are ideal for configuration files or simple logs. This version restricts fields to primitive types only (string, integer, number, boolean) but allows custom top-level keys for file-level metadata. Custom keys should follow PascalCase naming conventions to avoid collisions with mandatory keys.
Function Signature:
bejsonCore.create104a(recordsType, fields, values, customHeaders = {})
- recordsType (string): A single string representing the type of records.
- fields (array of objects): An array defining the schema. Field type must be one of "string", "integer", "number", or "boolean".
- values (array of arrays): An array of records.
- customHeaders (object, optional): An object containing additional top-level key-value pairs for metadata. These keys should be in PascalCase.
Example:
Here's how to create a BEJSON 104a document for application configuration, including custom metadata like ApplicationName and Environment.
const bejsonCore = require('bejson-js-library').core;
const recordsType104a = "ConfigParam";
const fields104a = [
{"name": "key", "type": "string"},
{"name": "value", "type": "string"},
{"name": "sensitive", "type": "boolean"}
];
const values104a = [
["db_host", "localhost", false],
["max_connections", "100", false],
["api_key", "secret123", true]
];
const customHeaders104a = {
"ApplicationName": "MyWebApp",
"Environment": "Development",
"SchemaVersion": "1.0"
};
const doc104a = bejsonCore.create104a(recordsType104a, fields104a, values104a, customHeaders104a);
console.log("\nBEJSON 104a Document:");
console.log(bejsonCore.prettyPrint(doc104a));
Note how ApplicationName, Environment, and SchemaVersion are included directly at the top level of the document.
Creating BEJSON 104db Documents
The create104db() function is used to construct BEJSON 104db documents, which function as lightweight, multi-entity databases. This version allows for multiple record types within a single document and supports complex data types. A key distinction is the mandatory first field, Record_Type_Parent, which acts as a discriminator for the entity type of each record. Additionally, every other field must explicitly declare its associated Record_Type_Parent. Non-applicable fields for a given record must be null.
Function Signature:
bejsonCore.create104db(recordsTypes, fields, values)
- recordsTypes (array of strings): An array containing two or more unique strings, each representing a distinct entity type within the document.
- fields (array of objects): An array defining the schema. The first field object must be
{"name": "Record_Type_Parent", "type": "string"}. All other field objects must include a Record_Type_Parent property that matches one of the strings in recordsTypes. - values (array of arrays): An array of records. The first element of each record array must be one of the declared recordsTypes. Fields not applicable to a specific record's type must be null.
Example:
Let's create a BEJSON 104db document to store both User and Order entities.
const bejsonCore = require('bejson-js-library').core;
const recordsTypes104db = ["User", "Order"];
const fields104db = [
{"name": "Record_Type_Parent", "type": "string"},
{"name": "user_id", "type": "string", "Record_Type_Parent": "User"},
{"name": "username", "type": "string", "Record_Type_Parent": "User"},
{"name": "email", "type": "string", "Record_Type_Parent": "User"},
{"name": "order_id", "type": "string", "Record_Type_Parent": "Order"},
{"name": "product_name", "type": "string", "Record_Type_Parent": "Order"},
{"name": "quantity", "type": "integer", "Record_Type_Parent": "Order"},
{"name": "user_id_fk", "type": "string", "Record_Type_Parent": "Order"} // Foreign key convention
];
const values104db = [
// User records
["User", "U001", "alice", "alice@example.com", null, null, null, null],
["User", "U002", "bob", "bob@example.com", null, null, null, null],
// Order records
["Order", null, null, null, "O001", "Laptop", 1, "U001"],
["Order", null, null, null, "O002", "Mouse", 2, "U001"],
["Order", null, null, null, "O003", "Keyboard", 1, "U002"]
];
const doc104db = bejsonCore.create104db(recordsTypes104db, fields104db, values104db);
console.log("\nBEJSON 104db Document:");
console.log(bejsonCore.prettyPrint(doc104db));
Observe how fields specific to "User" records (like username, email) are null for "Order" records, and vice-versa. The user_id_fk field demonstrates the recommended naming convention for foreign keys in 104db.
After creating a document using these helper functions, it is always a good practice to validate it using the validator module (as discussed in Chapter 2) to ensure it fully complies with the BEJSON specification.
Loading and Accessing Document Data
Once you have created BEJSON documents or obtained them from an external source, the BEJSON JavaScript Library provides robust functionalities to load them into your application and access their data efficiently. The core module of the library offers functions to load documents from both file paths and JSON strings, along with a suite of methods for retrieving various pieces of information from the loaded document.
const bejsonCore = require('bejson-js-library').core;
Loading BEJSON Documents
The library offers two main functions for loading BEJSON documents, each handling a different source. Both functions perform an internal validation step upon loading to ensure the document's integrity. If validation fails, a BEJSONCoreError will be thrown.
-
Loading from a File: loadFile(filePath)
This function reads a BEJSON document from the specified file path. It's suitable for persistent storage scenarios in Node.js environments.
const bejsonCore = require('bejson-js-library').core; const fs = require('fs'); const filePath = './my_data.bejson'; // Create a dummy BEJSON file for demonstration fs.writeFileSync(filePath, JSON.stringify(bejsonCore.create104( "LogEntry", [{"name": "timestamp", "type": "string"}, {"name": "message", "type": "string"}], [["2026-03-01T10:00:00Z", "App started"], ["2026-03-01T10:05:00Z", "Task complete"]] ), null, 2)); try { const loadedDoc = bejsonCore.loadFile(filePath); console.log("Document loaded successfully from file:"); console.log(bejsonCore.prettyPrint(loadedDoc)); } catch (e) { console.error(`Error loading file: ${e.message}`); } finally { fs.unlinkSync(filePath); // Clean up the dummy file } -
Loading from a String: loadString(jsonString)
Use this function to parse a BEJSON document from a JavaScript string. This is useful when you receive BEJSON data over a network or from an in-memory source.
const bejsonCore = require('bejson-js-library').core; const bejsonString = `{ "Format": "BEJSON", "Format_Version": "104a", "Format_Creator": "Elton Boehnen", "SchemaVersion": "1.0", "Records_Type": ["ConfigParam"], "Fields": [ {"name": "key", "type": "string"}, {"name": "value", "type": "string"} ], "Values": [ ["timeout_ms", "5000"], ["api_endpoint", "https://api.example.com"] ] }`; try { const loadedDoc = bejsonCore.loadString(bejsonString); console.log("Document loaded successfully from string:"); console.log(bejsonCore.prettyPrint(loadedDoc)); } catch (e) { console.error(`Error loading string: ${e.message}`); }
Retrieving Document-Level Metadata
Once a BEJSON document is loaded, you can easily access its top-level metadata using dedicated getter functions.
- getVersion(doc): Returns the Format_Version of the document (e.g., "104", "104a", "104db").
- getRecordsTypes(doc): Returns the array of record types defined in Records_Type.
- getFieldCount(doc): Returns the total number of fields (columns) in the document.
- getRecordCount(doc): Returns the total number of records (rows) in the document.
- getStats(doc): Returns an object containing a summary of document statistics, including version, field count, record count, and record types.
Example:
const bejsonCore = require('bejson-js-library').core;
const doc = bejsonCore.create104a(
"AppSetting",
[{"name": "name", "type": "string"}, {"name": "value", "type": "string"}],
[["theme", "dark"], ["language", "en"]],
{"AppName": "SettingsManager", "Version": "2.0"}
);
console.log(`\nDocument Version: ${bejsonCore.getVersion(doc)}`);
console.log(`Records Types: ${bejsonCore.getRecordsTypes(doc).join(', ')}`);
console.log(`Field Count: ${bejsonCore.getFieldCount(doc)}`);
console.log(`Record Count: ${bejsonCore.getRecordCount(doc)}`);
console.log("Document Stats:", bejsonCore.getStats(doc));
Retrieving Field Definitions
Understanding the schema of your BEJSON document is crucial for correct data handling. The library provides functions to inspect the Fields array.
- getFields(doc): Returns the entire Fields array, providing all field definitions.
- getFieldIndex(doc, fieldName): Returns the zero-based index of a field given its name. Throws E_CORE_FIELD_NOT_FOUND if the field does not exist.
-
getFieldDef(doc, fieldName): Returns the full field definition object (e.g.,
) for a given field name. Throws E_CORE_FIELD_NOT_FOUND if the field does not exist.{"name": "field_name", "type": "string"} - getFieldApplicability(doc, fieldName): For BEJSON 104db documents, this returns the Record_Type_Parent associated with a field, or "common" if it's the discriminator field itself or if the document is not 104db.
Example:
const bejsonCore = require('bejson-js-library').core;
const doc104db = bejsonCore.create104db(
["User", "Product"],
[
{"name": "Record_Type_Parent", "type": "string"},
{"name": "user_id", "type": "string", "Record_Type_Parent": "User"},
{"name": "username", "type": "string", "Record_Type_Parent": "User"},
{"name": "product_id", "type": "string", "Record_Type_Parent": "Product"},
{"name": "product_name", "type": "string", "Record_Type_Parent": "Product"}
],
[
["User", "U001", "alice", null, null],
["Product", null, null, "P001", "Laptop"]
]
);
console.log("\nAll Fields:", bejsonCore.getFields(doc104db));
console.log("Index of 'username':", bejsonCore.getFieldIndex(doc104db, "username"));
console.log("Definition of 'product_name':", bejsonCore.getFieldDef(doc104db, "product_name"));
console.log("Applicability of 'user_id':", bejsonCore.getFieldApplicability(doc104db, "user_id"));
console.log("Applicability of 'Record_Type_Parent':", bejsonCore.getFieldApplicability(doc104db, "Record_Type_Parent"));
try {
bejsonCore.getFieldIndex(doc104db, "non_existent_field");
} catch (e) {
console.error(`Error finding field: ${e.message}`); // Catches E_CORE_FIELD_NOT_FOUND
}
Accessing Individual Record Values
The library provides several ways to retrieve the actual data stored in the Values array.
- getValueAt(doc, recordIndex, fieldIndex): Retrieves the value at a specific row (record index) and column (field index). Both indices are zero-based. Throws E_CORE_INDEX_OUT_OF_BOUNDS if indices are invalid.
- getRecord(doc, recordIndex): Retrieves an entire record (an array of values) at the specified zero-based index. Throws E_CORE_INDEX_OUT_OF_BOUNDS if the record index is invalid.
- getFieldValues(doc, fieldName): Retrieves an array containing all values for a specific field (column) across all records. Throws E_CORE_FIELD_NOT_FOUND if the field does not exist.
Example:
const bejsonCore = require('bejson-js-library').core;
const doc = bejsonCore.create104(
"Task",
[
{"name": "task_id", "type": "string"},
{"name": "description", "type": "string"},
{"name": "is_complete", "type": "boolean"}
],
[
["T001", "Review documentation", false],
["T002", "Implement feature X", true],
["T003", "Write unit tests", false]
]
);
console.log("\nValue at record 0, field 1:", bejsonCore.getValueAt(doc, 0, 1)); // "Review documentation"
console.log("Record at index 2:", bejsonCore.getRecord(doc, 2)); // ["T003", "Write unit tests", false]
console.log("All 'description' values:", bejsonCore.getFieldValues(doc, "description"));
try {
bejsonCore.getValueAt(doc, 99, 0); // Out of bounds record
} catch (e) {
console.error(`Error accessing value: ${e.message}`); // Catches E_CORE_INDEX_OUT_OF_BOUNDS
}
These loading and access functions form the foundation for interacting with BEJSON documents, allowing you to parse, understand, and extract data before performing any modifications.
Modifying Records and Fields
The BEJSON JavaScript Library provides a straightforward set of functions for modifying the data within your BEJSON documents. A crucial aspect of these modification functions is their immutable approach. Instead of altering the original document object directly, these functions return a new BEJSON document object with the desired changes applied. This design promotes predictable data flow and simplifies state management in applications, as the original document remains untouched.
All record and field modification functions are available through the core module of the library:
const bejsonCore = require('bejson-js-library').core;
Adding Records
To add a new record (row) to a BEJSON document, use the addRecord() function. This function appends the new record to the end of the Values array.
Function Signature:
bejsonCore.addRecord(doc, values)
- doc (object): The original BEJSON document object.
- values (array): An array of values for the new record. This array must have the same number of elements as there are fields defined in the document's Fields array. The values will be automatically coerced to the declared field types where possible.
Example:
Let's add a new sensor reading to an existing BEJSON 104 document.
const bejsonCore = require('bejson-js-library').core;
let sensorReadings = bejsonCore.create104(
"SensorReading",
[
{"name": "sensor_id", "type": "string"},
{"name": "timestamp", "type": "string"},
{"name": "temperature", "type": "number"}
],
[
["S001", "2026-01-10T12:00:00Z", 23.5],
["S002", "2026-01-10T12:00:00Z", 19.8]
]
);
console.log("Original Document:");
console.log(bejsonCore.prettyPrint(sensorReadings));
const newRecord = ["S003", "2026-01-10T12:05:00Z", 24.1];
const updatedReadings = bejsonCore.addRecord(sensorReadings, newRecord);
console.log("\nDocument After Adding Record:");
console.log(bejsonCore.prettyPrint(updatedReadings));
console.log("\nOriginal document remains unchanged:");
console.log(bejsonCore.prettyPrint(sensorReadings)); // Shows original content
If the values array does not match the expected field count, a BEJSONCoreError with code E_CORE_INVALID_OPERATION will be thrown.
Removing Records
To remove a record from a BEJSON document, use the removeRecord() function, specifying the zero-based index of the record to be removed.
Function Signature:
bejsonCore.removeRecord(doc, recordIndex)
- doc (object): The original BEJSON document object.
- recordIndex (integer): The zero-based index of the record to remove.
Example:
Let's remove the second sensor reading from our document.
const bejsonCore = require('bejson-js-library').core;
let sensorReadings = bejsonCore.create104(
"SensorReading",
[
{"name": "sensor_id", "type": "string"},
{"name": "timestamp", "type": "string"},
{"name": "temperature", "type": "number"}
],
[
["S001", "2026-01-10T12:00:00Z", 23.5],
["S002", "2026-01-10T12:00:00Z", 19.8],
["S003", "2026-01-10T12:05:00Z", 24.1]
]
);
console.log("Original Document:");
console.log(bejsonCore.prettyPrint(sensorReadings));
// Remove the record at index 1 ("S002")
const updatedReadings = bejsonCore.removeRecord(sensorReadings, 1);
console.log("\nDocument After Removing Record at index 1:");
console.log(bejsonCore.prettyPrint(updatedReadings));
Attempting to remove a record using an index that is out of bounds will result in a BEJSONCoreError with code E_CORE_INDEX_OUT_OF_BOUNDS.
Updating Individual Field Values
You can update a specific value within a record using either its numerical index or its field name. The library automatically attempts to coerce the new value to the field's declared type.
-
Updating by Index: setValueAt(doc, recordIndex, fieldIndex, newValue)
This function updates the value at a specific record and field index.
Function Signature:
bejsonCore.setValueAt(doc, recordIndex, fieldIndex, newValue)- doc (object): The original BEJSON document object.
- recordIndex (integer): The zero-based index of the record.
- fieldIndex (integer): The zero-based index of the field (column).
- newValue (any): The new value to set.
Example:
const bejsonCore = require('bejson-js-library').core; let sensorReadings = bejsonCore.create104( "SensorReading", [ {"name": "sensor_id", "type": "string"}, {"name": "timestamp", "type": "string"}, {"name": "temperature", "type": "number"} ], [ ["S001", "2026-01-10T12:00:00Z", 23.5] ] ); console.log("Original Document:"); console.log(bejsonCore.prettyPrint(sensorReadings)); // Update temperature of S001 (record 0, field 2) let updatedReadingsByIndex = bejsonCore.setValueAt(sensorReadings, 0, 2, 25.0); console.log("\nDocument After Updating Temperature by Index:"); console.log(bejsonCore.prettyPrint(updatedReadingsByIndex)); -
Updating by Field Name: updateField(doc, recordIndex, fieldName, newValue)
This is a convenience function that uses the field name instead of its index, internally resolving the index before calling setValueAt().
Function Signature:
bejsonCore.updateField(doc, recordIndex, fieldName, newValue)- doc (object): The original BEJSON document object.
- recordIndex (integer): The zero-based index of the record.
- fieldName (string): The name of the field (column) to update.
- newValue (any): The new value to set.
Example:
const bejsonCore = require('bejson-js-library').core; let sensorReadings = bejsonCore.create104( "SensorReading", [ {"name": "sensor_id", "type": "string"}, {"name": "timestamp", "type": "string"}, {"name": "temperature", "type": "number"} ], [ ["S001", "2026-01-10T12:00:00Z", 23.5] ] ); console.log("Original Document:"); console.log(bejsonCore.prettyPrint(sensorReadings)); // Update timestamp of S001 (record 0, field "timestamp") let updatedReadingsByName = bejsonCore.updateField(sensorReadings, 0, "timestamp", "2026-01-10T12:10:00Z"); console.log("\nDocument After Updating Timestamp by Name:"); console.log(bejsonCore.prettyPrint(updatedReadingsByName));If the recordIndex or fieldIndex (or fieldName) is invalid, a BEJSONCoreError will be thrown (either E_CORE_INDEX_OUT_OF_BOUNDS or E_CORE_FIELD_NOT_FOUND). If the newValue cannot be coerced to the field's declared type, a BEJSONCoreError with code E_CORE_TYPE_CONVERSION_FAILED will be thrown.
These functions provide the fundamental building blocks for modifying the content of your BEJSON documents while adhering to the library's immutable data principles, ensuring that your data remains consistent and predictable.
Advanced Data Manipulation: Querying, Filtering, and Sorting
Beyond basic record and field modifications, the BEJSON JavaScript Library offers powerful functions for querying, filtering, and sorting your data. These operations enable you to extract specific subsets of records, refine your data based on custom logic, and present information in a structured order. Like the modification functions, these operations generally adhere to an immutable pattern, returning new document objects or arrays of records rather than modifying the original document in place.
All advanced data manipulation functions are accessible through the core module:
const bejsonCore = require('bejson-js-library').core;
Querying Records
The library provides functions to query records based on the values of specific fields, allowing you to quickly find records that match certain criteria.
-
Simple Querying: queryRecords(doc, fieldName, searchValue)
This function returns an array of records where the specified field matches a given search value.
Function Signature:
bejsonCore.queryRecords(doc, fieldName, searchValue)- doc (object): The BEJSON document object to query.
- fieldName (string): The name of the field to check.
- searchValue (any): The value to match against the field.
Example:
Find all sensor readings from a specific sensor ID.
const bejsonCore = require('bejson-js-library').core; const sensorData = bejsonCore.create104( "SensorReading", [ {"name": "sensor_id", "type": "string"}, {"name": "timestamp", "type": "string"}, {"name": "temperature", "type": "number"} ], [ ["S001", "2026-01-10T12:00:00Z", 23.5], ["S002", "2026-01-10T12:00:00Z", 19.8], ["S001", "2026-01-10T12:05:00Z", 24.1], ["S003", "2026-01-10T12:10:00Z", 21.0] ] ); console.log("Original Sensor Data:"); console.log(bejsonCore.prettyPrint(sensorData)); const readingsForS001 = bejsonCore.queryRecords(sensorData, "sensor_id", "S001"); console.log("\nReadings for Sensor S001:"); console.log(JSON.stringify(readingsForS001, null, 2)); -
Advanced Querying: queryRecordsAdvanced(doc, conditions)
This function allows you to query records based on multiple field conditions. It returns an array of records that satisfy all provided conditions.
Function Signature:
bejsonCore.queryRecordsAdvanced(doc, conditions)- doc (object): The BEJSON document object to query.
- conditions (object): An object where keys are field names and values are the exact values to match.
Example:
Find all sensor readings from "S001" with a temperature of 23.5.
const bejsonCore = require('bejson-js-library').core; const sensorData = bejsonCore.create104( "SensorReading", [ {"name": "sensor_id", "type": "string"}, {"name": "timestamp", "type": "string"}, {"name": "temperature", "type": "number"} ], [ ["S001", "2026-01-10T12:00:00Z", 23.5], ["S002", "2026-01-10T12:00:00Z", 19.8], ["S001", "2026-01-10T12:05:00Z", 24.1] ] ); const specificReading = bejsonCore.queryRecordsAdvanced(sensorData, { "sensor_id": "S001", "temperature": 23.5 }); console.log("\nSpecific Reading (S001, 23.5):"); console.log(JSON.stringify(specificReading, null, 2)); -
Querying by Record Type (104db only): getRecordsByType(doc, recordType)
For BEJSON 104db documents, this function allows you to retrieve all records belonging to a specific entity type.
Function Signature:
bejsonCore.getRecordsByType(doc, recordType)- doc (object): The BEJSON 104db document object.
- recordType (string): The entity type to filter by (must be one of the types in Records_Type).
Example:
Retrieve all "User" records from a 104db document.
const bejsonCore = require('bejson-js-library').core; const userProductData = bejsonCore.create104db( ["User", "Product"], [ {"name": "Record_Type_Parent", "type": "string"}, {"name": "user_id", "type": "string", "Record_Type_Parent": "User"}, {"name": "username", "type": "string", "Record_Type_Parent": "User"}, {"name": "product_id", "type": "string", "Record_Type_Parent": "Product"}, {"name": "product_name", "type": "string", "Record_Type_Parent": "Product"} ], [ ["User", "U001", "alice", null, null], ["Product", null, null, "P001", "Laptop"], ["User", "U002", "bob", null, null], ["Product", null, null, "P002", "Mouse"] ] ); console.log("\nOriginal User/Product Data:"); console.log(bejsonCore.prettyPrint(userProductData)); const users = bejsonCore.getRecordsByType(userProductData, "User"); console.log("\nAll User Records:"); console.log(JSON.stringify(users, null, 2));Attempting to use getRecordsByType() on a non-104db document will throw a BEJSONCoreError with code E_CORE_INVALID_OPERATION.
Filtering Documents with Custom Predicates
For more complex filtering logic that cannot be achieved with simple key-value matching, the filterRows() function allows you to provide a custom predicate function.
Function Signature:
bejsonCore.filterRows(doc, predicateFn)
- doc (object): The BEJSON document object to filter.
- predicateFn (function): A function that takes a single record (array of values) as an argument and returns true to include the record or false to exclude it.
Example:
Filter sensor data to include only readings with a temperature above 20.0.
const bejsonCore = require('bejson-js-library').core;
const sensorData = bejsonCore.create104(
"SensorReading",
[
{"name": "sensor_id", "type": "string"},
{"name": "timestamp", "type": "string"},
{"name": "temperature", "type": "number"}
],
[
["S001", "2026-01-10T12:00:00Z", 23.5],
["S002", "2026-01-10T12:00:00Z", 19.8],
["S001", "2026-01-10T12:05:00Z", 24.1],
["S003", "2026-01-10T12:10:00Z", 21.0]
]
);
console.log("Original Sensor Data:");
console.log(bejsonCore.prettyPrint(sensorData));
const temperatureFieldIndex = bejsonCore.getFieldIndex(sensorData, "temperature");
const highTempReadings = bejsonCore.filterRows(sensorData, record => {
return record[temperatureFieldIndex] > 20.0;
});
console.log("\nHigh Temperature Readings (above 20.0):");
console.log(bejsonCore.prettyPrint(highTempReadings));
Sorting Records
The sortByField() function allows you to sort the records in a BEJSON document based on the values of a specified field, either in ascending or descending order.
Function Signature:
bejsonCore.sortByField(doc, fieldName, ascending = true)
- doc (object): The BEJSON document object to sort.
- fieldName (string): The name of the field to sort by.
- ascending (boolean, optional): If true (default), sorts in ascending order. If false, sorts in descending order.
Example:
Sort sensor data by temperature in ascending order, and then by timestamp in descending order.
const bejsonCore = require('bejson-js-library').core;
const sensorData = bejsonCore.create104(
"SensorReading",
[
{"name": "sensor_id", "type": "string"},
{"name": "timestamp", "type": "string"},
{"name": "temperature", "type": "number"}
],
[
["S001", "2026-01-10T12:00:00Z", 23.5],
["S002", "2026-01-10T12:00:00Z", 19.8],
["S001", "2026-01-10T12:05:00Z", 24.1],
["S003", "2026-01-10T12:10:00Z", 21.0],
["S002", "2026-01-10T12:15:00Z", 20.5]
]
);
console.log("Original Sensor Data:");
console.log(bejsonCore.prettyPrint(sensorData));
// Sort by temperature ascending
const sortedByTemp = bejsonCore.sortByField(sensorData, "temperature");
console.log("\nSorted by Temperature (Ascending):");
console.log(bejsonCore.prettyPrint(sortedByTemp));
// Sort by timestamp descending
const sortedByTimestampDesc = bejsonCore.sortByField(sensorData, "timestamp", false);
console.log("\nSorted by Timestamp (Descending):");
console.log(bejsonCore.prettyPrint(sortedByTimestampDesc));
These advanced manipulation functions provide powerful tools for working with BEJSON data, enabling you to transform and analyze your datasets effectively while maintaining the integrity of your original documents.
Column-Level Operations
The BEJSON JavaScript Library provides a dedicated set of functions for managing the structure of your BEJSON documents at the column (field) level. These operations allow you to dynamically add, remove, and rename fields, as well as retrieve and set entire columns of data. Consistent with the library's design philosophy, these functions return a new BEJSON document object with the schema changes applied, leaving the original document unaltered.
All column-level operations are exposed via the core module:
const bejsonCore = require('bejson-js-library').core;
Adding a New Column
To extend your BEJSON document's schema, you can add new fields (columns) using the addColumn() function. This function appends a new field definition to the Fields array and a corresponding default value to every existing record in the Values array.
Function Signature:
bejsonCore.addColumn(doc, fieldName, fieldType, defaultValue = null, recordTypeParent = "")
- doc (object): The original BEJSON document object.
- fieldName (string): The name of the new field.
- fieldType (string): The data type of the new field (e.g., "string", "integer", "number", "boolean", "array", "object").
- defaultValue (any, optional): The value to populate for this new field in all existing records. Defaults to null.
- recordTypeParent (string, optional): For BEJSON 104db documents only. Specifies which entity type this field belongs to. If not provided for 104db, it will lead to validation errors.
Example:
Let's add a new "status" column to a BEJSON 104 document and a "department" column to a BEJSON 104db document.
const bejsonCore = require('bejson-js-library').core;
// Example BEJSON 104 document
let tasksDoc = bejsonCore.create104(
"Task",
[
{"name": "task_id", "type": "string"},
{"name": "description", "type": "string"}
],
[
["T001", "Review code"],
["T002", "Deploy app"]
]
);
console.log("Original Tasks Document (104):");
console.log(bejsonCore.prettyPrint(tasksDoc));
// Add a 'status' column with a default value
let updatedTasksDoc = bejsonCore.addColumn(tasksDoc, "status", "string", "Pending");
console.log("\nTasks Document After Adding 'status' Column:");
console.log(bejsonCore.prettyPrint(updatedTasksDoc));
// Example BEJSON 104db document
let employeesDoc = bejsonCore.create104db(
["Employee", "Project"],
[
{"name": "Record_Type_Parent", "type": "string"},
{"name": "employee_id", "type": "string", "Record_Type_Parent": "Employee"},
{"name": "name", "type": "string", "Record_Type_Parent": "Employee"},
{"name": "project_id", "type": "string", "Record_Type_Parent": "Project"},
{"name": "project_name", "type": "string", "Record_Type_Parent": "Project"}
],
[
["Employee", "E001", "Alice", null, null],
["Employee", "E002", "Bob", null, null],
["Project", null, null, "P100", "Frontend Redesign"]
]
);
console.log("\nOriginal Employees/Projects Document (104db):");
console.log(bejsonCore.prettyPrint(employeesDoc));
// Add a 'department' column for 'Employee' records in 104db
let updatedEmployeesDoc = bejsonCore.addColumn(employeesDoc, "department", "string", null, "Employee");
console.log("\nEmployees/Projects Document After Adding 'department' Column:");
console.log(bejsonCore.prettyPrint(updatedEmployeesDoc));
Attempting to add a column with a name that already exists will throw a BEJSONCoreError with code E_CORE_INVALID_OPERATION.
Removing an Existing Column
To remove a field (column) from a BEJSON document, use the removeColumn() function. This function removes the field definition from the Fields array and deletes the corresponding value from every record in the Values array.
Function Signature:
bejsonCore.removeColumn(doc, fieldName)
- doc (object): The original BEJSON document object.
- fieldName (string): The name of the field to remove.
Example:
Let's remove the "description" column from our tasks document.
const bejsonCore = require('bejson-js-library').core;
let tasksDoc = bejsonCore.create104(
"Task",
[
{"name": "task_id", "type": "string"},
{"name": "description", "type": "string"},
{"name": "status", "type": "string"}
],
[
["T001", "Review code", "Pending"],
["T002", "Deploy app", "Completed"]
]
);
console.log("Original Tasks Document:");
console.log(bejsonCore.prettyPrint(tasksDoc));
// Remove the 'description' column
let docWithoutDescription = bejsonCore.removeColumn(tasksDoc, "description");
console.log("\nTasks Document After Removing 'description' Column:");
console.log(bejsonCore.prettyPrint(docWithoutDescription));
Attempting to remove a non-existent field will throw a BEJSONCoreError with code E_CORE_FIELD_NOT_FOUND.
Renaming a Column
To change the name of an existing field, use the renameColumn() function. This updates the name property in the corresponding field definition within the Fields array.
Function Signature:
bejsonCore.renameColumn(doc, oldName, newName)
- doc (object): The original BEJSON document object.
- oldName (string): The current name of the field.
- newName (string): The new name for the field.
Example:
Let's rename "task_id" to "id" in our tasks document.
const bejsonCore = require('bejson-js-library').core;
let tasksDoc = bejsonCore.create104(
"Task",
[
{"name": "task_id", "type": "string"},
{"name": "description", "type": "string"}
],
[
["T001", "Review code"],
["T002", "Deploy app"]
]
);
console.log("Original Tasks Document:");
console.log(bejsonCore.prettyPrint(tasksDoc));
// Rename 'task_id' to 'id'
let docWithRenamedColumn = bejsonCore.renameColumn(tasksDoc, "task_id", "id");
console.log("\nTasks Document After Renaming 'task_id' to 'id':");
console.log(bejsonCore.prettyPrint(docWithRenamedColumn));
Attempting to rename a non-existent field or rename a field to a name that already exists will throw a BEJSONCoreError (codes E_CORE_FIELD_NOT_FOUND or E_CORE_INVALID_OPERATION, respectively).
Retrieving Entire Column Data
To get an array of all values for a specific column across all records, use the getColumn() function. This is equivalent to getFieldValues() mentioned in Chapter 4.
Function Signature:
bejsonCore.getColumn(doc, fieldName)
- doc (object): The BEJSON document object.
- fieldName (string): The name of the field whose values you want to retrieve.
Example:
Get all task descriptions.
const bejsonCore = require('bejson-js-library').core;
const tasksDoc = bejsonCore.create104(
"Task",
[
{"name": "task_id", "type": "string"},
{"name": "description", "type": "string"}
],
[
["T001", "Review code"],
["T002", "Deploy app"]
]
);
console.log("\nAll task descriptions:", bejsonCore.getColumn(tasksDoc, "description"));
Setting Entire Column Data
To update all values within a specific column at once, use the setColumn() function. The provided array of values must match the number of records in the document.
Function Signature:
bejsonCore.setColumn(doc, fieldName, valuesArray)
- doc (object): The original BEJSON document object.
- fieldName (string): The name of the field (column) to update.
- valuesArray (array): An array of new values for the column. Its length must match the number of records in the document.
Example:
Let's update the status of all tasks.
const bejsonCore = require('bejson-js-library').core;
let tasksDoc = bejsonCore.create104(
"Task",
[
{"name": "task_id", "type": "string"},
{"name": "description", "type": "string"},
{"name": "status", "type": "string"}
],
[
["T001", "Review code", "Pending"],
["T002", "Deploy app", "In Progress"]
]
);
console.log("Original Tasks Document:");
console.log(bejsonCore.prettyPrint(tasksDoc));
const newStatuses = ["Completed", "Completed"];
let docWithUpdatedStatuses = bejsonCore.setColumn(tasksDoc, "status", newStatuses);
console.log("\nTasks Document After Setting 'status' Column:");
console.log(bejsonCore.prettyPrint(docWithUpdatedStatuses));
If the valuesArray length does not match the record count, a BEJSONCoreError with code E_CORE_INVALID_OPERATION will be thrown.
These column-level operations provide a flexible way to manage the schema and bulk data of your BEJSON documents, enabling dynamic adjustments to your data structure as application requirements evolve.
Atomic File Operations and Utilities
This final chapter covers the BEJSON JavaScript Library's capabilities for safely writing BEJSON documents to disk and a collection of utility functions that enhance your workflow. The library emphasizes robust file operations, particularly through its atomic write mechanism, which safeguards against data corruption during save operations.
All discussed functions are part of the core module:
const bejsonCore = require('bejson-js-library').core;
Atomic File Operations
Writing data to a file can be prone to issues such as power outages or application crashes, which might leave the file in a corrupted or incomplete state. The BEJSON library addresses this with atomic file operations, specifically the atomicWrite() function. An atomic write ensures that either the entire file is written successfully, or the original file remains untouched, preventing partial writes. This is achieved by writing to a temporary file, validating it, and then atomically replacing the original file.
Function Signature:
bejsonCore.atomicWrite(filePath, content, createBackup = true)
- filePath (string): The path to the file where the BEJSON document should be saved.
- content (object): The BEJSON document object to write to the file.
- createBackup (boolean, optional): If true (default), a timestamped backup of the original file will be created before writing.
How it Works:
- If createBackup is true and the filePath exists, a backup of the current file is created (e.g.,
my_data.bejson.backup.YYYYMMDDTHHMMSS). - The content is serialized to a JSON string and written to a temporary file (e.g.,
my_data.bejson.tmp.TIMESTAMP). - The temporary file is then internally validated as a BEJSON document. If validation fails, the temporary file is deleted, and the original file (or its backup if created) is restored.
- If validation passes, the temporary file is atomically renamed to the filePath, replacing the original file.
- If a backup was created and the write was successful, the backup file is then deleted.
Example:
const bejsonCore = require('bejson-js-library').core;
const fs = require('fs');
const filePath = './my_atomic_data.bejson';
const initialDoc = bejsonCore.create104(
"Device",
[{"name": "id", "type": "string"}, {"name": "status", "type": "string"}],
[["D001", "Online"], ["D002", "Offline"]]
);
// Initial write
try {
bejsonCore.atomicWrite(filePath, initialDoc);
console.log("Initial document written atomically to", filePath);
} catch (e) {
console.error("Error during initial write:", e.message);
}
// Modify the document
let updatedDoc = bejsonCore.addRecord(initialDoc, ["D003", "Idle"]);
updatedDoc = bejsonCore.updateField(updatedDoc, 0, "status", "Maintenance");
// Atomic write with backup
try {
bejsonCore.atomicWrite(filePath, updatedDoc, true); // createBackup is true by default
console.log("\nDocument updated atomically with backup.");
console.log("Final document content:");
console.log(bejsonCore.prettyPrint(bejsonCore.loadFile(filePath)));
} catch (e) {
console.error("\nError during update write:", e.message);
} finally {
// Clean up
if (fs.existsSync(filePath)) fs.unlinkSync(filePath);
// Note: backup files are automatically cleaned up on successful atomicWrite
// but if an error occurred during atomicWrite, a backup file might remain
// with a timestamp suffix (e.g., my_atomic_data.bejson.backup.20260302T150000)
// You might want to implement a separate cleanup for orphaned backups in production.
}
This function is critical for applications where data integrity during file persistence is paramount.
Utility Functions
The BEJSON library includes several utility functions to help with formatting, inspection, and overall management of your BEJSON data.
-
Pretty Printing: prettyPrint(doc)
Returns a JSON string representation of the BEJSON document, formatted with indentation for human readability.
const bejsonCore = require('bejson-js-library').core; const doc = bejsonCore.create104("Test", [{"name": "key", "type": "string"}], [["value"]]); console.log("\nPretty Printed Document:"); console.log(bejsonCore.prettyPrint(doc)); -
Compact Printing: compactPrint(doc)
Returns a JSON string representation of the BEJSON document, without any extra whitespace or indentation, suitable for storage or network transmission where size optimization is important.
const bejsonCore = require('bejson-js-library').core; const doc = bejsonCore.create104("Test", [{"name": "key", "type": "string"}], [["value"]]); console.log("\nCompact Printed Document:"); console.log(bejsonCore.compactPrint(doc)); -
Checking Document Validity: isValid(doc)
Performs a full BEJSON validation on the provided document object and returns a boolean indicating whether it is valid (true) or not (false). This function does not throw an error on invalidity, making it suitable for quick checks. For detailed error information, use the validator.getReport() function from the validator module.
const bejsonCore = require('bejson-js-library').core; const { validator } = require('bejson-js-library').validator; const validDoc = bejsonCore.create104("Test", [{"name": "key", "type": "string"}], [["value"]]); const invalidDoc = { ...validDoc, Format_Version: "999" }; // Intentionally make it invalid console.log("\nIs validDoc valid?", bejsonCore.isValid(validDoc)); // true console.log("Is invalidDoc valid?", bejsonCore.isValid(invalidDoc)); // false console.log("Detailed report for invalidDoc:"); console.log(validator.getReport(JSON.stringify(invalidDoc))); -
Getting Document Statistics: getStats(doc)
Returns an object containing key statistics about the BEJSON document, such as its version, the number of fields, the number of records, and the defined record types. This is identical to the function discussed in Chapter 4.
const bejsonCore = require('bejson-js-library').core; const doc = bejsonCore.create104db( ["User", "Role"], [ {"name": "Record_Type_Parent", "type": "string"}, {"name": "user_id", "type": "string", "Record_Type_Parent": "User"}, {"name": "role_id", "type": "string", "Record_Type_Parent": "Role"} ], [ ["User", "U001", null], ["Role", null, "R001"] ] ); console.log("\nDocument Statistics:"); console.log(bejsonCore.getStats(doc));
These atomic file operations and utility functions complete the BEJSON JavaScript Library's toolkit, providing everything you need for robust document management, from safe persistence to convenient data inspection and formatting.

