Skip to content

About

A modular, type-safe foundation for building expressive, maintainable applications. This package provides core abstractions for domain modeling, HTTP integration, authentication, state management, and more — designed to be framework-agnostic and highly extensible.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

📦 Shared Kernel

A modular, type-safe foundation for building expressive, maintainable applications. This package provides core abstractions for domain modeling, HTTP integration, authentication, state management, and more — designed to be framework-agnostic and highly extensible.

🚀 Installation

npm install @schorts/shared-kernel --save

🤖 Using it with AI coding agents

The package ships agent docs in node_modules/@schorts/shared-kernel/ai/: an AGENTS.md overview, per-area rules, and step-by-step skills (add a command, create an aggregate, implement a DAO, and more) with type-checked examples. Point your agent at them, for example in CLAUDE.md:

Before writing code that uses @schorts/shared-kernel, read
node_modules/@schorts/shared-kernel/ai/AGENTS.md and follow its rules and skills.

ai/README.md has setup for Claude Code (including linking the skills), Cursor, Copilot, and other tools.

🏗️ Architecture & Modules

The Shared Kernel is organized into several domains of functionality, providing robust primitives for your applications.

🧬 Core Domain & DDD

Primitives for expressing your business domain cleanly and enforcing invariants.

  • Aggregates:
    • AggregateRoot: Base class for a cluster of domain objects that can be treated as a single unit. Inherits from Entity and provides built-in domain event recording capabilities.
  • Entities:
    • Entity: Base class for identity-based domain entities.
    • EntityRegistry: Dynamic registry for entity constructors, enabling polymorphic instantiation.
  • Value Objects: A vast collection of primitives that enforce domain constraints and immutability (e.g., CoordinatesValue, EmailValue, StringValue, UUIDValue, URLValue, DateValue, etc.).
  • Domain Events:
    • DomainEvent: Base class for domain-driven event dispatching.
  • Result:
    • Result: Type-safe wrapper for success/failure outcomes. Enforces disciplined error handling without exceptions. Includes accessors (getValue, getError) and guards.
  • Models:
    • BaseModel: Base class for serializable, type-safe models.

⚙️ Command & Event Processing

Abstractions for CQRS, Event Sourcing, and orchestrating complex distributed workflows.

  • CQRS:
    • Command / CommandHandler: Encapsulate intent and state changes.
    • Query / QueryHandler: Define read-side operations.
    • CommandBus / QueryBus: Centralized dispatchers (includes InMemoryCommandBus and InMemoryQueryBus).
  • Sagas:
    • Saga: Abstract base for defining long-running, stateful business processes.
    • SagaManager: Orchestrates saga execution and event routing.
    • SagaStateStore: Stores the ongoing state of a Saga to resume across restarts.
  • Event Bus:
    • EventSubscriber: Clean, type-safe event handlers.
    • InMemoryEventBus: Dispatcher with support for retries and requeueing.
    • DomainEventRegistry: Centralized registry for hydrating polymorphic domain events.
    • InMemoryEventStore: Tracks and replays events.
    • DeadLetterStore: Captures events that failed after maximum retries.

🛡️ Security & Access Control

Tools for managing identities and permissions across applications.

  • Auth:
    • AuthProvider: Abstract interface for authentication strategies.
    • IdentityProvider: Contract for external identity services (Firebase, Auth0, Cognito).
  • RBAC (Role-Based Access Control):
    • RBACPolicy: Base class for defining role-based permission logic.
    • Permission: Lightweight value object for action-resource pairs (e.g., read:orders).
  • ABAC (Attribute-Based Access Control): Extend RBAC with dynamic, contextual attributes using composable predicates.

💾 Persistence & Data Access

Interfaces to decouple application logic from database engines.

  • DAO (Data Access Object): Generic interface defining CRUD operations for entities.
  • UnitOfWork: Enables transactional coordination across multiple persistence operations.
  • Criteria: Fluent query builder for filtering, sorting, and pagination.

📡 Offline & Resilience

Infrastructure for offline persistence, replay, and durability.

  • OfflineStore:
    • Contract for queuing and replaying commands or service calls when offline.
    • Methods: enqueue, list, dequeue, clear.
    • Default payload type: { type: string; args: any[]; meta?: { userId, tenantId, timestamp, retries, correlationId, origin, version } }.

🌐 Networking & APIs

Integrate seamlessly with external services and clients.

  • HTTP:
    • HTTPProvider: Abstract interface for HTTP transport.
    • FetchHTTPProvider: Concrete implementation using fetch.
  • JSON:API:
    • JSONAPIConnector: Interact with JSON:API-compliant endpoints.
    • URLCriteriaParser: Parses JSON:API-style URL parameters into a type-safe Criteria object.
    • EntityJSONAPIMapper: Converts Entity instances into JSON:API-compliant payloads.
  • Pub-Sub:
    • Publisher: Dispatch real-time events to external transports (Pusher, Socket.IO).
    • Subscription: Client-side abstraction for subscribing to real-time channels.
  • Mail:
    • Mailer: Interface for sending email messages.
    • Mail: Type-safe structure representing an email payload.

💻 State Management

Framework-neutral helpers for managing application state.

  • State Manager:
    • StateManager: Abstract reactive state manager with listener support.
    • Includes InMemoryStateManager for in-memory state.
    • Extend StateManager in your application to provide custom persistence.
  • i18n (Internationalization):
    • TranslationResolver: Infrastructure-agnostic interface for resolving localized strings within the domain.

🩺 Observability & Tracking

Diagnostics, error handling, and structured logging.

  • Logger:
    • Logger: Structured, context-aware logging (log, info, debug, warn, error).
    • ConsoleLogger: Local development implementation.
    • ScopedLogger: Composable logging scopes via .child().
  • Error Tracking:
    • ErrorTracker: Coordinator class to track, store, and upload errors robustly with configurable ignore rules.
    • ErrorStore & ErrorUploader: Interfaces to plug into telemetry systems (Sentry, Datadog).
    • TrackedError: Generic model for a tracked error payload.

🛠️ Utilities

Essential helper functions and types used across bounded contexts.

  • Types: Core utility types such as Constructor, DeepPartial, Dictionary, JSON, MaybePromise, Nullable, and Optional.
  • Utils: Common functions for assertion, async flows, object manipulation, string handling, and url parsing.
  • Formatters: Utilities like PascalCamelToSnake case conversion.
  • Converters: Utilities like RemoteFileToBase64.

🧠 Philosophy

This kernel is built around:

  • Type safety: Every abstraction is strongly typed and composable.
  • Domain expressiveness: Value objects, entities, and events encode business logic directly.
  • Extensibility: Plug in your own HTTP, auth, or state strategies.
  • Framework independence: Use it with Node.js, frontend apps, or serverless functions.

📦 Example Usage

import { Criteria } from "@schorts/shared-kernel/criteria";
import { FetchHTTPProvider } from "@schorts/shared-kernel/http";
import { JSONAPIConnector } from "@schorts/shared-kernel/json-api";

type UserAttributes = { name: string; status: string; created_at: string };

const usersURL = new URL("https://api.example.com/users");

const criteria = Criteria.none()
  .where("status", "EQUAL", "active")
  .orderBy("created_at", "DESC")
  .limitResults(10);

const connector = new JSONAPIConnector(new FetchHTTPProvider());

const users = await connector.findMany<UserAttributes>(usersURL, {
  criteria,
  include: ["organization"],
});

users.data.forEach(user => console.log(user.id, user.attributes.name));

Migrating to 11.0

11.0 requires Node.js 20 or later. The CHANGELOG lists every change; the migrate-to-v11 skill walks through the upgrade step by step (and works as instructions for an AI agent).

Removed modules

Guided tours and browser-backed state managers have been removed from the kernel.

  • Remove imports from @schorts/shared-kernel/tour-guide. TourGuide, TourGuideOptions, BaseTourGuide, TourStep, TourSide, and TourAlign are no longer exported from the package root either. Keep tour integrations and their types in your application.
  • LocalStorageStateManager and SessionStorageStateManager are no longer exported from the package root or @schorts/shared-kernel/state-manager. Implement browser persistence in your application by extending StateManager; InMemoryStateManager is not a persistent replacement.
  • StateManager and InMemoryStateManager remain available from the package root and @schorts/shared-kernel/state-manager.

No replacement UI package is provided.

Command and query handlers

execute is no longer part of the CommandHandler and QueryHandler interfaces, and it is protected on AbstractCommandHandler and AbstractQueryHandler.

  • Handlers that extend the abstract classes keep working. Declaring execute as protected is recommended but not required.
  • Hand-written handlers only need handle; remove any execute you added just to satisfy the interface.
  • Replace direct handler.execute(command) calls with handler.handle(command) or bus.dispatch(command). Calling execute directly skipped validation, authorization, idempotency, and timeouts.

unknown instead of any

Values the kernel hands back are now unknown instead of any, so mistakes that used to compile now surface as type errors. The CHANGELOG lists every affected type. Typical fixes:

  • HTTPException.body, exception details, JSON:API attributes, identity claims, and context values: narrow with a type guard or cast to the shape you expect.
  • Command, Query, and DomainEvent without a type argument now have an unknown payload. Pass the payload type (AbstractCommand<CreateUserPayload>) as usual.

Validation rules, sagas, and mail

  • The snake_case validation rules (greater_than, greater_than_or_equal, less_than, less_than_or_equal) are gone; use greaterThan, greaterThanOrEqual, lessThan, lessThanOrEqual. Schemas that still use the old keys throw a TypeError naming the replacement.
  • A saga whose step failed is now final, and the event bus no longer retries saga deliveries. Retry transient work inside the step; delete the saga's state to run it again.
  • MailAttachment.content is string | Uint8Array. Node Buffers still work.

Typed criteria values

Criteria.where checks value against the operator: IN, NOT_IN, and ARRAY_CONTAINS_ANY need an array, LIKE a string, range operators a number, string, boolean, bigint, or Date, BETWEEN two bounds, and GEO_RADIUS a center and radius. Custom DAOs can switch (filter.operator) to get a typed filter.value, and use readGeoRadius / readBetweenBounds to accept the same shapes as InMemoryDAO.

🧪 Testing

Tests use Jest and live in __tests__/, in folders that mirror src/ (for example __tests__/cqrs/), plus __tests__/integration/ for tests that span modules. CI runs them on every push and pull request, with minimum coverage levels set in jest.config.js.

npm test

Before publishing, npm run prepublishOnly also checks import paths, types, the build, and that every entry point loads with both import and require.

📜 License

Licensed under LGPL-3.0-or-later. See LICENSE for the LGPLv3 text and COPYING for the GPLv3 terms it incorporates.

About

A modular, type-safe foundation for building expressive, maintainable applications. This package provides core abstractions for domain modeling, HTTP integration, authentication, state management, and more — designed to be framework-agnostic and highly extensible.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages