@altraplay/core
v2.1.3
Published
A centralized NPM package for the utilities frequently used across Altraplay's TypeScript microservices
Maintainers
Readme
@altraplay/core
A centralized NPM package for the utilities frequently used across our TypeScript microservices.
Installation
You can install this package using npm or bun:
npm install @altraplay/core
# or
bun add @altraplay/coreConfiguration
This package uses standard environment variables for all configuration. No external secrets service required.
Naming Convention:
Use PascalCase in code - it automatically converts to SCREAMING_SNAKE_CASE env vars.
import { config } from '@altraplay/core'
// Get value with optional fallback
config.get('ApiKey', 'default-key')
// Internally converts 'ApiKey' to 'API_KEY'Common Config Keys:
KafkaNodes: Kafka broker nodes (comma-separated).LogsKafkaNodes: Kafka brokers for logging.DbNodes: ScyllaDB/Cassandra contact points (comma-separated).DbDc: The datacenter for ScyllaDB (default:datacenter1).DbUser: The username for ScyllaDB (default:cassandra).DbPass: The password for ScyllaDB (default:cassandra).DbKs: The keyspace for ScyllaDB (default:altraplay).RedisUrl: The connection URL for Redis.S3Region: AWS region for S3 (default:ap-south-1).S3AccessKeyId: AWS access key ID for S3 authentication.S3SecretAccessKey: AWS secret access key for S3 authentication.S3Endpoint: Optional custom S3 endpoint.S3Bucket: Default S3 bucket name.
Example:
KAFKA_NODES=kafka1:9092,kafka2:9092
LOGS_KAFKA_NODES=logs-kafka:9092
DB_NODES=scylla1:9042Modules and Functions
InitService (Core Initialization)
The InitService class provides a convenient way to initialize and access various core utilities within your microservice. It aggregates functionalities from other modules and manages configuration.
new InitService(serviceName: string, configOverrides?: Record<string, string>)
Initializes the service synchronously.
serviceName: The name of the service, used as client ID for Kafka.configOverrides: Optional config values to override env vars.
Aggregated Methods & Properties:
config: The fully resolved configuration object.instanceId: Unique UUID for this service instance.serviceName: The name of the service.randomString: Accesses theULID.genfunction for generating unique IDs.logger: Accesses theKafkaLoggerinstance witherror,warn,info, anddebugmethods.S3: Creates an S3 client with credentials from env vars.exec: Accesses theexecmethod of aScyllainstance.emit: Accesses theemitmethod of a Kafka producer instance for publishing domain events.redis: A Redis client instance using Bun's native client withget,set,del, andupdateConfigmethods.validate.isVisible: Accesses theisVisiblefunction fromsrc/validate.ts.
import { InitService, config } from '@altraplay/core'
// Access config directly
const apiKey = config.get('API_KEY', 'default')
const dbUrl = config.getRequired('DB_URL')
// Initialize service
const service = new InitService('my-microservice')
// Example usage:
const randomId = service.randomString() // Uses ULID.gen()
await service.logger.info({
msg: 'Service started',
route: 'system',
action: 'init',
location: 'main.ts'
})
const s3Client = service.S3({ defaultBucket: 'my-bucket' })
const dbResult = await service.exec('SELECT * FROM users')
await service.emit('user.signup', [{
data: { userId: '123' },
meta: { cid: 'request-id-123' }
}])Re-exported Modules:
The Scylla class, createRedisClient, Config, and config helpers are also directly re-exported.
import { Scylla, createRedisClient, Config, config } from '@altraplay/core'validate.isVisible
Checks if a piece of content should be visible to a specific user.
isVisible(content?: Record<string, any> | null, viewer?: string | null): boolean
content: An object containing content details, which must include auid(the content owner's ID) and avisibilityarray.viewer: The ID of the user attempting to view the content.
Returns true if:
- The viewer is the owner of the content (
content.uid === viewer). - The content is public (
content.visibility?.includes('pub')). - The viewer's ID is in the
visibilityarray.
const { validate } = service // from InitService.start('my-microservice')
const publicContent = { uid: 'user-a', visibility: ['pub'] }
const privateContent = { uid: 'user-a', visibility: ['user-b'] }
validate.isVisible(publicContent, 'user-c') // true
validate.isVisible(privateContent, 'user-a') // true
validate.isVisible(privateContent, 'user-b') // true
validate.isVisible(privateContent, 'user-c') // falsecreateS3Client (AWS S3 Utility)
Creates an S3 client instance using Bun's native S3 client. Credentials are fetched from environment variables. It provides convenient methods for get, put, and delete operations, including support for generating presigned URLs.
service.S3(config?: S3ClientConfig)
config: An optional configuration object extending Bun'sS3Options, with an addeddefaultBucketproperty. S3 credentials are loaded from env vars.
Returned Methods:
get(params: GetParameters): Promise<GetOutput>: Retrieves an object. Can return the body in various formats or a presigned URL.put(params: PutParameters): Promise<PutOutput>: Uploads an object or generates a presigned URL for uploading.delete(params: DeleteParameters): Promise<DeleteOutput>: Deletes an object or generates a presigned URL for deletion.
const s3 = service.S3({ defaultBucket: 'my-default-bucket' })
// Upload a file
await s3.put({ Key: 'my-file.txt', Body: 'Hello, World!' })
// Get a file
const { Body } = await s3.get({ Key: 'my-file.txt', ResponseType: 'text' })
console.log(Body) // 'Hello, World!'
// Generate a presigned URL for a GET request
const { PresignedUrl } = await s3.get({
Key: 'my-file.txt',
PresignConfig: { expiresIn: 60 } // URL expires in 60 seconds
})Scylla (ScyllaDB/Cassandra Utility)
The Scylla class provides a robust interface for interacting with ScyllaDB or Apache Cassandra databases.
new Scylla(config: ScyllaClientOptions, logger: KafkaLogger)
Initializes a new database client instance with configuration and logger injection.
config: AScyllaClientOptionsobject containing connection details (nodes,dc,user,pass,ks).logger: AKafkaLoggerinstance for error logging.
exec
Executes a database query or a batch of queries. This method is overloaded to support single queries, detailed results with pagination, and batch operations.
const { exec } = service // from InitService.start('my-microservice')
// Fetching a single user
const user = await exec<{ id: string; name: string }>('SELECT id, name FROM users WHERE id = ?', [
'user123'
])updateConfig
Updates the database configuration and reconnects (for hot config reload).
await service.scylla.updateConfig({
nodes: ['new-node1:9042', 'new-node2:9042'],
dc: 'datacenter1',
user: 'cassandra',
pass: 'new-password',
ks: 'mykeyspace'
})createProducer (Kafka Utility)
Creates a Kafka producer instance with ZSTD compression.
createProducer(serviceName: string, config: Config): { emit: (event: string, data: KafkaMessage[]) => Promise<void>; producer: Producer; updateConfig: (config: Config) => Promise<void> }
serviceName: The name of the service, used as the KafkaclientIdand event source.config: A configuration object withnodesarray.
Event Format:
The emit function expects events in the following format:
{
data: Record<string, any> // Event payload
meta?: { // Optional metadata (auto-enriched)
id?: string // Event UUID (auto-generated if not provided)
ts?: number // Timestamp (auto-generated if not provided)
cid?: string // Correlation ID
src?: string // Source service (auto-set)
ver?: string // Schema version (default: '1.0')
}
ctx?: Record<string, any> // Optional context
}Usage:
const { emit } = service // from InitService.start('my-microservice')
// Publish an event
await emit('user.signup', [{
data: { userId: '123', email: '[email protected]' },
meta: { cid: 'request-123' },
ctx: { ip: '192.168.1.1' }
}])
// Event topic will be 'user.signup' or if no dot in event, 'servicename.event'KafkaLogger (Logging Utility)
A comprehensive logging class that pushes structured log entries to a Kafka topic and logs to the console.
new KafkaLogger(serviceName: string, config: Config)
Initializes the Kafka logger.
serviceName: The name of the service generating the logs.config: A configuration object withnodesarray.
Structured Logging Methods
All methods accept a structured log data object:
interface LogData {
msg: string // Log message
route: string // Route/endpoint
action: string // Action being performed
location: string // Source file location
uid?: string // Optional user ID
coId?: string // Optional correlation ID
extra?: Record<string, any> // Optional extra data
}Methods:
error(data: Omit<LogData, 'level'>): Promise<void>warn(data: Omit<LogData, 'level'>): Promise<void>info(data: Omit<LogData, 'level'>): Promise<void>debug(data: Omit<LogData, 'level'>): Promise<void>
const { logger } = service // from InitService.start('my-microservice')
await logger.error({
msg: 'Database connection failed',
route: 'api/users',
action: 'database_query',
location: 'users.ts:45',
uid: 'user-123',
coId: 'req-456',
extra: { query: 'SELECT * FROM users', error: err.message }
})
await logger.info({
msg: 'User created successfully',
route: 'api/users',
action: 'user_create',
location: 'users.ts:67',
uid: 'user-123'
})createRedisClient (Redis Utility)
Creates a Redis client instance using Bun's native Redis client.
createRedisClient(serviceName: string, config: RedisConfig, logger: KafkaLogger): RedisClient
serviceName: The name of the service, used for logging errors.config: A configuration object withurlproperty.logger: AKafkaLoggerinstance for error logging.
Returned Methods:
get<T>(key: string, meta?: Partial<LogData>): Promise<T | null>: Retrieves a value by key.set<T>(key: string, value: T, ttlSeconds?: number, meta?: Partial<LogData>): Promise<'OK' | null>: Sets a value with optional TTL (default: 3 days).del(key: string | string[], meta?: Partial<LogData>): Promise<number>: Deletes one or more keys.updateConfig(config: RedisConfig): void: Updates Redis configuration and reconnects.client: Read-only access to the underlying Redis client instance.
const { redis } = service // from InitService.start('my-microservice')
// Set with default TTL (3 days)
await redis.set('user:123', { name: 'John Doe' })
// Set with custom TTL (1 hour)
await redis.set('session:456', { data: '...' }, 3600)
// Get
const user = await redis.get('user:123')
// Delete
await redis.del('user:123')
await redis.del(['key1', 'key2', 'key3'])MatrixCollector (Resource Monitoring)
Automatically collects and publishes system metrics (CPU, memory, uptime) to Kafka.
new MatrixCollector(service: InitService, uid: string)
Creates a new matrix collector for the service.
start(ms = 60000): void
Starts collecting metrics at the specified interval (default: 60 seconds).
stop(): void
Stops the metrics collection.
// Automatically started by InitService
// Metrics are published to 'system.matrix' topic
// Access via service.matrix if needed
service.matrix.stop() // Stop collecting
service.matrix.start(30000) // Restart with 30s intervalHot Configuration Reload
All major services support hot configuration reload without restart:
// Manual config update
await service.scylla.updateConfig(newConfig.scylla)
service.redis.updateConfig(newConfig.redis)
await service.producerObj.updateConfig(newConfig.kafka)Dependencies
cassandra-driverkafkajsbun(native S3 and Redis clients)
Changelog
See CHANGELOG.md for version history and migration guides.
