@verbatra/sdk 0.5.0-next.1 → 0.5.0-next.2
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 +1 -1
- package/dist/index.cjs +112 -64
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -28
- package/dist/index.d.ts +38 -28
- package/dist/index.js +112 -64
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -100,7 +100,31 @@ interface Usage {
|
|
|
100
100
|
readonly inputTokens: number;
|
|
101
101
|
readonly outputTokens: number;
|
|
102
102
|
}
|
|
103
|
-
/**
|
|
103
|
+
/**
|
|
104
|
+
* Stable codes for a provider's graceful-degradation notices. These are returned DATA on a
|
|
105
|
+
* successful result, NOT thrown:
|
|
106
|
+
*
|
|
107
|
+
* - `FORMALITY_DOWNGRADED`: a requested formality was not applied (DeepL's free tier does not
|
|
108
|
+
* support it).
|
|
109
|
+
* - `GLOSSARY_IGNORED`: a supplied generic glossary term map was not applied (DeepL only applies a
|
|
110
|
+
* native glossary id, never a term map).
|
|
111
|
+
* - `PLACEHOLDER_UNSUPPORTED`: at least one placeholder- or ICU-bearing entry was left untranslated
|
|
112
|
+
* because the provider cannot preserve those tokens; such entries are withheld (absent from the
|
|
113
|
+
* result maps) rather than sent to the provider and mangled.
|
|
114
|
+
*/
|
|
115
|
+
type ProviderNoticeCode = "FORMALITY_DOWNGRADED" | "GLOSSARY_IGNORED" | "PLACEHOLDER_UNSUPPORTED";
|
|
116
|
+
/**
|
|
117
|
+
* An observable, structured signal that something was gracefully degraded (not an
|
|
118
|
+
* error). Carries only a stable code and a static message, never a key or content.
|
|
119
|
+
* Surfaced as result data, never thrown; callers inspect it but need not treat it as a failure.
|
|
120
|
+
*/
|
|
121
|
+
interface ProviderNotice {
|
|
122
|
+
/** The stable {@link ProviderNoticeCode} for what was degraded. */
|
|
123
|
+
readonly code: ProviderNoticeCode;
|
|
124
|
+
/** A static, safe description; never a key or translatable content. */
|
|
125
|
+
readonly message: string;
|
|
126
|
+
}
|
|
127
|
+
/** Result of a batch translation: per-key values, per-key integrity outcomes, and any notices. */
|
|
104
128
|
interface TranslateResult {
|
|
105
129
|
/** The translated value for each requested key. */
|
|
106
130
|
readonly values: ReadonlyMap<string, string>;
|
|
@@ -108,6 +132,12 @@ interface TranslateResult {
|
|
|
108
132
|
readonly integrity: ReadonlyMap<string, PlaceholderIntegrityResult$1>;
|
|
109
133
|
/** Token usage when the provider reports it; absent for token-less providers. */
|
|
110
134
|
readonly usage?: Usage;
|
|
135
|
+
/**
|
|
136
|
+
* Graceful-degradation notices for this batch. Every provider populates this as a present array:
|
|
137
|
+
* DeepL reports real notices (for example `GLOSSARY_IGNORED`); an LLM provider with nothing to
|
|
138
|
+
* report returns an empty array rather than omitting the field.
|
|
139
|
+
*/
|
|
140
|
+
readonly notices?: readonly ProviderNotice[];
|
|
111
141
|
}
|
|
112
142
|
/**
|
|
113
143
|
* The single contract every provider implements. It is narrow enough that a machine-translation API like
|
|
@@ -166,28 +196,6 @@ interface TranslationProvider {
|
|
|
166
196
|
* are still accepted. This drives editor completions only; the runtime schema validates.
|
|
167
197
|
*/
|
|
168
198
|
type AnthropicModel = Anthropic.Messages.Model;
|
|
169
|
-
/**
|
|
170
|
-
* Stable codes for the DeepL graceful-degradation notices, DeepL only. These are returned DATA on a
|
|
171
|
-
* successful result, NOT thrown:
|
|
172
|
-
*
|
|
173
|
-
* - `FORMALITY_DOWNGRADED`: a requested formality was not applied (the free tier does not support it).
|
|
174
|
-
* - `GLOSSARY_IGNORED`: a supplied generic glossary was not applied.
|
|
175
|
-
* - `PLACEHOLDER_UNSUPPORTED`: at least one placeholder- or ICU-bearing entry was left untranslated
|
|
176
|
-
* because DeepL cannot preserve those tokens; such entries are withheld (absent from the result maps)
|
|
177
|
-
* rather than sent to DeepL and mangled.
|
|
178
|
-
*/
|
|
179
|
-
type ProviderNoticeCode = "FORMALITY_DOWNGRADED" | "GLOSSARY_IGNORED" | "PLACEHOLDER_UNSUPPORTED";
|
|
180
|
-
/**
|
|
181
|
-
* An observable, structured signal that something was gracefully degraded (not an
|
|
182
|
-
* error). Carries only a stable code and a static message, never a key or content.
|
|
183
|
-
* Surfaced as result data, never thrown; callers inspect it but need not treat it as a failure.
|
|
184
|
-
*/
|
|
185
|
-
interface ProviderNotice {
|
|
186
|
-
/** The stable {@link ProviderNoticeCode} for what was degraded. */
|
|
187
|
-
readonly code: ProviderNoticeCode;
|
|
188
|
-
/** A static, safe description; never a key or translatable content. */
|
|
189
|
-
readonly message: string;
|
|
190
|
-
}
|
|
191
199
|
|
|
192
200
|
/**
|
|
193
201
|
* The Gemini authoring model type, sourced from the installed SDK's own model union so
|
|
@@ -943,11 +951,13 @@ interface LocaleSummary {
|
|
|
943
951
|
*/
|
|
944
952
|
readonly integrityMismatches: readonly string[];
|
|
945
953
|
/**
|
|
946
|
-
* Keys withheld because
|
|
947
|
-
*
|
|
948
|
-
*
|
|
949
|
-
* {@link LocaleSummary.notices} entry carries the secret-free failure code
|
|
950
|
-
*
|
|
954
|
+
* Keys withheld because nothing was translated for them this run, as distinct from a translation
|
|
955
|
+
* that came back and failed the placeholder-integrity check. This covers two causes: the provider
|
|
956
|
+
* call itself failed (for example a revoked API key, a rate limit, or a network timeout), in which
|
|
957
|
+
* case the corresponding {@link LocaleSummary.notices} entry carries the secret-free failure code
|
|
958
|
+
* and message; or the call succeeded but the key was still missing or duplicated in the response
|
|
959
|
+
* after the shared LLM layer's bounded reconcile repair round, in which case no notice is added.
|
|
960
|
+
* Empty in a dry-run.
|
|
951
961
|
*/
|
|
952
962
|
readonly providerFailures: readonly string[];
|
|
953
963
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -100,7 +100,31 @@ interface Usage {
|
|
|
100
100
|
readonly inputTokens: number;
|
|
101
101
|
readonly outputTokens: number;
|
|
102
102
|
}
|
|
103
|
-
/**
|
|
103
|
+
/**
|
|
104
|
+
* Stable codes for a provider's graceful-degradation notices. These are returned DATA on a
|
|
105
|
+
* successful result, NOT thrown:
|
|
106
|
+
*
|
|
107
|
+
* - `FORMALITY_DOWNGRADED`: a requested formality was not applied (DeepL's free tier does not
|
|
108
|
+
* support it).
|
|
109
|
+
* - `GLOSSARY_IGNORED`: a supplied generic glossary term map was not applied (DeepL only applies a
|
|
110
|
+
* native glossary id, never a term map).
|
|
111
|
+
* - `PLACEHOLDER_UNSUPPORTED`: at least one placeholder- or ICU-bearing entry was left untranslated
|
|
112
|
+
* because the provider cannot preserve those tokens; such entries are withheld (absent from the
|
|
113
|
+
* result maps) rather than sent to the provider and mangled.
|
|
114
|
+
*/
|
|
115
|
+
type ProviderNoticeCode = "FORMALITY_DOWNGRADED" | "GLOSSARY_IGNORED" | "PLACEHOLDER_UNSUPPORTED";
|
|
116
|
+
/**
|
|
117
|
+
* An observable, structured signal that something was gracefully degraded (not an
|
|
118
|
+
* error). Carries only a stable code and a static message, never a key or content.
|
|
119
|
+
* Surfaced as result data, never thrown; callers inspect it but need not treat it as a failure.
|
|
120
|
+
*/
|
|
121
|
+
interface ProviderNotice {
|
|
122
|
+
/** The stable {@link ProviderNoticeCode} for what was degraded. */
|
|
123
|
+
readonly code: ProviderNoticeCode;
|
|
124
|
+
/** A static, safe description; never a key or translatable content. */
|
|
125
|
+
readonly message: string;
|
|
126
|
+
}
|
|
127
|
+
/** Result of a batch translation: per-key values, per-key integrity outcomes, and any notices. */
|
|
104
128
|
interface TranslateResult {
|
|
105
129
|
/** The translated value for each requested key. */
|
|
106
130
|
readonly values: ReadonlyMap<string, string>;
|
|
@@ -108,6 +132,12 @@ interface TranslateResult {
|
|
|
108
132
|
readonly integrity: ReadonlyMap<string, PlaceholderIntegrityResult$1>;
|
|
109
133
|
/** Token usage when the provider reports it; absent for token-less providers. */
|
|
110
134
|
readonly usage?: Usage;
|
|
135
|
+
/**
|
|
136
|
+
* Graceful-degradation notices for this batch. Every provider populates this as a present array:
|
|
137
|
+
* DeepL reports real notices (for example `GLOSSARY_IGNORED`); an LLM provider with nothing to
|
|
138
|
+
* report returns an empty array rather than omitting the field.
|
|
139
|
+
*/
|
|
140
|
+
readonly notices?: readonly ProviderNotice[];
|
|
111
141
|
}
|
|
112
142
|
/**
|
|
113
143
|
* The single contract every provider implements. It is narrow enough that a machine-translation API like
|
|
@@ -166,28 +196,6 @@ interface TranslationProvider {
|
|
|
166
196
|
* are still accepted. This drives editor completions only; the runtime schema validates.
|
|
167
197
|
*/
|
|
168
198
|
type AnthropicModel = Anthropic.Messages.Model;
|
|
169
|
-
/**
|
|
170
|
-
* Stable codes for the DeepL graceful-degradation notices, DeepL only. These are returned DATA on a
|
|
171
|
-
* successful result, NOT thrown:
|
|
172
|
-
*
|
|
173
|
-
* - `FORMALITY_DOWNGRADED`: a requested formality was not applied (the free tier does not support it).
|
|
174
|
-
* - `GLOSSARY_IGNORED`: a supplied generic glossary was not applied.
|
|
175
|
-
* - `PLACEHOLDER_UNSUPPORTED`: at least one placeholder- or ICU-bearing entry was left untranslated
|
|
176
|
-
* because DeepL cannot preserve those tokens; such entries are withheld (absent from the result maps)
|
|
177
|
-
* rather than sent to DeepL and mangled.
|
|
178
|
-
*/
|
|
179
|
-
type ProviderNoticeCode = "FORMALITY_DOWNGRADED" | "GLOSSARY_IGNORED" | "PLACEHOLDER_UNSUPPORTED";
|
|
180
|
-
/**
|
|
181
|
-
* An observable, structured signal that something was gracefully degraded (not an
|
|
182
|
-
* error). Carries only a stable code and a static message, never a key or content.
|
|
183
|
-
* Surfaced as result data, never thrown; callers inspect it but need not treat it as a failure.
|
|
184
|
-
*/
|
|
185
|
-
interface ProviderNotice {
|
|
186
|
-
/** The stable {@link ProviderNoticeCode} for what was degraded. */
|
|
187
|
-
readonly code: ProviderNoticeCode;
|
|
188
|
-
/** A static, safe description; never a key or translatable content. */
|
|
189
|
-
readonly message: string;
|
|
190
|
-
}
|
|
191
199
|
|
|
192
200
|
/**
|
|
193
201
|
* The Gemini authoring model type, sourced from the installed SDK's own model union so
|
|
@@ -943,11 +951,13 @@ interface LocaleSummary {
|
|
|
943
951
|
*/
|
|
944
952
|
readonly integrityMismatches: readonly string[];
|
|
945
953
|
/**
|
|
946
|
-
* Keys withheld because
|
|
947
|
-
*
|
|
948
|
-
*
|
|
949
|
-
* {@link LocaleSummary.notices} entry carries the secret-free failure code
|
|
950
|
-
*
|
|
954
|
+
* Keys withheld because nothing was translated for them this run, as distinct from a translation
|
|
955
|
+
* that came back and failed the placeholder-integrity check. This covers two causes: the provider
|
|
956
|
+
* call itself failed (for example a revoked API key, a rate limit, or a network timeout), in which
|
|
957
|
+
* case the corresponding {@link LocaleSummary.notices} entry carries the secret-free failure code
|
|
958
|
+
* and message; or the call succeeded but the key was still missing or duplicated in the response
|
|
959
|
+
* after the shared LLM layer's bounded reconcile repair round, in which case no notice is added.
|
|
960
|
+
* Empty in a dry-run.
|
|
951
961
|
*/
|
|
952
962
|
readonly providerFailures: readonly string[];
|
|
953
963
|
/**
|
package/dist/index.js
CHANGED
|
@@ -473,16 +473,14 @@ function validateRequest(request) {
|
|
|
473
473
|
return parsed.data;
|
|
474
474
|
}
|
|
475
475
|
function toIntegrityInputs(entries, values) {
|
|
476
|
-
|
|
476
|
+
const inputs = [];
|
|
477
|
+
for (const entry of entries) {
|
|
477
478
|
const translatedValue = values.get(entry.key);
|
|
478
|
-
if (translatedValue
|
|
479
|
-
|
|
480
|
-
"INVALID_RESPONSE",
|
|
481
|
-
"The provider response is missing one or more keys."
|
|
482
|
-
);
|
|
479
|
+
if (translatedValue !== void 0) {
|
|
480
|
+
inputs.push({ key: entry.key, sourceValue: entry.value, translatedValue });
|
|
483
481
|
}
|
|
484
|
-
|
|
485
|
-
|
|
482
|
+
}
|
|
483
|
+
return inputs;
|
|
486
484
|
}
|
|
487
485
|
function toItem(entry) {
|
|
488
486
|
return {
|
|
@@ -514,25 +512,29 @@ function deriveJsonSchema(schema) {
|
|
|
514
512
|
}
|
|
515
513
|
return result;
|
|
516
514
|
}
|
|
517
|
-
function
|
|
518
|
-
const
|
|
519
|
-
const
|
|
515
|
+
function partitionTranslations(translations, requested) {
|
|
516
|
+
const firstSeen = /* @__PURE__ */ new Map();
|
|
517
|
+
const duplicated = /* @__PURE__ */ new Set();
|
|
520
518
|
for (const { key, value } of translations) {
|
|
521
|
-
if (!requested.has(key)
|
|
522
|
-
throw new ProviderError(
|
|
523
|
-
"INVALID_RESPONSE",
|
|
524
|
-
"The provider returned an unexpected or duplicate key."
|
|
525
|
-
);
|
|
519
|
+
if (!requested.has(key)) {
|
|
520
|
+
throw new ProviderError("INVALID_RESPONSE", "The provider returned an unexpected key.");
|
|
526
521
|
}
|
|
527
|
-
|
|
522
|
+
if (firstSeen.has(key)) {
|
|
523
|
+
duplicated.add(key);
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
firstSeen.set(key, value);
|
|
528
527
|
}
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
528
|
+
return { firstSeen, duplicated };
|
|
529
|
+
}
|
|
530
|
+
function reconcile(translations, requestedKeys) {
|
|
531
|
+
const requested = new Set(requestedKeys);
|
|
532
|
+
const { firstSeen, duplicated } = partitionTranslations(translations, requested);
|
|
533
|
+
const missingKeys = requestedKeys.filter((key) => duplicated.has(key) || !firstSeen.has(key));
|
|
534
|
+
for (const key of duplicated) {
|
|
535
|
+
firstSeen.delete(key);
|
|
534
536
|
}
|
|
535
|
-
return
|
|
537
|
+
return { accepted: firstSeen, missingKeys };
|
|
536
538
|
}
|
|
537
539
|
function reconcileResult(raw, requestedKeys) {
|
|
538
540
|
const parsed = translationsResultSchema.safeParse(raw);
|
|
@@ -544,22 +546,54 @@ function reconcileResult(raw, requestedKeys) {
|
|
|
544
546
|
}
|
|
545
547
|
return reconcile(parsed.data.translations, requestedKeys);
|
|
546
548
|
}
|
|
549
|
+
var MAX_REPAIR_ROUNDS = 1;
|
|
547
550
|
async function runLlmTranslation(request, mechanism) {
|
|
548
551
|
const data = validateRequest(request);
|
|
552
|
+
const signal = request.signal;
|
|
553
|
+
const first = await requestTranslations(mechanism, data, signal);
|
|
554
|
+
const values = first.outcome.accepted;
|
|
555
|
+
let usage = first.completion.usage;
|
|
556
|
+
let toRepair = entriesFor(data.entries, first.outcome.missingKeys);
|
|
557
|
+
for (let round = 0; round < MAX_REPAIR_ROUNDS && toRepair.length > 0; round += 1) {
|
|
558
|
+
const repair = await requestTranslations(mechanism, { ...data, entries: toRepair }, signal);
|
|
559
|
+
for (const [key, value] of repair.outcome.accepted) {
|
|
560
|
+
values.set(key, value);
|
|
561
|
+
}
|
|
562
|
+
usage = mergeUsage(usage, repair.completion.usage);
|
|
563
|
+
toRepair = entriesFor(data.entries, repair.outcome.missingKeys);
|
|
564
|
+
}
|
|
565
|
+
const integrity = checkBatchIntegrity(
|
|
566
|
+
toIntegrityInputs(data.entries, values),
|
|
567
|
+
request.extractPlaceholders,
|
|
568
|
+
request.comparePlaceholders
|
|
569
|
+
);
|
|
570
|
+
return usage === void 0 ? { values, integrity, notices: [] } : { values, integrity, usage, notices: [] };
|
|
571
|
+
}
|
|
572
|
+
async function requestTranslations(mechanism, data, signal) {
|
|
549
573
|
const payloadJson = JSON.stringify(buildDataPayload(data));
|
|
550
574
|
const requestedKeys = data.entries.map((entry) => entry.key);
|
|
551
575
|
const completion = await mechanism.translate({
|
|
552
576
|
payloadJson,
|
|
553
577
|
requestedKeys,
|
|
554
|
-
...
|
|
578
|
+
...signal !== void 0 ? { signal } : {}
|
|
555
579
|
});
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
580
|
+
return { completion, outcome: reconcileResult(completion.raw, requestedKeys) };
|
|
581
|
+
}
|
|
582
|
+
function entriesFor(entries, keys) {
|
|
583
|
+
const wanted = new Set(keys);
|
|
584
|
+
return entries.filter((entry) => wanted.has(entry.key));
|
|
585
|
+
}
|
|
586
|
+
function mergeUsage(first, second) {
|
|
587
|
+
if (first === void 0) {
|
|
588
|
+
return second;
|
|
589
|
+
}
|
|
590
|
+
if (second === void 0) {
|
|
591
|
+
return first;
|
|
592
|
+
}
|
|
593
|
+
return {
|
|
594
|
+
inputTokens: first.inputTokens + second.inputTokens,
|
|
595
|
+
outputTokens: first.outputTokens + second.outputTokens
|
|
596
|
+
};
|
|
563
597
|
}
|
|
564
598
|
var OUTPUT_TRUNCATED_MESSAGE = "The provider stopped because the output-token limit was reached. Reduce the batch size or raise the configured max output tokens.";
|
|
565
599
|
function assertNotTruncated(truncated) {
|
|
@@ -807,7 +841,10 @@ function createDeepLProvider(config, deps = {}) {
|
|
|
807
841
|
return {
|
|
808
842
|
id: PROVIDER_ID2,
|
|
809
843
|
kind: "machine-translation",
|
|
810
|
-
|
|
844
|
+
// Honest capability signal: DeepL only ever applies a pre-created native glossary id, never a
|
|
845
|
+
// generic term map (see buildTranslateOptions). Without one configured, a supplied term map is
|
|
846
|
+
// silently ignored and surfaces only as a GLOSSARY_IGNORED notice.
|
|
847
|
+
supportsGlossary: validConfig.glossaryId !== void 0,
|
|
811
848
|
translateBatch: (request) => translate(bundle, validConfig, request)
|
|
812
849
|
};
|
|
813
850
|
}
|
|
@@ -1111,16 +1148,19 @@ function buildResponseFormat(mode) {
|
|
|
1111
1148
|
}
|
|
1112
1149
|
};
|
|
1113
1150
|
}
|
|
1114
|
-
function buildOpenAiRequest(config, payloadJson, mode = "strict-schema") {
|
|
1115
|
-
|
|
1116
|
-
model: config.model,
|
|
1117
|
-
max_completion_tokens: config.maxOutputTokens,
|
|
1151
|
+
function buildOpenAiRequest(config, payloadJson, mode = "strict-schema", tokenLimitField = "max_completion_tokens") {
|
|
1152
|
+
const base = {
|
|
1118
1153
|
messages: [
|
|
1119
1154
|
{ role: "system", content: OPENAI_SYSTEM_RULES },
|
|
1120
1155
|
{ role: "user", content: payloadJson }
|
|
1121
1156
|
],
|
|
1157
|
+
model: config.model,
|
|
1122
1158
|
response_format: buildResponseFormat(mode)
|
|
1123
1159
|
};
|
|
1160
|
+
if (tokenLimitField === "max_tokens") {
|
|
1161
|
+
return { ...base, max_tokens: config.maxOutputTokens };
|
|
1162
|
+
}
|
|
1163
|
+
return { ...base, max_completion_tokens: config.maxOutputTokens };
|
|
1124
1164
|
}
|
|
1125
1165
|
function advanceStringScan(char, escaped) {
|
|
1126
1166
|
if (escaped) {
|
|
@@ -1291,7 +1331,7 @@ function createOpenAiCompatibleProvider(config, deps = {}) {
|
|
|
1291
1331
|
function createMechanism4(client, config) {
|
|
1292
1332
|
return {
|
|
1293
1333
|
translate: async ({ payloadJson, signal }) => {
|
|
1294
|
-
const body = buildOpenAiRequest(config, payloadJson, "strict-schema");
|
|
1334
|
+
const body = buildOpenAiRequest(config, payloadJson, "strict-schema", "max_tokens");
|
|
1295
1335
|
const completion = await callClient5(client, body, signal);
|
|
1296
1336
|
return extractOpenAiResult(completion, true);
|
|
1297
1337
|
}
|
|
@@ -1892,6 +1932,9 @@ async function atomicWriteFile(path, data, ops = nodeOps) {
|
|
|
1892
1932
|
throw error;
|
|
1893
1933
|
}
|
|
1894
1934
|
}
|
|
1935
|
+
function stripLeadingBom(content) {
|
|
1936
|
+
return content.charCodeAt(0) === 65279 ? content.slice(1) : content;
|
|
1937
|
+
}
|
|
1895
1938
|
async function readBoundedUtf82(handle, size) {
|
|
1896
1939
|
const buffer = Buffer.allocUnsafe(size);
|
|
1897
1940
|
let offset = 0;
|
|
@@ -1902,7 +1945,7 @@ async function readBoundedUtf82(handle, size) {
|
|
|
1902
1945
|
}
|
|
1903
1946
|
offset += bytesRead;
|
|
1904
1947
|
}
|
|
1905
|
-
return buffer.toString("utf8", 0, offset);
|
|
1948
|
+
return stripLeadingBom(buffer.toString("utf8", 0, offset));
|
|
1906
1949
|
}
|
|
1907
1950
|
async function readBounded2(filePath) {
|
|
1908
1951
|
const handle = await open(filePath, "r");
|
|
@@ -2945,15 +2988,8 @@ function subBatchFailedNotice(count, error) {
|
|
|
2945
2988
|
}
|
|
2946
2989
|
|
|
2947
2990
|
// src/flow/notices.ts
|
|
2948
|
-
function isNotice(value) {
|
|
2949
|
-
return typeof value === "object" && value !== null && typeof value.code === "string" && typeof value.message === "string";
|
|
2950
|
-
}
|
|
2951
2991
|
function readNotices(result) {
|
|
2952
|
-
|
|
2953
|
-
if (!Array.isArray(candidate)) {
|
|
2954
|
-
return [];
|
|
2955
|
-
}
|
|
2956
|
-
return candidate.filter(isNotice);
|
|
2992
|
+
return result.notices ?? [];
|
|
2957
2993
|
}
|
|
2958
2994
|
|
|
2959
2995
|
// src/flow/plural-categories.ts
|
|
@@ -3157,20 +3193,26 @@ async function runGenerationSubBatch(context, batch, accepted, withheld, provide
|
|
|
3157
3193
|
return [subBatchFailedNotice(batch.length, error)];
|
|
3158
3194
|
}
|
|
3159
3195
|
for (const item of batch) {
|
|
3160
|
-
|
|
3161
|
-
const integrity = result.integrity.get(item.targetKey);
|
|
3162
|
-
if (value !== void 0 && integrity?.matches === true) {
|
|
3163
|
-
accepted.push({
|
|
3164
|
-
targetKey: item.targetKey,
|
|
3165
|
-
entry: { ...syntheticEntry(item), value },
|
|
3166
|
-
lockHash: generatedLockHash(item.governingEntries, item.category)
|
|
3167
|
-
});
|
|
3168
|
-
} else {
|
|
3169
|
-
withheld.push(item.targetKey);
|
|
3170
|
-
}
|
|
3196
|
+
foldGenerationItem(item, result, accepted, withheld, providerFailures);
|
|
3171
3197
|
}
|
|
3172
3198
|
return readNotices(result);
|
|
3173
3199
|
}
|
|
3200
|
+
function foldGenerationItem(item, result, accepted, withheld, providerFailures) {
|
|
3201
|
+
const value = result.values.get(item.targetKey);
|
|
3202
|
+
if (value === void 0) {
|
|
3203
|
+
providerFailures.push(item.targetKey);
|
|
3204
|
+
return;
|
|
3205
|
+
}
|
|
3206
|
+
if (result.integrity.get(item.targetKey)?.matches === true) {
|
|
3207
|
+
accepted.push({
|
|
3208
|
+
targetKey: item.targetKey,
|
|
3209
|
+
entry: { ...syntheticEntry(item), value },
|
|
3210
|
+
lockHash: generatedLockHash(item.governingEntries, item.category)
|
|
3211
|
+
});
|
|
3212
|
+
} else {
|
|
3213
|
+
withheld.push(item.targetKey);
|
|
3214
|
+
}
|
|
3215
|
+
}
|
|
3174
3216
|
|
|
3175
3217
|
// src/flow/locale-run.ts
|
|
3176
3218
|
function emptyResource(locale, format) {
|
|
@@ -3358,16 +3400,22 @@ async function runSubBatch(provider, params, batch, accepted, integrityMismatche
|
|
|
3358
3400
|
return [subBatchFailedNotice(batch.length, error)];
|
|
3359
3401
|
}
|
|
3360
3402
|
for (const entry of batch) {
|
|
3361
|
-
|
|
3362
|
-
const integrity = result.integrity.get(entry.key);
|
|
3363
|
-
if (value !== void 0 && integrity?.matches === true) {
|
|
3364
|
-
accepted.set(entry.key, { value, source: entry });
|
|
3365
|
-
} else {
|
|
3366
|
-
integrityMismatches.push(entry.key);
|
|
3367
|
-
}
|
|
3403
|
+
foldEntryResult(entry, result, accepted, integrityMismatches, providerFailures);
|
|
3368
3404
|
}
|
|
3369
3405
|
return readNotices(result);
|
|
3370
3406
|
}
|
|
3407
|
+
function foldEntryResult(entry, result, accepted, integrityMismatches, providerFailures) {
|
|
3408
|
+
const value = result.values.get(entry.key);
|
|
3409
|
+
if (value === void 0) {
|
|
3410
|
+
providerFailures.push(entry.key);
|
|
3411
|
+
return;
|
|
3412
|
+
}
|
|
3413
|
+
if (result.integrity.get(entry.key)?.matches === true) {
|
|
3414
|
+
accepted.set(entry.key, { value, source: entry });
|
|
3415
|
+
} else {
|
|
3416
|
+
integrityMismatches.push(entry.key);
|
|
3417
|
+
}
|
|
3418
|
+
}
|
|
3371
3419
|
function computeLockEntries(params, merged, withheld, generated) {
|
|
3372
3420
|
const lockEntries = {};
|
|
3373
3421
|
const sourceBaseKeys = sourcePluralBaseKeys(params.source);
|