lingo.dev 0.74.10 → 0.74.11

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/build/cli.mjs CHANGED
@@ -580,7 +580,7 @@ import { bucketTypeSchema, localeCodeSchema, resolveOverridenLocale as resolveOv
580
580
  import { ReplexicaEngine } from "@lingo.dev/_sdk";
581
581
  import { Command as Command6 } from "interactive-commander";
582
582
  import Z4 from "zod";
583
- import _17 from "lodash";
583
+ import _18 from "lodash";
584
584
  import Ora5 from "ora";
585
585
 
586
586
  // src/cli/loaders/_utils.ts
@@ -682,26 +682,84 @@ function createJsonLoader() {
682
682
 
683
683
  // src/cli/loaders/flat.ts
684
684
  import { flatten, unflatten } from "flat";
685
+ import _5 from "lodash";
686
+ var OBJECT_NUMERIC_KEY_PREFIX = "__lingodotdev__obj__";
685
687
  function createFlatLoader() {
688
+ let denormalizedKeysMap;
686
689
  return createLoader({
687
690
  pull: async (locale, input) => {
688
- return flatten(input || {}, {
691
+ const denormalized = denormalizeObjectKeys(input || {});
692
+ const flattened = flatten(denormalized, {
689
693
  delimiter: "/",
690
694
  transformKey(key) {
691
695
  return encodeURIComponent(String(key));
692
696
  }
693
697
  });
698
+ denormalizedKeysMap = buildDenormalizedKeysMap(flattened);
699
+ const normalized = normalizeObjectKeys(flattened);
700
+ return normalized;
694
701
  },
695
702
  push: async (locale, data) => {
696
- return unflatten(data || {}, {
703
+ const denormalized = mapDeormalizedKeys(data, denormalizedKeysMap);
704
+ const unflattened = unflatten(denormalized || {}, {
697
705
  delimiter: "/",
698
706
  transformKey(key) {
699
707
  return decodeURIComponent(String(key));
700
708
  }
701
709
  });
710
+ const normalized = normalizeObjectKeys(unflattened);
711
+ return normalized;
702
712
  }
703
713
  });
704
714
  }
715
+ function buildDenormalizedKeysMap(obj) {
716
+ return Object.keys(obj).reduce(
717
+ (acc, key) => {
718
+ const normalizedKey = `${key}`.replace(OBJECT_NUMERIC_KEY_PREFIX, "");
719
+ acc[normalizedKey] = key;
720
+ return acc;
721
+ },
722
+ {}
723
+ );
724
+ }
725
+ function mapDeormalizedKeys(obj, denormalizedKeysMap) {
726
+ return Object.keys(obj).reduce(
727
+ (acc, key) => {
728
+ const denormalizedKey = denormalizedKeysMap[key];
729
+ acc[denormalizedKey] = obj[key];
730
+ return acc;
731
+ },
732
+ {}
733
+ );
734
+ }
735
+ function denormalizeObjectKeys(obj) {
736
+ if (_5.isObject(obj) && !_5.isArray(obj)) {
737
+ return _5.transform(
738
+ obj,
739
+ (result, value, key) => {
740
+ const newKey = !isNaN(Number(key)) ? `${OBJECT_NUMERIC_KEY_PREFIX}${key}` : key;
741
+ result[newKey] = _5.isObject(value) ? denormalizeObjectKeys(value) : value;
742
+ },
743
+ {}
744
+ );
745
+ } else {
746
+ return obj;
747
+ }
748
+ }
749
+ function normalizeObjectKeys(obj) {
750
+ if (_5.isObject(obj) && !_5.isArray(obj)) {
751
+ return _5.transform(
752
+ obj,
753
+ (result, value, key) => {
754
+ const newKey = `${key}`.replace(OBJECT_NUMERIC_KEY_PREFIX, "");
755
+ result[newKey] = _5.isObject(value) ? normalizeObjectKeys(value) : value;
756
+ },
757
+ {}
758
+ );
759
+ } else {
760
+ return obj;
761
+ }
762
+ }
705
763
 
706
764
  // src/cli/loaders/text-file.ts
707
765
  import fs5 from "fs/promises";
@@ -713,7 +771,7 @@ function createTextFileLoader(pathPattern) {
713
771
  const trimmedResult = result.trim();
714
772
  return trimmedResult;
715
773
  },
716
- async push(locale, data, _19, originalLocale) {
774
+ async push(locale, data, _20, originalLocale) {
717
775
  const draftPath = pathPattern.replace("[locale]", locale);
718
776
  const finalPath = path6.resolve(draftPath);
719
777
  const dirPath = path6.dirname(finalPath);
@@ -782,15 +840,15 @@ function createRootKeyLoader(replaceAll = false) {
782
840
  }
783
841
 
784
842
  // src/cli/loaders/flutter.ts
785
- import _5 from "lodash";
843
+ import _6 from "lodash";
786
844
  function createFlutterLoader() {
787
845
  return createLoader({
788
846
  async pull(locale, input) {
789
- const result = _5.pickBy(input, (value, key) => !key.startsWith("@"));
847
+ const result = _6.pickBy(input, (value, key) => !key.startsWith("@"));
790
848
  return result;
791
849
  },
792
850
  async push(locale, data, originalInput) {
793
- const result = _5.merge({}, originalInput, { "@@locale": locale }, data);
851
+ const result = _6.merge({}, originalInput, { "@@locale": locale }, data);
794
852
  return result;
795
853
  }
796
854
  });
@@ -892,7 +950,7 @@ function createAndroidLoader() {
892
950
  // src/cli/loaders/csv.ts
893
951
  import { parse } from "csv-parse/sync";
894
952
  import { stringify } from "csv-stringify/sync";
895
- import _6 from "lodash";
953
+ import _7 from "lodash";
896
954
  function createCsvLoader() {
897
955
  return createLoader({
898
956
  async pull(locale, _input) {
@@ -900,7 +958,7 @@ function createCsvLoader() {
900
958
  columns: true
901
959
  });
902
960
  const result = {};
903
- _6.forEach(input, (row) => {
961
+ _7.forEach(input, (row) => {
904
962
  const key = row.id;
905
963
  if (key && row[locale]) {
906
964
  result[key] = row[locale];
@@ -1118,7 +1176,7 @@ function createPropertiesLoader() {
1118
1176
  return result;
1119
1177
  },
1120
1178
  async push(locale, payload) {
1121
- const result = Object.entries(payload).filter(([_19, value]) => value != null).map(([key, value]) => `${key}=${value}`).join("\n");
1179
+ const result = Object.entries(payload).filter(([_20, value]) => value != null).map(([key, value]) => `${key}=${value}`).join("\n");
1122
1180
  return result;
1123
1181
  }
1124
1182
  });
@@ -1204,7 +1262,7 @@ function createXcodeStringsdictLoader() {
1204
1262
  }
1205
1263
 
1206
1264
  // src/cli/loaders/xcode-xcstrings.ts
1207
- import _7 from "lodash";
1265
+ import _8 from "lodash";
1208
1266
  function createXcodeXcstringsLoader() {
1209
1267
  return createLoader({
1210
1268
  async pull(locale, input) {
@@ -1268,7 +1326,7 @@ function createXcodeXcstringsLoader() {
1268
1326
  };
1269
1327
  }
1270
1328
  }
1271
- const result = _7.merge({}, originalInput, langDataToMerge);
1329
+ const result = _8.merge({}, originalInput, langDataToMerge);
1272
1330
  return result;
1273
1331
  }
1274
1332
  });
@@ -1310,17 +1368,17 @@ async function loadPrettierConfig() {
1310
1368
  }
1311
1369
 
1312
1370
  // src/cli/loaders/unlocalizable.ts
1313
- import _8 from "lodash";
1371
+ import _9 from "lodash";
1314
1372
  import _isUrl from "is-url";
1315
1373
  import { isValid, parseISO } from "date-fns";
1316
1374
  function createUnlocalizableLoader() {
1317
1375
  const rules = {
1318
- isEmpty: (v) => _8.isEmpty(v),
1319
- isNumber: (v) => !_8.isNaN(_8.toNumber(v)),
1320
- isBoolean: (v) => _8.isBoolean(v),
1321
- isIsoDate: (v) => _8.isString(v) && _isIsoDate(v),
1322
- isSystemId: (v) => _8.isString(v) && _isSystemId(v),
1323
- isUrl: (v) => _8.isString(v) && _isUrl(v)
1376
+ isEmpty: (v) => _9.isEmpty(v),
1377
+ isNumber: (v) => !_9.isNaN(_9.toNumber(v)),
1378
+ isBoolean: (v) => _9.isBoolean(v),
1379
+ isIsoDate: (v) => _9.isString(v) && _isIsoDate(v),
1380
+ isSystemId: (v) => _9.isString(v) && _isSystemId(v),
1381
+ isUrl: (v) => _9.isString(v) && _isUrl(v)
1324
1382
  };
1325
1383
  return createLoader({
1326
1384
  async pull(locale, input) {
@@ -1331,12 +1389,12 @@ function createUnlocalizableLoader() {
1331
1389
  }
1332
1390
  }
1333
1391
  return false;
1334
- }).map(([key, _19]) => key);
1335
- const result = _8.omitBy(input, (_19, key) => passthroughKeys.includes(key));
1392
+ }).map(([key, _20]) => key);
1393
+ const result = _9.omitBy(input, (_20, key) => passthroughKeys.includes(key));
1336
1394
  return result;
1337
1395
  },
1338
1396
  async push(locale, data, originalInput) {
1339
- const result = _8.merge({}, originalInput, data);
1397
+ const result = _9.merge({}, originalInput, data);
1340
1398
  return result;
1341
1399
  }
1342
1400
  });
@@ -1349,7 +1407,7 @@ function _isIsoDate(v) {
1349
1407
  }
1350
1408
 
1351
1409
  // src/cli/loaders/po/index.ts
1352
- import _9 from "lodash";
1410
+ import _10 from "lodash";
1353
1411
  import gettextParser from "gettext-parser";
1354
1412
  function createPoLoader(params = { multiline: false }) {
1355
1413
  return composeLoaders(createPoDataLoader(params), createPoContentLoader());
@@ -1362,7 +1420,7 @@ function createPoDataLoader(params) {
1362
1420
  const sections = input.split("\n\n").filter(Boolean);
1363
1421
  for (const section of sections) {
1364
1422
  const sectionPo = gettextParser.po.parse(section);
1365
- const contextKey = _9.keys(sectionPo.translations)[0];
1423
+ const contextKey = _10.keys(sectionPo.translations)[0];
1366
1424
  const entries = sectionPo.translations[contextKey];
1367
1425
  Object.entries(entries).forEach(([msgid, entry]) => {
1368
1426
  if (msgid && entry.msgid) {
@@ -1380,12 +1438,12 @@ function createPoDataLoader(params) {
1380
1438
  const sections = originalInput?.split("\n\n").filter(Boolean) || [];
1381
1439
  const result = sections.map((section) => {
1382
1440
  const sectionPo = gettextParser.po.parse(section);
1383
- const contextKey = _9.keys(sectionPo.translations)[0];
1441
+ const contextKey = _10.keys(sectionPo.translations)[0];
1384
1442
  const entries = sectionPo.translations[contextKey];
1385
1443
  const msgid = Object.keys(entries).find((key) => entries[key].msgid);
1386
1444
  if (!msgid) return section;
1387
1445
  if (data[msgid]) {
1388
- const updatedPo = _9.merge({}, sectionPo, {
1446
+ const updatedPo = _10.merge({}, sectionPo, {
1389
1447
  translations: {
1390
1448
  [contextKey]: {
1391
1449
  [msgid]: {
@@ -1405,7 +1463,7 @@ function createPoDataLoader(params) {
1405
1463
  function createPoContentLoader() {
1406
1464
  return createLoader({
1407
1465
  async pull(locale, input) {
1408
- const result = _9.chain(input).entries().filter(([, entry]) => !!entry.msgid).map(([, entry]) => [
1466
+ const result = _10.chain(input).entries().filter(([, entry]) => !!entry.msgid).map(([, entry]) => [
1409
1467
  entry.msgid,
1410
1468
  {
1411
1469
  singular: entry.msgstr[0] || entry.msgid,
@@ -1415,7 +1473,7 @@ function createPoContentLoader() {
1415
1473
  return result;
1416
1474
  },
1417
1475
  async push(locale, data, originalInput) {
1418
- const result = _9.chain(originalInput).entries().map(([, entry]) => [
1476
+ const result = _10.chain(originalInput).entries().map(([, entry]) => [
1419
1477
  entry.msgid,
1420
1478
  {
1421
1479
  ...entry,
@@ -1538,34 +1596,34 @@ var datoSettingsSchema = Z2.object({
1538
1596
  });
1539
1597
 
1540
1598
  // src/cli/loaders/dato/filter.ts
1541
- import _10 from "lodash";
1599
+ import _11 from "lodash";
1542
1600
  function createDatoFilterLoader() {
1543
1601
  return createLoader({
1544
1602
  async pull(locale, input) {
1545
1603
  const result = {};
1546
- for (const [modelId, modelInfo] of _10.entries(input)) {
1604
+ for (const [modelId, modelInfo] of _11.entries(input)) {
1547
1605
  result[modelId] = {};
1548
1606
  for (const record of modelInfo.records) {
1549
- result[modelId][record.id] = _10.chain(modelInfo.fields).mapKeys((field) => field.api_key).mapValues((field) => _10.get(record, [field.api_key, locale])).value();
1607
+ result[modelId][record.id] = _11.chain(modelInfo.fields).mapKeys((field) => field.api_key).mapValues((field) => _11.get(record, [field.api_key, locale])).value();
1550
1608
  }
1551
1609
  }
1552
1610
  return result;
1553
1611
  },
1554
1612
  async push(locale, data, originalInput, originalLocale) {
1555
- const result = _10.cloneDeep(originalInput || {});
1556
- for (const [modelId, modelInfo] of _10.entries(result)) {
1613
+ const result = _11.cloneDeep(originalInput || {});
1614
+ for (const [modelId, modelInfo] of _11.entries(result)) {
1557
1615
  for (const record of modelInfo.records) {
1558
- for (const [fieldId, fieldValue] of _10.entries(record)) {
1616
+ for (const [fieldId, fieldValue] of _11.entries(record)) {
1559
1617
  const fieldInfo = modelInfo.fields.find((field) => field.api_key === fieldId);
1560
1618
  if (fieldInfo) {
1561
- const sourceFieldValue = _10.get(fieldValue, [originalLocale]);
1562
- const targetFieldValue = _10.get(data, [modelId, record.id, fieldId]);
1619
+ const sourceFieldValue = _11.get(fieldValue, [originalLocale]);
1620
+ const targetFieldValue = _11.get(data, [modelId, record.id, fieldId]);
1563
1621
  if (targetFieldValue) {
1564
- _10.set(record, [fieldId, locale], targetFieldValue);
1622
+ _11.set(record, [fieldId, locale], targetFieldValue);
1565
1623
  } else {
1566
- _10.set(record, [fieldId, locale], sourceFieldValue);
1624
+ _11.set(record, [fieldId, locale], sourceFieldValue);
1567
1625
  }
1568
- _10.chain(fieldValue).keys().reject((loc) => loc === locale || loc === originalLocale).filter((loc) => _10.isEmpty(_10.get(fieldValue, [loc]))).forEach((loc) => _10.set(record, [fieldId, loc], sourceFieldValue)).value();
1626
+ _11.chain(fieldValue).keys().reject((loc) => loc === locale || loc === originalLocale).filter((loc) => _11.isEmpty(_11.get(fieldValue, [loc]))).forEach((loc) => _11.set(record, [fieldId, loc], sourceFieldValue)).value();
1569
1627
  }
1570
1628
  }
1571
1629
  }
@@ -1576,10 +1634,10 @@ function createDatoFilterLoader() {
1576
1634
  }
1577
1635
 
1578
1636
  // src/cli/loaders/dato/api.ts
1579
- import _12 from "lodash";
1637
+ import _13 from "lodash";
1580
1638
 
1581
1639
  // src/cli/loaders/dato/_utils.ts
1582
- import _11 from "lodash";
1640
+ import _12 from "lodash";
1583
1641
  import { buildClient } from "@datocms/cma-client-node";
1584
1642
  function createDatoClient(params) {
1585
1643
  if (!params.apiKey) {
@@ -1754,7 +1812,7 @@ function createDatoApiLoader(config, onConfigUpdate) {
1754
1812
  const result = {
1755
1813
  models: {}
1756
1814
  };
1757
- const updatedConfig = _12.cloneDeep(config);
1815
+ const updatedConfig = _13.cloneDeep(config);
1758
1816
  console.log(`Initializing DatoCMS loader...`);
1759
1817
  const project = await dato.findProject();
1760
1818
  const modelChoices = await getModelChoices(dato, config);
@@ -1772,7 +1830,7 @@ function createDatoApiLoader(config, onConfigUpdate) {
1772
1830
  delete updatedConfig.models[modelId];
1773
1831
  }
1774
1832
  }
1775
- for (const modelId of _12.keys(updatedConfig.models)) {
1833
+ for (const modelId of _13.keys(updatedConfig.models)) {
1776
1834
  const { modelName, fields } = await getModelFields(dato, modelId);
1777
1835
  if (fields.length > 0) {
1778
1836
  result.models[modelId] = { fields: [], records: [] };
@@ -1783,7 +1841,7 @@ function createDatoApiLoader(config, onConfigUpdate) {
1783
1841
  const isLocalized = await updateFieldLocalization(dato, fieldInfo, selectedFields.includes(fieldInfo.id));
1784
1842
  if (isLocalized) {
1785
1843
  result.models[modelId].fields.push(fieldInfo);
1786
- updatedConfig.models[modelId].fields = _12.uniq([
1844
+ updatedConfig.models[modelId].fields = _13.uniq([
1787
1845
  ...updatedConfig.models[modelId].fields || [],
1788
1846
  fieldInfo.api_key
1789
1847
  ]);
@@ -1802,7 +1860,7 @@ function createDatoApiLoader(config, onConfigUpdate) {
1802
1860
  },
1803
1861
  async pull(locale, input, initCtx) {
1804
1862
  const result = {};
1805
- for (const modelId of _12.keys(initCtx?.models || {})) {
1863
+ for (const modelId of _13.keys(initCtx?.models || {})) {
1806
1864
  let records = initCtx?.models[modelId].records || [];
1807
1865
  const recordIds = records.map((record) => record.id);
1808
1866
  records = await dato.findRecords(recordIds);
@@ -1817,7 +1875,7 @@ function createDatoApiLoader(config, onConfigUpdate) {
1817
1875
  return result;
1818
1876
  },
1819
1877
  async push(locale, data, originalInput) {
1820
- for (const modelId of _12.keys(data)) {
1878
+ for (const modelId of _13.keys(data)) {
1821
1879
  for (let i = 0; i < data[modelId].records.length; i++) {
1822
1880
  const record = data[modelId].records[i];
1823
1881
  console.log(`Updating record ${i + 1}/${data[modelId].records.length} for model ${modelId}...`);
@@ -1831,7 +1889,7 @@ async function getModelFields(dato, modelId) {
1831
1889
  const modelInfo = await dato.findModel(modelId);
1832
1890
  return {
1833
1891
  modelName: modelInfo.name,
1834
- fields: _12.filter(modelInfo.fields, (field) => field.type === "field")
1892
+ fields: _13.filter(modelInfo.fields, (field) => field.type === "field")
1835
1893
  };
1836
1894
  }
1837
1895
  async function getFieldDetails(dato, fields) {
@@ -1909,17 +1967,17 @@ async function promptModelSelection(choices) {
1909
1967
  }
1910
1968
 
1911
1969
  // src/cli/loaders/dato/extract.ts
1912
- import _13 from "lodash";
1970
+ import _14 from "lodash";
1913
1971
  function createDatoExtractLoader() {
1914
1972
  return createLoader({
1915
1973
  async pull(locale, input) {
1916
1974
  const result = {};
1917
- for (const [modelId, modelInfo] of _13.entries(input)) {
1918
- for (const [recordId, record] of _13.entries(modelInfo)) {
1919
- for (const [fieldName, fieldValue] of _13.entries(record)) {
1975
+ for (const [modelId, modelInfo] of _14.entries(input)) {
1976
+ for (const [recordId, record] of _14.entries(modelInfo)) {
1977
+ for (const [fieldName, fieldValue] of _14.entries(record)) {
1920
1978
  const parsedValue = createParsedDatoValue(fieldValue);
1921
1979
  if (parsedValue) {
1922
- _13.set(result, [modelId, `_${recordId}`, fieldName], parsedValue);
1980
+ _14.set(result, [modelId, `_${recordId}`, fieldName], parsedValue);
1923
1981
  }
1924
1982
  }
1925
1983
  }
@@ -1927,14 +1985,14 @@ function createDatoExtractLoader() {
1927
1985
  return result;
1928
1986
  },
1929
1987
  async push(locale, data, originalInput) {
1930
- const result = _13.cloneDeep(originalInput || {});
1931
- for (const [modelId, modelInfo] of _13.entries(data)) {
1932
- for (const [virtualRecordId, record] of _13.entries(modelInfo)) {
1933
- for (const [fieldName, fieldValue] of _13.entries(record)) {
1988
+ const result = _14.cloneDeep(originalInput || {});
1989
+ for (const [modelId, modelInfo] of _14.entries(data)) {
1990
+ for (const [virtualRecordId, record] of _14.entries(modelInfo)) {
1991
+ for (const [fieldName, fieldValue] of _14.entries(record)) {
1934
1992
  const [, recordId] = virtualRecordId.split("_");
1935
- const originalFieldValue = _13.get(originalInput, [modelId, recordId, fieldName]);
1993
+ const originalFieldValue = _14.get(originalInput, [modelId, recordId, fieldName]);
1936
1994
  const rawValue = createRawDatoValue(fieldValue, originalFieldValue, true);
1937
- _13.set(result, [modelId, recordId, fieldName], rawValue || originalFieldValue);
1995
+ _14.set(result, [modelId, recordId, fieldName], rawValue || originalFieldValue);
1938
1996
  }
1939
1997
  }
1940
1998
  }
@@ -1943,25 +2001,25 @@ function createDatoExtractLoader() {
1943
2001
  });
1944
2002
  }
1945
2003
  function detectDatoFieldType(rawDatoValue) {
1946
- if (_13.has(rawDatoValue, "document") && _13.get(rawDatoValue, "schema") === "dast") {
2004
+ if (_14.has(rawDatoValue, "document") && _14.get(rawDatoValue, "schema") === "dast") {
1947
2005
  return "structured_text";
1948
- } else if (_13.has(rawDatoValue, "no_index") || _13.has(rawDatoValue, "twitter_card")) {
2006
+ } else if (_14.has(rawDatoValue, "no_index") || _14.has(rawDatoValue, "twitter_card")) {
1949
2007
  return "seo";
1950
- } else if (_13.get(rawDatoValue, "type") === "item") {
2008
+ } else if (_14.get(rawDatoValue, "type") === "item") {
1951
2009
  return "single_block";
1952
- } else if (_13.isArray(rawDatoValue) && _13.every(rawDatoValue, (item) => _13.get(item, "type") === "item")) {
2010
+ } else if (_14.isArray(rawDatoValue) && _14.every(rawDatoValue, (item) => _14.get(item, "type") === "item")) {
1953
2011
  return "rich_text";
1954
2012
  } else if (_isFile(rawDatoValue)) {
1955
2013
  return "file";
1956
- } else if (_13.isArray(rawDatoValue) && _13.every(rawDatoValue, (item) => _isFile(item))) {
2014
+ } else if (_14.isArray(rawDatoValue) && _14.every(rawDatoValue, (item) => _isFile(item))) {
1957
2015
  return "gallery";
1958
2016
  } else if (_isJson(rawDatoValue)) {
1959
2017
  return "json";
1960
- } else if (_13.isString(rawDatoValue)) {
2018
+ } else if (_14.isString(rawDatoValue)) {
1961
2019
  return "string";
1962
2020
  } else if (_isVideo(rawDatoValue)) {
1963
2021
  return "video";
1964
- } else if (_13.isArray(rawDatoValue) && _13.every(rawDatoValue, (item) => _13.isString(item))) {
2022
+ } else if (_14.isArray(rawDatoValue) && _14.every(rawDatoValue, (item) => _14.isString(item))) {
1965
2023
  return "ref_list";
1966
2024
  } else {
1967
2025
  return null;
@@ -2023,9 +2081,9 @@ function serializeStructuredText(rawStructuredText) {
2023
2081
  if ("document" in node) {
2024
2082
  return serializeStructuredTextNode(node.document, [...path9, "document"], acc);
2025
2083
  }
2026
- if (!_13.isNil(node.value)) {
2084
+ if (!_14.isNil(node.value)) {
2027
2085
  acc[[...path9, "value"].join(".")] = node.value;
2028
- } else if (_13.get(node, "type") === "block") {
2086
+ } else if (_14.get(node, "type") === "block") {
2029
2087
  acc[[...path9, "item"].join(".")] = serializeBlock(node.item);
2030
2088
  }
2031
2089
  if (node.children) {
@@ -2037,44 +2095,44 @@ function serializeStructuredText(rawStructuredText) {
2037
2095
  }
2038
2096
  }
2039
2097
  function serializeSeo(rawSeo) {
2040
- return _13.chain(rawSeo).pick(["title", "description"]).value();
2098
+ return _14.chain(rawSeo).pick(["title", "description"]).value();
2041
2099
  }
2042
2100
  function serializeBlock(rawBlock) {
2043
- if (_13.get(rawBlock, "type") === "item" && _13.has(rawBlock, "id")) {
2101
+ if (_14.get(rawBlock, "type") === "item" && _14.has(rawBlock, "id")) {
2044
2102
  return serializeBlock(rawBlock.attributes);
2045
2103
  }
2046
2104
  const result = {};
2047
- for (const [attributeName, attributeValue] of _13.entries(rawBlock)) {
2105
+ for (const [attributeName, attributeValue] of _14.entries(rawBlock)) {
2048
2106
  result[attributeName] = createParsedDatoValue(attributeValue);
2049
2107
  }
2050
2108
  return result;
2051
2109
  }
2052
2110
  function serializeBlockList(rawBlockList) {
2053
- return _13.chain(rawBlockList).map((block) => serializeBlock(block)).value();
2111
+ return _14.chain(rawBlockList).map((block) => serializeBlock(block)).value();
2054
2112
  }
2055
2113
  function serializeVideo(rawVideo) {
2056
- return _13.chain(rawVideo).pick(["title"]).value();
2114
+ return _14.chain(rawVideo).pick(["title"]).value();
2057
2115
  }
2058
2116
  function serializeFile(rawFile) {
2059
- return _13.chain(rawFile).pick(["alt", "title"]).value();
2117
+ return _14.chain(rawFile).pick(["alt", "title"]).value();
2060
2118
  }
2061
2119
  function serializeGallery(rawGallery) {
2062
- return _13.chain(rawGallery).map((item) => serializeFile(item)).value();
2120
+ return _14.chain(rawGallery).map((item) => serializeFile(item)).value();
2063
2121
  }
2064
2122
  function deserializeFile(parsedFile, originalRawFile) {
2065
- return _13.chain(parsedFile).defaults(originalRawFile).value();
2123
+ return _14.chain(parsedFile).defaults(originalRawFile).value();
2066
2124
  }
2067
2125
  function deserializeGallery(parsedGallery, originalRawGallery) {
2068
- return _13.chain(parsedGallery).map((item, i) => deserializeFile(item, originalRawGallery[i])).value();
2126
+ return _14.chain(parsedGallery).map((item, i) => deserializeFile(item, originalRawGallery[i])).value();
2069
2127
  }
2070
2128
  function deserializeVideo(parsedVideo, originalRawVideo) {
2071
- return _13.chain(parsedVideo).defaults(originalRawVideo).value();
2129
+ return _14.chain(parsedVideo).defaults(originalRawVideo).value();
2072
2130
  }
2073
2131
  function deserializeBlock(payload, rawNode, isClean = false) {
2074
- const result = _13.cloneDeep(rawNode);
2075
- for (const [attributeName, attributeValue] of _13.entries(rawNode.attributes)) {
2132
+ const result = _14.cloneDeep(rawNode);
2133
+ for (const [attributeName, attributeValue] of _14.entries(rawNode.attributes)) {
2076
2134
  const rawValue = createRawDatoValue(payload[attributeName], attributeValue, isClean);
2077
- _13.set(result, ["attributes", attributeName], rawValue);
2135
+ _14.set(result, ["attributes", attributeName], rawValue);
2078
2136
  }
2079
2137
  if (isClean) {
2080
2138
  delete result["id"];
@@ -2082,33 +2140,33 @@ function deserializeBlock(payload, rawNode, isClean = false) {
2082
2140
  return result;
2083
2141
  }
2084
2142
  function deserializeSeo(parsedSeo, originalRawSeo) {
2085
- return _13.chain(parsedSeo).pick(["title", "description"]).defaults(originalRawSeo).value();
2143
+ return _14.chain(parsedSeo).pick(["title", "description"]).defaults(originalRawSeo).value();
2086
2144
  }
2087
2145
  function deserializeBlockList(parsedBlockList, originalRawBlockList, isClean = false) {
2088
- return _13.chain(parsedBlockList).map((block, i) => deserializeBlock(block, originalRawBlockList[i], isClean)).value();
2146
+ return _14.chain(parsedBlockList).map((block, i) => deserializeBlock(block, originalRawBlockList[i], isClean)).value();
2089
2147
  }
2090
2148
  function deserializeStructuredText(parsedStructuredText, originalRawStructuredText) {
2091
- const result = _13.cloneDeep(originalRawStructuredText);
2092
- for (const [path9, value] of _13.entries(parsedStructuredText)) {
2093
- const realPath = _13.chain(path9.split(".")).flatMap((s) => !_13.isNaN(_13.toNumber(s)) ? ["children", s] : s).value();
2094
- const deserializedValue = createRawDatoValue(value, _13.get(originalRawStructuredText, realPath), true);
2095
- _13.set(result, realPath, deserializedValue);
2149
+ const result = _14.cloneDeep(originalRawStructuredText);
2150
+ for (const [path9, value] of _14.entries(parsedStructuredText)) {
2151
+ const realPath = _14.chain(path9.split(".")).flatMap((s) => !_14.isNaN(_14.toNumber(s)) ? ["children", s] : s).value();
2152
+ const deserializedValue = createRawDatoValue(value, _14.get(originalRawStructuredText, realPath), true);
2153
+ _14.set(result, realPath, deserializedValue);
2096
2154
  }
2097
2155
  return result;
2098
2156
  }
2099
2157
  function _isJson(rawDatoValue) {
2100
2158
  try {
2101
- return _13.isString(rawDatoValue) && rawDatoValue.startsWith("{") && rawDatoValue.endsWith("}") && !!JSON.parse(rawDatoValue);
2159
+ return _14.isString(rawDatoValue) && rawDatoValue.startsWith("{") && rawDatoValue.endsWith("}") && !!JSON.parse(rawDatoValue);
2102
2160
  } catch (e) {
2103
2161
  return false;
2104
2162
  }
2105
2163
  }
2106
2164
  function _isFile(rawDatoValue) {
2107
- return _13.isObject(rawDatoValue) && ["alt", "title", "custom_data", "focal_point", "upload_id"].every((key) => _13.has(rawDatoValue, key));
2165
+ return _14.isObject(rawDatoValue) && ["alt", "title", "custom_data", "focal_point", "upload_id"].every((key) => _14.has(rawDatoValue, key));
2108
2166
  }
2109
2167
  function _isVideo(rawDatoValue) {
2110
- return _13.isObject(rawDatoValue) && ["url", "title", "width", "height", "provider", "provider_uid", "thumbnail_url"].every(
2111
- (key) => _13.has(rawDatoValue, key)
2168
+ return _14.isObject(rawDatoValue) && ["url", "title", "width", "height", "provider", "provider_uid", "thumbnail_url"].every(
2169
+ (key) => _14.has(rawDatoValue, key)
2112
2170
  );
2113
2171
  }
2114
2172
 
@@ -2169,7 +2227,7 @@ function createVttLoader() {
2169
2227
  }
2170
2228
 
2171
2229
  // src/cli/loaders/variable/index.ts
2172
- import _14 from "lodash";
2230
+ import _15 from "lodash";
2173
2231
  function createVariableLoader(params) {
2174
2232
  return composeLoaders(variableExtractLoader(params), variableContentLoader());
2175
2233
  }
@@ -2212,11 +2270,11 @@ function variableExtractLoader(params) {
2212
2270
  function variableContentLoader() {
2213
2271
  return createLoader({
2214
2272
  pull: async (locale, input) => {
2215
- const result = _14.mapValues(input, (payload) => payload.value);
2273
+ const result = _15.mapValues(input, (payload) => payload.value);
2216
2274
  return result;
2217
2275
  },
2218
2276
  push: async (locale, data, originalInput) => {
2219
- const result = _14.cloneDeep(originalInput || {});
2277
+ const result = _15.cloneDeep(originalInput || {});
2220
2278
  for (const [key, originalValueObj] of Object.entries(result)) {
2221
2279
  result[key] = {
2222
2280
  ...originalValueObj,
@@ -2239,20 +2297,20 @@ function getFormatSpecifierPattern(type) {
2239
2297
  }
2240
2298
 
2241
2299
  // src/cli/loaders/sync.ts
2242
- import _15 from "lodash";
2300
+ import _16 from "lodash";
2243
2301
  function createSyncLoader() {
2244
2302
  return createLoader({
2245
2303
  async pull(locale, input, originalInput) {
2246
2304
  if (!originalInput) {
2247
2305
  return input;
2248
2306
  }
2249
- return _15.chain(originalInput).mapValues((value, key) => input[key]).value();
2307
+ return _16.chain(originalInput).mapValues((value, key) => input[key]).value();
2250
2308
  },
2251
2309
  async push(locale, data, originalInput) {
2252
2310
  if (!originalInput) {
2253
2311
  return data;
2254
2312
  }
2255
- return _15.chain(originalInput || {}).mapValues((value, key) => data[key]).value();
2313
+ return _16.chain(originalInput || {}).mapValues((value, key) => data[key]).value();
2256
2314
  }
2257
2315
  });
2258
2316
  }
@@ -2479,7 +2537,7 @@ import path7 from "path";
2479
2537
  import Z3 from "zod";
2480
2538
  import YAML3 from "yaml";
2481
2539
  import { MD5 } from "object-hash";
2482
- import _16 from "lodash";
2540
+ import _17 from "lodash";
2483
2541
  function createLockfileHelper() {
2484
2542
  return {
2485
2543
  isLockfileExists: () => {
@@ -2489,23 +2547,23 @@ function createLockfileHelper() {
2489
2547
  registerSourceData: (pathPattern, sourceData) => {
2490
2548
  const lockfile = _loadLockfile();
2491
2549
  const sectionKey = MD5(pathPattern);
2492
- const sectionChecksums = _16.mapValues(sourceData, (value) => MD5(value));
2550
+ const sectionChecksums = _17.mapValues(sourceData, (value) => MD5(value));
2493
2551
  lockfile.checksums[sectionKey] = sectionChecksums;
2494
2552
  _saveLockfile(lockfile);
2495
2553
  },
2496
2554
  registerPartialSourceData: (pathPattern, partialSourceData) => {
2497
2555
  const lockfile = _loadLockfile();
2498
2556
  const sectionKey = MD5(pathPattern);
2499
- const sectionChecksums = _16.mapValues(partialSourceData, (value) => MD5(value));
2500
- lockfile.checksums[sectionKey] = _16.merge({}, lockfile.checksums[sectionKey] ?? {}, sectionChecksums);
2557
+ const sectionChecksums = _17.mapValues(partialSourceData, (value) => MD5(value));
2558
+ lockfile.checksums[sectionKey] = _17.merge({}, lockfile.checksums[sectionKey] ?? {}, sectionChecksums);
2501
2559
  _saveLockfile(lockfile);
2502
2560
  },
2503
2561
  extractUpdatedData: (pathPattern, sourceData) => {
2504
2562
  const lockfile = _loadLockfile();
2505
2563
  const sectionKey = MD5(pathPattern);
2506
- const currentChecksums = _16.mapValues(sourceData, (value) => MD5(value));
2564
+ const currentChecksums = _17.mapValues(sourceData, (value) => MD5(value));
2507
2565
  const savedChecksums = lockfile.checksums[sectionKey] || {};
2508
- const updatedData = _16.pickBy(sourceData, (value, key) => savedChecksums[key] !== currentChecksums[key]);
2566
+ const updatedData = _17.pickBy(sourceData, (value, key) => savedChecksums[key] !== currentChecksums[key]);
2509
2567
  return updatedData;
2510
2568
  }
2511
2569
  };
@@ -2753,7 +2811,7 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
2753
2811
  targetData
2754
2812
  });
2755
2813
  if (flags.key) {
2756
- processableData = _17.pickBy(processableData, (_19, key) => key === flags.key);
2814
+ processableData = _18.pickBy(processableData, (_20, key) => key === flags.key);
2757
2815
  }
2758
2816
  if (flags.verbose) {
2759
2817
  bucketOra.info(JSON.stringify(processableData, null, 2));
@@ -2789,7 +2847,7 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
2789
2847
  if (flags.verbose) {
2790
2848
  bucketOra.info(JSON.stringify(processedTargetData, null, 2));
2791
2849
  }
2792
- let finalTargetData = _17.merge({}, sourceData, targetData, processedTargetData);
2850
+ let finalTargetData = _18.merge({}, sourceData, targetData, processedTargetData);
2793
2851
  if (flags.interactive) {
2794
2852
  bucketOra.stop();
2795
2853
  const reviewedData = await reviewChanges({
@@ -2803,7 +2861,7 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
2803
2861
  finalTargetData = reviewedData;
2804
2862
  bucketOra.start(`Applying changes to ${bucketConfig} (${targetLocale})`);
2805
2863
  }
2806
- const finalDiffSize = _17.chain(finalTargetData).omitBy((value, key) => value === targetData[key]).size().value();
2864
+ const finalDiffSize = _18.chain(finalTargetData).omitBy((value, key) => value === targetData[key]).size().value();
2807
2865
  if (finalDiffSize > 0 || flags.force) {
2808
2866
  await bucketLoader.push(targetLocale, finalTargetData);
2809
2867
  bucketOra.succeed(`[${sourceLocale} -> ${targetLocale}] Localization completed`);
@@ -2848,9 +2906,9 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
2848
2906
  }
2849
2907
  });
2850
2908
  function calculateDataDelta(args) {
2851
- const newKeys = _17.difference(Object.keys(args.sourceData), Object.keys(args.targetData));
2909
+ const newKeys = _18.difference(Object.keys(args.sourceData), Object.keys(args.targetData));
2852
2910
  const updatedKeys = Object.keys(args.updatedSourceData);
2853
- const result = _17.chain(args.sourceData).pickBy((value, key) => newKeys.includes(key) || updatedKeys.includes(key)).value();
2911
+ const result = _18.chain(args.sourceData).pickBy((value, key) => newKeys.includes(key) || updatedKeys.includes(key)).value();
2854
2912
  return result;
2855
2913
  }
2856
2914
  async function retryWithExponentialBackoff(operation, maxAttempts, baseDelay = 1e3) {
@@ -2991,7 +3049,7 @@ Reviewing changes for ${chalk.blue(args.pathPattern)} (${chalk.yellow(args.targe
2991
3049
  return args.currentData;
2992
3050
  }
2993
3051
  const customData = { ...args.currentData };
2994
- const changes = _17.reduce(
3052
+ const changes = _18.reduce(
2995
3053
  args.proposedData,
2996
3054
  (result, value, key) => {
2997
3055
  if (args.currentData[key] !== value) {
@@ -3072,7 +3130,7 @@ var flagsSchema = Z5.object({
3072
3130
  // src/cli/cmd/cleanup.ts
3073
3131
  import { resolveOverridenLocale as resolveOverridenLocale5 } from "@lingo.dev/_spec";
3074
3132
  import { Command as Command8 } from "interactive-commander";
3075
- import _18 from "lodash";
3133
+ import _19 from "lodash";
3076
3134
  import Ora7 from "ora";
3077
3135
  var cleanup_default = new Command8().command("cleanup").description("Remove keys from target files that do not exist in the source file").helpOption("-h, --help", "Show help").option("--locale <locale>", "Specific locale to cleanup").option("--bucket <bucket>", "Specific bucket to cleanup").option("--dry-run", "Show what would be removed without making changes").option("--verbose", "Show verbose output").action(async function(options) {
3078
3136
  const ora = Ora7();
@@ -3102,7 +3160,7 @@ var cleanup_default = new Command8().command("cleanup").description("Remove keys
3102
3160
  try {
3103
3161
  const targetData = await bucketLoader.pull(targetLocale);
3104
3162
  const targetKeys = Object.keys(targetData);
3105
- const keysToRemove = _18.difference(targetKeys, sourceKeys);
3163
+ const keysToRemove = _19.difference(targetKeys, sourceKeys);
3106
3164
  if (keysToRemove.length === 0) {
3107
3165
  bucketOra.succeed(`[${targetLocale}] No keys to remove`);
3108
3166
  continue;
@@ -3111,7 +3169,7 @@ var cleanup_default = new Command8().command("cleanup").description("Remove keys
3111
3169
  bucketOra.info(`[${targetLocale}] Keys to remove: ${JSON.stringify(keysToRemove, null, 2)}`);
3112
3170
  }
3113
3171
  if (!options.dryRun) {
3114
- const cleanedData = _18.pick(targetData, sourceKeys);
3172
+ const cleanedData = _19.pick(targetData, sourceKeys);
3115
3173
  await bucketLoader.push(targetLocale, cleanedData);
3116
3174
  bucketOra.succeed(`[${targetLocale}] Removed ${keysToRemove.length} keys`);
3117
3175
  } else {
@@ -3163,7 +3221,7 @@ function displaySummary(results) {
3163
3221
  // package.json
3164
3222
  var package_default = {
3165
3223
  name: "lingo.dev",
3166
- version: "0.74.10",
3224
+ version: "0.74.11",
3167
3225
  description: "Lingo.dev CLI",
3168
3226
  private: false,
3169
3227
  publishConfig: {
@@ -3200,6 +3258,7 @@ var package_default = {
3200
3258
  dev: "tsup --watch",
3201
3259
  build: "tsc --noEmit && tsup",
3202
3260
  test: "vitest run",
3261
+ "test:watch": "vitest",
3203
3262
  clean: "rm -rf build"
3204
3263
  },
3205
3264
  keywords: [],