@xrmforge/typegen 0.10.0 → 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 +114 -18
- 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
|
}
|
|
@@ -1859,7 +1867,8 @@ function generateEntityInterface(info, options = {}) {
|
|
|
1859
1867
|
if (jsdocParts.length > 0) {
|
|
1860
1868
|
lines.push(` /** ${jsdocParts.join(" - ")} */`);
|
|
1861
1869
|
}
|
|
1862
|
-
|
|
1870
|
+
const nullable = attr.IsPrimaryId ? "" : " | null";
|
|
1871
|
+
lines.push(` ${propertyName}: ${tsType}${nullable};`);
|
|
1863
1872
|
}
|
|
1864
1873
|
if (partyListAttrs.length > 0) {
|
|
1865
1874
|
const relationship = info.oneToManyRelationships.find(
|
|
@@ -2558,7 +2567,7 @@ function groupCustomApis(apis) {
|
|
|
2558
2567
|
}
|
|
2559
2568
|
|
|
2560
2569
|
// src/orchestrator/file-writer.ts
|
|
2561
|
-
import { mkdir, writeFile, readFile, unlink } from "fs/promises";
|
|
2570
|
+
import { mkdir, writeFile, readFile, unlink, readdir, access } from "fs/promises";
|
|
2562
2571
|
import { join as join2, dirname } from "path";
|
|
2563
2572
|
async function writeGeneratedFile(outputDir, file) {
|
|
2564
2573
|
const absolutePath = join2(outputDir, file.relativePath);
|
|
@@ -2608,6 +2617,73 @@ async function deleteOrphanedFiles(outputDir, deletedEntityNames) {
|
|
|
2608
2617
|
}
|
|
2609
2618
|
return deleted;
|
|
2610
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
|
+
}
|
|
2611
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
|
|
2612
2688
|
// This file was generated by @xrmforge/typegen. Do not edit manually.
|
|
2613
2689
|
// Re-run 'xrmforge generate' to update.
|
|
@@ -2687,7 +2763,8 @@ var TypeGenerationOrchestrator = class {
|
|
|
2687
2763
|
actionsFilter: config.actionsFilter ?? "",
|
|
2688
2764
|
useCache: config.useCache ?? false,
|
|
2689
2765
|
cacheDir: config.cacheDir ?? ".xrmforge/cache",
|
|
2690
|
-
namespacePrefix: config.namespacePrefix ?? "XrmForge"
|
|
2766
|
+
namespacePrefix: config.namespacePrefix ?? "XrmForge",
|
|
2767
|
+
checkOnly: config.checkOnly ?? false
|
|
2691
2768
|
};
|
|
2692
2769
|
}
|
|
2693
2770
|
/**
|
|
@@ -2706,10 +2783,15 @@ var TypeGenerationOrchestrator = class {
|
|
|
2706
2783
|
if (signal?.aborted) {
|
|
2707
2784
|
return { entities: [], totalFiles: 0, totalWarnings: 0, durationMs: 0 };
|
|
2708
2785
|
}
|
|
2709
|
-
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", {
|
|
2710
2792
|
entities: this.config.entities,
|
|
2711
2793
|
outputDir: this.config.outputDir,
|
|
2712
|
-
useCache
|
|
2794
|
+
useCache
|
|
2713
2795
|
});
|
|
2714
2796
|
const httpClient = new DataverseHttpClient({
|
|
2715
2797
|
environmentUrl: this.config.environmentUrl,
|
|
@@ -2738,7 +2820,7 @@ var TypeGenerationOrchestrator = class {
|
|
|
2738
2820
|
let cache;
|
|
2739
2821
|
let newVersionStamp = null;
|
|
2740
2822
|
const deletedEntityNames = [];
|
|
2741
|
-
if (
|
|
2823
|
+
if (useCache) {
|
|
2742
2824
|
const cacheResult = await this.resolveCache(httpClient, entitiesToFetch);
|
|
2743
2825
|
cache = cacheResult.cache;
|
|
2744
2826
|
newVersionStamp = cacheResult.newVersionStamp;
|
|
@@ -2837,15 +2919,28 @@ var TypeGenerationOrchestrator = class {
|
|
|
2837
2919
|
};
|
|
2838
2920
|
allFiles.push(indexFile);
|
|
2839
2921
|
}
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
if (
|
|
2844
|
-
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);
|
|
2845
2943
|
}
|
|
2846
|
-
}
|
|
2847
|
-
if (this.config.useCache && cache) {
|
|
2848
|
-
await this.updateCache(cache, cachedEntityInfos, deletedEntityNames, newVersionStamp);
|
|
2849
2944
|
}
|
|
2850
2945
|
const durationMs = Date.now() - startTime;
|
|
2851
2946
|
const entityWarnings = entityResults.reduce((sum, r) => sum + r.warnings.length, 0);
|
|
@@ -2853,7 +2948,7 @@ var TypeGenerationOrchestrator = class {
|
|
|
2853
2948
|
for (const w of writeResult.warnings) {
|
|
2854
2949
|
this.logger.warn(w);
|
|
2855
2950
|
}
|
|
2856
|
-
this.logger.info("Type generation complete", {
|
|
2951
|
+
this.logger.info(checkOnly ? "Drift check complete" : "Type generation complete", {
|
|
2857
2952
|
entities: entityResults.length,
|
|
2858
2953
|
filesWritten: writeResult.written,
|
|
2859
2954
|
filesUnchanged: writeResult.unchanged,
|
|
@@ -2867,7 +2962,8 @@ var TypeGenerationOrchestrator = class {
|
|
|
2867
2962
|
totalFiles: allFiles.length,
|
|
2868
2963
|
totalWarnings,
|
|
2869
2964
|
durationMs,
|
|
2870
|
-
cacheStats
|
|
2965
|
+
cacheStats,
|
|
2966
|
+
checkResult
|
|
2871
2967
|
};
|
|
2872
2968
|
}
|
|
2873
2969
|
/**
|