Services and Initialization

Services and Initialization

Services and Initialization

Plugin DeveloperPlugin Developer Agent Kit — documentation written for AI agents, readable by humans.

Services provide dependency injection for server-side resources (databases, APIs, etc.).

createJayService

Create a typed service marker:

import { createJayService } from '@jay-framework/fullstack-component';

export interface ProductsDatabase {
  getProduct(slug: string): Promise<Product | null>;
  search(query: string): Promise<Product[]>;
}

export const PRODUCTS_DB = createJayService<ProductsDatabase>('ProductsDatabase');

The marker is a Symbol-based key — it provides type safety without coupling to a specific implementation.

makeJayInit

Initialize services and client-side state during app startup:

Server-only init

import { makeJayInit, registerService } from '@jay-framework/fullstack-component';

export const init = makeJayInit().withServer(async () => {
  const db = await connectToDatabase();
  registerService(PRODUCTS_DB, db);
});

Server + Client init

The server can pass data to the client via the return value:

export const init = makeJayInit()
  .withServer(async () => {
    registerService(PRODUCTS_DB, await connectDb());
    return { currency: 'USD', storeId: 'store-123' };
  })
  .withClient((data) => {
    // data is typed: { currency: string; storeId: string }
    registerReactiveGlobalContext(STORE_CONFIG, () => ({
      currency: data.currency,
      storeId: data.storeId,
    }));
  });

Client-only init

export const init = makeJayInit().withClient(() => {
  initAnalytics();
});

Using Services

In Components

makeJayStackComponent<MyContract>()
  .withServices(PRODUCTS_DB)
  .withSlowlyRender(async (props, db) => {
    const product = await db.getProduct(props.slug);
    return phaseOutput({ title: product.name }, {});
  });

In Actions

makeJayAction('products.search')
  .withServices(PRODUCTS_DB)
  .withHandler(async (input, db) => {
    return db.search(input.query);
  });

In loadParams

.withServices(PRODUCTS_DB)
.withLoadParams(async function* (db) {
    const products = await db.getAll();
    yield products.map(p => ({ slug: p.slug }));
})

Listing in plugin.yaml

If your plugin provides services for other plugins to consume, list them in plugin.yaml:

services:
  - name: products-db
    marker: PRODUCTS_DB
    description: Product catalog database API (query, search, get by slug)
    doc: ./docs/products-db-service.md # optional — markdown documentation

This makes the service discoverable in plugins-index.yaml. If doc is provided, the file must exist and be exported from the package.

Service Lifecycle

  • Services are registered during makeJayInit().withServer() callbacks
  • Registration order follows plugin dependency order
  • Services are available to all components and actions after init
  • Services are server-side only — they are not sent to the client

About this document

This page is part of the Jay Stack Agent Kit — documentation generated from the framework source and written primarily for AI agents. The language and structure are optimized for machine consumption — expect precise, specification-style prose rather than narrative documentation. Learn more about the Agent Kit →