kugelaudio 0.4.0 → 0.5.0

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.js CHANGED
@@ -22,10 +22,13 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  AuthenticationError: () => AuthenticationError,
24
24
  ConnectionError: () => ConnectionError,
25
+ DictionariesResource: () => DictionariesResource,
26
+ DictionaryEntriesResource: () => DictionaryEntriesResource,
25
27
  ErrorCodes: () => ErrorCodes,
26
28
  InsufficientCreditsError: () => InsufficientCreditsError,
27
29
  KugelAudio: () => KugelAudio,
28
30
  KugelAudioError: () => KugelAudioError,
31
+ NotFoundError: () => NotFoundError,
29
32
  RateLimitError: () => RateLimitError,
30
33
  ValidationError: () => ValidationError,
31
34
  WsCloseCodes: () => WsCloseCodes,
@@ -40,6 +43,187 @@ __export(index_exports, {
40
43
  });
41
44
  module.exports = __toCommonJS(index_exports);
42
45
 
46
+ // src/dictionaries.ts
47
+ function mapDictionary(raw) {
48
+ return {
49
+ id: raw.id,
50
+ projectId: raw.project_id,
51
+ name: raw.name,
52
+ description: raw.description ?? void 0,
53
+ language: raw.language ?? void 0,
54
+ isActive: raw.is_active ?? true,
55
+ createdAt: raw.created_at,
56
+ updatedAt: raw.updated_at
57
+ };
58
+ }
59
+ function mapEntry(raw) {
60
+ return {
61
+ id: raw.id,
62
+ dictionaryId: raw.dictionary_id,
63
+ word: raw.word,
64
+ replacement: raw.replacement,
65
+ ipa: raw.ipa ?? void 0,
66
+ caseSensitive: raw.case_sensitive ?? false,
67
+ createdAt: raw.created_at,
68
+ updatedAt: raw.updated_at
69
+ };
70
+ }
71
+ function entryPayload(input) {
72
+ const payload = {
73
+ word: input.word,
74
+ replacement: input.replacement
75
+ };
76
+ if (input.ipa !== void 0) payload.ipa = input.ipa;
77
+ if (input.caseSensitive !== void 0) {
78
+ payload.case_sensitive = input.caseSensitive;
79
+ }
80
+ return payload;
81
+ }
82
+ function buildPath(base, params) {
83
+ const search = new URLSearchParams();
84
+ for (const [key, val] of Object.entries(params)) {
85
+ if (val === void 0 || val === null) continue;
86
+ search.set(key, String(val));
87
+ }
88
+ const query = search.toString();
89
+ return query ? `${base}?${query}` : base;
90
+ }
91
+ var DictionaryEntriesResource = class {
92
+ constructor(client) {
93
+ this.client = client;
94
+ }
95
+ /** List entries with optional search + pagination. */
96
+ async list(dictionaryId, options) {
97
+ const path = buildPath(`/v1/dictionaries/${dictionaryId}/entries`, {
98
+ search: options?.search,
99
+ limit: options?.limit,
100
+ offset: options?.offset,
101
+ project_id: options?.projectId
102
+ });
103
+ const raw = await this.client.request("GET", path);
104
+ return {
105
+ entries: raw.entries.map(mapEntry),
106
+ total: raw.total,
107
+ limit: raw.limit,
108
+ offset: raw.offset
109
+ };
110
+ }
111
+ /** Add a single entry to a dictionary. */
112
+ async add(dictionaryId, entry, options) {
113
+ const path = buildPath(`/v1/dictionaries/${dictionaryId}/entries`, {
114
+ project_id: options?.projectId
115
+ });
116
+ const raw = await this.client.request(
117
+ "POST",
118
+ path,
119
+ entryPayload(entry)
120
+ );
121
+ return mapEntry(raw);
122
+ }
123
+ /** Update an existing entry. */
124
+ async update(dictionaryId, entryId, updates, options) {
125
+ const payload = {};
126
+ if (updates.word !== void 0) payload.word = updates.word;
127
+ if (updates.replacement !== void 0) payload.replacement = updates.replacement;
128
+ if (updates.ipa !== void 0) payload.ipa = updates.ipa;
129
+ if (updates.caseSensitive !== void 0) {
130
+ payload.case_sensitive = updates.caseSensitive;
131
+ }
132
+ const path = buildPath(`/v1/dictionaries/${dictionaryId}/entries/${entryId}`, {
133
+ project_id: options?.projectId
134
+ });
135
+ const raw = await this.client.request(
136
+ "PATCH",
137
+ path,
138
+ payload
139
+ );
140
+ return mapEntry(raw);
141
+ }
142
+ /** Delete a single entry. */
143
+ async delete(dictionaryId, entryId, options) {
144
+ const path = buildPath(`/v1/dictionaries/${dictionaryId}/entries/${entryId}`, {
145
+ project_id: options?.projectId
146
+ });
147
+ await this.client.request("DELETE", path);
148
+ }
149
+ /**
150
+ * Replace every entry in the dictionary atomically.
151
+ *
152
+ * Each item must have ``word`` and ``replacement``; existing entries
153
+ * whose ``word`` is not in the supplied list are deleted. Idempotent.
154
+ */
155
+ async replaceAll(dictionaryId, entries, options) {
156
+ const path = buildPath(`/v1/dictionaries/${dictionaryId}/entries`, {
157
+ project_id: options?.projectId
158
+ });
159
+ const raw = await this.client.request("PUT", path, {
160
+ entries: entries.map(entryPayload)
161
+ });
162
+ return raw;
163
+ }
164
+ };
165
+ var DictionariesResource = class {
166
+ constructor(client) {
167
+ this.client = client;
168
+ this.entries = new DictionaryEntriesResource(client);
169
+ }
170
+ /** List every dictionary in the caller's project. */
171
+ async list(options) {
172
+ const path = buildPath("/v1/dictionaries", {
173
+ project_id: options?.projectId
174
+ });
175
+ const raw = await this.client.request("GET", path);
176
+ return raw.dictionaries.map(mapDictionary);
177
+ }
178
+ /** Create a new dictionary scoped to the caller's project. */
179
+ async create(body, options) {
180
+ const path = buildPath("/v1/dictionaries", {
181
+ project_id: options?.projectId
182
+ });
183
+ const payload = { name: body.name };
184
+ if (body.description !== void 0) payload.description = body.description;
185
+ if (body.language !== void 0) payload.language = body.language;
186
+ const raw = await this.client.request(
187
+ "POST",
188
+ path,
189
+ payload
190
+ );
191
+ return mapDictionary(raw);
192
+ }
193
+ /** Fetch a single dictionary. */
194
+ async get(dictionaryId, options) {
195
+ const path = buildPath(`/v1/dictionaries/${dictionaryId}`, {
196
+ project_id: options?.projectId
197
+ });
198
+ const raw = await this.client.request("GET", path);
199
+ return mapDictionary(raw);
200
+ }
201
+ /** Update name / description / language / isActive. */
202
+ async update(dictionaryId, updates, options) {
203
+ const payload = {};
204
+ if (updates.name !== void 0) payload.name = updates.name;
205
+ if (updates.description !== void 0) payload.description = updates.description;
206
+ if (updates.language !== void 0) payload.language = updates.language;
207
+ if (updates.isActive !== void 0) payload.is_active = updates.isActive;
208
+ const path = buildPath(`/v1/dictionaries/${dictionaryId}`, {
209
+ project_id: options?.projectId
210
+ });
211
+ const raw = await this.client.request(
212
+ "PATCH",
213
+ path,
214
+ payload
215
+ );
216
+ return mapDictionary(raw);
217
+ }
218
+ /** Delete a dictionary (cascades to its entries). */
219
+ async delete(dictionaryId, options) {
220
+ const path = buildPath(`/v1/dictionaries/${dictionaryId}`, {
221
+ project_id: options?.projectId
222
+ });
223
+ await this.client.request("DELETE", path);
224
+ }
225
+ };
226
+
43
227
  // src/errors.ts
44
228
  var ErrorCodes = {
45
229
  UNAUTHORIZED: "UNAUTHORIZED",
@@ -112,6 +296,17 @@ var ConnectionError = class _ConnectionError extends KugelAudioError {
112
296
  Object.setPrototypeOf(this, _ConnectionError.prototype);
113
297
  }
114
298
  };
299
+ var NotFoundError = class _NotFoundError extends KugelAudioError {
300
+ constructor(message, options = {}) {
301
+ super(message ?? "Not found.", {
302
+ statusCode: 404,
303
+ errorCode: ErrorCodes.NOT_FOUND,
304
+ ...options
305
+ });
306
+ this.name = "NotFoundError";
307
+ Object.setPrototypeOf(this, _NotFoundError.prototype);
308
+ }
309
+ };
115
310
  function build(status, errorCode, message, opts = {}) {
116
311
  const common = { ...opts };
117
312
  if (status !== void 0) common.statusCode = status;
@@ -135,6 +330,9 @@ function build(status, errorCode, message, opts = {}) {
135
330
  common
136
331
  );
137
332
  }
333
+ if (errorCode === ErrorCodes.NOT_FOUND || status === 404) {
334
+ return new NotFoundError(message || void 0, common);
335
+ }
138
336
  return new KugelAudioError(message || `HTTP ${status}`, common);
139
337
  }
140
338
  function readHeader(headers, name) {
@@ -1553,6 +1751,7 @@ var KugelAudio = class _KugelAudio {
1553
1751
  this._keepalivePingInterval = options.keepalivePingInterval !== void 0 ? options.keepalivePingInterval : 2e4;
1554
1752
  this.models = new ModelsResource(this);
1555
1753
  this.voices = new VoicesResource(this);
1754
+ this.dictionaries = new DictionariesResource(this);
1556
1755
  this.tts = new TTSResource(this);
1557
1756
  }
1558
1757
  /**
@@ -1719,10 +1918,13 @@ var KugelAudio = class _KugelAudio {
1719
1918
  0 && (module.exports = {
1720
1919
  AuthenticationError,
1721
1920
  ConnectionError,
1921
+ DictionariesResource,
1922
+ DictionaryEntriesResource,
1722
1923
  ErrorCodes,
1723
1924
  InsufficientCreditsError,
1724
1925
  KugelAudio,
1725
1926
  KugelAudioError,
1927
+ NotFoundError,
1726
1928
  RateLimitError,
1727
1929
  ValidationError,
1728
1930
  WsCloseCodes,
package/dist/index.mjs CHANGED
@@ -5,6 +5,187 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
5
5
  throw Error('Dynamic require of "' + x + '" is not supported');
6
6
  });
7
7
 
8
+ // src/dictionaries.ts
9
+ function mapDictionary(raw) {
10
+ return {
11
+ id: raw.id,
12
+ projectId: raw.project_id,
13
+ name: raw.name,
14
+ description: raw.description ?? void 0,
15
+ language: raw.language ?? void 0,
16
+ isActive: raw.is_active ?? true,
17
+ createdAt: raw.created_at,
18
+ updatedAt: raw.updated_at
19
+ };
20
+ }
21
+ function mapEntry(raw) {
22
+ return {
23
+ id: raw.id,
24
+ dictionaryId: raw.dictionary_id,
25
+ word: raw.word,
26
+ replacement: raw.replacement,
27
+ ipa: raw.ipa ?? void 0,
28
+ caseSensitive: raw.case_sensitive ?? false,
29
+ createdAt: raw.created_at,
30
+ updatedAt: raw.updated_at
31
+ };
32
+ }
33
+ function entryPayload(input) {
34
+ const payload = {
35
+ word: input.word,
36
+ replacement: input.replacement
37
+ };
38
+ if (input.ipa !== void 0) payload.ipa = input.ipa;
39
+ if (input.caseSensitive !== void 0) {
40
+ payload.case_sensitive = input.caseSensitive;
41
+ }
42
+ return payload;
43
+ }
44
+ function buildPath(base, params) {
45
+ const search = new URLSearchParams();
46
+ for (const [key, val] of Object.entries(params)) {
47
+ if (val === void 0 || val === null) continue;
48
+ search.set(key, String(val));
49
+ }
50
+ const query = search.toString();
51
+ return query ? `${base}?${query}` : base;
52
+ }
53
+ var DictionaryEntriesResource = class {
54
+ constructor(client) {
55
+ this.client = client;
56
+ }
57
+ /** List entries with optional search + pagination. */
58
+ async list(dictionaryId, options) {
59
+ const path = buildPath(`/v1/dictionaries/${dictionaryId}/entries`, {
60
+ search: options?.search,
61
+ limit: options?.limit,
62
+ offset: options?.offset,
63
+ project_id: options?.projectId
64
+ });
65
+ const raw = await this.client.request("GET", path);
66
+ return {
67
+ entries: raw.entries.map(mapEntry),
68
+ total: raw.total,
69
+ limit: raw.limit,
70
+ offset: raw.offset
71
+ };
72
+ }
73
+ /** Add a single entry to a dictionary. */
74
+ async add(dictionaryId, entry, options) {
75
+ const path = buildPath(`/v1/dictionaries/${dictionaryId}/entries`, {
76
+ project_id: options?.projectId
77
+ });
78
+ const raw = await this.client.request(
79
+ "POST",
80
+ path,
81
+ entryPayload(entry)
82
+ );
83
+ return mapEntry(raw);
84
+ }
85
+ /** Update an existing entry. */
86
+ async update(dictionaryId, entryId, updates, options) {
87
+ const payload = {};
88
+ if (updates.word !== void 0) payload.word = updates.word;
89
+ if (updates.replacement !== void 0) payload.replacement = updates.replacement;
90
+ if (updates.ipa !== void 0) payload.ipa = updates.ipa;
91
+ if (updates.caseSensitive !== void 0) {
92
+ payload.case_sensitive = updates.caseSensitive;
93
+ }
94
+ const path = buildPath(`/v1/dictionaries/${dictionaryId}/entries/${entryId}`, {
95
+ project_id: options?.projectId
96
+ });
97
+ const raw = await this.client.request(
98
+ "PATCH",
99
+ path,
100
+ payload
101
+ );
102
+ return mapEntry(raw);
103
+ }
104
+ /** Delete a single entry. */
105
+ async delete(dictionaryId, entryId, options) {
106
+ const path = buildPath(`/v1/dictionaries/${dictionaryId}/entries/${entryId}`, {
107
+ project_id: options?.projectId
108
+ });
109
+ await this.client.request("DELETE", path);
110
+ }
111
+ /**
112
+ * Replace every entry in the dictionary atomically.
113
+ *
114
+ * Each item must have ``word`` and ``replacement``; existing entries
115
+ * whose ``word`` is not in the supplied list are deleted. Idempotent.
116
+ */
117
+ async replaceAll(dictionaryId, entries, options) {
118
+ const path = buildPath(`/v1/dictionaries/${dictionaryId}/entries`, {
119
+ project_id: options?.projectId
120
+ });
121
+ const raw = await this.client.request("PUT", path, {
122
+ entries: entries.map(entryPayload)
123
+ });
124
+ return raw;
125
+ }
126
+ };
127
+ var DictionariesResource = class {
128
+ constructor(client) {
129
+ this.client = client;
130
+ this.entries = new DictionaryEntriesResource(client);
131
+ }
132
+ /** List every dictionary in the caller's project. */
133
+ async list(options) {
134
+ const path = buildPath("/v1/dictionaries", {
135
+ project_id: options?.projectId
136
+ });
137
+ const raw = await this.client.request("GET", path);
138
+ return raw.dictionaries.map(mapDictionary);
139
+ }
140
+ /** Create a new dictionary scoped to the caller's project. */
141
+ async create(body, options) {
142
+ const path = buildPath("/v1/dictionaries", {
143
+ project_id: options?.projectId
144
+ });
145
+ const payload = { name: body.name };
146
+ if (body.description !== void 0) payload.description = body.description;
147
+ if (body.language !== void 0) payload.language = body.language;
148
+ const raw = await this.client.request(
149
+ "POST",
150
+ path,
151
+ payload
152
+ );
153
+ return mapDictionary(raw);
154
+ }
155
+ /** Fetch a single dictionary. */
156
+ async get(dictionaryId, options) {
157
+ const path = buildPath(`/v1/dictionaries/${dictionaryId}`, {
158
+ project_id: options?.projectId
159
+ });
160
+ const raw = await this.client.request("GET", path);
161
+ return mapDictionary(raw);
162
+ }
163
+ /** Update name / description / language / isActive. */
164
+ async update(dictionaryId, updates, options) {
165
+ const payload = {};
166
+ if (updates.name !== void 0) payload.name = updates.name;
167
+ if (updates.description !== void 0) payload.description = updates.description;
168
+ if (updates.language !== void 0) payload.language = updates.language;
169
+ if (updates.isActive !== void 0) payload.is_active = updates.isActive;
170
+ const path = buildPath(`/v1/dictionaries/${dictionaryId}`, {
171
+ project_id: options?.projectId
172
+ });
173
+ const raw = await this.client.request(
174
+ "PATCH",
175
+ path,
176
+ payload
177
+ );
178
+ return mapDictionary(raw);
179
+ }
180
+ /** Delete a dictionary (cascades to its entries). */
181
+ async delete(dictionaryId, options) {
182
+ const path = buildPath(`/v1/dictionaries/${dictionaryId}`, {
183
+ project_id: options?.projectId
184
+ });
185
+ await this.client.request("DELETE", path);
186
+ }
187
+ };
188
+
8
189
  // src/errors.ts
9
190
  var ErrorCodes = {
10
191
  UNAUTHORIZED: "UNAUTHORIZED",
@@ -77,6 +258,17 @@ var ConnectionError = class _ConnectionError extends KugelAudioError {
77
258
  Object.setPrototypeOf(this, _ConnectionError.prototype);
78
259
  }
79
260
  };
261
+ var NotFoundError = class _NotFoundError extends KugelAudioError {
262
+ constructor(message, options = {}) {
263
+ super(message ?? "Not found.", {
264
+ statusCode: 404,
265
+ errorCode: ErrorCodes.NOT_FOUND,
266
+ ...options
267
+ });
268
+ this.name = "NotFoundError";
269
+ Object.setPrototypeOf(this, _NotFoundError.prototype);
270
+ }
271
+ };
80
272
  function build(status, errorCode, message, opts = {}) {
81
273
  const common = { ...opts };
82
274
  if (status !== void 0) common.statusCode = status;
@@ -100,6 +292,9 @@ function build(status, errorCode, message, opts = {}) {
100
292
  common
101
293
  );
102
294
  }
295
+ if (errorCode === ErrorCodes.NOT_FOUND || status === 404) {
296
+ return new NotFoundError(message || void 0, common);
297
+ }
103
298
  return new KugelAudioError(message || `HTTP ${status}`, common);
104
299
  }
105
300
  function readHeader(headers, name) {
@@ -1518,6 +1713,7 @@ var KugelAudio = class _KugelAudio {
1518
1713
  this._keepalivePingInterval = options.keepalivePingInterval !== void 0 ? options.keepalivePingInterval : 2e4;
1519
1714
  this.models = new ModelsResource(this);
1520
1715
  this.voices = new VoicesResource(this);
1716
+ this.dictionaries = new DictionariesResource(this);
1521
1717
  this.tts = new TTSResource(this);
1522
1718
  }
1523
1719
  /**
@@ -1683,10 +1879,13 @@ var KugelAudio = class _KugelAudio {
1683
1879
  export {
1684
1880
  AuthenticationError,
1685
1881
  ConnectionError,
1882
+ DictionariesResource,
1883
+ DictionaryEntriesResource,
1686
1884
  ErrorCodes,
1687
1885
  InsufficientCreditsError,
1688
1886
  KugelAudio,
1689
1887
  KugelAudioError,
1888
+ NotFoundError,
1690
1889
  RateLimitError,
1691
1890
  ValidationError,
1692
1891
  WsCloseCodes,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kugelaudio",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Official JavaScript/TypeScript SDK for KugelAudio TTS API",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
package/src/client.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  * KugelAudio API Client.
3
3
  */
4
4
 
5
+ import { DictionariesResource } from './dictionaries';
5
6
  import {
6
7
  ConnectionError,
7
8
  KugelAudioError,
@@ -1614,6 +1615,8 @@ export class KugelAudio {
1614
1615
  public readonly models: ModelsResource;
1615
1616
  /** Voices resource */
1616
1617
  public readonly voices: VoicesResource;
1618
+ /** Custom dictionaries resource */
1619
+ public readonly dictionaries: DictionariesResource;
1617
1620
  /** TTS resource */
1618
1621
  public readonly tts: TTSResource;
1619
1622
 
@@ -1656,6 +1659,7 @@ export class KugelAudio {
1656
1659
 
1657
1660
  this.models = new ModelsResource(this);
1658
1661
  this.voices = new VoicesResource(this);
1662
+ this.dictionaries = new DictionariesResource(this);
1659
1663
  this.tts = new TTSResource(this);
1660
1664
  }
1661
1665