Skip to content

Feature: Support default config resolution for createClient and createConsumerClient #341

Description

@jamals86

Summary

Support default configuration resolution for both createClient() and createConsumerClient() so developers can start KalamDB apps, agents, workers, and consumers with less boilerplate.

Today, users need to manually pass connection and auth configuration into every client. This works, but it makes starter projects and local development more verbose than necessary.

Proposed API

Allow both clients to be created without explicitly passing config:

import { createClient, createConsumerClient } from '@kalamdb/client';

export const kalamClient = createClient();
export const consumerClient = createConsumerClient();

Also allow partial overrides:

const client = createClient({ namespace: 'tenant_a' });

const consumer = createConsumerClient({
  namespace: 'tenant_a',
  consumerGroup: 'email-workers',
});

Explicit options should override resolved defaults. Missing options should be resolved from environment variables or the active Kalam CLI profile.

Motivation

A developer should be able to run:

kalam login --instance kalam-dev
kalam dev

Then app code can simply use:

const client = createClient();
const consumer = createConsumerClient();

This avoids requiring a manually maintained local config file for the basic kalam dev workflow and reduces repeated setup across app code, workers, agents, and consumer processes.

CLI Profile Support

The Kalam CLI auth file should be treated as the source of truth for local authenticated development.

Important: the CLI auth file should not be expected to store the user password. It should use the existing token and refresh-token model.

When the SDK resolves config from the CLI profile, it should:

  1. Resolve the active profile.
  2. Read URL, namespace, and auth data for that profile.
  3. Build the SDK auth provider from the stored auth data.
  4. Refresh auth if needed.

kalam dev Integration

When running kalam dev, the CLI can launch child processes with the active profile context injected. This allows commands like:

npm run dev
npm run agent
npm run worker

to use the active Kalam profile without each process needing its own manual setup.

Expected Config Resolution Order

  1. Explicit options passed to createClient() / createConsumerClient()
  2. Environment variables
  3. Active CLI profile selected by the current dev context
  4. Default active Kalam CLI profile
  5. Clear error if required config is missing

Example:

createClient({ namespace: 'custom_namespace' });

This should use the explicit namespace while resolving the rest from env/profile.

Suggested Internal Helper

To avoid duplicating logic between createClient and createConsumerClient, add a shared resolver:

const resolvedConfig = await resolveKalamClientConfig(options);

Then both clients can use the same config resolution behavior.

The resolver should handle:

url
namespace
authProvider
profile
accessToken
refreshToken

Error Handling

If config cannot be resolved, the SDK should throw a helpful error explaining how to provide explicit config, define environment variables, or use kalam login followed by kalam dev.

Benefits

  • Less boilerplate
  • Better starter-project experience
  • Works for app clients and consumer clients
  • No required local config file when using kalam dev
  • Avoids storing passwords in local CLI config
  • Uses the existing CLI token/refresh-token model
  • Keeps explicit configuration fully supported
  • Makes workers, agents, and consumer processes easier to start

Notes

This should be backward compatible.

Existing code that passes url, namespace, and authProvider explicitly should continue to work.

The new behavior only adds default config resolution when values are not passed explicitly.

Implementation note: createClient() and createConsumerClient() should probably not each know about env vars, TOML paths, token refresh, and precedence. A shared resolver like resolveKalamClientConfig() would keep the SDK cleaner and make browser/server boundaries easier to handle later.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions