naijalingo 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -24,6 +24,7 @@ __export(index_exports, {
24
24
  AudioStream: () => AudioStream,
25
25
  AuthenticationError: () => AuthenticationError,
26
26
  ConnectionError: () => ConnectionError,
27
+ InferenceCapacityError: () => InferenceCapacityError,
27
28
  NaijaLingo: () => NaijaLingo,
28
29
  NaijaLingoError: () => NaijaLingoError,
29
30
  NotFoundError: () => NotFoundError,
@@ -69,6 +70,12 @@ var ServerError = class extends NaijaLingoError {
69
70
  this.name = "ServerError";
70
71
  }
71
72
  };
73
+ var InferenceCapacityError = class extends ServerError {
74
+ constructor(message, statusCode, response) {
75
+ super(message, statusCode, response);
76
+ this.name = "InferenceCapacityError";
77
+ }
78
+ };
72
79
  var ConnectionError = class extends NaijaLingoError {
73
80
  constructor(message, statusCode, response) {
74
81
  super(message, statusCode, response);
@@ -90,7 +97,7 @@ var BaseClient = class {
90
97
  this.baseUrl = base.replace(/\/+$/, "");
91
98
  this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;
92
99
  this.defaultHeaders = {
93
- "User-Agent": "naijalingo-js/0.1.0"
100
+ "User-Agent": "naijalingo-js/0.1.1"
94
101
  };
95
102
  if (this.apiKey) {
96
103
  this.defaultHeaders["X-API-Key"] = this.apiKey;
@@ -151,6 +158,10 @@ var BaseClient = class {
151
158
  } catch {
152
159
  detail = await response.text();
153
160
  }
161
+ const normalizedDetail = detail.toLowerCase();
162
+ if (status === 503 && (normalizedDetail.includes("inference capacity") || normalizedDetail.includes("inference component has no capacity") || normalizedDetail.includes("capacity is starting"))) {
163
+ throw new InferenceCapacityError(detail, status, body);
164
+ }
154
165
  if (status === 401 || status === 403) {
155
166
  throw new AuthenticationError(detail, status, body);
156
167
  }
@@ -666,7 +677,7 @@ function guessMime(filename) {
666
677
  }
667
678
 
668
679
  // src/index.ts
669
- var VERSION = "0.1.0";
680
+ var VERSION = "0.1.1";
670
681
  var NaijaLingo = class {
671
682
  _client;
672
683
  tts;
@@ -696,6 +707,7 @@ var NaijaLingo = class {
696
707
  AudioStream,
697
708
  AuthenticationError,
698
709
  ConnectionError,
710
+ InferenceCapacityError,
699
711
  NaijaLingo,
700
712
  NaijaLingoError,
701
713
  NotFoundError,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/client.ts","../src/tts.ts","../src/types.ts","../src/voice.ts"],"sourcesContent":["/**\n * 9jaLingo Node.js SDK\n *\n * Official SDK for the 9jaLingo API — Nigerian language Text-to-Speech.\n *\n * @example\n * ```ts\n * import { NaijaLingo } from \"naijalingo\";\n *\n * const client = new NaijaLingo(); // uses NAIJALINGO_API_KEY\n * const audio = await client.tts.generate(\"Bawo ni!\", {\n * voice: \"adeola_yo\",\n * lang: \"yo\",\n * });\n * await audio.save(\"greeting.wav\");\n * ```\n */\n\nimport { BaseClient, type ClientOptions } from \"./client.js\";\nimport { TTS } from \"./tts.js\";\nimport {\n apiInfoFromDict,\n modelListFromDict,\n serviceInfoFromDict,\n type APIInfo,\n type ModelList,\n type ServiceInfo,\n} from \"./types.js\";\n\nexport const VERSION = \"0.1.0\";\n\nexport {\n AuthenticationError,\n ConnectionError,\n NaijaLingoError,\n NotFoundError,\n RateLimitError,\n ServerError,\n} from \"./errors.js\";\n\nexport {\n AudioResponse,\n AudioStream,\n TTS,\n type CloneOptions,\n type GenerateOptions,\n type ListSpeakersOptions,\n type StreamOptions,\n} from \"./tts.js\";\n\nexport type {\n APIInfo,\n HealthStatus,\n Language,\n LanguageList,\n Model,\n ModelList,\n ResponseFormat,\n ServiceInfo,\n Speaker,\n SpeakerList,\n} from \"./types.js\";\n\nexport type { ClientOptions };\n\nexport class NaijaLingo {\n private readonly _client: BaseClient;\n readonly tts: TTS;\n\n constructor(options: ClientOptions = {}) {\n this._client = new BaseClient(options);\n this.tts = new TTS(this._client);\n }\n\n /** List available TTS models. GET /v1/models */\n async listModels(): Promise<ModelList> {\n const data = await this._client.getJson(\"/v1/models\");\n return modelListFromDict(data);\n }\n\n /** Root API information. GET / */\n async apiInfo(): Promise<APIInfo> {\n const data = await this._client.getJson(\"/\");\n return apiInfoFromDict(data);\n }\n\n /** v1 service metadata. GET /v1 */\n async serviceInfo(): Promise<ServiceInfo> {\n const data = await this._client.getJson(\"/v1\");\n return serviceInfoFromDict(data);\n }\n}\n","/** Base exception for all 9jaLingo SDK errors. */\nexport class NaijaLingoError extends Error {\n readonly statusCode?: number;\n readonly response?: unknown;\n\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message);\n this.name = \"NaijaLingoError\";\n this.statusCode = statusCode;\n this.response = response;\n }\n}\n\n/** Raised when the API key is missing or invalid. */\nexport class AuthenticationError extends NaijaLingoError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"AuthenticationError\";\n }\n}\n\n/** Raised when rate limit is exceeded. */\nexport class RateLimitError extends NaijaLingoError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"RateLimitError\";\n }\n}\n\n/** Raised when a requested resource is not found. */\nexport class NotFoundError extends NaijaLingoError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"NotFoundError\";\n }\n}\n\n/** Raised when the API returns a 5xx error. */\nexport class ServerError extends NaijaLingoError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"ServerError\";\n }\n}\n\n/** Raised when unable to connect to the API. */\nexport class ConnectionError extends NaijaLingoError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"ConnectionError\";\n }\n}\n","import {\n AuthenticationError,\n ConnectionError,\n NaijaLingoError,\n NotFoundError,\n RateLimitError,\n ServerError,\n} from \"./errors.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.9jalingo.org\";\nconst DEFAULT_TIMEOUT_MS = 300_000;\n\nexport interface ClientOptions {\n apiKey?: string;\n baseUrl?: string;\n /** Request timeout in milliseconds (default 300000). */\n timeout?: number;\n}\n\nexport class BaseClient {\n readonly apiKey: string;\n readonly baseUrl: string;\n readonly timeout: number;\n private readonly defaultHeaders: Record<string, string>;\n\n constructor(options: ClientOptions = {}) {\n this.apiKey =\n options.apiKey ?? process.env.NAIJALINGO_API_KEY ?? \"\";\n const base =\n options.baseUrl ??\n process.env.NAIJALINGO_BASE_URL ??\n DEFAULT_BASE_URL;\n this.baseUrl = base.replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;\n\n this.defaultHeaders = {\n \"User-Agent\": \"naijalingo-js/0.1.0\",\n };\n if (this.apiKey) {\n this.defaultHeaders[\"X-API-Key\"] = this.apiKey;\n }\n }\n\n private async request(\n method: string,\n path: string,\n init: RequestInit & { timeoutMs?: number } = {},\n ): Promise<Response> {\n const url = `${this.baseUrl}${path.startsWith(\"/\") ? path : `/${path}`}`;\n const timeoutMs = init.timeoutMs ?? this.timeout;\n let lastError: unknown;\n\n for (let attempt = 0; attempt < 3; attempt++) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const response = await fetch(url, {\n ...init,\n method,\n headers: {\n ...this.defaultHeaders,\n ...(init.headers as Record<string, string> | undefined),\n },\n signal: controller.signal,\n });\n clearTimeout(timer);\n\n if (response.ok) {\n return response;\n }\n await this.raiseForStatus(response);\n // unreachable\n return response;\n } catch (err) {\n clearTimeout(timer);\n if (err instanceof NaijaLingoError) {\n throw err;\n }\n lastError = err;\n const isAbort =\n err instanceof Error &&\n (err.name === \"AbortError\" || err.name === \"TimeoutError\");\n // Only retry connect-style failures, not aborts from long reads\n if (isAbort) {\n throw new ConnectionError(\n `Request timed out after ${timeoutMs}ms: ${String(err)}`,\n );\n }\n if (attempt < 2) {\n await sleep(1500);\n continue;\n }\n }\n }\n\n throw new ConnectionError(\n `Unable to connect to ${this.baseUrl}: ${String(lastError)}`,\n );\n }\n\n private async raiseForStatus(response: Response): Promise<never> {\n const status = response.status;\n let detail: string;\n let body: unknown;\n try {\n body = await response.json();\n detail =\n typeof body === \"object\" &&\n body !== null &&\n \"detail\" in body\n ? String((body as { detail: unknown }).detail)\n : JSON.stringify(body);\n } catch {\n detail = await response.text();\n }\n\n if (status === 401 || status === 403) {\n throw new AuthenticationError(detail, status, body);\n }\n if (status === 404) {\n throw new NotFoundError(detail, status, body);\n }\n if (status === 429) {\n throw new RateLimitError(detail, status, body);\n }\n if (status >= 500) {\n throw new ServerError(detail, status, body);\n }\n throw new NaijaLingoError(detail, status, body);\n }\n\n async getJson(\n path: string,\n params?: Record<string, string | undefined | null>,\n ): Promise<Record<string, unknown>> {\n let url = path;\n if (params) {\n const qs = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v != null) qs.set(k, v);\n }\n const s = qs.toString();\n if (s) url = `${path}?${s}`;\n }\n const resp = await this.request(\"GET\", url);\n return (await resp.json()) as Record<string, unknown>;\n }\n\n async postBytes(\n path: string,\n body: Record<string, unknown>,\n ): Promise<Uint8Array> {\n const resp = await this.request(\"POST\", path, {\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n return new Uint8Array(await resp.arrayBuffer());\n }\n\n async *postStream(\n path: string,\n body: Record<string, unknown>,\n ): AsyncGenerator<Uint8Array, void, unknown> {\n let lastError: unknown;\n for (let attempt = 0; attempt < 3; attempt++) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n try {\n const response = await fetch(\n `${this.baseUrl}${path.startsWith(\"/\") ? path : `/${path}`}`,\n {\n method: \"POST\",\n headers: {\n ...this.defaultHeaders,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n },\n );\n clearTimeout(timer);\n\n if (!response.ok) {\n await this.raiseForStatus(response);\n }\n if (!response.body) {\n throw new ConnectionError(\"No response body for stream\");\n }\n\n const reader = response.body.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value && value.length > 0) {\n yield value;\n }\n }\n } finally {\n reader.releaseLock();\n }\n return;\n } catch (err) {\n clearTimeout(timer);\n if (err instanceof NaijaLingoError) throw err;\n lastError = err;\n const isAbort =\n err instanceof Error &&\n (err.name === \"AbortError\" || err.name === \"TimeoutError\");\n if (isAbort) {\n throw new ConnectionError(`Request timed out: ${String(err)}`);\n }\n if (attempt < 2) {\n await sleep(1500);\n continue;\n }\n }\n }\n throw new ConnectionError(\n `Unable to connect to ${this.baseUrl}: ${String(lastError)}`,\n );\n }\n\n async postMultipart(\n path: string,\n form: FormData,\n timeoutMs?: number,\n ): Promise<Uint8Array> {\n const resp = await this.request(\"POST\", path, {\n body: form,\n timeoutMs: timeoutMs ?? Math.max(this.timeout, 600_000),\n // Let fetch set multipart boundary — do not set Content-Type\n });\n return new Uint8Array(await resp.arrayBuffer());\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { basename, dirname } from \"node:path\";\nimport { readFileSync } from \"node:fs\";\nimport { BaseClient } from \"./client.js\";\nimport {\n type HealthStatus,\n type LanguageList,\n type ResponseFormat,\n type Speaker,\n type SpeakerList,\n healthStatusFromDict,\n languageListFromDict,\n speakerFromDict,\n speakerListFromDict,\n} from \"./types.js\";\nimport {\n resolveCloneLangAndSpeaker,\n resolveTtsVoiceAndLang,\n} from \"./voice.js\";\n\nconst DEFAULT_MODEL_NAME = \"9jalingo-tts-1\";\n\nexport type GenerateOptions = {\n voice?: string;\n speaker?: string;\n lang?: string;\n language?: string;\n modelName?: string;\n speakerEmbedding?: number[];\n responseFormat?: ResponseFormat;\n temperature?: number;\n topP?: number;\n repetitionPenalty?: number;\n enableLongForm?: boolean;\n maxChunkDuration?: number;\n silenceDuration?: number;\n};\n\nexport type StreamOptions = Omit<\n GenerateOptions,\n \"modelName\" | \"responseFormat\"\n>;\n\nexport type CloneOptions = {\n voice?: string;\n lang?: string;\n speaker?: string;\n modelName?: string;\n temperature?: number;\n topP?: number;\n repetitionPenalty?: number;\n responseFormat?: ResponseFormat;\n};\n\nexport type ListSpeakersOptions = {\n language?: string;\n gender?: string;\n domain?: string;\n};\n\n/** Audio data returned from a generation request. */\nexport class AudioResponse {\n readonly content: Uint8Array;\n readonly mediaType: string;\n\n constructor(content: Uint8Array, mediaType = \"audio/wav\") {\n this.content = content;\n this.mediaType = mediaType;\n }\n\n /** Write the audio to a file. */\n async save(path: string): Promise<string> {\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, this.content);\n return path;\n }\n\n get length(): number {\n return this.content.length;\n }\n\n toString(): string {\n return `AudioResponse(${this.content.length} bytes, ${this.mediaType})`;\n }\n}\n\n/** Streaming audio response — yields byte chunks as they arrive. */\nexport class AudioStream implements AsyncIterable<Uint8Array> {\n private readonly chunks: AsyncIterable<Uint8Array>;\n private collected: Uint8Array | null = null;\n\n constructor(chunks: AsyncIterable<Uint8Array>) {\n this.chunks = chunks;\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<Uint8Array> {\n for await (const chunk of this.chunks) {\n yield chunk;\n }\n }\n\n /** Consume the entire stream and return an AudioResponse. */\n async collect(): Promise<AudioResponse> {\n if (this.collected == null) {\n const parts: Uint8Array[] = [];\n let total = 0;\n for await (const chunk of this.chunks) {\n parts.push(chunk);\n total += chunk.length;\n }\n const out = new Uint8Array(total);\n let offset = 0;\n for (const part of parts) {\n out.set(part, offset);\n offset += part.length;\n }\n this.collected = out;\n }\n return new AudioResponse(this.collected, \"audio/wav\");\n }\n}\n\nexport class TTS {\n private readonly client: BaseClient;\n\n constructor(client: BaseClient) {\n this.client = client;\n }\n\n /** Generate speech from text. */\n async generate(\n text: string,\n options: GenerateOptions = {},\n ): Promise<AudioResponse> {\n let [resolvedVoice, resolvedLang] = resolveTtsVoiceAndLang(options);\n if (resolvedVoice == null && options.speakerEmbedding == null) {\n resolvedVoice = \"blessing_pcm\";\n }\n const responseFormat = options.responseFormat ?? \"wav\";\n const body = buildBody({\n input: text,\n voice: resolvedVoice,\n lang: resolvedLang,\n model: options.modelName ?? DEFAULT_MODEL_NAME,\n speaker_embedding: options.speakerEmbedding,\n response_format: responseFormat,\n temperature: options.temperature,\n top_p: options.topP,\n repetition_penalty: options.repetitionPenalty,\n enable_long_form: options.enableLongForm ?? true,\n max_chunk_duration: options.maxChunkDuration,\n silence_duration: options.silenceDuration,\n });\n const content = await this.client.postBytes(\"/v1/audio/speech\", body);\n const mediaType = MEDIA_TYPES[responseFormat] ?? \"application/octet-stream\";\n return new AudioResponse(content, mediaType);\n }\n\n /** Stream speech generation — audio arrives as it's produced. */\n stream(text: string, options: StreamOptions = {}): AudioStream {\n let [resolvedVoice, resolvedLang] = resolveTtsVoiceAndLang(options);\n if (resolvedVoice == null && options.speakerEmbedding == null) {\n resolvedVoice = \"blessing_pcm\";\n }\n const body = buildBody({\n input: text,\n voice: resolvedVoice,\n lang: resolvedLang,\n speaker_embedding: options.speakerEmbedding,\n response_format: \"wav\",\n temperature: options.temperature,\n top_p: options.topP,\n repetition_penalty: options.repetitionPenalty,\n enable_long_form: options.enableLongForm ?? true,\n max_chunk_duration: options.maxChunkDuration,\n silence_duration: options.silenceDuration,\n });\n return new AudioStream(this.client.postStream(\"/v1/audio/speech/stream\", body));\n }\n\n /**\n * Generate speech using a cloned voice from a reference audio file.\n * `audioFile` may be a filesystem path, Buffer, Uint8Array, Blob, or File.\n */\n async clone(\n text: string,\n audioFile: string | Buffer | Uint8Array | Blob,\n options: CloneOptions = {},\n ): Promise<AudioResponse> {\n const voice = options.voice ?? \"pcm\";\n const [resolvedLang, resolvedSpeaker] = resolveCloneLangAndSpeaker(\n voice,\n { lang: options.lang, speaker: options.speaker },\n );\n const responseFormat = options.responseFormat ?? \"wav\";\n\n const form = new FormData();\n form.append(\"text\", text);\n form.append(\"lang\", resolvedLang);\n form.append(\"model_name\", options.modelName ?? DEFAULT_MODEL_NAME);\n form.append(\"response_format\", responseFormat);\n if (resolvedSpeaker) {\n form.append(\"voice\", resolvedSpeaker);\n }\n if (options.temperature != null) {\n form.append(\"temperature\", String(options.temperature));\n }\n if (options.topP != null) {\n form.append(\"top_p\", String(options.topP));\n }\n if (options.repetitionPenalty != null) {\n form.append(\"repetition_penalty\", String(options.repetitionPenalty));\n }\n\n const { blob, filename } = await toAudioBlob(audioFile);\n form.append(\"audio\", blob, filename);\n\n const content = await this.client.postMultipart(\"/v1/audio/clone\", form);\n const mediaType = MEDIA_TYPES[responseFormat] ?? \"application/octet-stream\";\n return new AudioResponse(content, mediaType);\n }\n\n async listSpeakers(\n options: ListSpeakersOptions = {},\n ): Promise<SpeakerList> {\n const data = await this.client.getJson(\"/v1/speakers\", {\n language: options.language,\n gender: options.gender,\n domain: options.domain,\n });\n return speakerListFromDict(data);\n }\n\n async getSpeaker(speakerId: string): Promise<Speaker> {\n const data = await this.client.getJson(`/v1/speakers/${speakerId}`);\n return speakerFromDict(data);\n }\n\n async listLanguages(): Promise<LanguageList> {\n const data = await this.client.getJson(\"/v1/languages\");\n return languageListFromDict(data);\n }\n\n async health(): Promise<HealthStatus> {\n const data = await this.client.getJson(\"/v1/health\");\n return healthStatusFromDict(data);\n }\n}\n\nconst MEDIA_TYPES: Record<string, string> = {\n wav: \"audio/wav\",\n pcm: \"application/octet-stream\",\n flac: \"audio/flac\",\n aac: \"audio/aac\",\n ogg: \"audio/ogg\",\n mp3: \"audio/mpeg\",\n alac: \"audio/alac\",\n};\n\nfunction buildBody(\n kwargs: Record<string, unknown>,\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(kwargs)) {\n if (v !== undefined && v !== null) out[k] = v;\n }\n return out;\n}\n\nasync function toAudioBlob(\n audioFile: string | Buffer | Uint8Array | Blob,\n): Promise<{ blob: Blob; filename: string }> {\n if (typeof audioFile === \"string\") {\n const bytes = readFileSync(audioFile);\n const filename = basename(audioFile);\n const mime = guessMime(filename);\n return {\n blob: new Blob([bytes], { type: mime }),\n filename,\n };\n }\n if (audioFile instanceof Blob) {\n return {\n blob: audioFile,\n filename: \"audio.wav\",\n };\n }\n // Buffer | Uint8Array\n const bytes =\n audioFile instanceof Uint8Array\n ? audioFile\n : new Uint8Array(audioFile);\n return {\n blob: new Blob([bytes], { type: \"application/octet-stream\" }),\n filename: \"audio.wav\",\n };\n}\n\nfunction guessMime(filename: string): string {\n const lower = filename.toLowerCase();\n if (lower.endsWith(\".wav\")) return \"audio/wav\";\n if (lower.endsWith(\".mp3\")) return \"audio/mpeg\";\n if (lower.endsWith(\".flac\")) return \"audio/flac\";\n if (lower.endsWith(\".ogg\")) return \"audio/ogg\";\n if (lower.endsWith(\".aac\") || lower.endsWith(\".m4a\")) return \"audio/aac\";\n return \"application/octet-stream\";\n}\n","/** A speaker voice identity. */\nexport interface Speaker {\n id: string;\n name: string;\n language: string;\n gender?: string | null;\n domain?: string | null;\n}\n\nexport function speakerFromDict(data: Record<string, unknown>): Speaker {\n return {\n id: String(data.id ?? data.speaker_id ?? \"\"),\n name: String(data.name ?? data.id ?? \"\"),\n language: String(data.language ?? \"\"),\n gender: (data.gender as string | null | undefined) ?? null,\n domain: (data.domain as string | null | undefined) ?? null,\n };\n}\n\n/** List of speakers with metadata. */\nexport interface SpeakerList {\n speakers: Speaker[];\n total: number;\n byLanguage: Record<string, number>;\n [Symbol.iterator](): Iterator<Speaker>;\n length: number;\n}\n\nexport function speakerListFromDict(data: Record<string, unknown>): SpeakerList {\n const raw = (data.speakers as Record<string, unknown>[] | undefined) ?? [];\n const speakers = raw.map(speakerFromDict);\n const total = typeof data.total === \"number\" ? data.total : speakers.length;\n const byLanguage =\n (data.by_language as Record<string, number> | undefined) ?? {};\n return {\n speakers,\n total,\n byLanguage,\n get length() {\n return total;\n },\n [Symbol.iterator]() {\n return speakers[Symbol.iterator]();\n },\n };\n}\n\n/** A supported language. */\nexport interface Language {\n code: string;\n name: string;\n speakerCount: number;\n}\n\nexport function languageFromDict(data: Record<string, unknown>): Language {\n return {\n code: String(data.code ?? \"\"),\n name: String(data.name ?? \"\"),\n speakerCount: Number(data.speaker_count ?? 0),\n };\n}\n\n/** List of supported languages and domains. */\nexport interface LanguageList {\n languages: Language[];\n domains: string[];\n}\n\nexport function languageListFromDict(data: Record<string, unknown>): LanguageList {\n const rawLangs = data.languages;\n let languages: Language[];\n\n if (rawLangs && typeof rawLangs === \"object\" && !Array.isArray(rawLangs)) {\n languages = Object.entries(rawLangs as Record<string, unknown>).map(\n ([code, value]) => {\n if (value && typeof value === \"object\") {\n const v = value as Record<string, unknown>;\n return {\n code,\n name: String(v.name ?? code),\n speakerCount: Number(v.speaker_count ?? 0),\n };\n }\n return { code, name: String(value), speakerCount: 0 };\n },\n );\n } else {\n const arr = (rawLangs as Record<string, unknown>[] | undefined) ?? [];\n languages = arr.map(languageFromDict);\n }\n\n return {\n languages,\n domains: (data.domains as string[] | undefined) ?? [],\n };\n}\n\n/** API health check result. */\nexport interface HealthStatus {\n status: string;\n engineReady: boolean;\n codecReady: boolean;\n totalSpeakers: number;\n languages: string[];\n voiceCloningAvailable: boolean;\n speakerProjectionLoaded: boolean;\n}\n\nexport function healthStatusFromDict(data: Record<string, unknown>): HealthStatus {\n const supported = data.supported_languages;\n let languages: string[] = [];\n if (Array.isArray(data.languages)) {\n languages = data.languages as string[];\n } else if (supported && typeof supported === \"object\") {\n languages = Object.keys(supported as Record<string, unknown>);\n }\n\n return {\n status: String(data.status ?? \"unknown\"),\n engineReady: Boolean(data.engine_ready ?? data.tts_initialized ?? false),\n codecReady: Boolean(data.codec_ready ?? false),\n totalSpeakers: Number(data.total_speakers ?? data.speakers_loaded ?? 0),\n languages,\n voiceCloningAvailable: Boolean(data.voice_cloning_available ?? false),\n speakerProjectionLoaded: Boolean(data.speaker_projection_loaded ?? false),\n };\n}\n\n/** An available TTS model. */\nexport interface Model {\n id: string;\n object: string;\n ownedBy: string;\n}\n\nexport function modelFromDict(data: Record<string, unknown>): Model {\n return {\n id: String(data.id ?? \"\"),\n object: String(data.object ?? \"model\"),\n ownedBy: String(data.owned_by ?? \"9jalingo\"),\n };\n}\n\n/** List of available models. */\nexport interface ModelList {\n models: Model[];\n object: string;\n [Symbol.iterator](): Iterator<Model>;\n length: number;\n}\n\nexport function modelListFromDict(data: Record<string, unknown>): ModelList {\n const raw = (data.data as Record<string, unknown>[] | undefined) ?? [];\n const models = raw.map(modelFromDict);\n return {\n models,\n object: String(data.object ?? \"list\"),\n get length() {\n return models.length;\n },\n [Symbol.iterator]() {\n return models[Symbol.iterator]();\n },\n };\n}\n\n/** Root API information returned by GET /. */\nexport interface APIInfo {\n name: string;\n version: string;\n description: string;\n endpoints: Record<string, string>;\n}\n\nexport function apiInfoFromDict(data: Record<string, unknown>): APIInfo {\n return {\n name: String(data.name ?? \"\"),\n version: String(data.version ?? \"\"),\n description: String(data.description ?? \"\"),\n endpoints: (data.endpoints as Record<string, string> | undefined) ?? {},\n };\n}\n\n/** Service metadata returned by GET /v1. */\nexport interface ServiceInfo {\n object: string;\n name: string;\n modelsUrl: string;\n speechUrl: string;\n speechStreamUrl: string;\n}\n\nexport function serviceInfoFromDict(data: Record<string, unknown>): ServiceInfo {\n return {\n object: String(data.object ?? \"service\"),\n name: String(data.name ?? \"\"),\n modelsUrl: String(data.models_url ?? \"\"),\n speechUrl: String(data.speech_url ?? \"\"),\n speechStreamUrl: String(data.speech_stream_url ?? \"\"),\n };\n}\n\nexport type ResponseFormat =\n | \"wav\"\n | \"pcm\"\n | \"flac\"\n | \"aac\"\n | \"ogg\"\n | \"mp3\"\n | \"alac\";\n","const LANG_ALIASES: Record<string, string> = {\n yo: \"yo\",\n yor: \"yo\",\n yoruba: \"yo\",\n ig: \"ig\",\n ibo: \"ig\",\n igbo: \"ig\",\n ha: \"ha\",\n hau: \"ha\",\n hausa: \"ha\",\n pcm: \"pcm\",\n pidgin: \"pcm\",\n};\n\nexport function normalizeLang(code: string): string | null {\n return LANG_ALIASES[code.trim().toLowerCase()] ?? null;\n}\n\n/**\n * Resolve speech API fields: voice/speaker + lang/language.\n * Returns [speakerId, langCode]. Bare language codes must be passed via lang/language.\n */\nexport function resolveTtsVoiceAndLang(options: {\n voice?: string | null;\n speaker?: string | null;\n lang?: string | null;\n language?: string | null;\n}): [string | null, string | null] {\n let resolvedLang: string | null = null;\n\n if (options.lang != null) {\n resolvedLang = normalizeLang(options.lang);\n if (resolvedLang == null) {\n throw new Error(\n `Unsupported language '${options.lang}'. Use ha, ig, yo, or pcm.`,\n );\n }\n } else if (options.language != null) {\n resolvedLang = normalizeLang(options.language);\n if (resolvedLang == null) {\n throw new Error(\n `Unsupported language '${options.language}'. Use ha, ig, yo, or pcm.`,\n );\n }\n }\n\n // speaker takes precedence over voice\n const candidate =\n options.speaker != null ? options.speaker : options.voice;\n if (candidate == null || !String(candidate).trim()) {\n return [null, resolvedLang];\n }\n\n const resolved = String(candidate).trim();\n const normalized = resolved.toLowerCase();\n if (normalized in LANG_ALIASES) {\n const langCode = LANG_ALIASES[normalized];\n throw new Error(\n `'${resolved}' is a language code, not a speaker ID. ` +\n `Pass speaker/voice='ada_pcm' (or another speaker ID) and ` +\n `lang='${langCode}' for the language. ` +\n `Browse speakers with: client.tts.listSpeakers({ language: '${langCode}' })`,\n );\n }\n\n if (resolvedLang == null && resolved.includes(\"_\")) {\n const suffix = resolved.split(\"_\").pop()!;\n resolvedLang = normalizeLang(suffix);\n }\n\n return [resolved, resolvedLang];\n}\n\n/**\n * Resolve clone form fields.\n * voice may be a language code (\"pcm\") or a speaker ID with a language suffix.\n */\nexport function resolveCloneLangAndSpeaker(\n voice: string,\n options: { lang?: string | null; speaker?: string | null } = {},\n): [string, string | null] {\n let resolvedLang =\n options.lang != null ? normalizeLang(options.lang) : null;\n let resolvedSpeaker = options.speaker?.trim() || null;\n\n const voiceStr = (voice || \"\").trim();\n const voiceNorm = voiceStr.toLowerCase();\n\n if (voiceNorm in LANG_ALIASES) {\n if (resolvedLang == null) {\n resolvedLang = LANG_ALIASES[voiceNorm];\n }\n } else if (voiceStr.includes(\"_\")) {\n if (resolvedSpeaker == null) {\n resolvedSpeaker = voiceStr;\n }\n if (resolvedLang == null) {\n const suffix = voiceStr.split(\"_\").pop()!;\n resolvedLang = normalizeLang(suffix);\n }\n } else if (voiceStr && resolvedLang == null) {\n throw new Error(\n `'${voice}' is not a language code (ha/ig/yo/pcm) or a speaker ID ` +\n `with a language suffix (e.g. 'daniel_pcm'). ` +\n `Pass voice='pcm' or lang='pcm'.`,\n );\n }\n\n if (!resolvedLang) {\n throw new Error(\n \"Clone requires a language. Pass voice='pcm' (or 'ha'/'ig'/'yo'), \" +\n \"lang='pcm', or a speaker ID ending in _pcm/_ha/_ig/_yo.\",\n );\n }\n\n return [resolvedLang, resolvedSpeaker];\n}\n"],"mappings":"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","names":["bytes"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/client.ts","../src/tts.ts","../src/types.ts","../src/voice.ts"],"sourcesContent":["/**\n * 9jaLingo Node.js SDK\n *\n * Official SDK for the 9jaLingo API — Nigerian language Text-to-Speech.\n *\n * @example\n * ```ts\n * import { NaijaLingo } from \"naijalingo\";\n *\n * const client = new NaijaLingo(); // uses NAIJALINGO_API_KEY\n * const audio = await client.tts.generate(\"Bawo ni!\", {\n * voice: \"adeola_yo\",\n * lang: \"yo\",\n * });\n * await audio.save(\"greeting.wav\");\n * ```\n */\n\nimport { BaseClient, type ClientOptions } from \"./client.js\";\nimport { TTS } from \"./tts.js\";\nimport {\n apiInfoFromDict,\n modelListFromDict,\n serviceInfoFromDict,\n type APIInfo,\n type ModelList,\n type ServiceInfo,\n} from \"./types.js\";\n\nexport const VERSION = \"0.1.1\";\n\nexport {\n AuthenticationError,\n ConnectionError,\n InferenceCapacityError,\n NaijaLingoError,\n NotFoundError,\n RateLimitError,\n ServerError,\n} from \"./errors.js\";\n\nexport {\n AudioResponse,\n AudioStream,\n TTS,\n type CloneOptions,\n type GenerateOptions,\n type ListSpeakersOptions,\n type StreamOptions,\n} from \"./tts.js\";\n\nexport type {\n APIInfo,\n HealthStatus,\n Language,\n LanguageList,\n Model,\n ModelList,\n ResponseFormat,\n ServiceInfo,\n Speaker,\n SpeakerList,\n} from \"./types.js\";\n\nexport type { ClientOptions };\n\nexport class NaijaLingo {\n private readonly _client: BaseClient;\n readonly tts: TTS;\n\n constructor(options: ClientOptions = {}) {\n this._client = new BaseClient(options);\n this.tts = new TTS(this._client);\n }\n\n /** List available TTS models. GET /v1/models */\n async listModels(): Promise<ModelList> {\n const data = await this._client.getJson(\"/v1/models\");\n return modelListFromDict(data);\n }\n\n /** Root API information. GET / */\n async apiInfo(): Promise<APIInfo> {\n const data = await this._client.getJson(\"/\");\n return apiInfoFromDict(data);\n }\n\n /** v1 service metadata. GET /v1 */\n async serviceInfo(): Promise<ServiceInfo> {\n const data = await this._client.getJson(\"/v1\");\n return serviceInfoFromDict(data);\n }\n}\n","/** Base exception for all 9jaLingo SDK errors. */\nexport class NaijaLingoError extends Error {\n readonly statusCode?: number;\n readonly response?: unknown;\n\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message);\n this.name = \"NaijaLingoError\";\n this.statusCode = statusCode;\n this.response = response;\n }\n}\n\n/** Raised when the API key is missing or invalid. */\nexport class AuthenticationError extends NaijaLingoError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"AuthenticationError\";\n }\n}\n\n/** Raised when rate limit is exceeded. */\nexport class RateLimitError extends NaijaLingoError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"RateLimitError\";\n }\n}\n\n/** Raised when a requested resource is not found. */\nexport class NotFoundError extends NaijaLingoError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"NotFoundError\";\n }\n}\n\n/** Raised when the API returns a 5xx error. */\nexport class ServerError extends NaijaLingoError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"ServerError\";\n }\n}\n\n/** Raised when the inference GPU is waking from scale-to-zero. */\nexport class InferenceCapacityError extends ServerError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"InferenceCapacityError\";\n }\n}\n\n/** Raised when unable to connect to the API. */\nexport class ConnectionError extends NaijaLingoError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"ConnectionError\";\n }\n}\n","import {\n AuthenticationError,\n ConnectionError,\n InferenceCapacityError,\n NaijaLingoError,\n NotFoundError,\n RateLimitError,\n ServerError,\n} from \"./errors.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.9jalingo.org\";\nconst DEFAULT_TIMEOUT_MS = 300_000;\n\nexport interface ClientOptions {\n apiKey?: string;\n baseUrl?: string;\n /** Request timeout in milliseconds (default 300000). */\n timeout?: number;\n}\n\nexport class BaseClient {\n readonly apiKey: string;\n readonly baseUrl: string;\n readonly timeout: number;\n private readonly defaultHeaders: Record<string, string>;\n\n constructor(options: ClientOptions = {}) {\n this.apiKey =\n options.apiKey ?? process.env.NAIJALINGO_API_KEY ?? \"\";\n const base =\n options.baseUrl ??\n process.env.NAIJALINGO_BASE_URL ??\n DEFAULT_BASE_URL;\n this.baseUrl = base.replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;\n\n this.defaultHeaders = {\n \"User-Agent\": \"naijalingo-js/0.1.1\",\n };\n if (this.apiKey) {\n this.defaultHeaders[\"X-API-Key\"] = this.apiKey;\n }\n }\n\n private async request(\n method: string,\n path: string,\n init: RequestInit & { timeoutMs?: number } = {},\n ): Promise<Response> {\n const url = `${this.baseUrl}${path.startsWith(\"/\") ? path : `/${path}`}`;\n const timeoutMs = init.timeoutMs ?? this.timeout;\n let lastError: unknown;\n\n for (let attempt = 0; attempt < 3; attempt++) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const response = await fetch(url, {\n ...init,\n method,\n headers: {\n ...this.defaultHeaders,\n ...(init.headers as Record<string, string> | undefined),\n },\n signal: controller.signal,\n });\n clearTimeout(timer);\n\n if (response.ok) {\n return response;\n }\n await this.raiseForStatus(response);\n // unreachable\n return response;\n } catch (err) {\n clearTimeout(timer);\n if (err instanceof NaijaLingoError) {\n throw err;\n }\n lastError = err;\n const isAbort =\n err instanceof Error &&\n (err.name === \"AbortError\" || err.name === \"TimeoutError\");\n // Only retry connect-style failures, not aborts from long reads\n if (isAbort) {\n throw new ConnectionError(\n `Request timed out after ${timeoutMs}ms: ${String(err)}`,\n );\n }\n if (attempt < 2) {\n await sleep(1500);\n continue;\n }\n }\n }\n\n throw new ConnectionError(\n `Unable to connect to ${this.baseUrl}: ${String(lastError)}`,\n );\n }\n\n private async raiseForStatus(response: Response): Promise<never> {\n const status = response.status;\n let detail: string;\n let body: unknown;\n try {\n body = await response.json();\n detail =\n typeof body === \"object\" &&\n body !== null &&\n \"detail\" in body\n ? String((body as { detail: unknown }).detail)\n : JSON.stringify(body);\n } catch {\n detail = await response.text();\n }\n\n const normalizedDetail = detail.toLowerCase();\n if (status === 503 && (\n normalizedDetail.includes(\"inference capacity\")\n || normalizedDetail.includes(\"inference component has no capacity\")\n || normalizedDetail.includes(\"capacity is starting\")\n )) {\n throw new InferenceCapacityError(detail, status, body);\n }\n if (status === 401 || status === 403) {\n throw new AuthenticationError(detail, status, body);\n }\n if (status === 404) {\n throw new NotFoundError(detail, status, body);\n }\n if (status === 429) {\n throw new RateLimitError(detail, status, body);\n }\n if (status >= 500) {\n throw new ServerError(detail, status, body);\n }\n throw new NaijaLingoError(detail, status, body);\n }\n\n async getJson(\n path: string,\n params?: Record<string, string | undefined | null>,\n ): Promise<Record<string, unknown>> {\n let url = path;\n if (params) {\n const qs = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v != null) qs.set(k, v);\n }\n const s = qs.toString();\n if (s) url = `${path}?${s}`;\n }\n const resp = await this.request(\"GET\", url);\n return (await resp.json()) as Record<string, unknown>;\n }\n\n async postBytes(\n path: string,\n body: Record<string, unknown>,\n ): Promise<Uint8Array> {\n const resp = await this.request(\"POST\", path, {\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n return new Uint8Array(await resp.arrayBuffer());\n }\n\n async *postStream(\n path: string,\n body: Record<string, unknown>,\n ): AsyncGenerator<Uint8Array, void, unknown> {\n let lastError: unknown;\n for (let attempt = 0; attempt < 3; attempt++) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n try {\n const response = await fetch(\n `${this.baseUrl}${path.startsWith(\"/\") ? path : `/${path}`}`,\n {\n method: \"POST\",\n headers: {\n ...this.defaultHeaders,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n },\n );\n clearTimeout(timer);\n\n if (!response.ok) {\n await this.raiseForStatus(response);\n }\n if (!response.body) {\n throw new ConnectionError(\"No response body for stream\");\n }\n\n const reader = response.body.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value && value.length > 0) {\n yield value;\n }\n }\n } finally {\n reader.releaseLock();\n }\n return;\n } catch (err) {\n clearTimeout(timer);\n if (err instanceof NaijaLingoError) throw err;\n lastError = err;\n const isAbort =\n err instanceof Error &&\n (err.name === \"AbortError\" || err.name === \"TimeoutError\");\n if (isAbort) {\n throw new ConnectionError(`Request timed out: ${String(err)}`);\n }\n if (attempt < 2) {\n await sleep(1500);\n continue;\n }\n }\n }\n throw new ConnectionError(\n `Unable to connect to ${this.baseUrl}: ${String(lastError)}`,\n );\n }\n\n async postMultipart(\n path: string,\n form: FormData,\n timeoutMs?: number,\n ): Promise<Uint8Array> {\n const resp = await this.request(\"POST\", path, {\n body: form,\n timeoutMs: timeoutMs ?? Math.max(this.timeout, 600_000),\n // Let fetch set multipart boundary — do not set Content-Type\n });\n return new Uint8Array(await resp.arrayBuffer());\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { basename, dirname } from \"node:path\";\nimport { readFileSync } from \"node:fs\";\nimport { BaseClient } from \"./client.js\";\nimport {\n type HealthStatus,\n type LanguageList,\n type ResponseFormat,\n type Speaker,\n type SpeakerList,\n healthStatusFromDict,\n languageListFromDict,\n speakerFromDict,\n speakerListFromDict,\n} from \"./types.js\";\nimport {\n resolveCloneLangAndSpeaker,\n resolveTtsVoiceAndLang,\n} from \"./voice.js\";\n\nconst DEFAULT_MODEL_NAME = \"9jalingo-tts-1\";\n\nexport type GenerateOptions = {\n voice?: string;\n speaker?: string;\n lang?: string;\n language?: string;\n modelName?: string;\n speakerEmbedding?: number[];\n responseFormat?: ResponseFormat;\n temperature?: number;\n topP?: number;\n repetitionPenalty?: number;\n enableLongForm?: boolean;\n maxChunkDuration?: number;\n silenceDuration?: number;\n};\n\nexport type StreamOptions = Omit<\n GenerateOptions,\n \"modelName\" | \"responseFormat\"\n>;\n\nexport type CloneOptions = {\n voice?: string;\n lang?: string;\n speaker?: string;\n modelName?: string;\n temperature?: number;\n topP?: number;\n repetitionPenalty?: number;\n responseFormat?: ResponseFormat;\n};\n\nexport type ListSpeakersOptions = {\n language?: string;\n gender?: string;\n domain?: string;\n};\n\n/** Audio data returned from a generation request. */\nexport class AudioResponse {\n readonly content: Uint8Array;\n readonly mediaType: string;\n\n constructor(content: Uint8Array, mediaType = \"audio/wav\") {\n this.content = content;\n this.mediaType = mediaType;\n }\n\n /** Write the audio to a file. */\n async save(path: string): Promise<string> {\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, this.content);\n return path;\n }\n\n get length(): number {\n return this.content.length;\n }\n\n toString(): string {\n return `AudioResponse(${this.content.length} bytes, ${this.mediaType})`;\n }\n}\n\n/** Streaming audio response — yields byte chunks as they arrive. */\nexport class AudioStream implements AsyncIterable<Uint8Array> {\n private readonly chunks: AsyncIterable<Uint8Array>;\n private collected: Uint8Array | null = null;\n\n constructor(chunks: AsyncIterable<Uint8Array>) {\n this.chunks = chunks;\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<Uint8Array> {\n for await (const chunk of this.chunks) {\n yield chunk;\n }\n }\n\n /** Consume the entire stream and return an AudioResponse. */\n async collect(): Promise<AudioResponse> {\n if (this.collected == null) {\n const parts: Uint8Array[] = [];\n let total = 0;\n for await (const chunk of this.chunks) {\n parts.push(chunk);\n total += chunk.length;\n }\n const out = new Uint8Array(total);\n let offset = 0;\n for (const part of parts) {\n out.set(part, offset);\n offset += part.length;\n }\n this.collected = out;\n }\n return new AudioResponse(this.collected, \"audio/wav\");\n }\n}\n\nexport class TTS {\n private readonly client: BaseClient;\n\n constructor(client: BaseClient) {\n this.client = client;\n }\n\n /** Generate speech from text. */\n async generate(\n text: string,\n options: GenerateOptions = {},\n ): Promise<AudioResponse> {\n let [resolvedVoice, resolvedLang] = resolveTtsVoiceAndLang(options);\n if (resolvedVoice == null && options.speakerEmbedding == null) {\n resolvedVoice = \"blessing_pcm\";\n }\n const responseFormat = options.responseFormat ?? \"wav\";\n const body = buildBody({\n input: text,\n voice: resolvedVoice,\n lang: resolvedLang,\n model: options.modelName ?? DEFAULT_MODEL_NAME,\n speaker_embedding: options.speakerEmbedding,\n response_format: responseFormat,\n temperature: options.temperature,\n top_p: options.topP,\n repetition_penalty: options.repetitionPenalty,\n enable_long_form: options.enableLongForm ?? true,\n max_chunk_duration: options.maxChunkDuration,\n silence_duration: options.silenceDuration,\n });\n const content = await this.client.postBytes(\"/v1/audio/speech\", body);\n const mediaType = MEDIA_TYPES[responseFormat] ?? \"application/octet-stream\";\n return new AudioResponse(content, mediaType);\n }\n\n /** Stream speech generation — audio arrives as it's produced. */\n stream(text: string, options: StreamOptions = {}): AudioStream {\n let [resolvedVoice, resolvedLang] = resolveTtsVoiceAndLang(options);\n if (resolvedVoice == null && options.speakerEmbedding == null) {\n resolvedVoice = \"blessing_pcm\";\n }\n const body = buildBody({\n input: text,\n voice: resolvedVoice,\n lang: resolvedLang,\n speaker_embedding: options.speakerEmbedding,\n response_format: \"wav\",\n temperature: options.temperature,\n top_p: options.topP,\n repetition_penalty: options.repetitionPenalty,\n enable_long_form: options.enableLongForm ?? true,\n max_chunk_duration: options.maxChunkDuration,\n silence_duration: options.silenceDuration,\n });\n return new AudioStream(this.client.postStream(\"/v1/audio/speech/stream\", body));\n }\n\n /**\n * Generate speech using a cloned voice from a reference audio file.\n * `audioFile` may be a filesystem path, Buffer, Uint8Array, Blob, or File.\n */\n async clone(\n text: string,\n audioFile: string | Buffer | Uint8Array | Blob,\n options: CloneOptions = {},\n ): Promise<AudioResponse> {\n const voice = options.voice ?? \"pcm\";\n const [resolvedLang, resolvedSpeaker] = resolveCloneLangAndSpeaker(\n voice,\n { lang: options.lang, speaker: options.speaker },\n );\n const responseFormat = options.responseFormat ?? \"wav\";\n\n const form = new FormData();\n form.append(\"text\", text);\n form.append(\"lang\", resolvedLang);\n form.append(\"model_name\", options.modelName ?? DEFAULT_MODEL_NAME);\n form.append(\"response_format\", responseFormat);\n if (resolvedSpeaker) {\n form.append(\"voice\", resolvedSpeaker);\n }\n if (options.temperature != null) {\n form.append(\"temperature\", String(options.temperature));\n }\n if (options.topP != null) {\n form.append(\"top_p\", String(options.topP));\n }\n if (options.repetitionPenalty != null) {\n form.append(\"repetition_penalty\", String(options.repetitionPenalty));\n }\n\n const { blob, filename } = await toAudioBlob(audioFile);\n form.append(\"audio\", blob, filename);\n\n const content = await this.client.postMultipart(\"/v1/audio/clone\", form);\n const mediaType = MEDIA_TYPES[responseFormat] ?? \"application/octet-stream\";\n return new AudioResponse(content, mediaType);\n }\n\n async listSpeakers(\n options: ListSpeakersOptions = {},\n ): Promise<SpeakerList> {\n const data = await this.client.getJson(\"/v1/speakers\", {\n language: options.language,\n gender: options.gender,\n domain: options.domain,\n });\n return speakerListFromDict(data);\n }\n\n async getSpeaker(speakerId: string): Promise<Speaker> {\n const data = await this.client.getJson(`/v1/speakers/${speakerId}`);\n return speakerFromDict(data);\n }\n\n async listLanguages(): Promise<LanguageList> {\n const data = await this.client.getJson(\"/v1/languages\");\n return languageListFromDict(data);\n }\n\n async health(): Promise<HealthStatus> {\n const data = await this.client.getJson(\"/v1/health\");\n return healthStatusFromDict(data);\n }\n}\n\nconst MEDIA_TYPES: Record<string, string> = {\n wav: \"audio/wav\",\n pcm: \"application/octet-stream\",\n flac: \"audio/flac\",\n aac: \"audio/aac\",\n ogg: \"audio/ogg\",\n mp3: \"audio/mpeg\",\n alac: \"audio/alac\",\n};\n\nfunction buildBody(\n kwargs: Record<string, unknown>,\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(kwargs)) {\n if (v !== undefined && v !== null) out[k] = v;\n }\n return out;\n}\n\nasync function toAudioBlob(\n audioFile: string | Buffer | Uint8Array | Blob,\n): Promise<{ blob: Blob; filename: string }> {\n if (typeof audioFile === \"string\") {\n const bytes = readFileSync(audioFile);\n const filename = basename(audioFile);\n const mime = guessMime(filename);\n return {\n blob: new Blob([bytes], { type: mime }),\n filename,\n };\n }\n if (audioFile instanceof Blob) {\n return {\n blob: audioFile,\n filename: \"audio.wav\",\n };\n }\n // Buffer | Uint8Array\n const bytes =\n audioFile instanceof Uint8Array\n ? audioFile\n : new Uint8Array(audioFile);\n return {\n blob: new Blob([bytes], { type: \"application/octet-stream\" }),\n filename: \"audio.wav\",\n };\n}\n\nfunction guessMime(filename: string): string {\n const lower = filename.toLowerCase();\n if (lower.endsWith(\".wav\")) return \"audio/wav\";\n if (lower.endsWith(\".mp3\")) return \"audio/mpeg\";\n if (lower.endsWith(\".flac\")) return \"audio/flac\";\n if (lower.endsWith(\".ogg\")) return \"audio/ogg\";\n if (lower.endsWith(\".aac\") || lower.endsWith(\".m4a\")) return \"audio/aac\";\n return \"application/octet-stream\";\n}\n","/** A speaker voice identity. */\nexport interface Speaker {\n id: string;\n name: string;\n language: string;\n gender?: string | null;\n domain?: string | null;\n}\n\nexport function speakerFromDict(data: Record<string, unknown>): Speaker {\n return {\n id: String(data.id ?? data.speaker_id ?? \"\"),\n name: String(data.name ?? data.id ?? \"\"),\n language: String(data.language ?? \"\"),\n gender: (data.gender as string | null | undefined) ?? null,\n domain: (data.domain as string | null | undefined) ?? null,\n };\n}\n\n/** List of speakers with metadata. */\nexport interface SpeakerList {\n speakers: Speaker[];\n total: number;\n byLanguage: Record<string, number>;\n [Symbol.iterator](): Iterator<Speaker>;\n length: number;\n}\n\nexport function speakerListFromDict(data: Record<string, unknown>): SpeakerList {\n const raw = (data.speakers as Record<string, unknown>[] | undefined) ?? [];\n const speakers = raw.map(speakerFromDict);\n const total = typeof data.total === \"number\" ? data.total : speakers.length;\n const byLanguage =\n (data.by_language as Record<string, number> | undefined) ?? {};\n return {\n speakers,\n total,\n byLanguage,\n get length() {\n return total;\n },\n [Symbol.iterator]() {\n return speakers[Symbol.iterator]();\n },\n };\n}\n\n/** A supported language. */\nexport interface Language {\n code: string;\n name: string;\n speakerCount: number;\n}\n\nexport function languageFromDict(data: Record<string, unknown>): Language {\n return {\n code: String(data.code ?? \"\"),\n name: String(data.name ?? \"\"),\n speakerCount: Number(data.speaker_count ?? 0),\n };\n}\n\n/** List of supported languages and domains. */\nexport interface LanguageList {\n languages: Language[];\n domains: string[];\n}\n\nexport function languageListFromDict(data: Record<string, unknown>): LanguageList {\n const rawLangs = data.languages;\n let languages: Language[];\n\n if (rawLangs && typeof rawLangs === \"object\" && !Array.isArray(rawLangs)) {\n languages = Object.entries(rawLangs as Record<string, unknown>).map(\n ([code, value]) => {\n if (value && typeof value === \"object\") {\n const v = value as Record<string, unknown>;\n return {\n code,\n name: String(v.name ?? code),\n speakerCount: Number(v.speaker_count ?? 0),\n };\n }\n return { code, name: String(value), speakerCount: 0 };\n },\n );\n } else {\n const arr = (rawLangs as Record<string, unknown>[] | undefined) ?? [];\n languages = arr.map(languageFromDict);\n }\n\n return {\n languages,\n domains: (data.domains as string[] | undefined) ?? [],\n };\n}\n\n/** API health check result. */\nexport interface HealthStatus {\n status: string;\n engineReady: boolean;\n codecReady: boolean;\n totalSpeakers: number;\n languages: string[];\n voiceCloningAvailable: boolean;\n speakerProjectionLoaded: boolean;\n}\n\nexport function healthStatusFromDict(data: Record<string, unknown>): HealthStatus {\n const supported = data.supported_languages;\n let languages: string[] = [];\n if (Array.isArray(data.languages)) {\n languages = data.languages as string[];\n } else if (supported && typeof supported === \"object\") {\n languages = Object.keys(supported as Record<string, unknown>);\n }\n\n return {\n status: String(data.status ?? \"unknown\"),\n engineReady: Boolean(data.engine_ready ?? data.tts_initialized ?? false),\n codecReady: Boolean(data.codec_ready ?? false),\n totalSpeakers: Number(data.total_speakers ?? data.speakers_loaded ?? 0),\n languages,\n voiceCloningAvailable: Boolean(data.voice_cloning_available ?? false),\n speakerProjectionLoaded: Boolean(data.speaker_projection_loaded ?? false),\n };\n}\n\n/** An available TTS model. */\nexport interface Model {\n id: string;\n object: string;\n ownedBy: string;\n}\n\nexport function modelFromDict(data: Record<string, unknown>): Model {\n return {\n id: String(data.id ?? \"\"),\n object: String(data.object ?? \"model\"),\n ownedBy: String(data.owned_by ?? \"9jalingo\"),\n };\n}\n\n/** List of available models. */\nexport interface ModelList {\n models: Model[];\n object: string;\n [Symbol.iterator](): Iterator<Model>;\n length: number;\n}\n\nexport function modelListFromDict(data: Record<string, unknown>): ModelList {\n const raw = (data.data as Record<string, unknown>[] | undefined) ?? [];\n const models = raw.map(modelFromDict);\n return {\n models,\n object: String(data.object ?? \"list\"),\n get length() {\n return models.length;\n },\n [Symbol.iterator]() {\n return models[Symbol.iterator]();\n },\n };\n}\n\n/** Root API information returned by GET /. */\nexport interface APIInfo {\n name: string;\n version: string;\n description: string;\n endpoints: Record<string, string>;\n}\n\nexport function apiInfoFromDict(data: Record<string, unknown>): APIInfo {\n return {\n name: String(data.name ?? \"\"),\n version: String(data.version ?? \"\"),\n description: String(data.description ?? \"\"),\n endpoints: (data.endpoints as Record<string, string> | undefined) ?? {},\n };\n}\n\n/** Service metadata returned by GET /v1. */\nexport interface ServiceInfo {\n object: string;\n name: string;\n modelsUrl: string;\n speechUrl: string;\n speechStreamUrl: string;\n}\n\nexport function serviceInfoFromDict(data: Record<string, unknown>): ServiceInfo {\n return {\n object: String(data.object ?? \"service\"),\n name: String(data.name ?? \"\"),\n modelsUrl: String(data.models_url ?? \"\"),\n speechUrl: String(data.speech_url ?? \"\"),\n speechStreamUrl: String(data.speech_stream_url ?? \"\"),\n };\n}\n\nexport type ResponseFormat =\n | \"wav\"\n | \"pcm\"\n | \"flac\"\n | \"aac\"\n | \"ogg\"\n | \"mp3\"\n | \"alac\";\n","const LANG_ALIASES: Record<string, string> = {\n yo: \"yo\",\n yor: \"yo\",\n yoruba: \"yo\",\n ig: \"ig\",\n ibo: \"ig\",\n igbo: \"ig\",\n ha: \"ha\",\n hau: \"ha\",\n hausa: \"ha\",\n pcm: \"pcm\",\n pidgin: \"pcm\",\n};\n\nexport function normalizeLang(code: string): string | null {\n return LANG_ALIASES[code.trim().toLowerCase()] ?? null;\n}\n\n/**\n * Resolve speech API fields: voice/speaker + lang/language.\n * Returns [speakerId, langCode]. Bare language codes must be passed via lang/language.\n */\nexport function resolveTtsVoiceAndLang(options: {\n voice?: string | null;\n speaker?: string | null;\n lang?: string | null;\n language?: string | null;\n}): [string | null, string | null] {\n let resolvedLang: string | null = null;\n\n if (options.lang != null) {\n resolvedLang = normalizeLang(options.lang);\n if (resolvedLang == null) {\n throw new Error(\n `Unsupported language '${options.lang}'. Use ha, ig, yo, or pcm.`,\n );\n }\n } else if (options.language != null) {\n resolvedLang = normalizeLang(options.language);\n if (resolvedLang == null) {\n throw new Error(\n `Unsupported language '${options.language}'. Use ha, ig, yo, or pcm.`,\n );\n }\n }\n\n // speaker takes precedence over voice\n const candidate =\n options.speaker != null ? options.speaker : options.voice;\n if (candidate == null || !String(candidate).trim()) {\n return [null, resolvedLang];\n }\n\n const resolved = String(candidate).trim();\n const normalized = resolved.toLowerCase();\n if (normalized in LANG_ALIASES) {\n const langCode = LANG_ALIASES[normalized];\n throw new Error(\n `'${resolved}' is a language code, not a speaker ID. ` +\n `Pass speaker/voice='ada_pcm' (or another speaker ID) and ` +\n `lang='${langCode}' for the language. ` +\n `Browse speakers with: client.tts.listSpeakers({ language: '${langCode}' })`,\n );\n }\n\n if (resolvedLang == null && resolved.includes(\"_\")) {\n const suffix = resolved.split(\"_\").pop()!;\n resolvedLang = normalizeLang(suffix);\n }\n\n return [resolved, resolvedLang];\n}\n\n/**\n * Resolve clone form fields.\n * voice may be a language code (\"pcm\") or a speaker ID with a language suffix.\n */\nexport function resolveCloneLangAndSpeaker(\n voice: string,\n options: { lang?: string | null; speaker?: string | null } = {},\n): [string, string | null] {\n let resolvedLang =\n options.lang != null ? normalizeLang(options.lang) : null;\n let resolvedSpeaker = options.speaker?.trim() || null;\n\n const voiceStr = (voice || \"\").trim();\n const voiceNorm = voiceStr.toLowerCase();\n\n if (voiceNorm in LANG_ALIASES) {\n if (resolvedLang == null) {\n resolvedLang = LANG_ALIASES[voiceNorm];\n }\n } else if (voiceStr.includes(\"_\")) {\n if (resolvedSpeaker == null) {\n resolvedSpeaker = voiceStr;\n }\n if (resolvedLang == null) {\n const suffix = voiceStr.split(\"_\").pop()!;\n resolvedLang = normalizeLang(suffix);\n }\n } else if (voiceStr && resolvedLang == null) {\n throw new Error(\n `'${voice}' is not a language code (ha/ig/yo/pcm) or a speaker ID ` +\n `with a language suffix (e.g. 'daniel_pcm'). ` +\n `Pass voice='pcm' or lang='pcm'.`,\n );\n }\n\n if (!resolvedLang) {\n throw new Error(\n \"Clone requires a language. Pass voice='pcm' (or 'ha'/'ig'/'yo'), \" +\n \"lang='pcm', or a speaker ID ending in _pcm/_ha/_ig/_yo.\",\n );\n }\n\n return [resolvedLang, resolvedSpeaker];\n}\n"],"mappings":"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","names":["bytes"]}
package/dist/index.d.cts CHANGED
@@ -175,6 +175,10 @@ declare class NotFoundError extends NaijaLingoError {
175
175
  declare class ServerError extends NaijaLingoError {
176
176
  constructor(message: string, statusCode?: number, response?: unknown);
177
177
  }
178
+ /** Raised when the inference GPU is waking from scale-to-zero. */
179
+ declare class InferenceCapacityError extends ServerError {
180
+ constructor(message: string, statusCode?: number, response?: unknown);
181
+ }
178
182
  /** Raised when unable to connect to the API. */
179
183
  declare class ConnectionError extends NaijaLingoError {
180
184
  constructor(message: string, statusCode?: number, response?: unknown);
@@ -198,7 +202,7 @@ declare class ConnectionError extends NaijaLingoError {
198
202
  * ```
199
203
  */
200
204
 
201
- declare const VERSION = "0.1.0";
205
+ declare const VERSION = "0.1.1";
202
206
 
203
207
  declare class NaijaLingo {
204
208
  private readonly _client;
@@ -212,4 +216,4 @@ declare class NaijaLingo {
212
216
  serviceInfo(): Promise<ServiceInfo>;
213
217
  }
214
218
 
215
- export { type APIInfo, AudioResponse, AudioStream, AuthenticationError, type ClientOptions, type CloneOptions, ConnectionError, type GenerateOptions, type HealthStatus, type Language, type LanguageList, type ListSpeakersOptions, type Model, type ModelList, NaijaLingo, NaijaLingoError, NotFoundError, RateLimitError, type ResponseFormat, ServerError, type ServiceInfo, type Speaker, type SpeakerList, type StreamOptions, TTS, VERSION };
219
+ export { type APIInfo, AudioResponse, AudioStream, AuthenticationError, type ClientOptions, type CloneOptions, ConnectionError, type GenerateOptions, type HealthStatus, InferenceCapacityError, type Language, type LanguageList, type ListSpeakersOptions, type Model, type ModelList, NaijaLingo, NaijaLingoError, NotFoundError, RateLimitError, type ResponseFormat, ServerError, type ServiceInfo, type Speaker, type SpeakerList, type StreamOptions, TTS, VERSION };
package/dist/index.d.ts CHANGED
@@ -175,6 +175,10 @@ declare class NotFoundError extends NaijaLingoError {
175
175
  declare class ServerError extends NaijaLingoError {
176
176
  constructor(message: string, statusCode?: number, response?: unknown);
177
177
  }
178
+ /** Raised when the inference GPU is waking from scale-to-zero. */
179
+ declare class InferenceCapacityError extends ServerError {
180
+ constructor(message: string, statusCode?: number, response?: unknown);
181
+ }
178
182
  /** Raised when unable to connect to the API. */
179
183
  declare class ConnectionError extends NaijaLingoError {
180
184
  constructor(message: string, statusCode?: number, response?: unknown);
@@ -198,7 +202,7 @@ declare class ConnectionError extends NaijaLingoError {
198
202
  * ```
199
203
  */
200
204
 
201
- declare const VERSION = "0.1.0";
205
+ declare const VERSION = "0.1.1";
202
206
 
203
207
  declare class NaijaLingo {
204
208
  private readonly _client;
@@ -212,4 +216,4 @@ declare class NaijaLingo {
212
216
  serviceInfo(): Promise<ServiceInfo>;
213
217
  }
214
218
 
215
- export { type APIInfo, AudioResponse, AudioStream, AuthenticationError, type ClientOptions, type CloneOptions, ConnectionError, type GenerateOptions, type HealthStatus, type Language, type LanguageList, type ListSpeakersOptions, type Model, type ModelList, NaijaLingo, NaijaLingoError, NotFoundError, RateLimitError, type ResponseFormat, ServerError, type ServiceInfo, type Speaker, type SpeakerList, type StreamOptions, TTS, VERSION };
219
+ export { type APIInfo, AudioResponse, AudioStream, AuthenticationError, type ClientOptions, type CloneOptions, ConnectionError, type GenerateOptions, type HealthStatus, InferenceCapacityError, type Language, type LanguageList, type ListSpeakersOptions, type Model, type ModelList, NaijaLingo, NaijaLingoError, NotFoundError, RateLimitError, type ResponseFormat, ServerError, type ServiceInfo, type Speaker, type SpeakerList, type StreamOptions, TTS, VERSION };
package/dist/index.js CHANGED
@@ -33,6 +33,12 @@ var ServerError = class extends NaijaLingoError {
33
33
  this.name = "ServerError";
34
34
  }
35
35
  };
36
+ var InferenceCapacityError = class extends ServerError {
37
+ constructor(message, statusCode, response) {
38
+ super(message, statusCode, response);
39
+ this.name = "InferenceCapacityError";
40
+ }
41
+ };
36
42
  var ConnectionError = class extends NaijaLingoError {
37
43
  constructor(message, statusCode, response) {
38
44
  super(message, statusCode, response);
@@ -54,7 +60,7 @@ var BaseClient = class {
54
60
  this.baseUrl = base.replace(/\/+$/, "");
55
61
  this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;
56
62
  this.defaultHeaders = {
57
- "User-Agent": "naijalingo-js/0.1.0"
63
+ "User-Agent": "naijalingo-js/0.1.1"
58
64
  };
59
65
  if (this.apiKey) {
60
66
  this.defaultHeaders["X-API-Key"] = this.apiKey;
@@ -115,6 +121,10 @@ var BaseClient = class {
115
121
  } catch {
116
122
  detail = await response.text();
117
123
  }
124
+ const normalizedDetail = detail.toLowerCase();
125
+ if (status === 503 && (normalizedDetail.includes("inference capacity") || normalizedDetail.includes("inference component has no capacity") || normalizedDetail.includes("capacity is starting"))) {
126
+ throw new InferenceCapacityError(detail, status, body);
127
+ }
118
128
  if (status === 401 || status === 403) {
119
129
  throw new AuthenticationError(detail, status, body);
120
130
  }
@@ -630,7 +640,7 @@ function guessMime(filename) {
630
640
  }
631
641
 
632
642
  // src/index.ts
633
- var VERSION = "0.1.0";
643
+ var VERSION = "0.1.1";
634
644
  var NaijaLingo = class {
635
645
  _client;
636
646
  tts;
@@ -659,6 +669,7 @@ export {
659
669
  AudioStream,
660
670
  AuthenticationError,
661
671
  ConnectionError,
672
+ InferenceCapacityError,
662
673
  NaijaLingo,
663
674
  NaijaLingoError,
664
675
  NotFoundError,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/client.ts","../src/tts.ts","../src/types.ts","../src/voice.ts","../src/index.ts"],"sourcesContent":["/** Base exception for all 9jaLingo SDK errors. */\nexport class NaijaLingoError extends Error {\n readonly statusCode?: number;\n readonly response?: unknown;\n\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message);\n this.name = \"NaijaLingoError\";\n this.statusCode = statusCode;\n this.response = response;\n }\n}\n\n/** Raised when the API key is missing or invalid. */\nexport class AuthenticationError extends NaijaLingoError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"AuthenticationError\";\n }\n}\n\n/** Raised when rate limit is exceeded. */\nexport class RateLimitError extends NaijaLingoError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"RateLimitError\";\n }\n}\n\n/** Raised when a requested resource is not found. */\nexport class NotFoundError extends NaijaLingoError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"NotFoundError\";\n }\n}\n\n/** Raised when the API returns a 5xx error. */\nexport class ServerError extends NaijaLingoError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"ServerError\";\n }\n}\n\n/** Raised when unable to connect to the API. */\nexport class ConnectionError extends NaijaLingoError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"ConnectionError\";\n }\n}\n","import {\n AuthenticationError,\n ConnectionError,\n NaijaLingoError,\n NotFoundError,\n RateLimitError,\n ServerError,\n} from \"./errors.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.9jalingo.org\";\nconst DEFAULT_TIMEOUT_MS = 300_000;\n\nexport interface ClientOptions {\n apiKey?: string;\n baseUrl?: string;\n /** Request timeout in milliseconds (default 300000). */\n timeout?: number;\n}\n\nexport class BaseClient {\n readonly apiKey: string;\n readonly baseUrl: string;\n readonly timeout: number;\n private readonly defaultHeaders: Record<string, string>;\n\n constructor(options: ClientOptions = {}) {\n this.apiKey =\n options.apiKey ?? process.env.NAIJALINGO_API_KEY ?? \"\";\n const base =\n options.baseUrl ??\n process.env.NAIJALINGO_BASE_URL ??\n DEFAULT_BASE_URL;\n this.baseUrl = base.replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;\n\n this.defaultHeaders = {\n \"User-Agent\": \"naijalingo-js/0.1.0\",\n };\n if (this.apiKey) {\n this.defaultHeaders[\"X-API-Key\"] = this.apiKey;\n }\n }\n\n private async request(\n method: string,\n path: string,\n init: RequestInit & { timeoutMs?: number } = {},\n ): Promise<Response> {\n const url = `${this.baseUrl}${path.startsWith(\"/\") ? path : `/${path}`}`;\n const timeoutMs = init.timeoutMs ?? this.timeout;\n let lastError: unknown;\n\n for (let attempt = 0; attempt < 3; attempt++) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const response = await fetch(url, {\n ...init,\n method,\n headers: {\n ...this.defaultHeaders,\n ...(init.headers as Record<string, string> | undefined),\n },\n signal: controller.signal,\n });\n clearTimeout(timer);\n\n if (response.ok) {\n return response;\n }\n await this.raiseForStatus(response);\n // unreachable\n return response;\n } catch (err) {\n clearTimeout(timer);\n if (err instanceof NaijaLingoError) {\n throw err;\n }\n lastError = err;\n const isAbort =\n err instanceof Error &&\n (err.name === \"AbortError\" || err.name === \"TimeoutError\");\n // Only retry connect-style failures, not aborts from long reads\n if (isAbort) {\n throw new ConnectionError(\n `Request timed out after ${timeoutMs}ms: ${String(err)}`,\n );\n }\n if (attempt < 2) {\n await sleep(1500);\n continue;\n }\n }\n }\n\n throw new ConnectionError(\n `Unable to connect to ${this.baseUrl}: ${String(lastError)}`,\n );\n }\n\n private async raiseForStatus(response: Response): Promise<never> {\n const status = response.status;\n let detail: string;\n let body: unknown;\n try {\n body = await response.json();\n detail =\n typeof body === \"object\" &&\n body !== null &&\n \"detail\" in body\n ? String((body as { detail: unknown }).detail)\n : JSON.stringify(body);\n } catch {\n detail = await response.text();\n }\n\n if (status === 401 || status === 403) {\n throw new AuthenticationError(detail, status, body);\n }\n if (status === 404) {\n throw new NotFoundError(detail, status, body);\n }\n if (status === 429) {\n throw new RateLimitError(detail, status, body);\n }\n if (status >= 500) {\n throw new ServerError(detail, status, body);\n }\n throw new NaijaLingoError(detail, status, body);\n }\n\n async getJson(\n path: string,\n params?: Record<string, string | undefined | null>,\n ): Promise<Record<string, unknown>> {\n let url = path;\n if (params) {\n const qs = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v != null) qs.set(k, v);\n }\n const s = qs.toString();\n if (s) url = `${path}?${s}`;\n }\n const resp = await this.request(\"GET\", url);\n return (await resp.json()) as Record<string, unknown>;\n }\n\n async postBytes(\n path: string,\n body: Record<string, unknown>,\n ): Promise<Uint8Array> {\n const resp = await this.request(\"POST\", path, {\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n return new Uint8Array(await resp.arrayBuffer());\n }\n\n async *postStream(\n path: string,\n body: Record<string, unknown>,\n ): AsyncGenerator<Uint8Array, void, unknown> {\n let lastError: unknown;\n for (let attempt = 0; attempt < 3; attempt++) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n try {\n const response = await fetch(\n `${this.baseUrl}${path.startsWith(\"/\") ? path : `/${path}`}`,\n {\n method: \"POST\",\n headers: {\n ...this.defaultHeaders,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n },\n );\n clearTimeout(timer);\n\n if (!response.ok) {\n await this.raiseForStatus(response);\n }\n if (!response.body) {\n throw new ConnectionError(\"No response body for stream\");\n }\n\n const reader = response.body.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value && value.length > 0) {\n yield value;\n }\n }\n } finally {\n reader.releaseLock();\n }\n return;\n } catch (err) {\n clearTimeout(timer);\n if (err instanceof NaijaLingoError) throw err;\n lastError = err;\n const isAbort =\n err instanceof Error &&\n (err.name === \"AbortError\" || err.name === \"TimeoutError\");\n if (isAbort) {\n throw new ConnectionError(`Request timed out: ${String(err)}`);\n }\n if (attempt < 2) {\n await sleep(1500);\n continue;\n }\n }\n }\n throw new ConnectionError(\n `Unable to connect to ${this.baseUrl}: ${String(lastError)}`,\n );\n }\n\n async postMultipart(\n path: string,\n form: FormData,\n timeoutMs?: number,\n ): Promise<Uint8Array> {\n const resp = await this.request(\"POST\", path, {\n body: form,\n timeoutMs: timeoutMs ?? Math.max(this.timeout, 600_000),\n // Let fetch set multipart boundary — do not set Content-Type\n });\n return new Uint8Array(await resp.arrayBuffer());\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { basename, dirname } from \"node:path\";\nimport { readFileSync } from \"node:fs\";\nimport { BaseClient } from \"./client.js\";\nimport {\n type HealthStatus,\n type LanguageList,\n type ResponseFormat,\n type Speaker,\n type SpeakerList,\n healthStatusFromDict,\n languageListFromDict,\n speakerFromDict,\n speakerListFromDict,\n} from \"./types.js\";\nimport {\n resolveCloneLangAndSpeaker,\n resolveTtsVoiceAndLang,\n} from \"./voice.js\";\n\nconst DEFAULT_MODEL_NAME = \"9jalingo-tts-1\";\n\nexport type GenerateOptions = {\n voice?: string;\n speaker?: string;\n lang?: string;\n language?: string;\n modelName?: string;\n speakerEmbedding?: number[];\n responseFormat?: ResponseFormat;\n temperature?: number;\n topP?: number;\n repetitionPenalty?: number;\n enableLongForm?: boolean;\n maxChunkDuration?: number;\n silenceDuration?: number;\n};\n\nexport type StreamOptions = Omit<\n GenerateOptions,\n \"modelName\" | \"responseFormat\"\n>;\n\nexport type CloneOptions = {\n voice?: string;\n lang?: string;\n speaker?: string;\n modelName?: string;\n temperature?: number;\n topP?: number;\n repetitionPenalty?: number;\n responseFormat?: ResponseFormat;\n};\n\nexport type ListSpeakersOptions = {\n language?: string;\n gender?: string;\n domain?: string;\n};\n\n/** Audio data returned from a generation request. */\nexport class AudioResponse {\n readonly content: Uint8Array;\n readonly mediaType: string;\n\n constructor(content: Uint8Array, mediaType = \"audio/wav\") {\n this.content = content;\n this.mediaType = mediaType;\n }\n\n /** Write the audio to a file. */\n async save(path: string): Promise<string> {\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, this.content);\n return path;\n }\n\n get length(): number {\n return this.content.length;\n }\n\n toString(): string {\n return `AudioResponse(${this.content.length} bytes, ${this.mediaType})`;\n }\n}\n\n/** Streaming audio response — yields byte chunks as they arrive. */\nexport class AudioStream implements AsyncIterable<Uint8Array> {\n private readonly chunks: AsyncIterable<Uint8Array>;\n private collected: Uint8Array | null = null;\n\n constructor(chunks: AsyncIterable<Uint8Array>) {\n this.chunks = chunks;\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<Uint8Array> {\n for await (const chunk of this.chunks) {\n yield chunk;\n }\n }\n\n /** Consume the entire stream and return an AudioResponse. */\n async collect(): Promise<AudioResponse> {\n if (this.collected == null) {\n const parts: Uint8Array[] = [];\n let total = 0;\n for await (const chunk of this.chunks) {\n parts.push(chunk);\n total += chunk.length;\n }\n const out = new Uint8Array(total);\n let offset = 0;\n for (const part of parts) {\n out.set(part, offset);\n offset += part.length;\n }\n this.collected = out;\n }\n return new AudioResponse(this.collected, \"audio/wav\");\n }\n}\n\nexport class TTS {\n private readonly client: BaseClient;\n\n constructor(client: BaseClient) {\n this.client = client;\n }\n\n /** Generate speech from text. */\n async generate(\n text: string,\n options: GenerateOptions = {},\n ): Promise<AudioResponse> {\n let [resolvedVoice, resolvedLang] = resolveTtsVoiceAndLang(options);\n if (resolvedVoice == null && options.speakerEmbedding == null) {\n resolvedVoice = \"blessing_pcm\";\n }\n const responseFormat = options.responseFormat ?? \"wav\";\n const body = buildBody({\n input: text,\n voice: resolvedVoice,\n lang: resolvedLang,\n model: options.modelName ?? DEFAULT_MODEL_NAME,\n speaker_embedding: options.speakerEmbedding,\n response_format: responseFormat,\n temperature: options.temperature,\n top_p: options.topP,\n repetition_penalty: options.repetitionPenalty,\n enable_long_form: options.enableLongForm ?? true,\n max_chunk_duration: options.maxChunkDuration,\n silence_duration: options.silenceDuration,\n });\n const content = await this.client.postBytes(\"/v1/audio/speech\", body);\n const mediaType = MEDIA_TYPES[responseFormat] ?? \"application/octet-stream\";\n return new AudioResponse(content, mediaType);\n }\n\n /** Stream speech generation — audio arrives as it's produced. */\n stream(text: string, options: StreamOptions = {}): AudioStream {\n let [resolvedVoice, resolvedLang] = resolveTtsVoiceAndLang(options);\n if (resolvedVoice == null && options.speakerEmbedding == null) {\n resolvedVoice = \"blessing_pcm\";\n }\n const body = buildBody({\n input: text,\n voice: resolvedVoice,\n lang: resolvedLang,\n speaker_embedding: options.speakerEmbedding,\n response_format: \"wav\",\n temperature: options.temperature,\n top_p: options.topP,\n repetition_penalty: options.repetitionPenalty,\n enable_long_form: options.enableLongForm ?? true,\n max_chunk_duration: options.maxChunkDuration,\n silence_duration: options.silenceDuration,\n });\n return new AudioStream(this.client.postStream(\"/v1/audio/speech/stream\", body));\n }\n\n /**\n * Generate speech using a cloned voice from a reference audio file.\n * `audioFile` may be a filesystem path, Buffer, Uint8Array, Blob, or File.\n */\n async clone(\n text: string,\n audioFile: string | Buffer | Uint8Array | Blob,\n options: CloneOptions = {},\n ): Promise<AudioResponse> {\n const voice = options.voice ?? \"pcm\";\n const [resolvedLang, resolvedSpeaker] = resolveCloneLangAndSpeaker(\n voice,\n { lang: options.lang, speaker: options.speaker },\n );\n const responseFormat = options.responseFormat ?? \"wav\";\n\n const form = new FormData();\n form.append(\"text\", text);\n form.append(\"lang\", resolvedLang);\n form.append(\"model_name\", options.modelName ?? DEFAULT_MODEL_NAME);\n form.append(\"response_format\", responseFormat);\n if (resolvedSpeaker) {\n form.append(\"voice\", resolvedSpeaker);\n }\n if (options.temperature != null) {\n form.append(\"temperature\", String(options.temperature));\n }\n if (options.topP != null) {\n form.append(\"top_p\", String(options.topP));\n }\n if (options.repetitionPenalty != null) {\n form.append(\"repetition_penalty\", String(options.repetitionPenalty));\n }\n\n const { blob, filename } = await toAudioBlob(audioFile);\n form.append(\"audio\", blob, filename);\n\n const content = await this.client.postMultipart(\"/v1/audio/clone\", form);\n const mediaType = MEDIA_TYPES[responseFormat] ?? \"application/octet-stream\";\n return new AudioResponse(content, mediaType);\n }\n\n async listSpeakers(\n options: ListSpeakersOptions = {},\n ): Promise<SpeakerList> {\n const data = await this.client.getJson(\"/v1/speakers\", {\n language: options.language,\n gender: options.gender,\n domain: options.domain,\n });\n return speakerListFromDict(data);\n }\n\n async getSpeaker(speakerId: string): Promise<Speaker> {\n const data = await this.client.getJson(`/v1/speakers/${speakerId}`);\n return speakerFromDict(data);\n }\n\n async listLanguages(): Promise<LanguageList> {\n const data = await this.client.getJson(\"/v1/languages\");\n return languageListFromDict(data);\n }\n\n async health(): Promise<HealthStatus> {\n const data = await this.client.getJson(\"/v1/health\");\n return healthStatusFromDict(data);\n }\n}\n\nconst MEDIA_TYPES: Record<string, string> = {\n wav: \"audio/wav\",\n pcm: \"application/octet-stream\",\n flac: \"audio/flac\",\n aac: \"audio/aac\",\n ogg: \"audio/ogg\",\n mp3: \"audio/mpeg\",\n alac: \"audio/alac\",\n};\n\nfunction buildBody(\n kwargs: Record<string, unknown>,\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(kwargs)) {\n if (v !== undefined && v !== null) out[k] = v;\n }\n return out;\n}\n\nasync function toAudioBlob(\n audioFile: string | Buffer | Uint8Array | Blob,\n): Promise<{ blob: Blob; filename: string }> {\n if (typeof audioFile === \"string\") {\n const bytes = readFileSync(audioFile);\n const filename = basename(audioFile);\n const mime = guessMime(filename);\n return {\n blob: new Blob([bytes], { type: mime }),\n filename,\n };\n }\n if (audioFile instanceof Blob) {\n return {\n blob: audioFile,\n filename: \"audio.wav\",\n };\n }\n // Buffer | Uint8Array\n const bytes =\n audioFile instanceof Uint8Array\n ? audioFile\n : new Uint8Array(audioFile);\n return {\n blob: new Blob([bytes], { type: \"application/octet-stream\" }),\n filename: \"audio.wav\",\n };\n}\n\nfunction guessMime(filename: string): string {\n const lower = filename.toLowerCase();\n if (lower.endsWith(\".wav\")) return \"audio/wav\";\n if (lower.endsWith(\".mp3\")) return \"audio/mpeg\";\n if (lower.endsWith(\".flac\")) return \"audio/flac\";\n if (lower.endsWith(\".ogg\")) return \"audio/ogg\";\n if (lower.endsWith(\".aac\") || lower.endsWith(\".m4a\")) return \"audio/aac\";\n return \"application/octet-stream\";\n}\n","/** A speaker voice identity. */\nexport interface Speaker {\n id: string;\n name: string;\n language: string;\n gender?: string | null;\n domain?: string | null;\n}\n\nexport function speakerFromDict(data: Record<string, unknown>): Speaker {\n return {\n id: String(data.id ?? data.speaker_id ?? \"\"),\n name: String(data.name ?? data.id ?? \"\"),\n language: String(data.language ?? \"\"),\n gender: (data.gender as string | null | undefined) ?? null,\n domain: (data.domain as string | null | undefined) ?? null,\n };\n}\n\n/** List of speakers with metadata. */\nexport interface SpeakerList {\n speakers: Speaker[];\n total: number;\n byLanguage: Record<string, number>;\n [Symbol.iterator](): Iterator<Speaker>;\n length: number;\n}\n\nexport function speakerListFromDict(data: Record<string, unknown>): SpeakerList {\n const raw = (data.speakers as Record<string, unknown>[] | undefined) ?? [];\n const speakers = raw.map(speakerFromDict);\n const total = typeof data.total === \"number\" ? data.total : speakers.length;\n const byLanguage =\n (data.by_language as Record<string, number> | undefined) ?? {};\n return {\n speakers,\n total,\n byLanguage,\n get length() {\n return total;\n },\n [Symbol.iterator]() {\n return speakers[Symbol.iterator]();\n },\n };\n}\n\n/** A supported language. */\nexport interface Language {\n code: string;\n name: string;\n speakerCount: number;\n}\n\nexport function languageFromDict(data: Record<string, unknown>): Language {\n return {\n code: String(data.code ?? \"\"),\n name: String(data.name ?? \"\"),\n speakerCount: Number(data.speaker_count ?? 0),\n };\n}\n\n/** List of supported languages and domains. */\nexport interface LanguageList {\n languages: Language[];\n domains: string[];\n}\n\nexport function languageListFromDict(data: Record<string, unknown>): LanguageList {\n const rawLangs = data.languages;\n let languages: Language[];\n\n if (rawLangs && typeof rawLangs === \"object\" && !Array.isArray(rawLangs)) {\n languages = Object.entries(rawLangs as Record<string, unknown>).map(\n ([code, value]) => {\n if (value && typeof value === \"object\") {\n const v = value as Record<string, unknown>;\n return {\n code,\n name: String(v.name ?? code),\n speakerCount: Number(v.speaker_count ?? 0),\n };\n }\n return { code, name: String(value), speakerCount: 0 };\n },\n );\n } else {\n const arr = (rawLangs as Record<string, unknown>[] | undefined) ?? [];\n languages = arr.map(languageFromDict);\n }\n\n return {\n languages,\n domains: (data.domains as string[] | undefined) ?? [],\n };\n}\n\n/** API health check result. */\nexport interface HealthStatus {\n status: string;\n engineReady: boolean;\n codecReady: boolean;\n totalSpeakers: number;\n languages: string[];\n voiceCloningAvailable: boolean;\n speakerProjectionLoaded: boolean;\n}\n\nexport function healthStatusFromDict(data: Record<string, unknown>): HealthStatus {\n const supported = data.supported_languages;\n let languages: string[] = [];\n if (Array.isArray(data.languages)) {\n languages = data.languages as string[];\n } else if (supported && typeof supported === \"object\") {\n languages = Object.keys(supported as Record<string, unknown>);\n }\n\n return {\n status: String(data.status ?? \"unknown\"),\n engineReady: Boolean(data.engine_ready ?? data.tts_initialized ?? false),\n codecReady: Boolean(data.codec_ready ?? false),\n totalSpeakers: Number(data.total_speakers ?? data.speakers_loaded ?? 0),\n languages,\n voiceCloningAvailable: Boolean(data.voice_cloning_available ?? false),\n speakerProjectionLoaded: Boolean(data.speaker_projection_loaded ?? false),\n };\n}\n\n/** An available TTS model. */\nexport interface Model {\n id: string;\n object: string;\n ownedBy: string;\n}\n\nexport function modelFromDict(data: Record<string, unknown>): Model {\n return {\n id: String(data.id ?? \"\"),\n object: String(data.object ?? \"model\"),\n ownedBy: String(data.owned_by ?? \"9jalingo\"),\n };\n}\n\n/** List of available models. */\nexport interface ModelList {\n models: Model[];\n object: string;\n [Symbol.iterator](): Iterator<Model>;\n length: number;\n}\n\nexport function modelListFromDict(data: Record<string, unknown>): ModelList {\n const raw = (data.data as Record<string, unknown>[] | undefined) ?? [];\n const models = raw.map(modelFromDict);\n return {\n models,\n object: String(data.object ?? \"list\"),\n get length() {\n return models.length;\n },\n [Symbol.iterator]() {\n return models[Symbol.iterator]();\n },\n };\n}\n\n/** Root API information returned by GET /. */\nexport interface APIInfo {\n name: string;\n version: string;\n description: string;\n endpoints: Record<string, string>;\n}\n\nexport function apiInfoFromDict(data: Record<string, unknown>): APIInfo {\n return {\n name: String(data.name ?? \"\"),\n version: String(data.version ?? \"\"),\n description: String(data.description ?? \"\"),\n endpoints: (data.endpoints as Record<string, string> | undefined) ?? {},\n };\n}\n\n/** Service metadata returned by GET /v1. */\nexport interface ServiceInfo {\n object: string;\n name: string;\n modelsUrl: string;\n speechUrl: string;\n speechStreamUrl: string;\n}\n\nexport function serviceInfoFromDict(data: Record<string, unknown>): ServiceInfo {\n return {\n object: String(data.object ?? \"service\"),\n name: String(data.name ?? \"\"),\n modelsUrl: String(data.models_url ?? \"\"),\n speechUrl: String(data.speech_url ?? \"\"),\n speechStreamUrl: String(data.speech_stream_url ?? \"\"),\n };\n}\n\nexport type ResponseFormat =\n | \"wav\"\n | \"pcm\"\n | \"flac\"\n | \"aac\"\n | \"ogg\"\n | \"mp3\"\n | \"alac\";\n","const LANG_ALIASES: Record<string, string> = {\n yo: \"yo\",\n yor: \"yo\",\n yoruba: \"yo\",\n ig: \"ig\",\n ibo: \"ig\",\n igbo: \"ig\",\n ha: \"ha\",\n hau: \"ha\",\n hausa: \"ha\",\n pcm: \"pcm\",\n pidgin: \"pcm\",\n};\n\nexport function normalizeLang(code: string): string | null {\n return LANG_ALIASES[code.trim().toLowerCase()] ?? null;\n}\n\n/**\n * Resolve speech API fields: voice/speaker + lang/language.\n * Returns [speakerId, langCode]. Bare language codes must be passed via lang/language.\n */\nexport function resolveTtsVoiceAndLang(options: {\n voice?: string | null;\n speaker?: string | null;\n lang?: string | null;\n language?: string | null;\n}): [string | null, string | null] {\n let resolvedLang: string | null = null;\n\n if (options.lang != null) {\n resolvedLang = normalizeLang(options.lang);\n if (resolvedLang == null) {\n throw new Error(\n `Unsupported language '${options.lang}'. Use ha, ig, yo, or pcm.`,\n );\n }\n } else if (options.language != null) {\n resolvedLang = normalizeLang(options.language);\n if (resolvedLang == null) {\n throw new Error(\n `Unsupported language '${options.language}'. Use ha, ig, yo, or pcm.`,\n );\n }\n }\n\n // speaker takes precedence over voice\n const candidate =\n options.speaker != null ? options.speaker : options.voice;\n if (candidate == null || !String(candidate).trim()) {\n return [null, resolvedLang];\n }\n\n const resolved = String(candidate).trim();\n const normalized = resolved.toLowerCase();\n if (normalized in LANG_ALIASES) {\n const langCode = LANG_ALIASES[normalized];\n throw new Error(\n `'${resolved}' is a language code, not a speaker ID. ` +\n `Pass speaker/voice='ada_pcm' (or another speaker ID) and ` +\n `lang='${langCode}' for the language. ` +\n `Browse speakers with: client.tts.listSpeakers({ language: '${langCode}' })`,\n );\n }\n\n if (resolvedLang == null && resolved.includes(\"_\")) {\n const suffix = resolved.split(\"_\").pop()!;\n resolvedLang = normalizeLang(suffix);\n }\n\n return [resolved, resolvedLang];\n}\n\n/**\n * Resolve clone form fields.\n * voice may be a language code (\"pcm\") or a speaker ID with a language suffix.\n */\nexport function resolveCloneLangAndSpeaker(\n voice: string,\n options: { lang?: string | null; speaker?: string | null } = {},\n): [string, string | null] {\n let resolvedLang =\n options.lang != null ? normalizeLang(options.lang) : null;\n let resolvedSpeaker = options.speaker?.trim() || null;\n\n const voiceStr = (voice || \"\").trim();\n const voiceNorm = voiceStr.toLowerCase();\n\n if (voiceNorm in LANG_ALIASES) {\n if (resolvedLang == null) {\n resolvedLang = LANG_ALIASES[voiceNorm];\n }\n } else if (voiceStr.includes(\"_\")) {\n if (resolvedSpeaker == null) {\n resolvedSpeaker = voiceStr;\n }\n if (resolvedLang == null) {\n const suffix = voiceStr.split(\"_\").pop()!;\n resolvedLang = normalizeLang(suffix);\n }\n } else if (voiceStr && resolvedLang == null) {\n throw new Error(\n `'${voice}' is not a language code (ha/ig/yo/pcm) or a speaker ID ` +\n `with a language suffix (e.g. 'daniel_pcm'). ` +\n `Pass voice='pcm' or lang='pcm'.`,\n );\n }\n\n if (!resolvedLang) {\n throw new Error(\n \"Clone requires a language. Pass voice='pcm' (or 'ha'/'ig'/'yo'), \" +\n \"lang='pcm', or a speaker ID ending in _pcm/_ha/_ig/_yo.\",\n );\n }\n\n return [resolvedLang, resolvedSpeaker];\n}\n","/**\n * 9jaLingo Node.js SDK\n *\n * Official SDK for the 9jaLingo API — Nigerian language Text-to-Speech.\n *\n * @example\n * ```ts\n * import { NaijaLingo } from \"naijalingo\";\n *\n * const client = new NaijaLingo(); // uses NAIJALINGO_API_KEY\n * const audio = await client.tts.generate(\"Bawo ni!\", {\n * voice: \"adeola_yo\",\n * lang: \"yo\",\n * });\n * await audio.save(\"greeting.wav\");\n * ```\n */\n\nimport { BaseClient, type ClientOptions } from \"./client.js\";\nimport { TTS } from \"./tts.js\";\nimport {\n apiInfoFromDict,\n modelListFromDict,\n serviceInfoFromDict,\n type APIInfo,\n type ModelList,\n type ServiceInfo,\n} from \"./types.js\";\n\nexport const VERSION = \"0.1.0\";\n\nexport {\n AuthenticationError,\n ConnectionError,\n NaijaLingoError,\n NotFoundError,\n RateLimitError,\n ServerError,\n} from \"./errors.js\";\n\nexport {\n AudioResponse,\n AudioStream,\n TTS,\n type CloneOptions,\n type GenerateOptions,\n type ListSpeakersOptions,\n type StreamOptions,\n} from \"./tts.js\";\n\nexport type {\n APIInfo,\n HealthStatus,\n Language,\n LanguageList,\n Model,\n ModelList,\n ResponseFormat,\n ServiceInfo,\n Speaker,\n SpeakerList,\n} from \"./types.js\";\n\nexport type { ClientOptions };\n\nexport class NaijaLingo {\n private readonly _client: BaseClient;\n readonly tts: TTS;\n\n constructor(options: ClientOptions = {}) {\n this._client = new BaseClient(options);\n this.tts = new TTS(this._client);\n }\n\n /** List available TTS models. GET /v1/models */\n async listModels(): Promise<ModelList> {\n const data = await this._client.getJson(\"/v1/models\");\n return modelListFromDict(data);\n }\n\n /** Root API information. GET / */\n async apiInfo(): Promise<APIInfo> {\n const data = await this._client.getJson(\"/\");\n return apiInfoFromDict(data);\n }\n\n /** v1 service metadata. GET /v1 */\n async serviceInfo(): Promise<ServiceInfo> {\n const data = await this._client.getJson(\"/v1\");\n return serviceInfoFromDict(data);\n }\n}\n"],"mappings":"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","names":["bytes"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/client.ts","../src/tts.ts","../src/types.ts","../src/voice.ts","../src/index.ts"],"sourcesContent":["/** Base exception for all 9jaLingo SDK errors. */\nexport class NaijaLingoError extends Error {\n readonly statusCode?: number;\n readonly response?: unknown;\n\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message);\n this.name = \"NaijaLingoError\";\n this.statusCode = statusCode;\n this.response = response;\n }\n}\n\n/** Raised when the API key is missing or invalid. */\nexport class AuthenticationError extends NaijaLingoError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"AuthenticationError\";\n }\n}\n\n/** Raised when rate limit is exceeded. */\nexport class RateLimitError extends NaijaLingoError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"RateLimitError\";\n }\n}\n\n/** Raised when a requested resource is not found. */\nexport class NotFoundError extends NaijaLingoError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"NotFoundError\";\n }\n}\n\n/** Raised when the API returns a 5xx error. */\nexport class ServerError extends NaijaLingoError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"ServerError\";\n }\n}\n\n/** Raised when the inference GPU is waking from scale-to-zero. */\nexport class InferenceCapacityError extends ServerError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"InferenceCapacityError\";\n }\n}\n\n/** Raised when unable to connect to the API. */\nexport class ConnectionError extends NaijaLingoError {\n constructor(message: string, statusCode?: number, response?: unknown) {\n super(message, statusCode, response);\n this.name = \"ConnectionError\";\n }\n}\n","import {\n AuthenticationError,\n ConnectionError,\n InferenceCapacityError,\n NaijaLingoError,\n NotFoundError,\n RateLimitError,\n ServerError,\n} from \"./errors.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.9jalingo.org\";\nconst DEFAULT_TIMEOUT_MS = 300_000;\n\nexport interface ClientOptions {\n apiKey?: string;\n baseUrl?: string;\n /** Request timeout in milliseconds (default 300000). */\n timeout?: number;\n}\n\nexport class BaseClient {\n readonly apiKey: string;\n readonly baseUrl: string;\n readonly timeout: number;\n private readonly defaultHeaders: Record<string, string>;\n\n constructor(options: ClientOptions = {}) {\n this.apiKey =\n options.apiKey ?? process.env.NAIJALINGO_API_KEY ?? \"\";\n const base =\n options.baseUrl ??\n process.env.NAIJALINGO_BASE_URL ??\n DEFAULT_BASE_URL;\n this.baseUrl = base.replace(/\\/+$/, \"\");\n this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;\n\n this.defaultHeaders = {\n \"User-Agent\": \"naijalingo-js/0.1.1\",\n };\n if (this.apiKey) {\n this.defaultHeaders[\"X-API-Key\"] = this.apiKey;\n }\n }\n\n private async request(\n method: string,\n path: string,\n init: RequestInit & { timeoutMs?: number } = {},\n ): Promise<Response> {\n const url = `${this.baseUrl}${path.startsWith(\"/\") ? path : `/${path}`}`;\n const timeoutMs = init.timeoutMs ?? this.timeout;\n let lastError: unknown;\n\n for (let attempt = 0; attempt < 3; attempt++) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const response = await fetch(url, {\n ...init,\n method,\n headers: {\n ...this.defaultHeaders,\n ...(init.headers as Record<string, string> | undefined),\n },\n signal: controller.signal,\n });\n clearTimeout(timer);\n\n if (response.ok) {\n return response;\n }\n await this.raiseForStatus(response);\n // unreachable\n return response;\n } catch (err) {\n clearTimeout(timer);\n if (err instanceof NaijaLingoError) {\n throw err;\n }\n lastError = err;\n const isAbort =\n err instanceof Error &&\n (err.name === \"AbortError\" || err.name === \"TimeoutError\");\n // Only retry connect-style failures, not aborts from long reads\n if (isAbort) {\n throw new ConnectionError(\n `Request timed out after ${timeoutMs}ms: ${String(err)}`,\n );\n }\n if (attempt < 2) {\n await sleep(1500);\n continue;\n }\n }\n }\n\n throw new ConnectionError(\n `Unable to connect to ${this.baseUrl}: ${String(lastError)}`,\n );\n }\n\n private async raiseForStatus(response: Response): Promise<never> {\n const status = response.status;\n let detail: string;\n let body: unknown;\n try {\n body = await response.json();\n detail =\n typeof body === \"object\" &&\n body !== null &&\n \"detail\" in body\n ? String((body as { detail: unknown }).detail)\n : JSON.stringify(body);\n } catch {\n detail = await response.text();\n }\n\n const normalizedDetail = detail.toLowerCase();\n if (status === 503 && (\n normalizedDetail.includes(\"inference capacity\")\n || normalizedDetail.includes(\"inference component has no capacity\")\n || normalizedDetail.includes(\"capacity is starting\")\n )) {\n throw new InferenceCapacityError(detail, status, body);\n }\n if (status === 401 || status === 403) {\n throw new AuthenticationError(detail, status, body);\n }\n if (status === 404) {\n throw new NotFoundError(detail, status, body);\n }\n if (status === 429) {\n throw new RateLimitError(detail, status, body);\n }\n if (status >= 500) {\n throw new ServerError(detail, status, body);\n }\n throw new NaijaLingoError(detail, status, body);\n }\n\n async getJson(\n path: string,\n params?: Record<string, string | undefined | null>,\n ): Promise<Record<string, unknown>> {\n let url = path;\n if (params) {\n const qs = new URLSearchParams();\n for (const [k, v] of Object.entries(params)) {\n if (v != null) qs.set(k, v);\n }\n const s = qs.toString();\n if (s) url = `${path}?${s}`;\n }\n const resp = await this.request(\"GET\", url);\n return (await resp.json()) as Record<string, unknown>;\n }\n\n async postBytes(\n path: string,\n body: Record<string, unknown>,\n ): Promise<Uint8Array> {\n const resp = await this.request(\"POST\", path, {\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n return new Uint8Array(await resp.arrayBuffer());\n }\n\n async *postStream(\n path: string,\n body: Record<string, unknown>,\n ): AsyncGenerator<Uint8Array, void, unknown> {\n let lastError: unknown;\n for (let attempt = 0; attempt < 3; attempt++) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeout);\n try {\n const response = await fetch(\n `${this.baseUrl}${path.startsWith(\"/\") ? path : `/${path}`}`,\n {\n method: \"POST\",\n headers: {\n ...this.defaultHeaders,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n },\n );\n clearTimeout(timer);\n\n if (!response.ok) {\n await this.raiseForStatus(response);\n }\n if (!response.body) {\n throw new ConnectionError(\"No response body for stream\");\n }\n\n const reader = response.body.getReader();\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value && value.length > 0) {\n yield value;\n }\n }\n } finally {\n reader.releaseLock();\n }\n return;\n } catch (err) {\n clearTimeout(timer);\n if (err instanceof NaijaLingoError) throw err;\n lastError = err;\n const isAbort =\n err instanceof Error &&\n (err.name === \"AbortError\" || err.name === \"TimeoutError\");\n if (isAbort) {\n throw new ConnectionError(`Request timed out: ${String(err)}`);\n }\n if (attempt < 2) {\n await sleep(1500);\n continue;\n }\n }\n }\n throw new ConnectionError(\n `Unable to connect to ${this.baseUrl}: ${String(lastError)}`,\n );\n }\n\n async postMultipart(\n path: string,\n form: FormData,\n timeoutMs?: number,\n ): Promise<Uint8Array> {\n const resp = await this.request(\"POST\", path, {\n body: form,\n timeoutMs: timeoutMs ?? Math.max(this.timeout, 600_000),\n // Let fetch set multipart boundary — do not set Content-Type\n });\n return new Uint8Array(await resp.arrayBuffer());\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { basename, dirname } from \"node:path\";\nimport { readFileSync } from \"node:fs\";\nimport { BaseClient } from \"./client.js\";\nimport {\n type HealthStatus,\n type LanguageList,\n type ResponseFormat,\n type Speaker,\n type SpeakerList,\n healthStatusFromDict,\n languageListFromDict,\n speakerFromDict,\n speakerListFromDict,\n} from \"./types.js\";\nimport {\n resolveCloneLangAndSpeaker,\n resolveTtsVoiceAndLang,\n} from \"./voice.js\";\n\nconst DEFAULT_MODEL_NAME = \"9jalingo-tts-1\";\n\nexport type GenerateOptions = {\n voice?: string;\n speaker?: string;\n lang?: string;\n language?: string;\n modelName?: string;\n speakerEmbedding?: number[];\n responseFormat?: ResponseFormat;\n temperature?: number;\n topP?: number;\n repetitionPenalty?: number;\n enableLongForm?: boolean;\n maxChunkDuration?: number;\n silenceDuration?: number;\n};\n\nexport type StreamOptions = Omit<\n GenerateOptions,\n \"modelName\" | \"responseFormat\"\n>;\n\nexport type CloneOptions = {\n voice?: string;\n lang?: string;\n speaker?: string;\n modelName?: string;\n temperature?: number;\n topP?: number;\n repetitionPenalty?: number;\n responseFormat?: ResponseFormat;\n};\n\nexport type ListSpeakersOptions = {\n language?: string;\n gender?: string;\n domain?: string;\n};\n\n/** Audio data returned from a generation request. */\nexport class AudioResponse {\n readonly content: Uint8Array;\n readonly mediaType: string;\n\n constructor(content: Uint8Array, mediaType = \"audio/wav\") {\n this.content = content;\n this.mediaType = mediaType;\n }\n\n /** Write the audio to a file. */\n async save(path: string): Promise<string> {\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, this.content);\n return path;\n }\n\n get length(): number {\n return this.content.length;\n }\n\n toString(): string {\n return `AudioResponse(${this.content.length} bytes, ${this.mediaType})`;\n }\n}\n\n/** Streaming audio response — yields byte chunks as they arrive. */\nexport class AudioStream implements AsyncIterable<Uint8Array> {\n private readonly chunks: AsyncIterable<Uint8Array>;\n private collected: Uint8Array | null = null;\n\n constructor(chunks: AsyncIterable<Uint8Array>) {\n this.chunks = chunks;\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<Uint8Array> {\n for await (const chunk of this.chunks) {\n yield chunk;\n }\n }\n\n /** Consume the entire stream and return an AudioResponse. */\n async collect(): Promise<AudioResponse> {\n if (this.collected == null) {\n const parts: Uint8Array[] = [];\n let total = 0;\n for await (const chunk of this.chunks) {\n parts.push(chunk);\n total += chunk.length;\n }\n const out = new Uint8Array(total);\n let offset = 0;\n for (const part of parts) {\n out.set(part, offset);\n offset += part.length;\n }\n this.collected = out;\n }\n return new AudioResponse(this.collected, \"audio/wav\");\n }\n}\n\nexport class TTS {\n private readonly client: BaseClient;\n\n constructor(client: BaseClient) {\n this.client = client;\n }\n\n /** Generate speech from text. */\n async generate(\n text: string,\n options: GenerateOptions = {},\n ): Promise<AudioResponse> {\n let [resolvedVoice, resolvedLang] = resolveTtsVoiceAndLang(options);\n if (resolvedVoice == null && options.speakerEmbedding == null) {\n resolvedVoice = \"blessing_pcm\";\n }\n const responseFormat = options.responseFormat ?? \"wav\";\n const body = buildBody({\n input: text,\n voice: resolvedVoice,\n lang: resolvedLang,\n model: options.modelName ?? DEFAULT_MODEL_NAME,\n speaker_embedding: options.speakerEmbedding,\n response_format: responseFormat,\n temperature: options.temperature,\n top_p: options.topP,\n repetition_penalty: options.repetitionPenalty,\n enable_long_form: options.enableLongForm ?? true,\n max_chunk_duration: options.maxChunkDuration,\n silence_duration: options.silenceDuration,\n });\n const content = await this.client.postBytes(\"/v1/audio/speech\", body);\n const mediaType = MEDIA_TYPES[responseFormat] ?? \"application/octet-stream\";\n return new AudioResponse(content, mediaType);\n }\n\n /** Stream speech generation — audio arrives as it's produced. */\n stream(text: string, options: StreamOptions = {}): AudioStream {\n let [resolvedVoice, resolvedLang] = resolveTtsVoiceAndLang(options);\n if (resolvedVoice == null && options.speakerEmbedding == null) {\n resolvedVoice = \"blessing_pcm\";\n }\n const body = buildBody({\n input: text,\n voice: resolvedVoice,\n lang: resolvedLang,\n speaker_embedding: options.speakerEmbedding,\n response_format: \"wav\",\n temperature: options.temperature,\n top_p: options.topP,\n repetition_penalty: options.repetitionPenalty,\n enable_long_form: options.enableLongForm ?? true,\n max_chunk_duration: options.maxChunkDuration,\n silence_duration: options.silenceDuration,\n });\n return new AudioStream(this.client.postStream(\"/v1/audio/speech/stream\", body));\n }\n\n /**\n * Generate speech using a cloned voice from a reference audio file.\n * `audioFile` may be a filesystem path, Buffer, Uint8Array, Blob, or File.\n */\n async clone(\n text: string,\n audioFile: string | Buffer | Uint8Array | Blob,\n options: CloneOptions = {},\n ): Promise<AudioResponse> {\n const voice = options.voice ?? \"pcm\";\n const [resolvedLang, resolvedSpeaker] = resolveCloneLangAndSpeaker(\n voice,\n { lang: options.lang, speaker: options.speaker },\n );\n const responseFormat = options.responseFormat ?? \"wav\";\n\n const form = new FormData();\n form.append(\"text\", text);\n form.append(\"lang\", resolvedLang);\n form.append(\"model_name\", options.modelName ?? DEFAULT_MODEL_NAME);\n form.append(\"response_format\", responseFormat);\n if (resolvedSpeaker) {\n form.append(\"voice\", resolvedSpeaker);\n }\n if (options.temperature != null) {\n form.append(\"temperature\", String(options.temperature));\n }\n if (options.topP != null) {\n form.append(\"top_p\", String(options.topP));\n }\n if (options.repetitionPenalty != null) {\n form.append(\"repetition_penalty\", String(options.repetitionPenalty));\n }\n\n const { blob, filename } = await toAudioBlob(audioFile);\n form.append(\"audio\", blob, filename);\n\n const content = await this.client.postMultipart(\"/v1/audio/clone\", form);\n const mediaType = MEDIA_TYPES[responseFormat] ?? \"application/octet-stream\";\n return new AudioResponse(content, mediaType);\n }\n\n async listSpeakers(\n options: ListSpeakersOptions = {},\n ): Promise<SpeakerList> {\n const data = await this.client.getJson(\"/v1/speakers\", {\n language: options.language,\n gender: options.gender,\n domain: options.domain,\n });\n return speakerListFromDict(data);\n }\n\n async getSpeaker(speakerId: string): Promise<Speaker> {\n const data = await this.client.getJson(`/v1/speakers/${speakerId}`);\n return speakerFromDict(data);\n }\n\n async listLanguages(): Promise<LanguageList> {\n const data = await this.client.getJson(\"/v1/languages\");\n return languageListFromDict(data);\n }\n\n async health(): Promise<HealthStatus> {\n const data = await this.client.getJson(\"/v1/health\");\n return healthStatusFromDict(data);\n }\n}\n\nconst MEDIA_TYPES: Record<string, string> = {\n wav: \"audio/wav\",\n pcm: \"application/octet-stream\",\n flac: \"audio/flac\",\n aac: \"audio/aac\",\n ogg: \"audio/ogg\",\n mp3: \"audio/mpeg\",\n alac: \"audio/alac\",\n};\n\nfunction buildBody(\n kwargs: Record<string, unknown>,\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(kwargs)) {\n if (v !== undefined && v !== null) out[k] = v;\n }\n return out;\n}\n\nasync function toAudioBlob(\n audioFile: string | Buffer | Uint8Array | Blob,\n): Promise<{ blob: Blob; filename: string }> {\n if (typeof audioFile === \"string\") {\n const bytes = readFileSync(audioFile);\n const filename = basename(audioFile);\n const mime = guessMime(filename);\n return {\n blob: new Blob([bytes], { type: mime }),\n filename,\n };\n }\n if (audioFile instanceof Blob) {\n return {\n blob: audioFile,\n filename: \"audio.wav\",\n };\n }\n // Buffer | Uint8Array\n const bytes =\n audioFile instanceof Uint8Array\n ? audioFile\n : new Uint8Array(audioFile);\n return {\n blob: new Blob([bytes], { type: \"application/octet-stream\" }),\n filename: \"audio.wav\",\n };\n}\n\nfunction guessMime(filename: string): string {\n const lower = filename.toLowerCase();\n if (lower.endsWith(\".wav\")) return \"audio/wav\";\n if (lower.endsWith(\".mp3\")) return \"audio/mpeg\";\n if (lower.endsWith(\".flac\")) return \"audio/flac\";\n if (lower.endsWith(\".ogg\")) return \"audio/ogg\";\n if (lower.endsWith(\".aac\") || lower.endsWith(\".m4a\")) return \"audio/aac\";\n return \"application/octet-stream\";\n}\n","/** A speaker voice identity. */\nexport interface Speaker {\n id: string;\n name: string;\n language: string;\n gender?: string | null;\n domain?: string | null;\n}\n\nexport function speakerFromDict(data: Record<string, unknown>): Speaker {\n return {\n id: String(data.id ?? data.speaker_id ?? \"\"),\n name: String(data.name ?? data.id ?? \"\"),\n language: String(data.language ?? \"\"),\n gender: (data.gender as string | null | undefined) ?? null,\n domain: (data.domain as string | null | undefined) ?? null,\n };\n}\n\n/** List of speakers with metadata. */\nexport interface SpeakerList {\n speakers: Speaker[];\n total: number;\n byLanguage: Record<string, number>;\n [Symbol.iterator](): Iterator<Speaker>;\n length: number;\n}\n\nexport function speakerListFromDict(data: Record<string, unknown>): SpeakerList {\n const raw = (data.speakers as Record<string, unknown>[] | undefined) ?? [];\n const speakers = raw.map(speakerFromDict);\n const total = typeof data.total === \"number\" ? data.total : speakers.length;\n const byLanguage =\n (data.by_language as Record<string, number> | undefined) ?? {};\n return {\n speakers,\n total,\n byLanguage,\n get length() {\n return total;\n },\n [Symbol.iterator]() {\n return speakers[Symbol.iterator]();\n },\n };\n}\n\n/** A supported language. */\nexport interface Language {\n code: string;\n name: string;\n speakerCount: number;\n}\n\nexport function languageFromDict(data: Record<string, unknown>): Language {\n return {\n code: String(data.code ?? \"\"),\n name: String(data.name ?? \"\"),\n speakerCount: Number(data.speaker_count ?? 0),\n };\n}\n\n/** List of supported languages and domains. */\nexport interface LanguageList {\n languages: Language[];\n domains: string[];\n}\n\nexport function languageListFromDict(data: Record<string, unknown>): LanguageList {\n const rawLangs = data.languages;\n let languages: Language[];\n\n if (rawLangs && typeof rawLangs === \"object\" && !Array.isArray(rawLangs)) {\n languages = Object.entries(rawLangs as Record<string, unknown>).map(\n ([code, value]) => {\n if (value && typeof value === \"object\") {\n const v = value as Record<string, unknown>;\n return {\n code,\n name: String(v.name ?? code),\n speakerCount: Number(v.speaker_count ?? 0),\n };\n }\n return { code, name: String(value), speakerCount: 0 };\n },\n );\n } else {\n const arr = (rawLangs as Record<string, unknown>[] | undefined) ?? [];\n languages = arr.map(languageFromDict);\n }\n\n return {\n languages,\n domains: (data.domains as string[] | undefined) ?? [],\n };\n}\n\n/** API health check result. */\nexport interface HealthStatus {\n status: string;\n engineReady: boolean;\n codecReady: boolean;\n totalSpeakers: number;\n languages: string[];\n voiceCloningAvailable: boolean;\n speakerProjectionLoaded: boolean;\n}\n\nexport function healthStatusFromDict(data: Record<string, unknown>): HealthStatus {\n const supported = data.supported_languages;\n let languages: string[] = [];\n if (Array.isArray(data.languages)) {\n languages = data.languages as string[];\n } else if (supported && typeof supported === \"object\") {\n languages = Object.keys(supported as Record<string, unknown>);\n }\n\n return {\n status: String(data.status ?? \"unknown\"),\n engineReady: Boolean(data.engine_ready ?? data.tts_initialized ?? false),\n codecReady: Boolean(data.codec_ready ?? false),\n totalSpeakers: Number(data.total_speakers ?? data.speakers_loaded ?? 0),\n languages,\n voiceCloningAvailable: Boolean(data.voice_cloning_available ?? false),\n speakerProjectionLoaded: Boolean(data.speaker_projection_loaded ?? false),\n };\n}\n\n/** An available TTS model. */\nexport interface Model {\n id: string;\n object: string;\n ownedBy: string;\n}\n\nexport function modelFromDict(data: Record<string, unknown>): Model {\n return {\n id: String(data.id ?? \"\"),\n object: String(data.object ?? \"model\"),\n ownedBy: String(data.owned_by ?? \"9jalingo\"),\n };\n}\n\n/** List of available models. */\nexport interface ModelList {\n models: Model[];\n object: string;\n [Symbol.iterator](): Iterator<Model>;\n length: number;\n}\n\nexport function modelListFromDict(data: Record<string, unknown>): ModelList {\n const raw = (data.data as Record<string, unknown>[] | undefined) ?? [];\n const models = raw.map(modelFromDict);\n return {\n models,\n object: String(data.object ?? \"list\"),\n get length() {\n return models.length;\n },\n [Symbol.iterator]() {\n return models[Symbol.iterator]();\n },\n };\n}\n\n/** Root API information returned by GET /. */\nexport interface APIInfo {\n name: string;\n version: string;\n description: string;\n endpoints: Record<string, string>;\n}\n\nexport function apiInfoFromDict(data: Record<string, unknown>): APIInfo {\n return {\n name: String(data.name ?? \"\"),\n version: String(data.version ?? \"\"),\n description: String(data.description ?? \"\"),\n endpoints: (data.endpoints as Record<string, string> | undefined) ?? {},\n };\n}\n\n/** Service metadata returned by GET /v1. */\nexport interface ServiceInfo {\n object: string;\n name: string;\n modelsUrl: string;\n speechUrl: string;\n speechStreamUrl: string;\n}\n\nexport function serviceInfoFromDict(data: Record<string, unknown>): ServiceInfo {\n return {\n object: String(data.object ?? \"service\"),\n name: String(data.name ?? \"\"),\n modelsUrl: String(data.models_url ?? \"\"),\n speechUrl: String(data.speech_url ?? \"\"),\n speechStreamUrl: String(data.speech_stream_url ?? \"\"),\n };\n}\n\nexport type ResponseFormat =\n | \"wav\"\n | \"pcm\"\n | \"flac\"\n | \"aac\"\n | \"ogg\"\n | \"mp3\"\n | \"alac\";\n","const LANG_ALIASES: Record<string, string> = {\n yo: \"yo\",\n yor: \"yo\",\n yoruba: \"yo\",\n ig: \"ig\",\n ibo: \"ig\",\n igbo: \"ig\",\n ha: \"ha\",\n hau: \"ha\",\n hausa: \"ha\",\n pcm: \"pcm\",\n pidgin: \"pcm\",\n};\n\nexport function normalizeLang(code: string): string | null {\n return LANG_ALIASES[code.trim().toLowerCase()] ?? null;\n}\n\n/**\n * Resolve speech API fields: voice/speaker + lang/language.\n * Returns [speakerId, langCode]. Bare language codes must be passed via lang/language.\n */\nexport function resolveTtsVoiceAndLang(options: {\n voice?: string | null;\n speaker?: string | null;\n lang?: string | null;\n language?: string | null;\n}): [string | null, string | null] {\n let resolvedLang: string | null = null;\n\n if (options.lang != null) {\n resolvedLang = normalizeLang(options.lang);\n if (resolvedLang == null) {\n throw new Error(\n `Unsupported language '${options.lang}'. Use ha, ig, yo, or pcm.`,\n );\n }\n } else if (options.language != null) {\n resolvedLang = normalizeLang(options.language);\n if (resolvedLang == null) {\n throw new Error(\n `Unsupported language '${options.language}'. Use ha, ig, yo, or pcm.`,\n );\n }\n }\n\n // speaker takes precedence over voice\n const candidate =\n options.speaker != null ? options.speaker : options.voice;\n if (candidate == null || !String(candidate).trim()) {\n return [null, resolvedLang];\n }\n\n const resolved = String(candidate).trim();\n const normalized = resolved.toLowerCase();\n if (normalized in LANG_ALIASES) {\n const langCode = LANG_ALIASES[normalized];\n throw new Error(\n `'${resolved}' is a language code, not a speaker ID. ` +\n `Pass speaker/voice='ada_pcm' (or another speaker ID) and ` +\n `lang='${langCode}' for the language. ` +\n `Browse speakers with: client.tts.listSpeakers({ language: '${langCode}' })`,\n );\n }\n\n if (resolvedLang == null && resolved.includes(\"_\")) {\n const suffix = resolved.split(\"_\").pop()!;\n resolvedLang = normalizeLang(suffix);\n }\n\n return [resolved, resolvedLang];\n}\n\n/**\n * Resolve clone form fields.\n * voice may be a language code (\"pcm\") or a speaker ID with a language suffix.\n */\nexport function resolveCloneLangAndSpeaker(\n voice: string,\n options: { lang?: string | null; speaker?: string | null } = {},\n): [string, string | null] {\n let resolvedLang =\n options.lang != null ? normalizeLang(options.lang) : null;\n let resolvedSpeaker = options.speaker?.trim() || null;\n\n const voiceStr = (voice || \"\").trim();\n const voiceNorm = voiceStr.toLowerCase();\n\n if (voiceNorm in LANG_ALIASES) {\n if (resolvedLang == null) {\n resolvedLang = LANG_ALIASES[voiceNorm];\n }\n } else if (voiceStr.includes(\"_\")) {\n if (resolvedSpeaker == null) {\n resolvedSpeaker = voiceStr;\n }\n if (resolvedLang == null) {\n const suffix = voiceStr.split(\"_\").pop()!;\n resolvedLang = normalizeLang(suffix);\n }\n } else if (voiceStr && resolvedLang == null) {\n throw new Error(\n `'${voice}' is not a language code (ha/ig/yo/pcm) or a speaker ID ` +\n `with a language suffix (e.g. 'daniel_pcm'). ` +\n `Pass voice='pcm' or lang='pcm'.`,\n );\n }\n\n if (!resolvedLang) {\n throw new Error(\n \"Clone requires a language. Pass voice='pcm' (or 'ha'/'ig'/'yo'), \" +\n \"lang='pcm', or a speaker ID ending in _pcm/_ha/_ig/_yo.\",\n );\n }\n\n return [resolvedLang, resolvedSpeaker];\n}\n","/**\n * 9jaLingo Node.js SDK\n *\n * Official SDK for the 9jaLingo API — Nigerian language Text-to-Speech.\n *\n * @example\n * ```ts\n * import { NaijaLingo } from \"naijalingo\";\n *\n * const client = new NaijaLingo(); // uses NAIJALINGO_API_KEY\n * const audio = await client.tts.generate(\"Bawo ni!\", {\n * voice: \"adeola_yo\",\n * lang: \"yo\",\n * });\n * await audio.save(\"greeting.wav\");\n * ```\n */\n\nimport { BaseClient, type ClientOptions } from \"./client.js\";\nimport { TTS } from \"./tts.js\";\nimport {\n apiInfoFromDict,\n modelListFromDict,\n serviceInfoFromDict,\n type APIInfo,\n type ModelList,\n type ServiceInfo,\n} from \"./types.js\";\n\nexport const VERSION = \"0.1.1\";\n\nexport {\n AuthenticationError,\n ConnectionError,\n InferenceCapacityError,\n NaijaLingoError,\n NotFoundError,\n RateLimitError,\n ServerError,\n} from \"./errors.js\";\n\nexport {\n AudioResponse,\n AudioStream,\n TTS,\n type CloneOptions,\n type GenerateOptions,\n type ListSpeakersOptions,\n type StreamOptions,\n} from \"./tts.js\";\n\nexport type {\n APIInfo,\n HealthStatus,\n Language,\n LanguageList,\n Model,\n ModelList,\n ResponseFormat,\n ServiceInfo,\n Speaker,\n SpeakerList,\n} from \"./types.js\";\n\nexport type { ClientOptions };\n\nexport class NaijaLingo {\n private readonly _client: BaseClient;\n readonly tts: TTS;\n\n constructor(options: ClientOptions = {}) {\n this._client = new BaseClient(options);\n this.tts = new TTS(this._client);\n }\n\n /** List available TTS models. GET /v1/models */\n async listModels(): Promise<ModelList> {\n const data = await this._client.getJson(\"/v1/models\");\n return modelListFromDict(data);\n }\n\n /** Root API information. GET / */\n async apiInfo(): Promise<APIInfo> {\n const data = await this._client.getJson(\"/\");\n return apiInfoFromDict(data);\n }\n\n /** v1 service metadata. GET /v1 */\n async serviceInfo(): Promise<ServiceInfo> {\n const data = await this._client.getJson(\"/v1\");\n return serviceInfoFromDict(data);\n }\n}\n"],"mappings":"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","names":["bytes"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "naijalingo",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Official Node.js SDK for 9jaLingo — AI-powered Text-to-Speech and Voice Cloning for Nigerian languages including Hausa, Igbo, Yoruba, and Nigerian Pidgin with 240+ speaker voices.",
5
5
  "license": "MIT",
6
6
  "author": "9jaLingo <support@9jalingo.org>",