What type of request is this?
New feature idea
Clear and concise description of the feature you are proposing
Problem
The @enclosed/lib SDK currently exposes standalone utility functions (createNote, fetchNote, storeNote, etc.) that each accept an optional apiBaseUrl parameter to override the default https://enclosed.cc instance. This forces consumers to pass configuration values on every single call, which is verbose:
// Today: apiBaseUrl must be repeated everywhere
const note = await createNote({
content: 'Hello',
apiBaseUrl: 'https://my-enclosed-instance.com', // again...
clientBaseUrl: 'https://my-enclosed-instance.com',
});
const fetched = await fetchNote({
noteId,
apiBaseUrl: 'https://my-enclosed-instance.com', // and again
});
The CLI partially solves this by storing instance-url in a local config file (enclosed config set instance-url …) and reading it before each command, but this is not something in the current lib.
Well-designed SDKs (Anthropic, OpenAI, AWS SDK v3, FastAPI's FastAPI() app instance, Axios's axios.create(...)) follow a configure-once pattern: you initialize a client with your settings and all subsequent calls inherit them.
Proposed Solution
Export a createEnclosedClient factory from @enclosed/lib that returns a pre-configured set of the existing utility functions:
import { createEnclosedClient } from '@enclosed/lib';
const enclosed = createEnclosedClient({
apiBaseUrl: 'https://my-enclosed-instance.com',
clientBaseUrl: 'https://my-enclosed-instance.com',
// other params/defaults: encryptionAlgorithm, serializationFormat, etc.
});
// All methods inherit the configured baseUrls
const { noteUrl } = await enclosed.createNote({ content: 'Hello' });
const { payload } = await enclosed.fetchNote({ noteId });
The factory would bind the provided config to each underlying function, returning an object that mirrors the current free-function API surface:
type EnclosedClient = {
createNote: (params: Omit<CreateNoteParams, 'apiBaseUrl' | 'clientBaseUrl'>) => Promise<CreateNoteResult>;
fetchNote: (params: Omit<FetchNoteParams, 'apiBaseUrl'>) => Promise<FetchNoteResult>;
storeNote: (params: Omit<StoreNoteParams, 'apiBaseUrl'>) => Promise<StoreNoteResult>;
// … rest of the API surface
};
function createEnclosedClient(config: {
apiBaseUrl?: string; // default: 'https://enclosed.cc'
clientBaseUrl?: string; // default: apiBaseUrl
encryptionAlgorithm?: EncryptionAlgorithm;
serializationFormat?: SerializationFormat;
}): EnclosedClient;
The standalone free functions remain unchanged for backward compatibility. createEnclosedClient is purely additive.
Additional context
- The internal
apiClient factory in packages/lib/src/api/api.client.ts already accepts a baseUrl parameter but is not exported. createEnclosedClient would expose this capability at the public API level.
- The CLI's
config.usecases.ts already demonstrates the need: it calls getInstanceUrl() before every command to retrieve the stored URL. An SDK-level client object would eliminate this boilerplate for programmatic consumers.
- This pattern is idiomatic for TypeScript SDKs and would improve the developer experience for self-hosted Enclosed deployments, where every call currently requires specifying a custom
apiBaseUrl.
Validations
What type of request is this?
New feature idea
Clear and concise description of the feature you are proposing
Problem
The
@enclosed/libSDK currently exposes standalone utility functions (createNote,fetchNote,storeNote, etc.) that each accept an optionalapiBaseUrlparameter to override the defaulthttps://enclosed.ccinstance. This forces consumers to pass configuration values on every single call, which is verbose:The CLI partially solves this by storing
instance-urlin a local config file (enclosed config set instance-url …) and reading it before each command, but this is not something in the current lib.Well-designed SDKs (Anthropic, OpenAI, AWS SDK v3, FastAPI's
FastAPI()app instance, Axios'saxios.create(...)) follow a configure-once pattern: you initialize a client with your settings and all subsequent calls inherit them.Proposed Solution
Export a
createEnclosedClientfactory from@enclosed/libthat returns a pre-configured set of the existing utility functions:The factory would bind the provided config to each underlying function, returning an object that mirrors the current free-function API surface:
The standalone free functions remain unchanged for backward compatibility.
createEnclosedClientis purely additive.Additional context
apiClientfactory inpackages/lib/src/api/api.client.tsalready accepts abaseUrlparameter but is not exported.createEnclosedClientwould expose this capability at the public API level.config.usecases.tsalready demonstrates the need: it callsgetInstanceUrl()before every command to retrieve the stored URL. An SDK-level client object would eliminate this boilerplate for programmatic consumers.apiBaseUrl.Validations