@xrmforge/typegen 0.10.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +48 -1
- package/dist/index.js +112 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -765,6 +765,10 @@ declare class MetadataClient {
|
|
|
765
765
|
* Queries the customapi, customapirequestparameter, and customapiresponseproperty
|
|
766
766
|
* tables and joins them into CustomApiTypeInfo objects.
|
|
767
767
|
*
|
|
768
|
+
* APIs, request parameters, and response properties are sorted alphabetically
|
|
769
|
+
* by uniquename (ordinal) so the result is deterministic regardless of
|
|
770
|
+
* server row order.
|
|
771
|
+
*
|
|
768
772
|
* @param solutionFilter - Optional: filter by solution unique name
|
|
769
773
|
* @returns Array of complete Custom API definitions
|
|
770
774
|
*/
|
|
@@ -1543,6 +1547,19 @@ interface GenerateConfig {
|
|
|
1543
1547
|
cacheDir?: string;
|
|
1544
1548
|
/** XrmForge namespace prefix (default: "XrmForge") */
|
|
1545
1549
|
namespacePrefix?: string;
|
|
1550
|
+
/**
|
|
1551
|
+
* Check mode (drift detection): generate in-memory and compare the result
|
|
1552
|
+
* byte-by-byte against the files in outputDir WITHOUT any write access
|
|
1553
|
+
* (no output files, no cache reads or updates, no orphan deletion).
|
|
1554
|
+
* The comparison result is returned in GenerationResult.checkResult.
|
|
1555
|
+
* Intended as a CI step that fails when the checked-in generated files
|
|
1556
|
+
* no longer match the live environment.
|
|
1557
|
+
* When enabled, useCache is ignored: the check must run against live
|
|
1558
|
+
* metadata, otherwise a stale local cache would mask exactly the drift
|
|
1559
|
+
* it is supposed to find.
|
|
1560
|
+
* @defaultValue false
|
|
1561
|
+
*/
|
|
1562
|
+
checkOnly?: boolean;
|
|
1546
1563
|
}
|
|
1547
1564
|
/** Result of generating types for a single entity */
|
|
1548
1565
|
interface EntityGenerationResult {
|
|
@@ -1575,6 +1592,30 @@ interface CacheStats {
|
|
|
1575
1592
|
/** Number of entities removed (deleted in Dataverse) */
|
|
1576
1593
|
entitiesDeleted: number;
|
|
1577
1594
|
}
|
|
1595
|
+
/** A single drift finding from check mode */
|
|
1596
|
+
interface CheckFinding {
|
|
1597
|
+
/** Relative path from outputDir (e.g. "actions/global.ts") */
|
|
1598
|
+
relativePath: string;
|
|
1599
|
+
/** Category of the file (matches GeneratedFile.type) */
|
|
1600
|
+
type: GeneratedFile['type'];
|
|
1601
|
+
/**
|
|
1602
|
+
* Drift class:
|
|
1603
|
+
* - "changed": file exists on disk but differs from freshly generated content
|
|
1604
|
+
* - "missing": generator produces this file but it does not exist on disk
|
|
1605
|
+
* - "orphaned": file exists on disk but the generator no longer produces it
|
|
1606
|
+
* (e.g. the entity or Custom API was deleted in Dataverse)
|
|
1607
|
+
*/
|
|
1608
|
+
status: 'changed' | 'missing' | 'orphaned';
|
|
1609
|
+
}
|
|
1610
|
+
/** Result of a drift check (GenerateConfig.checkOnly) */
|
|
1611
|
+
interface CheckResult {
|
|
1612
|
+
/** True if at least one finding exists (generated output drifted) */
|
|
1613
|
+
drift: boolean;
|
|
1614
|
+
/** Number of files that are byte-identical on disk */
|
|
1615
|
+
unchanged: number;
|
|
1616
|
+
/** All drift findings (changed, missing, orphaned files) */
|
|
1617
|
+
findings: CheckFinding[];
|
|
1618
|
+
}
|
|
1578
1619
|
/** Overall result of the generation process */
|
|
1579
1620
|
interface GenerationResult {
|
|
1580
1621
|
/** Per-entity results */
|
|
@@ -1587,6 +1628,12 @@ interface GenerationResult {
|
|
|
1587
1628
|
durationMs: number;
|
|
1588
1629
|
/** Cache statistics (present when useCache was enabled) */
|
|
1589
1630
|
cacheStats?: CacheStats;
|
|
1631
|
+
/**
|
|
1632
|
+
* Drift check result (present when checkOnly was enabled and all entities
|
|
1633
|
+
* were fetched successfully; absent on fetch failures or abort, because a
|
|
1634
|
+
* partial generation would produce misleading missing/orphaned findings).
|
|
1635
|
+
*/
|
|
1636
|
+
checkResult?: CheckResult;
|
|
1590
1637
|
}
|
|
1591
1638
|
|
|
1592
1639
|
/**
|
|
@@ -1663,4 +1710,4 @@ declare class TypeGenerationOrchestrator {
|
|
|
1663
1710
|
private generateFormMapping;
|
|
1664
1711
|
}
|
|
1665
1712
|
|
|
1666
|
-
export { type ActionGeneratorOptions, ApiRequestError, type AttributeMetadata, type AuthConfig, type AuthMethod, AuthenticationError, type CacheStats, type ChangeDetectionResult, ChangeDetector, type ClientCredentialsAuth, ConfigError, ConsoleLogSink, type CustomApiTypeInfo, DEFAULT_LABEL_CONFIG, DataverseHttpClient, type DateTimeAttributeMetadata, type DecimalAttributeMetadata, type DeviceCodeAuth, type EntityFieldsGeneratorOptions, type EntityGenerationResult, type EntityGeneratorOptions, type EntityMetadata, type EntityNamesGeneratorOptions, type EntityTypeInfo, ErrorCode, FastXmlParser, type FormControl, type FormGeneratorOptions, type FormSection, type FormTab, type GenerateConfig, type GeneratedFile, GenerationError, type GenerationResult, type GroupedCustomApis, type HttpClientOptions, type IntegerAttributeMetadata, type InteractiveAuth, JsonLogSink, type Label, type LabelConfig, type LocalizedLabel, type LogEntry, LogLevel, type LogSink, Logger, type LookupAttributeMetadata, type ManyToManyRelationshipMetadata, MetadataCache, MetadataClient, MetadataError, type MoneyAttributeMetadata, type OneToManyRelationshipMetadata, type OptionMetadata, type OptionSetGeneratorOptions, type OptionSetMetadata, type ParsedForm, type PicklistAttributeMetadata, SilentLogSink, type SolutionComponent, type StateAttributeMetadata, type StatusAttributeMetadata, type StringAttributeMetadata, type SystemFormMetadata, TypeGenerationOrchestrator, type XmlElement, type XmlParser, XrmForgeError, configureLogging, createCredential, createLogger, defaultXmlParser, disambiguateEnumMembers, extractControlFields, getJSDocLabel as formatDualLabel, generateActionDeclarations, generateActionModule, generateActivityPartyInterface, generateEntityFieldsEnum, generateEntityForms, generateEntityInterface, generateEntityNamesEnum, generateEntityNavigationProperties, generateEntityOptionSets, generateEnumMembers, generateFormInterface, generateOptionSetEnum, getEntityPropertyType, getFormAttributeType, getFormControlType, getFormMockValueType, getJSDocLabel, getLabelLanguagesParam, getPrimaryLabel, getSecondaryLabel, groupCustomApis, isLookupType, isPartyListType, isRateLimitError, isXrmForgeError, labelToIdentifier, parseForm, shouldIncludeInEntityInterface, toLookupValueProperty, toPascalCase, toSafeIdentifier };
|
|
1713
|
+
export { type ActionGeneratorOptions, ApiRequestError, type AttributeMetadata, type AuthConfig, type AuthMethod, AuthenticationError, type CacheStats, type ChangeDetectionResult, ChangeDetector, type CheckFinding, type CheckResult, type ClientCredentialsAuth, ConfigError, ConsoleLogSink, type CustomApiTypeInfo, DEFAULT_LABEL_CONFIG, DataverseHttpClient, type DateTimeAttributeMetadata, type DecimalAttributeMetadata, type DeviceCodeAuth, type EntityFieldsGeneratorOptions, type EntityGenerationResult, type EntityGeneratorOptions, type EntityMetadata, type EntityNamesGeneratorOptions, type EntityTypeInfo, ErrorCode, FastXmlParser, type FormControl, type FormGeneratorOptions, type FormSection, type FormTab, type GenerateConfig, type GeneratedFile, GenerationError, type GenerationResult, type GroupedCustomApis, type HttpClientOptions, type IntegerAttributeMetadata, type InteractiveAuth, JsonLogSink, type Label, type LabelConfig, type LocalizedLabel, type LogEntry, LogLevel, type LogSink, Logger, type LookupAttributeMetadata, type ManyToManyRelationshipMetadata, MetadataCache, MetadataClient, MetadataError, type MoneyAttributeMetadata, type OneToManyRelationshipMetadata, type OptionMetadata, type OptionSetGeneratorOptions, type OptionSetMetadata, type ParsedForm, type PicklistAttributeMetadata, SilentLogSink, type SolutionComponent, type StateAttributeMetadata, type StatusAttributeMetadata, type StringAttributeMetadata, type SystemFormMetadata, TypeGenerationOrchestrator, type XmlElement, type XmlParser, XrmForgeError, configureLogging, createCredential, createLogger, defaultXmlParser, disambiguateEnumMembers, extractControlFields, getJSDocLabel as formatDualLabel, generateActionDeclarations, generateActionModule, generateActivityPartyInterface, generateEntityFieldsEnum, generateEntityForms, generateEntityInterface, generateEntityNamesEnum, generateEntityNavigationProperties, generateEntityOptionSets, generateEnumMembers, generateFormInterface, generateOptionSetEnum, getEntityPropertyType, getFormAttributeType, getFormControlType, getFormMockValueType, getJSDocLabel, getLabelLanguagesParam, getPrimaryLabel, getSecondaryLabel, groupCustomApis, isLookupType, isPartyListType, isRateLimitError, isXrmForgeError, labelToIdentifier, parseForm, shouldIncludeInEntityInterface, toLookupValueProperty, toPascalCase, toSafeIdentifier };
|
package/dist/index.js
CHANGED
|
@@ -919,6 +919,9 @@ function extractParameter(controlElement, paramName) {
|
|
|
919
919
|
var log4 = createLogger("metadata");
|
|
920
920
|
var FORM_TYPE_MAIN = 2;
|
|
921
921
|
var COMPONENT_TYPE_ENTITY = 1;
|
|
922
|
+
function byUniqueName(a, b) {
|
|
923
|
+
return a.uniquename < b.uniquename ? -1 : a.uniquename > b.uniquename ? 1 : 0;
|
|
924
|
+
}
|
|
922
925
|
var ENTITY_SELECT = "LogicalName,SchemaName,EntitySetName,DisplayName,PrimaryIdAttribute,PrimaryNameAttribute,OwnershipType,IsCustomEntity,LogicalCollectionName,MetadataId";
|
|
923
926
|
var ATTRIBUTE_SELECT = "LogicalName,SchemaName,AttributeType,AttributeTypeName,DisplayName,IsPrimaryId,IsPrimaryName,RequiredLevel,IsValidForRead,IsValidForCreate,IsValidForUpdate,MetadataId";
|
|
924
927
|
var FORM_SELECT = "name,formid,formxml,description,isdefault";
|
|
@@ -1183,6 +1186,10 @@ var MetadataClient = class {
|
|
|
1183
1186
|
* Queries the customapi, customapirequestparameter, and customapiresponseproperty
|
|
1184
1187
|
* tables and joins them into CustomApiTypeInfo objects.
|
|
1185
1188
|
*
|
|
1189
|
+
* APIs, request parameters, and response properties are sorted alphabetically
|
|
1190
|
+
* by uniquename (ordinal) so the result is deterministic regardless of
|
|
1191
|
+
* server row order.
|
|
1192
|
+
*
|
|
1186
1193
|
* @param solutionFilter - Optional: filter by solution unique name
|
|
1187
1194
|
* @returns Array of complete Custom API definitions
|
|
1188
1195
|
*/
|
|
@@ -1236,10 +1243,11 @@ var MetadataClient = class {
|
|
|
1236
1243
|
displayname: api.displayname,
|
|
1237
1244
|
description: api.description
|
|
1238
1245
|
},
|
|
1239
|
-
requestParameters: paramsByApi.get(api.customapiid) ?? [],
|
|
1240
|
-
responseProperties: propsByApi.get(api.customapiid) ?? []
|
|
1246
|
+
requestParameters: (paramsByApi.get(api.customapiid) ?? []).sort(byUniqueName),
|
|
1247
|
+
responseProperties: (propsByApi.get(api.customapiid) ?? []).sort(byUniqueName)
|
|
1241
1248
|
});
|
|
1242
1249
|
}
|
|
1250
|
+
result.sort((a, b) => byUniqueName(a.api, b.api));
|
|
1243
1251
|
log4.info(`Loaded ${result.length} Custom APIs with parameters and response properties`);
|
|
1244
1252
|
return result;
|
|
1245
1253
|
}
|
|
@@ -2559,7 +2567,7 @@ function groupCustomApis(apis) {
|
|
|
2559
2567
|
}
|
|
2560
2568
|
|
|
2561
2569
|
// src/orchestrator/file-writer.ts
|
|
2562
|
-
import { mkdir, writeFile, readFile, unlink } from "fs/promises";
|
|
2570
|
+
import { mkdir, writeFile, readFile, unlink, readdir, access } from "fs/promises";
|
|
2563
2571
|
import { join as join2, dirname } from "path";
|
|
2564
2572
|
async function writeGeneratedFile(outputDir, file) {
|
|
2565
2573
|
const absolutePath = join2(outputDir, file.relativePath);
|
|
@@ -2609,6 +2617,73 @@ async function deleteOrphanedFiles(outputDir, deletedEntityNames) {
|
|
|
2609
2617
|
}
|
|
2610
2618
|
return deleted;
|
|
2611
2619
|
}
|
|
2620
|
+
var GENERATED_SUBDIRS = ["entities", "optionsets", "forms", "fields", "actions", "functions"];
|
|
2621
|
+
var GENERATED_ROOT_FILES = ["entity-names.ts", "form-mapping.json", "index.ts"];
|
|
2622
|
+
function typeFromRelativePath(relativePath) {
|
|
2623
|
+
if (relativePath.startsWith("optionsets/")) return "optionset";
|
|
2624
|
+
if (relativePath.startsWith("forms/")) return "form";
|
|
2625
|
+
if (relativePath.startsWith("fields/")) return "fields";
|
|
2626
|
+
if (relativePath.startsWith("actions/") || relativePath.startsWith("functions/")) return "action";
|
|
2627
|
+
return "entity";
|
|
2628
|
+
}
|
|
2629
|
+
async function checkGeneratedFile(outputDir, file) {
|
|
2630
|
+
const absolutePath = join2(outputDir, file.relativePath);
|
|
2631
|
+
try {
|
|
2632
|
+
const existing = await readFile(absolutePath, "utf-8");
|
|
2633
|
+
return existing === file.content ? "unchanged" : "changed";
|
|
2634
|
+
} catch (error) {
|
|
2635
|
+
if (error.code === "ENOENT") {
|
|
2636
|
+
return "missing";
|
|
2637
|
+
}
|
|
2638
|
+
throw error;
|
|
2639
|
+
}
|
|
2640
|
+
}
|
|
2641
|
+
async function findOrphanedFiles(outputDir, expectedPaths) {
|
|
2642
|
+
const orphans = [];
|
|
2643
|
+
for (const subdir of GENERATED_SUBDIRS) {
|
|
2644
|
+
let entries;
|
|
2645
|
+
try {
|
|
2646
|
+
entries = await readdir(join2(outputDir, subdir), { withFileTypes: true });
|
|
2647
|
+
} catch (error) {
|
|
2648
|
+
if (error.code === "ENOENT") continue;
|
|
2649
|
+
throw error;
|
|
2650
|
+
}
|
|
2651
|
+
for (const entry of entries) {
|
|
2652
|
+
if (!entry.isFile() || !entry.name.endsWith(".ts")) continue;
|
|
2653
|
+
const relativePath = `${subdir}/${entry.name}`;
|
|
2654
|
+
if (!expectedPaths.has(relativePath)) {
|
|
2655
|
+
orphans.push(relativePath);
|
|
2656
|
+
}
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
for (const rootFile of GENERATED_ROOT_FILES) {
|
|
2660
|
+
if (expectedPaths.has(rootFile)) continue;
|
|
2661
|
+
try {
|
|
2662
|
+
await access(join2(outputDir, rootFile));
|
|
2663
|
+
orphans.push(rootFile);
|
|
2664
|
+
} catch {
|
|
2665
|
+
}
|
|
2666
|
+
}
|
|
2667
|
+
return orphans.sort();
|
|
2668
|
+
}
|
|
2669
|
+
async function checkAllFiles(outputDir, files) {
|
|
2670
|
+
const findings = [];
|
|
2671
|
+
let unchanged = 0;
|
|
2672
|
+
for (const file of files) {
|
|
2673
|
+
const status = await checkGeneratedFile(outputDir, file);
|
|
2674
|
+
if (status === "unchanged") {
|
|
2675
|
+
unchanged++;
|
|
2676
|
+
} else {
|
|
2677
|
+
findings.push({ relativePath: file.relativePath, type: file.type, status });
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
const expectedPaths = new Set(files.map((f) => f.relativePath));
|
|
2681
|
+
const orphans = await findOrphanedFiles(outputDir, expectedPaths);
|
|
2682
|
+
for (const relativePath of orphans) {
|
|
2683
|
+
findings.push({ relativePath, type: typeFromRelativePath(relativePath), status: "orphaned" });
|
|
2684
|
+
}
|
|
2685
|
+
return { drift: findings.length > 0, unchanged, findings };
|
|
2686
|
+
}
|
|
2612
2687
|
var GENERATED_HEADER = `// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
2613
2688
|
// This file was generated by @xrmforge/typegen. Do not edit manually.
|
|
2614
2689
|
// Re-run 'xrmforge generate' to update.
|
|
@@ -2688,7 +2763,8 @@ var TypeGenerationOrchestrator = class {
|
|
|
2688
2763
|
actionsFilter: config.actionsFilter ?? "",
|
|
2689
2764
|
useCache: config.useCache ?? false,
|
|
2690
2765
|
cacheDir: config.cacheDir ?? ".xrmforge/cache",
|
|
2691
|
-
namespacePrefix: config.namespacePrefix ?? "XrmForge"
|
|
2766
|
+
namespacePrefix: config.namespacePrefix ?? "XrmForge",
|
|
2767
|
+
checkOnly: config.checkOnly ?? false
|
|
2692
2768
|
};
|
|
2693
2769
|
}
|
|
2694
2770
|
/**
|
|
@@ -2707,10 +2783,15 @@ var TypeGenerationOrchestrator = class {
|
|
|
2707
2783
|
if (signal?.aborted) {
|
|
2708
2784
|
return { entities: [], totalFiles: 0, totalWarnings: 0, durationMs: 0 };
|
|
2709
2785
|
}
|
|
2710
|
-
this.
|
|
2786
|
+
const checkOnly = this.config.checkOnly;
|
|
2787
|
+
const useCache = this.config.useCache && !checkOnly;
|
|
2788
|
+
if (this.config.useCache && checkOnly) {
|
|
2789
|
+
this.logger.warn("Check mode ignores the metadata cache (drift check must run against live metadata)");
|
|
2790
|
+
}
|
|
2791
|
+
this.logger.info(checkOnly ? "Starting drift check (read-only)" : "Starting type generation", {
|
|
2711
2792
|
entities: this.config.entities,
|
|
2712
2793
|
outputDir: this.config.outputDir,
|
|
2713
|
-
useCache
|
|
2794
|
+
useCache
|
|
2714
2795
|
});
|
|
2715
2796
|
const httpClient = new DataverseHttpClient({
|
|
2716
2797
|
environmentUrl: this.config.environmentUrl,
|
|
@@ -2739,7 +2820,7 @@ var TypeGenerationOrchestrator = class {
|
|
|
2739
2820
|
let cache;
|
|
2740
2821
|
let newVersionStamp = null;
|
|
2741
2822
|
const deletedEntityNames = [];
|
|
2742
|
-
if (
|
|
2823
|
+
if (useCache) {
|
|
2743
2824
|
const cacheResult = await this.resolveCache(httpClient, entitiesToFetch);
|
|
2744
2825
|
cache = cacheResult.cache;
|
|
2745
2826
|
newVersionStamp = cacheResult.newVersionStamp;
|
|
@@ -2838,15 +2919,28 @@ var TypeGenerationOrchestrator = class {
|
|
|
2838
2919
|
};
|
|
2839
2920
|
allFiles.push(indexFile);
|
|
2840
2921
|
}
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
if (
|
|
2845
|
-
this.
|
|
2922
|
+
let checkResult;
|
|
2923
|
+
let writeResult = { written: 0, unchanged: 0, warnings: [] };
|
|
2924
|
+
if (checkOnly) {
|
|
2925
|
+
if (failedEntities.size === 0 && !signal?.aborted) {
|
|
2926
|
+
checkResult = await checkAllFiles(this.config.outputDir, allFiles);
|
|
2927
|
+
this.logger.info(
|
|
2928
|
+
checkResult.drift ? `Drift detected: ${checkResult.findings.length} finding(s), ${checkResult.unchanged} files unchanged` : `No drift: ${checkResult.unchanged} files unchanged`
|
|
2929
|
+
);
|
|
2930
|
+
} else {
|
|
2931
|
+
this.logger.warn("Drift check skipped: generation incomplete (fetch failures or abort)");
|
|
2932
|
+
}
|
|
2933
|
+
} else {
|
|
2934
|
+
writeResult = await writeAllFiles(this.config.outputDir, allFiles);
|
|
2935
|
+
if (deletedEntityNames.length > 0) {
|
|
2936
|
+
const deleted = await deleteOrphanedFiles(this.config.outputDir, deletedEntityNames);
|
|
2937
|
+
if (deleted > 0) {
|
|
2938
|
+
this.logger.info(`Deleted ${deleted} orphaned files for removed entities`);
|
|
2939
|
+
}
|
|
2940
|
+
}
|
|
2941
|
+
if (useCache && cache) {
|
|
2942
|
+
await this.updateCache(cache, cachedEntityInfos, deletedEntityNames, newVersionStamp);
|
|
2846
2943
|
}
|
|
2847
|
-
}
|
|
2848
|
-
if (this.config.useCache && cache) {
|
|
2849
|
-
await this.updateCache(cache, cachedEntityInfos, deletedEntityNames, newVersionStamp);
|
|
2850
2944
|
}
|
|
2851
2945
|
const durationMs = Date.now() - startTime;
|
|
2852
2946
|
const entityWarnings = entityResults.reduce((sum, r) => sum + r.warnings.length, 0);
|
|
@@ -2854,7 +2948,7 @@ var TypeGenerationOrchestrator = class {
|
|
|
2854
2948
|
for (const w of writeResult.warnings) {
|
|
2855
2949
|
this.logger.warn(w);
|
|
2856
2950
|
}
|
|
2857
|
-
this.logger.info("Type generation complete", {
|
|
2951
|
+
this.logger.info(checkOnly ? "Drift check complete" : "Type generation complete", {
|
|
2858
2952
|
entities: entityResults.length,
|
|
2859
2953
|
filesWritten: writeResult.written,
|
|
2860
2954
|
filesUnchanged: writeResult.unchanged,
|
|
@@ -2868,7 +2962,8 @@ var TypeGenerationOrchestrator = class {
|
|
|
2868
2962
|
totalFiles: allFiles.length,
|
|
2869
2963
|
totalWarnings,
|
|
2870
2964
|
durationMs,
|
|
2871
|
-
cacheStats
|
|
2965
|
+
cacheStats,
|
|
2966
|
+
checkResult
|
|
2872
2967
|
};
|
|
2873
2968
|
}
|
|
2874
2969
|
/**
|