@oapiex/sdk-kit
v0.1.13
Published
A TypeScript Base for building SDKs using OpenAPI specifications extracted by OAPIEX.
Maintainers
Readme
@oapiex/sdk-kit
Core runtime primitives for SDKs generated by oapiex.
This package provides the shared building blocks used by generated SDK packages:
Corefor authenticated SDK instancesBaseApifor SDK-specific API binders and API classescreateSdk()for manifest-driven runtime SDKs- shared HTTP utilities, exceptions, contracts, and helper types
Most consumers will install a generated SDK package instead of using this package directly. Use @oapiex/sdk-kit when you want to build or customize an SDK on top of the generated OpenAPI manifest output.
Install
pnpm add @oapiex/sdk-kitQuick Start
Class-based SDK
import { BaseApi, Core, Http } from '@oapiex/sdk-kit';
class ExampleApi extends BaseApi {
async list() {
await this.core.validateAccess();
const { data } = await Http.send(
this.core.builder.buildTargetUrl('/v1/examples', {}, {}),
'GET',
{},
{},
);
return data;
}
}
class ApiBinder extends BaseApi {
examples!: ExampleApi;
protected override boot() {
this.examples = new ExampleApi(this.core);
}
}
class ExampleCore extends Core {
static override apiClass = ApiBinder;
declare api: ApiBinder;
}
const sdk = new ExampleCore({
clientId: process.env.CLIENT_ID!,
clientSecret: process.env.CLIENT_SECRET!,
environment: 'sandbox',
urls: {
sandbox: 'https://sandbox-api.example.com',
},
headers: {
'X-SDK-Version': '1.0.0',
},
timeout: 10000,
auth: {
type: 'bearer',
token: process.env.ACCESS_TOKEN!,
},
});
await sdk.api.examples.list();Runtime manifest SDK
import { createSdk, type RuntimeSdkBundle } from '@oapiex/sdk-kit';
const bundle = {
document: {},
manifest: {
groups: [
{
className: 'Example',
propertyName: 'examples',
operations: [
{
path: '/v1/examples',
method: 'GET',
methodName: 'list',
responseType: 'Example[]',
inputType: 'Record<string, never>',
queryType: 'Record<string, never>',
headerType: 'Record<string, never>',
paramsType: 'Record<string, never>',
hasBody: false,
bodyRequired: false,
pathParams: [],
queryParams: [],
headerParams: [],
},
],
},
],
},
} satisfies RuntimeSdkBundle;
const sdk = createSdk(bundle, {
clientId: process.env.CLIENT_ID!,
clientSecret: process.env.CLIENT_SECRET!,
environment: 'sandbox',
auth: {
type: 'apiKey',
name: 'X-API-Key',
value: process.env.API_KEY!,
in: 'header',
},
});
await sdk.api.examples.list();Init Options
Core and createSdk() both accept the same InitOptions object.
clientId: optional API client identifier, useful when your validator or auth exchange still needs client credentialsclientSecret: optional whenauthis already provided, otherwise requiredenvironment: selectssandboxorliveurls: optional base URL overrides per environmentheaders: optional default headers added to every requesttimeout: optional Axios timeout in millisecondsencryptionKey: optional runtime encryption key overrideauth: one auth strategy or an array of strategies applied to outgoing requestsdebugLevel: optional HTTP debug verbosity, one of0 | 1 | 2 | 3
const sdk = new Core({
clientId: process.env.CLIENT_ID!,
clientSecret: process.env.CLIENT_SECRET!,
environment: 'sandbox',
urls: {
sandbox: 'https://sandbox-api.example.com',
live: 'https://api.example.com',
},
headers: {
'X-Trace-Source': 'example-sdk',
},
timeout: 15000,
debugLevel: 1,
});If you already have a token or API key strategy, you can initialize without client credentials:
const sdk = new Core({
environment: 'sandbox',
auth: {
type: 'bearer',
token: process.env.ACCESS_TOKEN!,
},
debugLevel: 1,
});@oapiex/sdk-kit can also read SDK init config from oapiex.config.ts, oapiex.config.js, or oapiex.config.cjs in the current working directory.
For an SDK-focused config file, prefer defineConfig() from @oapiex/sdk-kit:
import { defineConfig } from '@oapiex/sdk-kit';
export default defineConfig({
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
environment: 'sandbox',
urls: {
sandbox: 'https://sandbox-api.example.com',
},
headers: {
'X-Trace-Source': 'example-sdk',
},
timeout: 15000,
auth: {
type: 'bearer',
token: process.env.ACCESS_TOKEN,
},
debugLevel: 1,
});If you use the same oapiex.config.* file for extraction and SDK runtime defaults, prefer the root oapiex helper and scope the SDK settings under sdkKit:
import { defineConfig } from 'oapiex';
export default defineConfig({
sdkKit: {
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
environment: 'sandbox',
urls: {
sandbox: 'https://sandbox-api.example.com',
},
headers: {
'X-Trace-Source': 'example-sdk',
},
timeout: 15000,
auth: {
type: 'bearer',
token: process.env.ACCESS_TOKEN,
},
debugLevel: 1,
},
});Explicit constructor options override values loaded from oapiex.config.*.
Debugging
SDK HTTP debugging is disabled by default.
- Use
sdk.debug(level)after initialization when you want to enable or adjust request logging. - Use
debugLevelinInitOptionswhen you want debug logging active immediately during construction. - Supported levels are
0 | 1 | 2 | 3.
const sdk = new Core({
environment: 'sandbox',
auth: {
type: 'bearer',
token: process.env.ACCESS_TOKEN!,
},
debugLevel: 2,
});
sdk.debug(3);Auth Shapes
The auth option accepts any AuthConfig supported by the transport layer.
Bearer
auth: {
type: 'bearer',
token: process.env.ACCESS_TOKEN!,
}Basic
auth: {
type: 'basic',
username: process.env.API_USERNAME!,
password: process.env.API_PASSWORD!,
}API Key
auth: {
type: 'apiKey',
name: 'X-API-Key',
value: process.env.API_KEY!,
in: 'header',
}OAuth2 Token
auth: {
type: 'oauth2',
accessToken: process.env.ACCESS_TOKEN!,
tokenType: 'Bearer',
}Multiple Strategies
auth: [
{
type: 'apiKey',
name: 'X-Partner-Key',
value: process.env.PARTNER_KEY!,
in: 'header',
},
{
type: 'apiKey',
name: 'api_key',
value: process.env.QUERY_KEY!,
in: 'query',
},
];Custom
auth: {
type: 'custom',
apply: async (request) => ({
...request,
headers: {
...request.headers,
Authorization: `Token ${process.env.CUSTOM_TOKEN!}`,
},
}),
}Generated SDK packages can now expose auth helper functions derived from OpenAPI securitySchemes, plus securitySchemes and security metadata exports for inspection.
Access Validator Auth Refresh
setAccessValidator() can be used to replace auth before the actual SDK request is sent. This is useful for APIs like Flutterwave where you first exchange API keys for a bearer token.
The validator can:
- return
trueto allow the request as-is - return a string to fail validation with a custom message
- return an
AuthConfigorAuthConfig[]to replace auth for the pending request - return a partial config object such as
{ auth, headers, timeout } - call
core.setAuth(...)orcore.configure(...)directly
import axios from 'axios';
import { Core } from '@oapiex/sdk-kit';
const sdk = new Core({
clientId: process.env.CLIENT_ID!,
clientSecret: process.env.CLIENT_SECRET!,
environment: 'sandbox',
urls: {
sandbox: 'https://developersandbox-api.example.com',
},
});
sdk.setAccessValidator(async (core) => {
const response = await axios.post(
'https://developersandbox-api.example.com/auth/token',
{
client_id: core.getClientId(),
client_secret: core.getClientSecret(),
},
);
return {
type: 'bearer',
token: response.data.access_token,
};
});
await sdk.api.examples.list();If you need to update more than auth, return a config object instead:
sdk.setAccessValidator(async (core) => {
const response = await axios.post(
'https://developersandbox-api.example.com/auth/token',
{
client_id: core.getClientId(),
client_secret: core.getClientSecret(),
},
);
return {
auth: {
type: 'bearer',
token: response.data.access_token,
},
headers: {
'X-Token-Source': 'access-validator',
},
};
});If the token endpoint returns an expiry value, use createAccessTokenCache() so the validator does not fetch a new token on every request.
import axios from 'axios';
import { Core, createAccessTokenCache } from '@oapiex/sdk-kit';
const sdk = new Core({
clientId: process.env.CLIENT_ID!,
clientSecret: process.env.CLIENT_SECRET!,
environment: 'sandbox',
urls: {
sandbox: 'https://developersandbox-api.example.com',
},
});
const tokenCache = createAccessTokenCache(async (core) => {
const response = await axios.post(
'https://developersandbox-api.example.com/auth/token',
{
client_id: core.getClientId(),
client_secret: core.getClientSecret(),
},
);
return {
token: response.data.access_token,
expiresInSeconds: Math.max((response.data.expires_in ?? 60) - 30, 1),
};
});
sdk.setAccessValidator(tokenCache);Main Exports
Core: base SDK client with environment setup, access validation, and runtime bundle supportBaseApi: base class for SDK-specific API binders and API classescreateSdk(): helper for creating a runtime SDK from a manifest bundleAuthConfig: shared auth strategy union used byInitOptions.authcreateAccessTokenCache(): helper for caching validator-fetched tokens until expirysetAccessValidator(): hook for readiness checks, auth refresh, and config replacement before requestsHttp,Builder, and exceptions: lower-level request and error primitivesInitOptions,UnifiedResponse, and runtime manifest types: shared contracts for generated SDKs
Commands
Run these inside packages/sdk-kit:
pnpm test
pnpm build
pnpm coverage