@xrmforge/typegen 0.10.1 → 0.11.1
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 +116 -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
|
}
|
|
@@ -2559,13 +2567,16 @@ 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";
|
|
2572
|
+
function normalizeLineEndings(content) {
|
|
2573
|
+
return content.replace(/\r\n?/g, "\n");
|
|
2574
|
+
}
|
|
2564
2575
|
async function writeGeneratedFile(outputDir, file) {
|
|
2565
2576
|
const absolutePath = join2(outputDir, file.relativePath);
|
|
2566
2577
|
try {
|
|
2567
2578
|
const existing = await readFile(absolutePath, "utf-8");
|
|
2568
|
-
if (existing === file.content) {
|
|
2579
|
+
if (normalizeLineEndings(existing) === normalizeLineEndings(file.content)) {
|
|
2569
2580
|
return false;
|
|
2570
2581
|
}
|
|
2571
2582
|
} catch {
|
|
@@ -2609,6 +2620,73 @@ async function deleteOrphanedFiles(outputDir, deletedEntityNames) {
|
|
|
2609
2620
|
}
|
|
2610
2621
|
return deleted;
|
|
2611
2622
|
}
|
|
2623
|
+
var GENERATED_SUBDIRS = ["entities", "optionsets", "forms", "fields", "actions", "functions"];
|
|
2624
|
+
var GENERATED_ROOT_FILES = ["entity-names.ts", "form-mapping.json", "index.ts"];
|
|
2625
|
+
function typeFromRelativePath(relativePath) {
|
|
2626
|
+
if (relativePath.startsWith("optionsets/")) return "optionset";
|
|
2627
|
+
if (relativePath.startsWith("forms/")) return "form";
|
|
2628
|
+
if (relativePath.startsWith("fields/")) return "fields";
|
|
2629
|
+
if (relativePath.startsWith("actions/") || relativePath.startsWith("functions/")) return "action";
|
|
2630
|
+
return "entity";
|
|
2631
|
+
}
|
|
2632
|
+
async function checkGeneratedFile(outputDir, file) {
|
|
2633
|
+
const absolutePath = join2(outputDir, file.relativePath);
|
|
2634
|
+
try {
|
|
2635
|
+
const existing = await readFile(absolutePath, "utf-8");
|
|
2636
|
+
return normalizeLineEndings(existing) === normalizeLineEndings(file.content) ? "unchanged" : "changed";
|
|
2637
|
+
} catch (error) {
|
|
2638
|
+
if (error.code === "ENOENT") {
|
|
2639
|
+
return "missing";
|
|
2640
|
+
}
|
|
2641
|
+
throw error;
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
async function findOrphanedFiles(outputDir, expectedPaths) {
|
|
2645
|
+
const orphans = [];
|
|
2646
|
+
for (const subdir of GENERATED_SUBDIRS) {
|
|
2647
|
+
let entries;
|
|
2648
|
+
try {
|
|
2649
|
+
entries = await readdir(join2(outputDir, subdir), { withFileTypes: true });
|
|
2650
|
+
} catch (error) {
|
|
2651
|
+
if (error.code === "ENOENT") continue;
|
|
2652
|
+
throw error;
|
|
2653
|
+
}
|
|
2654
|
+
for (const entry of entries) {
|
|
2655
|
+
if (!entry.isFile() || !entry.name.endsWith(".ts")) continue;
|
|
2656
|
+
const relativePath = `${subdir}/${entry.name}`;
|
|
2657
|
+
if (!expectedPaths.has(relativePath)) {
|
|
2658
|
+
orphans.push(relativePath);
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
for (const rootFile of GENERATED_ROOT_FILES) {
|
|
2663
|
+
if (expectedPaths.has(rootFile)) continue;
|
|
2664
|
+
try {
|
|
2665
|
+
await access(join2(outputDir, rootFile));
|
|
2666
|
+
orphans.push(rootFile);
|
|
2667
|
+
} catch {
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
return orphans.sort();
|
|
2671
|
+
}
|
|
2672
|
+
async function checkAllFiles(outputDir, files) {
|
|
2673
|
+
const findings = [];
|
|
2674
|
+
let unchanged = 0;
|
|
2675
|
+
for (const file of files) {
|
|
2676
|
+
const status = await checkGeneratedFile(outputDir, file);
|
|
2677
|
+
if (status === "unchanged") {
|
|
2678
|
+
unchanged++;
|
|
2679
|
+
} else {
|
|
2680
|
+
findings.push({ relativePath: file.relativePath, type: file.type, status });
|
|
2681
|
+
}
|
|
2682
|
+
}
|
|
2683
|
+
const expectedPaths = new Set(files.map((f) => f.relativePath));
|
|
2684
|
+
const orphans = await findOrphanedFiles(outputDir, expectedPaths);
|
|
2685
|
+
for (const relativePath of orphans) {
|
|
2686
|
+
findings.push({ relativePath, type: typeFromRelativePath(relativePath), status: "orphaned" });
|
|
2687
|
+
}
|
|
2688
|
+
return { drift: findings.length > 0, unchanged, findings };
|
|
2689
|
+
}
|
|
2612
2690
|
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
2691
|
// This file was generated by @xrmforge/typegen. Do not edit manually.
|
|
2614
2692
|
// Re-run 'xrmforge generate' to update.
|
|
@@ -2688,7 +2766,8 @@ var TypeGenerationOrchestrator = class {
|
|
|
2688
2766
|
actionsFilter: config.actionsFilter ?? "",
|
|
2689
2767
|
useCache: config.useCache ?? false,
|
|
2690
2768
|
cacheDir: config.cacheDir ?? ".xrmforge/cache",
|
|
2691
|
-
namespacePrefix: config.namespacePrefix ?? "XrmForge"
|
|
2769
|
+
namespacePrefix: config.namespacePrefix ?? "XrmForge",
|
|
2770
|
+
checkOnly: config.checkOnly ?? false
|
|
2692
2771
|
};
|
|
2693
2772
|
}
|
|
2694
2773
|
/**
|
|
@@ -2707,10 +2786,15 @@ var TypeGenerationOrchestrator = class {
|
|
|
2707
2786
|
if (signal?.aborted) {
|
|
2708
2787
|
return { entities: [], totalFiles: 0, totalWarnings: 0, durationMs: 0 };
|
|
2709
2788
|
}
|
|
2710
|
-
this.
|
|
2789
|
+
const checkOnly = this.config.checkOnly;
|
|
2790
|
+
const useCache = this.config.useCache && !checkOnly;
|
|
2791
|
+
if (this.config.useCache && checkOnly) {
|
|
2792
|
+
this.logger.warn("Check mode ignores the metadata cache (drift check must run against live metadata)");
|
|
2793
|
+
}
|
|
2794
|
+
this.logger.info(checkOnly ? "Starting drift check (read-only)" : "Starting type generation", {
|
|
2711
2795
|
entities: this.config.entities,
|
|
2712
2796
|
outputDir: this.config.outputDir,
|
|
2713
|
-
useCache
|
|
2797
|
+
useCache
|
|
2714
2798
|
});
|
|
2715
2799
|
const httpClient = new DataverseHttpClient({
|
|
2716
2800
|
environmentUrl: this.config.environmentUrl,
|
|
@@ -2739,7 +2823,7 @@ var TypeGenerationOrchestrator = class {
|
|
|
2739
2823
|
let cache;
|
|
2740
2824
|
let newVersionStamp = null;
|
|
2741
2825
|
const deletedEntityNames = [];
|
|
2742
|
-
if (
|
|
2826
|
+
if (useCache) {
|
|
2743
2827
|
const cacheResult = await this.resolveCache(httpClient, entitiesToFetch);
|
|
2744
2828
|
cache = cacheResult.cache;
|
|
2745
2829
|
newVersionStamp = cacheResult.newVersionStamp;
|
|
@@ -2838,15 +2922,28 @@ var TypeGenerationOrchestrator = class {
|
|
|
2838
2922
|
};
|
|
2839
2923
|
allFiles.push(indexFile);
|
|
2840
2924
|
}
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
if (
|
|
2845
|
-
this.
|
|
2925
|
+
let checkResult;
|
|
2926
|
+
let writeResult = { written: 0, unchanged: 0, warnings: [] };
|
|
2927
|
+
if (checkOnly) {
|
|
2928
|
+
if (failedEntities.size === 0 && !signal?.aborted) {
|
|
2929
|
+
checkResult = await checkAllFiles(this.config.outputDir, allFiles);
|
|
2930
|
+
this.logger.info(
|
|
2931
|
+
checkResult.drift ? `Drift detected: ${checkResult.findings.length} finding(s), ${checkResult.unchanged} files unchanged` : `No drift: ${checkResult.unchanged} files unchanged`
|
|
2932
|
+
);
|
|
2933
|
+
} else {
|
|
2934
|
+
this.logger.warn("Drift check skipped: generation incomplete (fetch failures or abort)");
|
|
2935
|
+
}
|
|
2936
|
+
} else {
|
|
2937
|
+
writeResult = await writeAllFiles(this.config.outputDir, allFiles);
|
|
2938
|
+
if (deletedEntityNames.length > 0) {
|
|
2939
|
+
const deleted = await deleteOrphanedFiles(this.config.outputDir, deletedEntityNames);
|
|
2940
|
+
if (deleted > 0) {
|
|
2941
|
+
this.logger.info(`Deleted ${deleted} orphaned files for removed entities`);
|
|
2942
|
+
}
|
|
2943
|
+
}
|
|
2944
|
+
if (useCache && cache) {
|
|
2945
|
+
await this.updateCache(cache, cachedEntityInfos, deletedEntityNames, newVersionStamp);
|
|
2846
2946
|
}
|
|
2847
|
-
}
|
|
2848
|
-
if (this.config.useCache && cache) {
|
|
2849
|
-
await this.updateCache(cache, cachedEntityInfos, deletedEntityNames, newVersionStamp);
|
|
2850
2947
|
}
|
|
2851
2948
|
const durationMs = Date.now() - startTime;
|
|
2852
2949
|
const entityWarnings = entityResults.reduce((sum, r) => sum + r.warnings.length, 0);
|
|
@@ -2854,7 +2951,7 @@ var TypeGenerationOrchestrator = class {
|
|
|
2854
2951
|
for (const w of writeResult.warnings) {
|
|
2855
2952
|
this.logger.warn(w);
|
|
2856
2953
|
}
|
|
2857
|
-
this.logger.info("Type generation complete", {
|
|
2954
|
+
this.logger.info(checkOnly ? "Drift check complete" : "Type generation complete", {
|
|
2858
2955
|
entities: entityResults.length,
|
|
2859
2956
|
filesWritten: writeResult.written,
|
|
2860
2957
|
filesUnchanged: writeResult.unchanged,
|
|
@@ -2868,7 +2965,8 @@ var TypeGenerationOrchestrator = class {
|
|
|
2868
2965
|
totalFiles: allFiles.length,
|
|
2869
2966
|
totalWarnings,
|
|
2870
2967
|
durationMs,
|
|
2871
|
-
cacheStats
|
|
2968
|
+
cacheStats,
|
|
2969
|
+
checkResult
|
|
2872
2970
|
};
|
|
2873
2971
|
}
|
|
2874
2972
|
/**
|