Skip to content

Latest commit

 

History

History
163 lines (124 loc) · 6.08 KB

File metadata and controls

163 lines (124 loc) · 6.08 KB
title Service Contracts Overview
description Reference for all ObjectStack service contracts — TypeScript interfaces that define the API between the Kernel and plugins

Service Contracts Overview

Service contracts are TypeScript interfaces that define the boundaries between the ObjectStack Kernel and its plugins. Every plugin implements one or more contracts, and the Kernel consumes them through dependency injection.

**Design Principle:** Contracts contain zero business logic. They define the shape of each service — method signatures, input types, and return types — so that implementations can be swapped without changing consumers.

Why Contracts?

Benefit Description
Decoupling The Kernel never depends on a concrete implementation
Testability Mock any service by implementing its contract interface
Portability Swap SQL for NoSQL, local auth for OAuth — same contract
Type Safety Full TypeScript inference from Zod schemas to contract interfaces
Plugin Ecosystem Third-party plugins implement contracts to extend the platform

Contract Catalog

Data Contracts

Contract Interface Description
Data Engine IDataEngine Core data persistence — CRUD, queries, aggregations, transactions
Metadata Service IMetadataService Object and field definition management, schema registry
Search Service ISearchService Full-text search indexing and querying
Data Driver IDataDriver Low-level database adapter (SQL, NoSQL, API)

Authentication & Security Contracts

Contract Interface Description
Auth Service IAuthService Authentication — login, verify, logout, session management
Security Service ISecurityService Query surface for access decisions — row-level read scope, readable-field projection, effective permission sets, access explanation
Sharing Service ISharingService Record sharing rules and access grants

Storage & Caching Contracts

Contract Interface Description
Storage Service IStorageService File upload, download, and management
Cache Service ICacheService Key-value caching with TTL support

System Contracts

Contract Interface Description
Realtime Service IRealtimeService Publish/subscribe event system for triggers and realtime
Lifecycle Events IPluginLifecycleEvents Typed plugin and kernel lifecycle events
Logger Logger Structured logging with levels and context
Service Registry IServiceRegistry Service registration and resolution

Integration Contracts

Contract Interface Description
Email Service IEmailService Transactional and bulk email delivery
Notification Service INotificationService Multi-channel notifications (email, push, in-app)
Job Service IJobService Cron-based background job scheduling and execution

AI Contracts

Contract Interface Description
AI Service IAIService LLM inference — chat, completion, embedding
Knowledge Service IKnowledgeService Document indexing, retrieval, and augmented generation

Contract Structure

Every contract is a plain TypeScript interface that depends only on shared types — never on a concrete implementation:

// packages/spec/src/contracts/data-engine.ts
import type {
  EngineQueryOptions,
  DataEngineInsertOptions,
  EngineUpdateOptions,
  EngineDeleteOptions,
} from '../data/index.js';

/**
 * IDataEngine — abstract interface for data persistence.
 * Plugins depend on this interface, not on concrete database implementations.
 */
export interface IDataEngine {
  find(objectName: string, query?: EngineQueryOptions): Promise<any[]>;
  findOne(objectName: string, query?: EngineQueryOptions): Promise<any>;
  insert(objectName: string, data: any | any[], options?: DataEngineInsertOptions): Promise<any>;
  update(objectName: string, data: any, options?: EngineUpdateOptions): Promise<any>;
  delete(objectName: string, options?: EngineDeleteOptions): Promise<any>;
  // ...
}
**Convention:** Contract interfaces are prefixed with `I` (e.g., `IDataEngine`). Services are registered and resolved by **string name** through the kernel service registry (e.g., `ctx.registerService('data', impl)` — see the `CoreServiceName` enum for the standard names).

Using Contracts in Plugins

Plugins declare which contracts they implement and which they consume:

import type { Plugin } from '@objectstack/core';
import type { IDataEngine } from '@objectstack/spec/contracts';

export const myPlugin: Plugin = {
  name: 'my-plugin',

  // Declare which other plugins must be initialized first
  dependencies: ['com.objectstack.cache'],

  // Init phase: register the services this plugin provides
  init(ctx) {
    ctx.registerService('data', new MyDataEngine(ctx));

    // Consume a service another plugin registered
    const cache = ctx.getService('cache');
  },
};

Contract Lifecycle

flowchart LR
    A[Plugin Registered] --> B[Dependencies Resolved]
    B --> C[init: Services Registered]
    C --> D[start: Service Started]
    D --> E[Ready to Serve]
    E --> F[destroy: Shutdown / Teardown]
Loading
Phase Description
Registered Plugin is added to the kernel with its name and dependencies
Resolved Kernel resolves the dependency graph across all plugins
Initialized Plugin init(ctx) hook runs — services are registered
Started Plugin start(ctx) hook runs — connections established, servers started
Ready Contract methods are available to the Kernel and other plugins
Teardown Plugin destroy() hook runs — connections closed, resources freed
**See also:** - [Plugin Development](/docs/plugins/development) for implementing contracts - [Service Registry](/docs/kernel/services) for runtime architecture