@messagevisor/catalog 0.6.0 → 0.7.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/assets/{index-DJ8oQlZp.js → index-Cx9rnVIG.js} +10 -10
- package/dist/index.html +1 -1
- package/lib/node/index.js +382 -298
- package/lib/node/index.js.map +1 -1
- package/package.json +2 -2
- package/src/api.spec.ts +46 -1
- package/src/api.ts +29 -1
- package/src/node/index.spec.ts +131 -3
- package/src/node/index.ts +182 -46
package/src/node/index.ts
CHANGED
|
@@ -104,6 +104,12 @@ class CatalogProgressReporter {
|
|
|
104
104
|
return Date.now();
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
substep(label: string, detail?: string) {
|
|
108
|
+
const suffix = detail ? `: ${colorize(detail, 2)}` : "";
|
|
109
|
+
console.log(` ${colorize("•", 36)} ${label}${suffix}`);
|
|
110
|
+
return Date.now();
|
|
111
|
+
}
|
|
112
|
+
|
|
107
113
|
done(startedAt: number, detail?: string) {
|
|
108
114
|
const suffix = detail ? ` ${detail}` : "";
|
|
109
115
|
console.log(CLI_FORMAT_DIM, ` done in ${prettyDuration(Date.now() - startedAt)}${suffix}`);
|
|
@@ -352,6 +358,7 @@ export interface CatalogServerHandle {
|
|
|
352
358
|
interface CatalogBuildContext {
|
|
353
359
|
rootDirectoryPath: string;
|
|
354
360
|
repositoryRootDirectoryPath: string;
|
|
361
|
+
repositorySourceRootDirectoryPath: string;
|
|
355
362
|
outputDirectoryPath: string;
|
|
356
363
|
dataDirectoryPath: string;
|
|
357
364
|
historyIndex: CatalogHistoryIndex;
|
|
@@ -361,6 +368,7 @@ interface CatalogBuildContext {
|
|
|
361
368
|
withTranslationSearch: boolean;
|
|
362
369
|
withDuplicates: boolean;
|
|
363
370
|
progress: CatalogProgressReporter;
|
|
371
|
+
writer: CatalogJsonWriter;
|
|
364
372
|
}
|
|
365
373
|
|
|
366
374
|
interface SourceFileInfo {
|
|
@@ -723,9 +731,41 @@ function toLocaleDuplicatesFile(
|
|
|
723
731
|
};
|
|
724
732
|
}
|
|
725
733
|
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
734
|
+
class CatalogJsonWriter {
|
|
735
|
+
private readonly directories = new Map<string, Promise<void>>();
|
|
736
|
+
|
|
737
|
+
private ensureDirectory(directoryPath: string) {
|
|
738
|
+
let promise = this.directories.get(directoryPath);
|
|
739
|
+
|
|
740
|
+
if (!promise) {
|
|
741
|
+
promise = fs.promises.mkdir(directoryPath, { recursive: true }).then(() => undefined);
|
|
742
|
+
this.directories.set(directoryPath, promise);
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
return promise;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
async write(filePath: string, content: unknown) {
|
|
749
|
+
await this.ensureDirectory(path.dirname(filePath));
|
|
750
|
+
await fs.promises.writeFile(filePath, JSON.stringify(content, null, 2));
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
async function mapWithConcurrency<T>(
|
|
755
|
+
items: T[],
|
|
756
|
+
concurrency: number,
|
|
757
|
+
callback: (item: T, index: number) => Promise<void>,
|
|
758
|
+
) {
|
|
759
|
+
let nextIndex = 0;
|
|
760
|
+
const workerCount = Math.min(concurrency, items.length);
|
|
761
|
+
const workers = Array.from({ length: workerCount }, async () => {
|
|
762
|
+
while (nextIndex < items.length) {
|
|
763
|
+
const index = nextIndex++;
|
|
764
|
+
await callback(items[index], index);
|
|
765
|
+
}
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
await Promise.all(workers);
|
|
729
769
|
}
|
|
730
770
|
|
|
731
771
|
function getEntityDirectoryPaths(config: any): Record<CatalogEntityType | "test", string> {
|
|
@@ -870,6 +910,18 @@ function addHistoryIndexEntry(
|
|
|
870
910
|
target[key].push(entry);
|
|
871
911
|
}
|
|
872
912
|
|
|
913
|
+
function toEntityHistoryEntry(
|
|
914
|
+
entry: CatalogHistoryEntry,
|
|
915
|
+
entity: CatalogHistoryEntity,
|
|
916
|
+
): CatalogHistoryEntry {
|
|
917
|
+
return {
|
|
918
|
+
commit: entry.commit,
|
|
919
|
+
author: entry.author,
|
|
920
|
+
timestamp: entry.timestamp,
|
|
921
|
+
entities: [entity],
|
|
922
|
+
};
|
|
923
|
+
}
|
|
924
|
+
|
|
873
925
|
function buildCatalogHistoryIndex(entries: CatalogHistoryEntry[]): CatalogHistoryIndex {
|
|
874
926
|
const index = createEmptyHistoryIndex();
|
|
875
927
|
index.entries = entries;
|
|
@@ -883,7 +935,7 @@ function buildCatalogHistoryIndex(entries: CatalogHistoryEntry[]): CatalogHistor
|
|
|
883
935
|
}
|
|
884
936
|
|
|
885
937
|
const entityKey = getHistoryEntityKey(entity.type, entity.key, entity.set);
|
|
886
|
-
addHistoryIndexEntry(index.byEntity, entityKey, entry);
|
|
938
|
+
addHistoryIndexEntry(index.byEntity, entityKey, toEntityHistoryEntry(entry, entity));
|
|
887
939
|
|
|
888
940
|
if (!index.lastModifiedByEntity[entityKey]) {
|
|
889
941
|
index.lastModifiedByEntity[entityKey] = toLastModified(entry);
|
|
@@ -1129,6 +1181,25 @@ function getRepositoryRootDirectoryPath(rootDirectoryPath: string) {
|
|
|
1129
1181
|
}
|
|
1130
1182
|
}
|
|
1131
1183
|
|
|
1184
|
+
function getRepositorySourceRootDirectoryPath(rootDirectoryPath: string) {
|
|
1185
|
+
try {
|
|
1186
|
+
const gitRootDirectoryPath =
|
|
1187
|
+
runGit(rootDirectoryPath, ["rev-parse", "--show-toplevel"]).trim() || rootDirectoryPath;
|
|
1188
|
+
const realRootDirectoryPath = getRealPath(rootDirectoryPath);
|
|
1189
|
+
|
|
1190
|
+
if (realRootDirectoryPath !== rootDirectoryPath) {
|
|
1191
|
+
return path.resolve(
|
|
1192
|
+
rootDirectoryPath,
|
|
1193
|
+
path.relative(realRootDirectoryPath, gitRootDirectoryPath),
|
|
1194
|
+
);
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
return gitRootDirectoryPath;
|
|
1198
|
+
} catch (_error) {
|
|
1199
|
+
return rootDirectoryPath;
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1132
1203
|
function getOwnerAndRepoFromGitRemote(origin: string, host: string) {
|
|
1133
1204
|
const escapedHost = host.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
|
|
1134
1205
|
const match = origin.match(new RegExp(`${escapedHost}[:/]([^/]+)/(.+?)(?:\\.git)?$`));
|
|
@@ -1204,17 +1275,28 @@ function chunkHistory(history: CatalogHistoryEntry[], pageSize = CATALOG_HISTORY
|
|
|
1204
1275
|
return pages.length > 0 ? pages : [[]];
|
|
1205
1276
|
}
|
|
1206
1277
|
|
|
1207
|
-
async function writeHistoryPages(
|
|
1278
|
+
async function writeHistoryPages(
|
|
1279
|
+
writer: CatalogJsonWriter,
|
|
1280
|
+
directoryPath: string,
|
|
1281
|
+
history: CatalogHistoryEntry[],
|
|
1282
|
+
options: { skipEmpty?: boolean } = {},
|
|
1283
|
+
) {
|
|
1284
|
+
if (options.skipEmpty && history.length === 0) {
|
|
1285
|
+
return 1;
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1208
1288
|
const pages = chunkHistory(history);
|
|
1209
1289
|
|
|
1210
1290
|
for (let index = 0; index < pages.length; index++) {
|
|
1211
|
-
await
|
|
1291
|
+
await writer.write(path.join(directoryPath, `page-${index + 1}.json`), {
|
|
1212
1292
|
page: index + 1,
|
|
1213
1293
|
pageSize: CATALOG_HISTORY_PAGE_SIZE,
|
|
1214
1294
|
totalPages: pages.length,
|
|
1215
1295
|
entries: pages[index],
|
|
1216
1296
|
});
|
|
1217
1297
|
}
|
|
1298
|
+
|
|
1299
|
+
return 0;
|
|
1218
1300
|
}
|
|
1219
1301
|
|
|
1220
1302
|
function getHistoryForEntity(
|
|
@@ -1227,11 +1309,12 @@ function getHistoryForEntity(
|
|
|
1227
1309
|
}
|
|
1228
1310
|
|
|
1229
1311
|
function getSourceFileInfo(
|
|
1230
|
-
|
|
1312
|
+
repositorySourceRootDirectoryPath: string,
|
|
1231
1313
|
rootDirectoryPath: string,
|
|
1232
1314
|
projectConfig: any,
|
|
1233
1315
|
type: CatalogEntityType,
|
|
1234
1316
|
key: string,
|
|
1317
|
+
options: { resolveAbsolutePath?: boolean } = {},
|
|
1235
1318
|
): SourceFileInfo {
|
|
1236
1319
|
const directoryByType: Record<CatalogEntityType, string> = {
|
|
1237
1320
|
locale: projectConfig.localesDirectoryPath,
|
|
@@ -1248,10 +1331,10 @@ function getSourceFileInfo(
|
|
|
1248
1331
|
...key.split(projectConfig.namespaceCharacter),
|
|
1249
1332
|
) + extension,
|
|
1250
1333
|
);
|
|
1251
|
-
const absolutePath = getRealPath(filePath);
|
|
1334
|
+
const absolutePath = options.resolveAbsolutePath ? getRealPath(filePath) : filePath;
|
|
1252
1335
|
|
|
1253
1336
|
return {
|
|
1254
|
-
sourcePath: toPosixPath(path.relative(
|
|
1337
|
+
sourcePath: toPosixPath(path.relative(repositorySourceRootDirectoryPath, filePath)),
|
|
1255
1338
|
absolutePath,
|
|
1256
1339
|
};
|
|
1257
1340
|
}
|
|
@@ -1284,13 +1367,13 @@ async function buildSetCatalog(
|
|
|
1284
1367
|
const outputDirectoryPath = path.join(context.dataDirectoryPath, outputRelativeDirectory);
|
|
1285
1368
|
const setStartedAt = context.progress.setStart(set);
|
|
1286
1369
|
const entitiesStartedAt = context.progress.step("Processing entities");
|
|
1287
|
-
const [localeKeys, messageKeys, attributeKeys, segmentKeys, targetKeys] = await Promise.all([
|
|
1370
|
+
const [localeKeys, messageKeys, attributeKeys, segmentKeys, targetKeys] = (await Promise.all([
|
|
1288
1371
|
datasource.listLocales(),
|
|
1289
1372
|
datasource.listMessages(),
|
|
1290
1373
|
datasource.listAttributes(),
|
|
1291
1374
|
datasource.listSegments(),
|
|
1292
1375
|
datasource.listTargets(),
|
|
1293
|
-
]);
|
|
1376
|
+
])) as [string[], string[], string[], string[], string[]];
|
|
1294
1377
|
const [locales, messages, attributes, segments, targets] = await Promise.all([
|
|
1295
1378
|
readAll<Locale>(localeKeys, (key) => datasource.readLocale(key)),
|
|
1296
1379
|
readAll<Message>(messageKeys, (key) => datasource.readMessage(key)),
|
|
@@ -1440,7 +1523,7 @@ async function buildSetCatalog(
|
|
|
1440
1523
|
};
|
|
1441
1524
|
|
|
1442
1525
|
const historyStartedAt = context.progress.step("Writing history pages");
|
|
1443
|
-
await writeHistoryPages(path.join(outputDirectoryPath, "history"), history);
|
|
1526
|
+
await writeHistoryPages(context.writer, path.join(outputDirectoryPath, "history"), history);
|
|
1444
1527
|
context.progress.done(historyStartedAt, `(${pluralize(history.length, "entry", "entries")})`);
|
|
1445
1528
|
|
|
1446
1529
|
const examplesStartedAt = context.progress.step("Evaluating examples");
|
|
@@ -1492,14 +1575,16 @@ async function buildSetCatalog(
|
|
|
1492
1575
|
);
|
|
1493
1576
|
|
|
1494
1577
|
const localesStartedAt = context.progress.step("Writing locales");
|
|
1495
|
-
|
|
1578
|
+
let skippedEmptyHistoryCount = 0;
|
|
1579
|
+
await mapWithConcurrency(localeKeys, 32, async (localeKey) => {
|
|
1496
1580
|
const locale = locales[localeKey];
|
|
1497
1581
|
const sourceFileInfo = getSourceFileInfo(
|
|
1498
|
-
context.
|
|
1582
|
+
context.repositorySourceRootDirectoryPath,
|
|
1499
1583
|
context.rootDirectoryPath,
|
|
1500
1584
|
projectConfig,
|
|
1501
1585
|
"locale",
|
|
1502
1586
|
localeKey,
|
|
1587
|
+
{ resolveAbsolutePath: context.devEditors.length > 0 },
|
|
1503
1588
|
);
|
|
1504
1589
|
const detail = {
|
|
1505
1590
|
type: "locale",
|
|
@@ -1525,26 +1610,28 @@ async function buildSetCatalog(
|
|
|
1525
1610
|
targets: sortStrings(Array.from(localeTargets[localeKey] || [])),
|
|
1526
1611
|
}),
|
|
1527
1612
|
);
|
|
1528
|
-
await
|
|
1613
|
+
await context.writer.write(
|
|
1529
1614
|
path.join(outputDirectoryPath, "entities", "locale", `${encodeKey(localeKey)}.json`),
|
|
1530
1615
|
detail,
|
|
1531
1616
|
);
|
|
1532
|
-
await writeHistoryPages(
|
|
1617
|
+
skippedEmptyHistoryCount += await writeHistoryPages(
|
|
1618
|
+
context.writer,
|
|
1533
1619
|
path.join(outputDirectoryPath, "history", "locale", encodeKey(localeKey)),
|
|
1534
1620
|
getHistoryForEntity(context.historyIndex, "locale", localeKey, set || undefined),
|
|
1621
|
+
{ skipEmpty: true },
|
|
1535
1622
|
);
|
|
1536
|
-
}
|
|
1623
|
+
});
|
|
1537
1624
|
context.progress.done(localesStartedAt, `(${pluralize(localeKeys.length, "locale")})`);
|
|
1538
1625
|
|
|
1539
1626
|
if (context.withDuplicates) {
|
|
1540
1627
|
const duplicatesStartedAt = context.progress.step("Writing duplicate reports");
|
|
1541
1628
|
|
|
1542
|
-
|
|
1543
|
-
await
|
|
1629
|
+
await mapWithConcurrency(localeKeys, 32, async (localeKey) => {
|
|
1630
|
+
await context.writer.write(
|
|
1544
1631
|
path.join(outputDirectoryPath, "duplicates", "locales", `${encodeKey(localeKey)}.json`),
|
|
1545
1632
|
toLocaleDuplicatesFile(localeKey, duplicatesByLocale),
|
|
1546
1633
|
);
|
|
1547
|
-
}
|
|
1634
|
+
});
|
|
1548
1635
|
|
|
1549
1636
|
context.progress.done(duplicatesStartedAt, `(${pluralize(localeKeys.length, "locale")})`);
|
|
1550
1637
|
}
|
|
@@ -1568,7 +1655,9 @@ async function buildSetCatalog(
|
|
|
1568
1655
|
}
|
|
1569
1656
|
|
|
1570
1657
|
const messagesStartedAt = context.progress.step("Writing messages");
|
|
1571
|
-
|
|
1658
|
+
const messageDetailsStartedAt = context.progress.substep("Writing message details");
|
|
1659
|
+
let skippedEmptyMessageHistoryCount = 0;
|
|
1660
|
+
await mapWithConcurrency(messageKeys, 32, async (messageKey) => {
|
|
1572
1661
|
const message = messages[messageKey];
|
|
1573
1662
|
const overrides = (message.overrides || []).map((override: Override) => {
|
|
1574
1663
|
const attributes = new Set<string>();
|
|
@@ -1583,11 +1672,12 @@ async function buildSetCatalog(
|
|
|
1583
1672
|
};
|
|
1584
1673
|
});
|
|
1585
1674
|
const sourceFileInfo = getSourceFileInfo(
|
|
1586
|
-
context.
|
|
1675
|
+
context.repositorySourceRootDirectoryPath,
|
|
1587
1676
|
context.rootDirectoryPath,
|
|
1588
1677
|
projectConfig,
|
|
1589
1678
|
"message",
|
|
1590
1679
|
messageKey,
|
|
1680
|
+
{ resolveAbsolutePath: context.devEditors.length > 0 },
|
|
1591
1681
|
);
|
|
1592
1682
|
const detail = {
|
|
1593
1683
|
type: "message",
|
|
@@ -1629,16 +1719,40 @@ async function buildSetCatalog(
|
|
|
1629
1719
|
...(overrideLocalesList.length > 0 ? { overrideLocales: overrideLocalesList } : {}),
|
|
1630
1720
|
}),
|
|
1631
1721
|
);
|
|
1632
|
-
await
|
|
1722
|
+
await context.writer.write(
|
|
1633
1723
|
path.join(outputDirectoryPath, "entities", "message", `${encodeKey(messageKey)}.json`),
|
|
1634
1724
|
detail,
|
|
1635
1725
|
);
|
|
1636
|
-
|
|
1726
|
+
});
|
|
1727
|
+
context.progress.done(messageDetailsStartedAt, `(${pluralize(messageKeys.length, "message")})`);
|
|
1728
|
+
|
|
1729
|
+
const messageHistoryStartedAt = context.progress.substep("Writing message history pages");
|
|
1730
|
+
await mapWithConcurrency(messageKeys, 32, async (messageKey) => {
|
|
1731
|
+
const skippedHistory = await writeHistoryPages(
|
|
1732
|
+
context.writer,
|
|
1637
1733
|
path.join(outputDirectoryPath, "history", "message", encodeKey(messageKey)),
|
|
1638
1734
|
getHistoryForEntity(context.historyIndex, "message", messageKey, set || undefined),
|
|
1735
|
+
{ skipEmpty: true },
|
|
1639
1736
|
);
|
|
1640
|
-
|
|
1641
|
-
|
|
1737
|
+
skippedEmptyMessageHistoryCount += skippedHistory;
|
|
1738
|
+
skippedEmptyHistoryCount += skippedHistory;
|
|
1739
|
+
});
|
|
1740
|
+
context.progress.done(
|
|
1741
|
+
messageHistoryStartedAt,
|
|
1742
|
+
`(${pluralize(messageKeys.length, "message")}, ${pluralize(
|
|
1743
|
+
skippedEmptyMessageHistoryCount,
|
|
1744
|
+
"empty history",
|
|
1745
|
+
"empty histories",
|
|
1746
|
+
)} skipped)`,
|
|
1747
|
+
);
|
|
1748
|
+
context.progress.done(
|
|
1749
|
+
messagesStartedAt,
|
|
1750
|
+
`(${pluralize(messageKeys.length, "message")}, ${pluralize(
|
|
1751
|
+
skippedEmptyMessageHistoryCount,
|
|
1752
|
+
"empty history",
|
|
1753
|
+
"empty histories",
|
|
1754
|
+
)} skipped)`,
|
|
1755
|
+
);
|
|
1642
1756
|
|
|
1643
1757
|
if (context.withTranslationSearch) {
|
|
1644
1758
|
const translationSearchStartedAt = context.progress.step("Building translation search shards");
|
|
@@ -1666,7 +1780,10 @@ async function buildSetCatalog(
|
|
|
1666
1780
|
for (const [msgKey, valueSet] of Object.entries(messageMap)) {
|
|
1667
1781
|
shardData[msgKey] = Array.from(valueSet);
|
|
1668
1782
|
}
|
|
1669
|
-
await
|
|
1783
|
+
await context.writer.write(
|
|
1784
|
+
path.join(outputDirectoryPath, "translations", `${prefix}.json`),
|
|
1785
|
+
shardData,
|
|
1786
|
+
);
|
|
1670
1787
|
}
|
|
1671
1788
|
context.progress.done(
|
|
1672
1789
|
translationSearchStartedAt,
|
|
@@ -1675,14 +1792,15 @@ async function buildSetCatalog(
|
|
|
1675
1792
|
}
|
|
1676
1793
|
|
|
1677
1794
|
const attributesStartedAt = context.progress.step("Writing attributes");
|
|
1678
|
-
|
|
1795
|
+
await mapWithConcurrency(attributeKeys, 32, async (attributeKey) => {
|
|
1679
1796
|
const attribute = attributes[attributeKey];
|
|
1680
1797
|
const sourceFileInfo = getSourceFileInfo(
|
|
1681
|
-
context.
|
|
1798
|
+
context.repositorySourceRootDirectoryPath,
|
|
1682
1799
|
context.rootDirectoryPath,
|
|
1683
1800
|
projectConfig,
|
|
1684
1801
|
"attribute",
|
|
1685
1802
|
attributeKey,
|
|
1803
|
+
{ resolveAbsolutePath: context.devEditors.length > 0 },
|
|
1686
1804
|
);
|
|
1687
1805
|
const detail = {
|
|
1688
1806
|
type: "attribute",
|
|
@@ -1714,28 +1832,31 @@ async function buildSetCatalog(
|
|
|
1714
1832
|
},
|
|
1715
1833
|
),
|
|
1716
1834
|
);
|
|
1717
|
-
await
|
|
1835
|
+
await context.writer.write(
|
|
1718
1836
|
path.join(outputDirectoryPath, "entities", "attribute", `${encodeKey(attributeKey)}.json`),
|
|
1719
1837
|
detail,
|
|
1720
1838
|
);
|
|
1721
|
-
await writeHistoryPages(
|
|
1839
|
+
skippedEmptyHistoryCount += await writeHistoryPages(
|
|
1840
|
+
context.writer,
|
|
1722
1841
|
path.join(outputDirectoryPath, "history", "attribute", encodeKey(attributeKey)),
|
|
1723
1842
|
getHistoryForEntity(context.historyIndex, "attribute", attributeKey, set || undefined),
|
|
1843
|
+
{ skipEmpty: true },
|
|
1724
1844
|
);
|
|
1725
|
-
}
|
|
1845
|
+
});
|
|
1726
1846
|
context.progress.done(attributesStartedAt, `(${pluralize(attributeKeys.length, "attribute")})`);
|
|
1727
1847
|
|
|
1728
1848
|
const segmentsStartedAt = context.progress.step("Writing segments");
|
|
1729
|
-
|
|
1849
|
+
await mapWithConcurrency(segmentKeys, 32, async (segmentKey) => {
|
|
1730
1850
|
const segment = segments[segmentKey];
|
|
1731
1851
|
const usedAttributes = new Set<string>();
|
|
1732
1852
|
collectAttributeKeysFromConditions(segment.conditions, usedAttributes);
|
|
1733
1853
|
const sourceFileInfo = getSourceFileInfo(
|
|
1734
|
-
context.
|
|
1854
|
+
context.repositorySourceRootDirectoryPath,
|
|
1735
1855
|
context.rootDirectoryPath,
|
|
1736
1856
|
projectConfig,
|
|
1737
1857
|
"segment",
|
|
1738
1858
|
segmentKey,
|
|
1859
|
+
{ resolveAbsolutePath: context.devEditors.length > 0 },
|
|
1739
1860
|
);
|
|
1740
1861
|
const detail = {
|
|
1741
1862
|
type: "segment",
|
|
@@ -1755,19 +1876,21 @@ async function buildSetCatalog(
|
|
|
1755
1876
|
targets: sortStrings(Array.from(segmentTargets[segmentKey] || [])),
|
|
1756
1877
|
}),
|
|
1757
1878
|
);
|
|
1758
|
-
await
|
|
1879
|
+
await context.writer.write(
|
|
1759
1880
|
path.join(outputDirectoryPath, "entities", "segment", `${encodeKey(segmentKey)}.json`),
|
|
1760
1881
|
detail,
|
|
1761
1882
|
);
|
|
1762
|
-
await writeHistoryPages(
|
|
1883
|
+
skippedEmptyHistoryCount += await writeHistoryPages(
|
|
1884
|
+
context.writer,
|
|
1763
1885
|
path.join(outputDirectoryPath, "history", "segment", encodeKey(segmentKey)),
|
|
1764
1886
|
getHistoryForEntity(context.historyIndex, "segment", segmentKey, set || undefined),
|
|
1887
|
+
{ skipEmpty: true },
|
|
1765
1888
|
);
|
|
1766
|
-
}
|
|
1889
|
+
});
|
|
1767
1890
|
context.progress.done(segmentsStartedAt, `(${pluralize(segmentKeys.length, "segment")})`);
|
|
1768
1891
|
|
|
1769
1892
|
const targetsStartedAt = context.progress.step("Writing targets");
|
|
1770
|
-
|
|
1893
|
+
await mapWithConcurrency(targetKeys, 32, async (targetKey) => {
|
|
1771
1894
|
const target = targets[targetKey];
|
|
1772
1895
|
const targetLocaleKeys = target.locales?.length ? target.locales : localeKeys;
|
|
1773
1896
|
const formatsByLocale: Record<string, FormatPresets | undefined> = {};
|
|
@@ -1779,11 +1902,12 @@ async function buildSetCatalog(
|
|
|
1779
1902
|
}
|
|
1780
1903
|
|
|
1781
1904
|
const sourceFileInfo = getSourceFileInfo(
|
|
1782
|
-
context.
|
|
1905
|
+
context.repositorySourceRootDirectoryPath,
|
|
1783
1906
|
context.rootDirectoryPath,
|
|
1784
1907
|
projectConfig,
|
|
1785
1908
|
"target",
|
|
1786
1909
|
targetKey,
|
|
1910
|
+
{ resolveAbsolutePath: context.devEditors.length > 0 },
|
|
1787
1911
|
);
|
|
1788
1912
|
const detail = {
|
|
1789
1913
|
type: "target",
|
|
@@ -1803,15 +1927,17 @@ async function buildSetCatalog(
|
|
|
1803
1927
|
messageCount: targetMessages[targetKey].length,
|
|
1804
1928
|
}),
|
|
1805
1929
|
);
|
|
1806
|
-
await
|
|
1930
|
+
await context.writer.write(
|
|
1807
1931
|
path.join(outputDirectoryPath, "entities", "target", `${encodeKey(targetKey)}.json`),
|
|
1808
1932
|
detail,
|
|
1809
1933
|
);
|
|
1810
|
-
await writeHistoryPages(
|
|
1934
|
+
skippedEmptyHistoryCount += await writeHistoryPages(
|
|
1935
|
+
context.writer,
|
|
1811
1936
|
path.join(outputDirectoryPath, "history", "target", encodeKey(targetKey)),
|
|
1812
1937
|
getHistoryForEntity(context.historyIndex, "target", targetKey, set || undefined),
|
|
1938
|
+
{ skipEmpty: true },
|
|
1813
1939
|
);
|
|
1814
|
-
}
|
|
1940
|
+
});
|
|
1815
1941
|
context.progress.done(targetsStartedAt, `(${pluralize(targetKeys.length, "target")})`);
|
|
1816
1942
|
|
|
1817
1943
|
const indexStartedAt = context.progress.step("Writing catalog index");
|
|
@@ -1819,9 +1945,12 @@ async function buildSetCatalog(
|
|
|
1819
1945
|
index.entities[type].sort((a, b) => a.key.localeCompare(b.key));
|
|
1820
1946
|
}
|
|
1821
1947
|
|
|
1822
|
-
await
|
|
1948
|
+
await context.writer.write(path.join(outputDirectoryPath, "index.json"), index);
|
|
1823
1949
|
context.progress.done(indexStartedAt);
|
|
1824
|
-
context.progress.done(
|
|
1950
|
+
context.progress.done(
|
|
1951
|
+
setStartedAt,
|
|
1952
|
+
`total (${pluralize(skippedEmptyHistoryCount, "empty history", "empty histories")} skipped)`,
|
|
1953
|
+
);
|
|
1825
1954
|
|
|
1826
1955
|
return index;
|
|
1827
1956
|
}
|
|
@@ -1862,6 +1991,7 @@ export async function exportCatalog(
|
|
|
1862
1991
|
const withTranslationSearch = options.withTranslationSearch === true;
|
|
1863
1992
|
const withDuplicates = options.withDuplicates === true;
|
|
1864
1993
|
const progress = new CatalogProgressReporter(rootDirectoryPath, outputDirectoryPath);
|
|
1994
|
+
const writer = new CatalogJsonWriter();
|
|
1865
1995
|
|
|
1866
1996
|
progress.start({
|
|
1867
1997
|
browserRouter: options.browserRouter !== false,
|
|
@@ -1921,6 +2051,7 @@ export async function exportCatalog(
|
|
|
1921
2051
|
const context: CatalogBuildContext = {
|
|
1922
2052
|
rootDirectoryPath,
|
|
1923
2053
|
repositoryRootDirectoryPath: getRepositoryRootDirectoryPath(rootDirectoryPath),
|
|
2054
|
+
repositorySourceRootDirectoryPath: getRepositorySourceRootDirectoryPath(rootDirectoryPath),
|
|
1924
2055
|
outputDirectoryPath,
|
|
1925
2056
|
dataDirectoryPath,
|
|
1926
2057
|
historyIndex,
|
|
@@ -1930,6 +2061,7 @@ export async function exportCatalog(
|
|
|
1930
2061
|
withTranslationSearch,
|
|
1931
2062
|
withDuplicates,
|
|
1932
2063
|
progress,
|
|
2064
|
+
writer,
|
|
1933
2065
|
};
|
|
1934
2066
|
stepStartedAt = progress.step("Discovering project sets");
|
|
1935
2067
|
const executions = await runtime.getProjectSetExecutions(projectConfig, datasource);
|
|
@@ -1942,7 +2074,11 @@ export async function exportCatalog(
|
|
|
1942
2074
|
const setIndexes: Record<string, CatalogSetIndex> = {};
|
|
1943
2075
|
|
|
1944
2076
|
stepStartedAt = progress.step("Writing project history");
|
|
1945
|
-
await writeHistoryPages(
|
|
2077
|
+
await writeHistoryPages(
|
|
2078
|
+
writer,
|
|
2079
|
+
path.join(dataDirectoryPath, "project", "history"),
|
|
2080
|
+
historyIndex.entries,
|
|
2081
|
+
);
|
|
1946
2082
|
progress.done(stepStartedAt, `(${pluralize(historyIndex.entries.length, "entry", "entries")})`);
|
|
1947
2083
|
|
|
1948
2084
|
for (const execution of executions) {
|
|
@@ -1984,7 +2120,7 @@ export async function exportCatalog(
|
|
|
1984
2120
|
counts: Object.fromEntries(Object.keys(setIndexes).map((key) => [key, setIndexes[key].counts])),
|
|
1985
2121
|
};
|
|
1986
2122
|
|
|
1987
|
-
await
|
|
2123
|
+
await writer.write(path.join(dataDirectoryPath, "manifest.json"), manifest);
|
|
1988
2124
|
progress.done(stepStartedAt);
|
|
1989
2125
|
|
|
1990
2126
|
progress.complete();
|