@verbatra/sdk 0.3.0 → 0.4.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/README.md +28 -2
- package/dist/index.cjs +714 -238
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +206 -146
- package/dist/index.d.ts +206 -146
- package/dist/index.js +712 -240
- package/dist/index.js.map +1 -1
- package/package.json +7 -5
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
|
+
export { SupportedFormat } from '@verbatra/core';
|
|
1
2
|
import { AnthropicModel, OpenAiModel, GeminiModel, ProviderNotice, TranslationProvider } from '@verbatra/ai-providers';
|
|
2
3
|
import { z } from 'zod';
|
|
3
4
|
import { AdapterRegistry } from '@verbatra/format-adapters';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
* The provider section of the config: a discriminated union over the provider id,
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* This union and the factory table below are co-located on purpose: adding a provider
|
|
11
|
-
* is a single edit here (one union variant plus one table entry), and the mapped-type
|
|
12
|
-
* table makes the two sets provably identical at compile time.
|
|
7
|
+
* The provider section of the config: a discriminated union over the provider id, reusing each
|
|
8
|
+
* provider's own config schema. There is no key field anywhere in this union; the provider reads its
|
|
9
|
+
* API key from the environment at construction.
|
|
13
10
|
*/
|
|
14
11
|
declare const providerConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
15
12
|
id: z.ZodLiteral<"anthropic">;
|
|
@@ -38,6 +35,11 @@ declare const providerConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
38
35
|
type ProviderConfig = z.infer<typeof providerConfigSchema>;
|
|
39
36
|
type ProviderId = ProviderConfig["id"];
|
|
40
37
|
|
|
38
|
+
/**
|
|
39
|
+
* The verbatra project configuration. It carries no API key (the provider reads its key from the
|
|
40
|
+
* environment), and unknown top-level keys are rejected so a stray secret cannot hide in it. Validated
|
|
41
|
+
* with zod at the boundary regardless of where it was loaded from.
|
|
42
|
+
*/
|
|
41
43
|
declare const verbatraConfigSchema: z.ZodObject<{
|
|
42
44
|
sourceLocale: z.ZodString;
|
|
43
45
|
targetLocales: z.ZodArray<z.ZodString>;
|
|
@@ -46,6 +48,9 @@ declare const verbatraConfigSchema: z.ZodObject<{
|
|
|
46
48
|
"vue-i18n-json": "vue-i18n-json";
|
|
47
49
|
"next-intl-json": "next-intl-json";
|
|
48
50
|
"ngx-translate-json": "ngx-translate-json";
|
|
51
|
+
xliff: "xliff";
|
|
52
|
+
yaml: "yaml";
|
|
53
|
+
arb: "arb";
|
|
49
54
|
}>;
|
|
50
55
|
files: z.ZodObject<{
|
|
51
56
|
pattern: z.ZodString;
|
|
@@ -86,16 +91,6 @@ declare const verbatraConfigSchema: z.ZodObject<{
|
|
|
86
91
|
}, z.core.$strict>;
|
|
87
92
|
type VerbatraConfig = z.infer<typeof verbatraConfigSchema>;
|
|
88
93
|
|
|
89
|
-
/**
|
|
90
|
-
* The closed set of a provider's known model IDs: exactly the string literals its SDK
|
|
91
|
-
* model type ships, with the SDK's own open `string & {}` arm stripped out. Distributing
|
|
92
|
-
* over the union and dropping any arm the wide `string` extends leaves only the literals,
|
|
93
|
-
* so the authoring field offers and ACCEPTS only the selected provider's known models. A
|
|
94
|
-
* foreign or unknown model (for example a Claude model under `id: "gemini"`) is a type
|
|
95
|
-
* error at authoring time. This is a static authoring constraint only; the runtime schema
|
|
96
|
-
* stays `z.string().min(1)` and still accepts any non-empty string, so a brand-new model
|
|
97
|
-
* the installed SDK does not yet list is flagged in the editor but still runs.
|
|
98
|
-
*/
|
|
99
94
|
type KnownModels<M extends string> = M extends string ? (string extends M ? never : M) : never;
|
|
100
95
|
type AuthoringVariant<Id extends ProviderId, M extends string> = Extract<ProviderConfig, {
|
|
101
96
|
id: Id;
|
|
@@ -108,13 +103,6 @@ type AuthoringVariant<Id extends ProviderId, M extends string> = Extract<Provide
|
|
|
108
103
|
model: KnownModels<M>;
|
|
109
104
|
};
|
|
110
105
|
} : never : never;
|
|
111
|
-
/**
|
|
112
|
-
* The authoring view of one provider variant, keyed by id. LLM providers (anthropic,
|
|
113
|
-
* openai, gemini) restrict `options.model` to that provider's known model literals; DeepL
|
|
114
|
-
* has no model field and is carried through unchanged. Keying by id (rather than a flat
|
|
115
|
-
* union) lets {@link AuthoringConfigFor} select exactly one variant for a literal id, so
|
|
116
|
-
* the `options.model` site is one provider's literal set and never a multi-provider union.
|
|
117
|
-
*/
|
|
118
106
|
type AuthoringProviderVariant = {
|
|
119
107
|
anthropic: AuthoringVariant<"anthropic", AnthropicModel>;
|
|
120
108
|
openai: AuthoringVariant<"openai", OpenAiModel>;
|
|
@@ -124,20 +112,10 @@ type AuthoringProviderVariant = {
|
|
|
124
112
|
}>;
|
|
125
113
|
};
|
|
126
114
|
/**
|
|
127
|
-
* The authoring view of the whole config for a
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
* `options.model` is that provider's known model literals alone and not a union across
|
|
132
|
-
* providers. `defineConfig` declares one overload per provider parameterized on this type
|
|
133
|
-
* (`AuthoringConfigFor<"openai">` and so on), so overload resolution picks the variant from
|
|
134
|
-
* the `provider.id` literal. That, together with the closed {@link KnownModels} set, makes a
|
|
135
|
-
* foreign model (for example a Claude model under `id: "gemini"`) a type error and aims to
|
|
136
|
-
* keep editors with weaker discriminated-union narrowing (for example the JetBrains/WebStorm
|
|
137
|
-
* completion engine) offering only the selected provider's models, since each overload's
|
|
138
|
-
* parameter is already a single variant with no nested union to narrow. When `TId` defaults
|
|
139
|
-
* to `ProviderId`, `provider` is the full authoring union. Every value assignable here is
|
|
140
|
-
* assignable to {@link VerbatraConfig}, because a model literal is a subtype of `string`.
|
|
115
|
+
* The authoring view of the whole config for a provider id: a {@link VerbatraConfig} whose `provider`
|
|
116
|
+
* is that id's single authoring variant, so `options.model` offers only that provider's models. When
|
|
117
|
+
* `TId` defaults to `ProviderId`, `provider` is the full authoring union. Every value here is assignable
|
|
118
|
+
* to {@link VerbatraConfig}, since a model literal is a subtype of `string`.
|
|
141
119
|
*/
|
|
142
120
|
type AuthoringConfigFor<TId extends ProviderId = ProviderId> = Omit<VerbatraConfig, "provider"> & {
|
|
143
121
|
provider: AuthoringProviderVariant[TId];
|
|
@@ -150,30 +128,16 @@ type AuthoringConfigFor<TId extends ProviderId = ProviderId> = Omit<VerbatraConf
|
|
|
150
128
|
type AuthoringConfig = AuthoringConfigFor;
|
|
151
129
|
|
|
152
130
|
/**
|
|
153
|
-
* Identity helper for authoring a
|
|
154
|
-
*
|
|
155
|
-
*
|
|
131
|
+
* Identity helper for authoring a typed `verbatra.config.ts`. It returns its argument unchanged; its
|
|
132
|
+
* only purpose is full type inference and editor autocomplete on the config object, including
|
|
133
|
+
* completion of the selected provider's known model literals.
|
|
156
134
|
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
* known model literals, with no union across providers and no generic for an editor to
|
|
161
|
-
* infer. Overload resolution selects the matching overload from the `provider.id` literal,
|
|
162
|
-
* so the editor offers only the selected provider's models and a foreign or unknown model
|
|
163
|
-
* (for example a Claude model under `id: "gemini"`) is a type error. This is deliberately
|
|
164
|
-
* overload-based: a generic whose type parameter is inferred from a nested `provider.id`
|
|
165
|
-
* collapses correctly in tsserver but not in editors with weaker inference (notably the
|
|
166
|
-
* JetBrains/WebStorm completion engine), which then fall back to the full union and offer
|
|
167
|
-
* every provider's models. Concrete per-provider signatures avoid that inference step.
|
|
135
|
+
* The model restriction is a static authoring constraint only: `loadConfig` validates `model` as a
|
|
136
|
+
* non-empty string, so a model the installed provider SDK does not yet list is flagged in the editor
|
|
137
|
+
* but still runs.
|
|
168
138
|
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
* type-checks.
|
|
172
|
-
*
|
|
173
|
-
* The return type is the runtime {@link VerbatraConfig}. The model restriction is a static
|
|
174
|
-
* authoring constraint, not a runtime one: `loadConfig` still validates `model` as
|
|
175
|
-
* `z.string().min(1)`, so a model the installed provider SDK does not yet list is flagged
|
|
176
|
-
* in the editor but still runs.
|
|
139
|
+
* @param config - The verbatra configuration object.
|
|
140
|
+
* @returns The same config, typed as {@link VerbatraConfig}.
|
|
177
141
|
*/
|
|
178
142
|
declare function defineConfig(config: AuthoringConfigFor<"anthropic">): VerbatraConfig;
|
|
179
143
|
declare function defineConfig(config: AuthoringConfigFor<"openai">): VerbatraConfig;
|
|
@@ -190,12 +154,10 @@ interface LoadConfigOptions {
|
|
|
190
154
|
*/
|
|
191
155
|
readonly configOverride?: unknown;
|
|
192
156
|
/**
|
|
193
|
-
* An explicit config file to load instead of searching. A relative path resolves
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
* present-but-unparseable/invalid file is CONFIG_INVALID. Precedence: configOverride
|
|
198
|
-
* wins over configPath, which wins over search.
|
|
157
|
+
* An explicit config file to load instead of searching. A relative path resolves against `cwd`; an
|
|
158
|
+
* absolute path is used as given. Parsed and zod-validated exactly like a searched file: a missing
|
|
159
|
+
* file is `CONFIG_NOT_FOUND`, a present but invalid one is `CONFIG_INVALID`. Takes precedence over
|
|
160
|
+
* search, but `configOverride` takes precedence over it.
|
|
199
161
|
*/
|
|
200
162
|
readonly configPath?: string;
|
|
201
163
|
}
|
|
@@ -259,14 +221,148 @@ declare class SdkError extends Error {
|
|
|
259
221
|
constructor(code: SdkErrorCode, message: string);
|
|
260
222
|
}
|
|
261
223
|
|
|
224
|
+
/** Outcome of a bounded read: the content, or why it could not be read in bounds. */
|
|
225
|
+
type BoundedFileRead = {
|
|
226
|
+
readonly kind: "ok";
|
|
227
|
+
readonly content: string;
|
|
228
|
+
} | {
|
|
229
|
+
readonly kind: "missing";
|
|
230
|
+
} | {
|
|
231
|
+
readonly kind: "too-large";
|
|
232
|
+
};
|
|
233
|
+
/** Outcome of a bounded binary read: the bytes, or why they could not be read in bounds. */
|
|
234
|
+
type BoundedBytesRead = {
|
|
235
|
+
readonly kind: "ok";
|
|
236
|
+
readonly bytes: Uint8Array;
|
|
237
|
+
} | {
|
|
238
|
+
readonly kind: "missing";
|
|
239
|
+
} | {
|
|
240
|
+
readonly kind: "too-large";
|
|
241
|
+
};
|
|
242
|
+
/**
|
|
243
|
+
* The minimal file-system surface the SDK needs. Reads are bounded and writes are atomic. Injectable so
|
|
244
|
+
* tests stay deterministic; the format adapters do their own file IO and bypass this seam.
|
|
245
|
+
*/
|
|
246
|
+
interface SdkFs {
|
|
247
|
+
/** Whether a readable file exists at the path. */
|
|
248
|
+
fileExists(path: string): Promise<boolean>;
|
|
249
|
+
/**
|
|
250
|
+
* Read a file as UTF-8 through a single handle, bounded to maxBytes. TOCTOU-safe: the handle is
|
|
251
|
+
* fstat'd and the read never advances past the sized length, so swapping in a larger file cannot
|
|
252
|
+
* bypass the cap. A missing or unreadable path is "missing"; a file over the cap is "too-large".
|
|
253
|
+
*/
|
|
254
|
+
readFileBounded(path: string, maxBytes: number): Promise<BoundedFileRead>;
|
|
255
|
+
/** Read a file as raw bytes with the same TOCTOU-safe, bounded discipline as {@link readFileBounded}. */
|
|
256
|
+
readBytesBounded(path: string, maxBytes: number): Promise<BoundedBytesRead>;
|
|
257
|
+
/** Write atomically: a temp file in the same directory, then rename over the target. */
|
|
258
|
+
writeFile(path: string, data: string): Promise<void>;
|
|
259
|
+
/** Write raw bytes atomically (temp file, then rename over the target). Used for the workbook. */
|
|
260
|
+
writeBytes(path: string, data: Uint8Array): Promise<void>;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/** Per-locale drift status: counts only, no key lists. */
|
|
264
|
+
interface LocaleCheckSummary {
|
|
265
|
+
/** The target locale this entry reports on. */
|
|
266
|
+
readonly locale: string;
|
|
267
|
+
/** Keys present in source but absent from the target. */
|
|
268
|
+
readonly missing: number;
|
|
269
|
+
/** Keys whose source changed since the target was last translated. */
|
|
270
|
+
readonly stale: number;
|
|
271
|
+
/** Keys whose recorded baseline still matches the source. */
|
|
272
|
+
readonly upToDate: number;
|
|
273
|
+
/** True when nothing needs (re)translating for this locale. */
|
|
274
|
+
readonly inSync: boolean;
|
|
275
|
+
}
|
|
276
|
+
/** The aggregate read-only status across all checked target locales. */
|
|
277
|
+
interface CheckSummary {
|
|
278
|
+
/** True only when every checked locale is in sync. */
|
|
279
|
+
readonly inSync: boolean;
|
|
280
|
+
/** One entry per checked target locale, in config order. */
|
|
281
|
+
readonly locales: readonly LocaleCheckSummary[];
|
|
282
|
+
}
|
|
283
|
+
/** Input for {@link check}: the validated config and which locales to check. */
|
|
284
|
+
interface CheckInput {
|
|
285
|
+
/** The validated configuration (typically from {@link loadConfig}). */
|
|
286
|
+
readonly config: VerbatraConfig;
|
|
287
|
+
/** Directory the file pattern and lock-file resolve against; defaults to cwd. */
|
|
288
|
+
readonly cwd?: string;
|
|
289
|
+
/** Subset of target locales to check; defaults to all configured target locales. */
|
|
290
|
+
readonly locales?: readonly string[];
|
|
291
|
+
}
|
|
292
|
+
/** Composition seam for {@link check}: inject a registry and a file system for tests. */
|
|
293
|
+
interface CheckDeps {
|
|
294
|
+
readonly adapterRegistry?: AdapterRegistry;
|
|
295
|
+
readonly fs?: SdkFs;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Report which keys are missing or stale per target locale, without calling a provider, writing any
|
|
299
|
+
* file, or touching the lock. Each locale is reported as counts only (missing, stale, up-to-date);
|
|
300
|
+
* a locale is `inSync` when nothing is missing or stale, and the top-level `inSync` is true only when
|
|
301
|
+
* every checked locale is. Orphaned keys and integrity are not reported, since they concern a write.
|
|
302
|
+
*
|
|
303
|
+
* @param input - The validated config and which locales to check.
|
|
304
|
+
* @param deps - Optional composition seams (registry, file system) for tests.
|
|
305
|
+
* @returns The aggregate and per-locale drift status.
|
|
306
|
+
* @throws {@link SdkError} `UNKNOWN_FORMAT`, `SOURCE_UNREADABLE`, `SOURCE_INVALID`, `LOCK_FILE_INVALID`
|
|
307
|
+
* with the same meanings as in `translate`.
|
|
308
|
+
*/
|
|
309
|
+
declare function check(input: CheckInput, deps?: CheckDeps): Promise<CheckSummary>;
|
|
310
|
+
|
|
311
|
+
/** Per-locale pending change: the key lists, not counts. */
|
|
312
|
+
interface LocaleDiff {
|
|
313
|
+
/** The target locale this entry reports on. */
|
|
314
|
+
readonly locale: string;
|
|
315
|
+
/** Keys present in source but absent from the target; would be added by a run. */
|
|
316
|
+
readonly missing: readonly string[];
|
|
317
|
+
/** Keys whose source changed since last translated; would be re-translated. */
|
|
318
|
+
readonly changed: readonly string[];
|
|
319
|
+
/** Keys present in target but absent from source; report-only, never pending. */
|
|
320
|
+
readonly orphaned: readonly string[];
|
|
321
|
+
/** True when the locale has missing or changed keys; orphaned keys do not count. */
|
|
322
|
+
readonly hasPendingChanges: boolean;
|
|
323
|
+
}
|
|
324
|
+
/** The aggregate read-only diff across all checked target locales. */
|
|
325
|
+
interface DiffSummary {
|
|
326
|
+
/** True when any checked locale has pending changes. */
|
|
327
|
+
readonly hasPendingChanges: boolean;
|
|
328
|
+
/** One entry per checked target locale, in config order. */
|
|
329
|
+
readonly locales: readonly LocaleDiff[];
|
|
330
|
+
}
|
|
331
|
+
/** Input for {@link diff}: the validated config and which locales to diff. */
|
|
332
|
+
interface DiffInput {
|
|
333
|
+
/** The validated configuration (typically from {@link loadConfig}). */
|
|
334
|
+
readonly config: VerbatraConfig;
|
|
335
|
+
/** Directory the file pattern and lock-file resolve against; defaults to cwd. */
|
|
336
|
+
readonly cwd?: string;
|
|
337
|
+
/** Subset of target locales to diff; defaults to all configured target locales. */
|
|
338
|
+
readonly locales?: readonly string[];
|
|
339
|
+
}
|
|
340
|
+
/** Composition seam for {@link diff}: inject a registry and a file system for tests. */
|
|
341
|
+
interface DiffDeps {
|
|
342
|
+
readonly adapterRegistry?: AdapterRegistry;
|
|
343
|
+
readonly fs?: SdkFs;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Report the exact pending change per target locale as three key lists (missing, changed, orphaned),
|
|
347
|
+
* without calling a provider, writing any file, or touching the lock. This is the detailed sibling of
|
|
348
|
+
* {@link check}. A locale's `hasPendingChanges` is driven by missing or changed only; orphaned keys are
|
|
349
|
+
* reported but do not flip it, since a default `translate` run does not prune. The top-level
|
|
350
|
+
* `hasPendingChanges` is true when any checked locale has pending changes.
|
|
351
|
+
*
|
|
352
|
+
* @param input - The validated config and which locales to diff.
|
|
353
|
+
* @param deps - Optional composition seams (registry, file system) for tests.
|
|
354
|
+
* @returns The aggregate and per-locale pending change.
|
|
355
|
+
* @throws {@link SdkError} `UNKNOWN_FORMAT`, `SOURCE_UNREADABLE`, `SOURCE_INVALID`, `LOCK_FILE_INVALID`
|
|
356
|
+
* with the same meanings as in `translate`.
|
|
357
|
+
*/
|
|
358
|
+
declare function diff(input: DiffInput, deps?: DiffDeps): Promise<DiffSummary>;
|
|
359
|
+
|
|
262
360
|
/** A stable code for an SDK-originated notice (not a provider notice). */
|
|
263
361
|
type SdkNoticeCode = "PLURAL_CATEGORIES_INCOMPLETE" | "SUB_BATCH_FAILED";
|
|
264
362
|
/**
|
|
265
363
|
* A notice raised by the SDK itself (not a provider), structurally identical to a {@link ProviderNotice}
|
|
266
364
|
* so both share the {@link LocaleSummary.notices} channel. Carries only a stable code and a static,
|
|
267
|
-
* secret-free message; never a key value or translatable content.
|
|
268
|
-
* the ai-providers `ProviderNoticeCode` union stays free of SDK concerns (the dependency arrow points
|
|
269
|
-
* sdk -> ai-providers, never the reverse).
|
|
365
|
+
* secret-free message; never a key value or translatable content.
|
|
270
366
|
*/
|
|
271
367
|
interface SdkNotice {
|
|
272
368
|
/** The stable {@link SdkNoticeCode} for what the SDK is reporting. */
|
|
@@ -302,10 +398,9 @@ interface LocaleSummary {
|
|
|
302
398
|
/** Translated keys that failed the placeholder-integrity check and were withheld. */
|
|
303
399
|
readonly integrityMismatches: readonly string[];
|
|
304
400
|
/**
|
|
305
|
-
* Plural-category keys verbatra
|
|
306
|
-
* never supplied), kept distinct from {@link translated}
|
|
307
|
-
*
|
|
308
|
-
* was enabled and acted. In a dry-run this is empty (the provider is not called).
|
|
401
|
+
* Plural-category keys verbatra synthesized this run (for example a Polish `items_few` the source
|
|
402
|
+
* never supplied), kept distinct from {@link translated}. Empty unless plural generation was enabled
|
|
403
|
+
* and acted, and empty in a dry-run.
|
|
309
404
|
*/
|
|
310
405
|
readonly generated: readonly string[];
|
|
311
406
|
/**
|
|
@@ -336,54 +431,6 @@ interface RunSummary {
|
|
|
336
431
|
readonly failed: readonly string[];
|
|
337
432
|
}
|
|
338
433
|
|
|
339
|
-
/** Outcome of a bounded read: the content, or why it could not be read in bounds. */
|
|
340
|
-
type BoundedFileRead = {
|
|
341
|
-
readonly kind: "ok";
|
|
342
|
-
readonly content: string;
|
|
343
|
-
} | {
|
|
344
|
-
readonly kind: "missing";
|
|
345
|
-
} | {
|
|
346
|
-
readonly kind: "too-large";
|
|
347
|
-
};
|
|
348
|
-
/** Outcome of a bounded binary read: the bytes, or why they could not be read in bounds. */
|
|
349
|
-
type BoundedBytesRead = {
|
|
350
|
-
readonly kind: "ok";
|
|
351
|
-
readonly bytes: Uint8Array;
|
|
352
|
-
} | {
|
|
353
|
-
readonly kind: "missing";
|
|
354
|
-
} | {
|
|
355
|
-
readonly kind: "too-large";
|
|
356
|
-
};
|
|
357
|
-
/**
|
|
358
|
-
* The minimal file-system surface the SDK needs: existence checks, the lock-file read/write,
|
|
359
|
-
* and the untrusted workbook bytes read/write for the export/import flow. Reads are bounded
|
|
360
|
-
* (see {@link readFileBounded} / {@link readBytesBounded}) and writes are atomic. Injectable so
|
|
361
|
-
* tests stay deterministic; the format adapters do their own file IO and are not routed through
|
|
362
|
-
* this seam.
|
|
363
|
-
*/
|
|
364
|
-
interface SdkFs {
|
|
365
|
-
/** Whether a readable file exists at the path. */
|
|
366
|
-
fileExists(path: string): Promise<boolean>;
|
|
367
|
-
/**
|
|
368
|
-
* Read a file as UTF-8 through a single handle, bounded to maxBytes. TOCTOU-safe: the
|
|
369
|
-
* handle is fstat'd and the read never advances past the sized length, so swapping the
|
|
370
|
-
* path for a larger file after the size check cannot bypass the cap. A missing or
|
|
371
|
-
* unreadable path is "missing" (first-run); a file over the cap is "too-large".
|
|
372
|
-
*/
|
|
373
|
-
readFileBounded(path: string, maxBytes: number): Promise<BoundedFileRead>;
|
|
374
|
-
/**
|
|
375
|
-
* Read a file as raw bytes through a single handle, bounded to maxBytes, with the SAME
|
|
376
|
-
* TOCTOU-safe discipline as {@link readFileBounded}: the handle is fstat'd and the read never
|
|
377
|
-
* advances past the sized length. Used for the untrusted workbook on import; a file over the
|
|
378
|
-
* cap is "too-large", a missing path is "missing".
|
|
379
|
-
*/
|
|
380
|
-
readBytesBounded(path: string, maxBytes: number): Promise<BoundedBytesRead>;
|
|
381
|
-
/** Write atomically: a temp file in the same directory, then rename over the target. */
|
|
382
|
-
writeFile(path: string, data: string): Promise<void>;
|
|
383
|
-
/** Write raw bytes atomically (temp file, then rename over the target). Used for the workbook. */
|
|
384
|
-
writeBytes(path: string, data: Uint8Array): Promise<void>;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
434
|
/** Builds the provider from its config. Injectable so tests stay offline. */
|
|
388
435
|
type CreateProvider = (config: ProviderConfig) => TranslationProvider;
|
|
389
436
|
|
|
@@ -497,11 +544,10 @@ interface ExportWorkbookResult {
|
|
|
497
544
|
}[];
|
|
498
545
|
}
|
|
499
546
|
/**
|
|
500
|
-
* Export the strings needing human translation into a styled `.xlsx` workbook.
|
|
501
|
-
*
|
|
502
|
-
*
|
|
503
|
-
*
|
|
504
|
-
* writes the bytes through the {@link SdkFs} seam. No provider is called and no lock-file is written.
|
|
547
|
+
* Export the strings needing human translation into a styled `.xlsx` workbook. Each target locale is
|
|
548
|
+
* diffed against the source and lock baseline to pick the rows (missing and changed by default; add
|
|
549
|
+
* unchanged with `includeUnchanged`), and the bytes are written to `out`. No provider is called and no
|
|
550
|
+
* lock-file is written.
|
|
505
551
|
*
|
|
506
552
|
* @param input - The validated config and export options.
|
|
507
553
|
* @param deps - Optional composition seams (registry, file system) for tests.
|
|
@@ -528,19 +574,16 @@ interface ImportWorkbookDeps {
|
|
|
528
574
|
readonly fs?: SdkFs;
|
|
529
575
|
}
|
|
530
576
|
/**
|
|
531
|
-
* Import a filled workbook back into the locale files.
|
|
532
|
-
*
|
|
533
|
-
*
|
|
534
|
-
*
|
|
535
|
-
* `validateMessage`), writes the accepted values through the format adapter, and updates the lock
|
|
536
|
-
* through the existing lock logic. Returns a {@link RunSummary} structurally identical to
|
|
537
|
-
* `translate`'s, so the CLI formatter and exit-code rule are shared with no special case.
|
|
577
|
+
* Import a filled workbook back into the locale files. Each target-locale data sheet runs the same
|
|
578
|
+
* source-drift, placeholder, and ICU checks as the translate flow, the accepted values are written
|
|
579
|
+
* through the format adapter, and the lock is updated. Returns a {@link RunSummary} structurally
|
|
580
|
+
* identical to `translate`'s.
|
|
538
581
|
*
|
|
539
582
|
* Whole-run failures (unknown format, unreadable/invalid/oversized workbook, corrupt lock) throw a
|
|
540
583
|
* structured {@link SdkError}. A per-sheet failure (a locale not in config, a broken-round-trip key,
|
|
541
584
|
* a write failure) is isolated as that locale's `status: "failed"`, not a throw; per-row rejections
|
|
542
|
-
* are withheld and reported on the locale
|
|
543
|
-
*
|
|
585
|
+
* are withheld and reported on the locale. Dry-run validates and reports without writing any locale or
|
|
586
|
+
* lock file.
|
|
544
587
|
*
|
|
545
588
|
* @param input - The validated config, the workbook path, and run options.
|
|
546
589
|
* @param deps - Optional composition seams (registry, file system) for tests.
|
|
@@ -549,6 +592,28 @@ interface ImportWorkbookDeps {
|
|
|
549
592
|
*/
|
|
550
593
|
declare function importWorkbook(input: ImportWorkbookInput, deps?: ImportWorkbookDeps): Promise<RunSummary>;
|
|
551
594
|
|
|
595
|
+
/**
|
|
596
|
+
* Read-only metadata the CLI `init` scaffold derives its tables from, so the CLI never restates the
|
|
597
|
+
* provider, env-var, model, or format truth owned by core and ai-providers.
|
|
598
|
+
*/
|
|
599
|
+
declare const scaffoldingMetadata: {
|
|
600
|
+
/** Provider id -> the environment variable its API key is read from. Owned by ai-providers. */
|
|
601
|
+
readonly providerEnv: {
|
|
602
|
+
readonly anthropic: "ANTHROPIC_API_KEY";
|
|
603
|
+
readonly openai: "OPENAI_API_KEY";
|
|
604
|
+
readonly gemini: "GEMINI_API_KEY";
|
|
605
|
+
readonly deepl: "DEEPL_API_KEY";
|
|
606
|
+
};
|
|
607
|
+
/** LLM provider id -> a cosmetic default scaffold model. Owned by ai-providers. DeepL has none. */
|
|
608
|
+
readonly scaffoldModels: {
|
|
609
|
+
readonly anthropic: "claude-sonnet-4-6";
|
|
610
|
+
readonly openai: "gpt-5.4-mini";
|
|
611
|
+
readonly gemini: "gemini-2.5-flash";
|
|
612
|
+
};
|
|
613
|
+
/** The closed set of source format ids. Owned by core. */
|
|
614
|
+
readonly supportedFormats: readonly ["i18next-json", "vue-i18n-json", "next-intl-json", "ngx-translate-json", "xliff", "yaml", "arb"];
|
|
615
|
+
};
|
|
616
|
+
|
|
552
617
|
/** A minimal source-change event source. Production wraps chokidar; tests inject a stub. */
|
|
553
618
|
interface Watcher {
|
|
554
619
|
/** Register a listener invoked once per coalesced source-change event. */
|
|
@@ -605,16 +670,11 @@ interface WatchController {
|
|
|
605
670
|
stop(): Promise<void>;
|
|
606
671
|
}
|
|
607
672
|
/**
|
|
608
|
-
* Start watching the source file and re-run the one-shot translate on each debounced change.
|
|
609
|
-
*
|
|
610
|
-
*
|
|
611
|
-
*
|
|
612
|
-
*
|
|
613
|
-
* watching continues. Returns a controller whose stop() closes the watcher and awaits the in-flight
|
|
614
|
-
* run (the caller wires any signal, e.g. SIGINT, to it).
|
|
615
|
-
*
|
|
616
|
-
* Only the startup source check throws; every run outcome after start is surfaced through `onRun` as a
|
|
617
|
-
* {@link WatchRunResult} (a failed run never rejects the in-flight promise).
|
|
673
|
+
* Start watching the source file and re-run the one-shot {@link translate} on each debounced change.
|
|
674
|
+
* Runs are serialized: changes during a run collapse into a single follow-up, so two runs never
|
|
675
|
+
* overlap. A missing source at startup throws; every run outcome after start is surfaced through
|
|
676
|
+
* `onRun` as a {@link WatchRunResult} and watching continues. Returns a controller whose `stop()`
|
|
677
|
+
* closes the watcher and awaits the in-flight run.
|
|
618
678
|
*
|
|
619
679
|
* @param input - The config, optional cwd/debounce, and the `onRun` callback that receives each result.
|
|
620
680
|
* @param deps - Optional composition seams (watcher, run, registry, provider builder, file system) for tests.
|
|
@@ -646,4 +706,4 @@ interface WatchController {
|
|
|
646
706
|
*/
|
|
647
707
|
declare function watch(input: WatchInput, deps?: WatchDeps): Promise<WatchController>;
|
|
648
708
|
|
|
649
|
-
export { type CreateProvider, type CreateWatcher, DEFAULT_WORKBOOK_PATH, type ExportWorkbookDeps, type ExportWorkbookInput, type ExportWorkbookResult, type ImportWorkbookDeps, type ImportWorkbookInput, type LoadConfigOptions, type LocaleNotice, type LocaleSummary, type ProviderConfig, type ProviderId, type RunSummary, type RunTranslate, SdkError, type SdkErrorCode, type SdkFs, type SdkNotice, type SdkNoticeCode, type TranslateDeps, type TranslateInput, type VerbatraConfig, type WatchController, type WatchDeps, type WatchInput, type WatchRunResult, type Watcher, defineConfig, exportWorkbook, importWorkbook, loadConfig, translate, verbatraConfigSchema, watch };
|
|
709
|
+
export { type CheckDeps, type CheckInput, type CheckSummary, type CreateProvider, type CreateWatcher, DEFAULT_WORKBOOK_PATH, type DiffDeps, type DiffInput, type DiffSummary, type ExportWorkbookDeps, type ExportWorkbookInput, type ExportWorkbookResult, type ImportWorkbookDeps, type ImportWorkbookInput, type LoadConfigOptions, type LocaleCheckSummary, type LocaleDiff, type LocaleNotice, type LocaleSummary, type ProviderConfig, type ProviderId, type RunSummary, type RunTranslate, SdkError, type SdkErrorCode, type SdkFs, type SdkNotice, type SdkNoticeCode, type TranslateDeps, type TranslateInput, type VerbatraConfig, type WatchController, type WatchDeps, type WatchInput, type WatchRunResult, type Watcher, check, defineConfig, diff, exportWorkbook, importWorkbook, loadConfig, scaffoldingMetadata, translate, verbatraConfigSchema, watch };
|