@schematize/util-db
v0.4.6
Published
Schematize DB Utility Library
Readme
@schematize/util-db
Database utility functions for the Schematize platform. This package provides comprehensive database operations for UML metamodel instances, including CRUD operations, relationship management, and secure SQL generation with automatic inheritance handling.
Features
- Instance Management: Create, read, update, and delete UML instances
- Relationship Handling: Manage associations and links between instances
- Inheritance Support: Automatic handling of UML inheritance hierarchies
- Secure SQL Generation: SQL injection protection with parameterized queries
- Filter Support: Complex filtering with value specifications
- Include Support: Fetch related instances and associations
- MySQL Integration: Built on mysql2 with connection pooling
Dependencies
@schematize/instance.js: Instance management and utilities@schematize/metamodel: UML metamodel operations@schematize/refs: Reference utilities for cross-platform compatibilitymysql2: MySQL database driver
Installation
npm install @schematize/util-dbUsage
import {
fetchInstances,
saveInstance,
deleteInstance,
fetchLinks,
saveLink,
deleteLink
} from '@schematize/util-db';
// Fetch instances with filtering
const users = await fetchInstances({
credentials: { host: 'localhost', user: 'root', hostRead: 'db_host_here' },
classifier: UserClass,
filter: { name: 'John' },
limit: 10
});
// Save a new instance
const newUser = await saveInstance({
credentials: dbCredentials,
instance: new User({ name: 'Jane', email: '[email protected]' }),
owner: currentUser
});API Reference
Core Database Operations
credentials parameter
Common among each of these methods is the credentials parameter. These are the details of the parameter:
The credentials object contains database connection information required to establish connections to your MySQL database. It supports both read and write database separation for improved performance and scalability.
Properties
user(String, required): Database username for authenticationpassword(String, required): Database password for authenticationhost(String, optional): Primary database host (used as fallback for read/write hosts)hostRead(String, optional): Read-only database host for query operationshostWrite(String, optional): Write database host for insert/update/delete operations
Usage Examples
// Basic credentials with single host
const credentials = {
user: 'root',
password: 'password',
host: 'localhost'
};
// Credentials with separate read/write hosts
const credentials = {
user: 'root',
password: 'password',
hostRead: 'read-db.example.com',
hostWrite: 'write-db.example.com'
};
// Credentials using environment variables
const credentials = {
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
hostRead: process.env.DB_HOST_READ,
hostWrite: process.env.DB_HOST
};Connection Behavior
- If
hostReadis provided, read operations (queries) will use this host - If
hostWriteis provided, write operations (inserts/updates/deletes) will use this host - If only
hostis provided, all operations will use this host - If neither
hostReadnorhostWriteis provided,hostwill be used for all operations - The connection uses MySQL2 with connection pooling and optimized settings for the Schematize platform
fetchInstances
Fetches instances of a classifier from the database with support for filtering, inheritance, and pagination.
Parameters
credentials(Object): Database connection credentialsclassifier(Object): UML classifier to fetch instances forfilterInternal(Boolean): Filter out internal properties (default: true)filteredProperties(Object): Properties to filter from resultsfilter(Object): Filter conditions using symbol/operand format (e.g.,{ symbol: '&&', operand: [...] })classifierFilters(Object): Specific filters for individual classifiers using{ language: ['SQL'], body: ['condition'] }formatlimit(Number): Maximum number of instances to returnbefore(Function): Hook function called before executionreturnType(String): Return format - 'object' or 'instance' (default: 'object')log(Function): Logging functionlogLine(Function): Line-by-line logging function
Returns
Promise<Object>: Fetched instances as objects or instances
Usage
const instances = await fetchInstances({
credentials: {
user: 'root',
password: 'password',
hostRead: 'db_host_here'
},
classifier: UserClass,
filter: {
symbol: '&&',
operand: [
{
language: ['SQL'],
body: ['name LIKE "%John%"']
},
{
language: ['SQL'],
body: ['age >= 18']
}
]
},
classifierFilters: {
[UserClass.__id__]: {
language: ['SQL'],
body: ['status = "active"']
}
},
limit: 50,
returnType: 'object'
});saveInstance
Saves an instance to the database, handling both inserts and updates.
Parameters
credentials(Object): Database connection credentialsinstance(Object): Instance to saveowner(Object): Owner of the instancereturnType(String): Return format (default: 'object')expectExists(Boolean): Whether instance should already existbefore(Function): Hook function called before saveafter(Function): Hook function called after savelog(Function): Logging functionlogLine(Function): Line-by-line logging function
Returns
Promise<Object>: Saved instance
Usage
const savedUser = await saveInstance({
credentials: dbCredentials,
instance: new User({
name: 'John Doe',
email: '[email protected]',
age: 30
}),
owner: currentUser,
before: (instance) => {
instance.createdAt = new Date();
}
});deleteInstance
Deletes an instance from the database, including all related links.
Parameters
credentials(Object): Database connection credentialsinstance(Object): Instance to deletebefore(Function): Hook function called before deletionlog(Function): Logging functionlogLine(Function): Line-by-line logging function
Returns
Promise<void>: Promise that resolves when deletion is complete
Usage
await deleteInstance({
credentials: dbCredentials,
instance: userToDelete,
before: (instance) => {
console.log(`Deleting user: ${instance.name}`);
}
});Relationship Operations
fetchLinks
Fetches association links between instances.
Parameters
credentials(Object): Database connection credentialsclassifier(Object): Association classifier to fetch links forfilteredProperties(Object): Properties to filter from resultsreturnType(String): Return format (default: 'object')filter(Object): Filter conditionsclassifierFilters(Object): Specific filters for classifiersbefore(Function): Hook function called before executionlog(Function): Logging functionlogLine(Function): Line-by-line logging function
Returns
Promise<Object|Array>: Fetched links
Usage
const userRoles = await fetchLinks({
credentials: dbCredentials,
classifier: UserRoleAssociation,
filter: {
symbol: '&&',
operand: [
{
language: ['SQL'],
body: [`user__id__ = ${v(userId)}`]
},
{
language: ['SQL'],
body: ['role.name = "admin"']
}
]
}
});saveLink
Saves an association link between instances.
Parameters
credentials(Object): Database connection credentialsinstance(Object): Link instance to savereturnType(String): Return format (default: 'object')expectExists(Boolean): Whether link should already existbefore(Function): Hook function called before saveafter(Function): Hook function called after savelog(Function): Logging functionlogLine(Function): Line-by-line logging function
Returns
Promise<Object>: Saved link
Usage
const userRole = await saveLink({
credentials: dbCredentials,
instance: new UserRoleAssociation({
user: userInstance,
role: adminRole,
assignedBy: currentUser
})
});deleteLink
Deletes an association link between instances.
Parameters
credentials(Object): Database connection credentialsinstance(Object): Link instance to deletebefore(Function): Hook function called before deletionlog(Function): Logging functionlogLine(Function): Line-by-line logging function
Returns
Promise<void>: Promise that resolves when deletion is complete
Usage
await deleteLink({
credentials: dbCredentials,
instance: userRoleLink
});Related Data Operations
fetchRelated
Fetches instances related to a given instance through a specific property.
Parameters
credentials(Object): Database connection credentialsinstance(Object): Source instancepropertyName(String): Property name to fetch related instances forreturnType(String): Return format (default: 'object')filteredProperties(Object): Properties to filter from resultsfilter(Object): Additional filter conditionslimit(Number): Maximum number of related instancesbefore(Function): Hook function called before executionlog(Function): Logging functionlogLine(Function): Line-by-line logging function
Returns
Promise<Object|Array>: Related instances
Usage
const userPosts = await fetchRelated({
credentials: dbCredentials,
instance: userInstance,
propertyName: 'posts',
filter: { published: true },
limit: 20
});fetchIncludes
Fetches related instances and association links for a given set of starting instances, following JSON:API include semantics (including intermediate resources for multi-part paths).
Parameters
credentials(Object): Database credentials/execution contextinstances(Array): Starting instances to expand includes for (required)include(Array | Object): Include paths as dot-notation strings (e.g.['posts.author', 'posts.comments']) or a pre-built include tree objectreturnType(any): Propagated to lower-level fetchers; controls return shapingfilteredProperties(any): Optional sparse field handling passed through to fetchersbefore(Function): Hook invoked before executionlog(Function): LoggerlogLine(Function): Line-level logger
Returns
Promise<{ links: Array<Object>, instances: Array<Object> }>: Related association links and included instances
Usage
// Given a set of already-fetched resources (e.g., posts),
// fetch related authors and comments (and each comment's author).
const { links, instances: included } = await fetchIncludes({
credentials: dbCredentials,
instances: postsArray,
include: ['author', 'comments', 'comments.author'],
});SQL Generation Utilities
secureSQLCondition
Generates secure SQL conditions with parameterized queries to prevent SQL injection.
Parameters
condition(String): SQL condition string to sanitizetranslateSymbol(Function): Function to translate symbols to safe values
Returns
String: Sanitized SQL condition
Usage
const safeCondition = secureSQLCondition(
'name = "John" AND age > 18',
(symbol) => ({ s: symbol.toUpperCase() })
);valueSpecificationToSQL
Converts value specification objects to SQL conditions.
Parameters
vs(Object): Value specification objecttranslateSymbol(Function): Function to translate symbols
Returns
String: SQL condition string
Usage
const sqlCondition = valueSpecificationToSQL({
and: [
{ name: { $eq: 'John' } },
{ age: { $gte: 18 } }
]
}, translateSymbol);Utility Functions
createError
Creates standardized error objects with status codes and error types.
Parameters
code(String): Error code (default: 'ERROR_INTERNAL_SERVER_ERROR')statusCode(Number): HTTP status codetitle(String): Error titlemessage(String): Error messagefatal(Boolean): Whether error is fatal (default: false)
Returns
Error: Error object with additional properties
Usage
const error = createError({
code: 'ERROR_USER_NOT_FOUND',
statusCode: 404,
title: 'User Not Found',
message: 'The requested user does not exist',
fatal: false
});Database Schema
The package expects a specific database schema that mirrors the UML metamodel:
- Instance Tables: One table per UML class with columns for each attribute
- Link Tables: Association tables for UML associations
- Inheritance: Handled through table joins based on UML generalization relationships
- Primary Keys: Uses
__id__as the primary key for all instances - Foreign Keys: Uses
__id__references for relationships
Security Features
- SQL Injection Protection: All queries use parameterized statements
- Input Sanitization: Automatic sanitization of user inputs
- Access Control: Support for owner-based access control
- Audit Logging: Built-in logging capabilities for all operations
Error Handling
The package provides comprehensive error handling with standardized error codes:
try {
const result = await fetchInstances({
credentials: dbCredentials,
classifier: UserClass
});
} catch (error) {
if (error.code === 'ERROR_CLASSIFIER_REQUIRED') {
// Handle missing classifier
} else if (error.statusCode === 500) {
// Handle server error
}
}License
MIT
Author
Benjamin Bytheway
