@xrmforge/typegen 0.3.0 → 0.5.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 CHANGED
@@ -21,6 +21,7 @@ declare enum ErrorCode {
21
21
  META_SOLUTION_NOT_FOUND = "META_3002",
22
22
  META_FORM_PARSE_FAILED = "META_3003",
23
23
  META_ATTRIBUTE_UNKNOWN_TYPE = "META_3004",
24
+ META_VERSION_STAMP_EXPIRED = "META_3005",
24
25
  GEN_OUTPUT_WRITE_FAILED = "GEN_4001",
25
26
  GEN_TEMPLATE_FAILED = "GEN_4002",
26
27
  GEN_INVALID_IDENTIFIER = "GEN_4003",
@@ -302,6 +303,8 @@ declare class DataverseHttpClient {
302
303
  private readonly maxRateLimitRetries;
303
304
  private readonly readOnly;
304
305
  private cachedToken;
306
+ /** Pending token refresh promise (prevents concurrent token requests) */
307
+ private pendingTokenRefresh;
305
308
  private activeConcurrentRequests;
306
309
  private readonly waitQueue;
307
310
  constructor(options: HttpClientOptions);
@@ -360,6 +363,8 @@ declare class DataverseHttpClient {
360
363
  */
361
364
  static escapeODataString(value: string): string;
362
365
  private getToken;
366
+ /** Internal: actually acquire a new token from the credential provider. */
367
+ private refreshToken;
363
368
  /**
364
369
  * Execute a request within the concurrency semaphore.
365
370
  * The semaphore is acquired ONCE per logical request. Retries happen
@@ -800,9 +805,11 @@ declare class MetadataCache {
800
805
  private readonly cacheDir;
801
806
  private readonly cacheFilePath;
802
807
  /**
803
- * @param projectRoot - Root directory of the project (where .xrmforge/ will be created)
808
+ * @param cacheDir - Directory where cache files are stored.
809
+ * Can be an absolute path or relative to cwd.
810
+ * Defaults to ".xrmforge/cache" when constructed without argument.
804
811
  */
805
- constructor(projectRoot: string);
812
+ constructor(cacheDir?: string);
806
813
  /**
807
814
  * Load cached metadata from disk.
808
815
  * Returns null if no cache exists, cache is for a different environment,
@@ -837,6 +844,58 @@ declare class MetadataCache {
837
844
  exists(): Promise<boolean>;
838
845
  }
839
846
 
847
+ /**
848
+ * @xrmforge/typegen - Metadata Change Detector
849
+ *
850
+ * Uses the Dataverse RetrieveMetadataChanges action to determine
851
+ * which entities have changed since the last generation run.
852
+ * This enables incremental type generation (only re-fetch changed entities).
853
+ *
854
+ * @see https://learn.microsoft.com/en-us/power-apps/developer/data-platform/webapi/samples/retrievemetadatachanges
855
+ */
856
+
857
+ /** Result of a change detection query */
858
+ interface ChangeDetectionResult {
859
+ /** Entity logical names that have changed (new or modified) */
860
+ changedEntityNames: string[];
861
+ /** Entity logical names that have been deleted */
862
+ deletedEntityNames: string[];
863
+ /** New server version stamp (store this for the next run) */
864
+ newVersionStamp: string;
865
+ }
866
+ /**
867
+ * Detects metadata changes in Dataverse using RetrieveMetadataChanges.
868
+ *
869
+ * Usage:
870
+ * ```typescript
871
+ * const detector = new ChangeDetector(httpClient);
872
+ * const result = await detector.detectChanges(cachedVersionStamp);
873
+ * // result.changedEntityNames = ['account', 'contact']
874
+ * // result.newVersionStamp = 'new-stamp-to-cache'
875
+ * ```
876
+ */
877
+ declare class ChangeDetector {
878
+ private readonly http;
879
+ constructor(http: DataverseHttpClient);
880
+ /**
881
+ * Detect which entities have changed since the given version stamp.
882
+ *
883
+ * @param clientVersionStamp - The ServerVersionStamp from the last run (from cache)
884
+ * @returns Changed entity names, deleted entity names, and new version stamp
885
+ * @throws {MetadataError} with META_VERSION_STAMP_EXPIRED if stamp is too old (>90 days)
886
+ */
887
+ detectChanges(clientVersionStamp: string): Promise<ChangeDetectionResult>;
888
+ /**
889
+ * Perform an initial metadata query to get the first ServerVersionStamp.
890
+ * This is used on the very first run (no cache exists).
891
+ *
892
+ * @returns The initial server version stamp
893
+ */
894
+ getInitialVersionStamp(): Promise<string>;
895
+ /** Check if an error is the expired version stamp error (0x80044352) */
896
+ private isExpiredVersionStampError;
897
+ }
898
+
840
899
  /**
841
900
  * @xrmforge/typegen - Label Utilities
842
901
  *
@@ -1815,15 +1874,15 @@ interface GenerateConfig {
1815
1874
  actionsFilter?: string;
1816
1875
  /**
1817
1876
  * Whether to use metadata cache for faster re-generation.
1818
- * @alpha Not yet implemented. Setting this to true will throw a ConfigError.
1819
- * Planned for v0.2.0.
1877
+ * When enabled, only changed entities are re-fetched from Dataverse
1878
+ * using RetrieveMetadataChanges delta detection.
1879
+ * On first run or expired cache, a full refresh is performed automatically.
1820
1880
  * @defaultValue false
1821
1881
  */
1822
1882
  useCache?: boolean;
1823
1883
  /**
1824
- * Cache directory for metadata cache.
1825
- * @alpha Not yet implemented. Ignored until useCache is implemented.
1826
- * Planned for v0.2.0.
1884
+ * Directory for metadata cache files.
1885
+ * Relative paths are resolved from the current working directory.
1827
1886
  * @defaultValue ".xrmforge/cache"
1828
1887
  */
1829
1888
  cacheDir?: string;
@@ -1848,6 +1907,19 @@ interface GeneratedFile {
1848
1907
  /** Type of generated content */
1849
1908
  type: 'entity' | 'optionset' | 'form' | 'action';
1850
1909
  }
1910
+ /** Statistics about cache usage during generation */
1911
+ interface CacheStats {
1912
+ /** Whether the cache was used in this run */
1913
+ cacheUsed: boolean;
1914
+ /** Whether this was a full refresh (no prior cache or expired stamp) */
1915
+ fullRefresh: boolean;
1916
+ /** Number of entities loaded from cache (unchanged) */
1917
+ entitiesFromCache: number;
1918
+ /** Number of entities fetched from Dataverse (new or changed) */
1919
+ entitiesFetched: number;
1920
+ /** Number of entities removed (deleted in Dataverse) */
1921
+ entitiesDeleted: number;
1922
+ }
1851
1923
  /** Overall result of the generation process */
1852
1924
  interface GenerationResult {
1853
1925
  /** Per-entity results */
@@ -1858,6 +1930,8 @@ interface GenerationResult {
1858
1930
  totalWarnings: number;
1859
1931
  /** Duration in milliseconds */
1860
1932
  durationMs: number;
1933
+ /** Cache statistics (present when useCache was enabled) */
1934
+ cacheStats?: CacheStats;
1861
1935
  }
1862
1936
 
1863
1937
  /**
@@ -1902,9 +1976,24 @@ declare class TypeGenerationOrchestrator {
1902
1976
  signal?: AbortSignal;
1903
1977
  }): Promise<GenerationResult>;
1904
1978
  /**
1905
- * Process a single entity: fetch metadata, generate all output files.
1979
+ * Resolve the cache: load existing cache, detect changes, determine which
1980
+ * entities need to be fetched vs. can be served from cache.
1981
+ *
1982
+ * On any failure (corrupt cache, expired stamp), falls back to full refresh.
1983
+ */
1984
+ private resolveCache;
1985
+ /**
1986
+ * Update the metadata cache after a successful generation run.
1987
+ */
1988
+ private updateCache;
1989
+ /**
1990
+ * Generate all output files for a single entity from its metadata.
1991
+ */
1992
+ private generateEntityFiles;
1993
+ /**
1994
+ * Generate Custom API Action/Function executor files.
1906
1995
  */
1907
- private processEntity;
1996
+ private generateActions;
1908
1997
  /**
1909
1998
  * Extract picklist attributes with their OptionSet metadata.
1910
1999
  * Maps the raw EntityTypeInfo data to the format expected by the OptionSet generator.
@@ -1912,4 +2001,4 @@ declare class TypeGenerationOrchestrator {
1912
2001
  private getPicklistAttributes;
1913
2002
  }
1914
2003
 
1915
- export { type ActionGeneratorOptions, ApiRequestError, type AttributeMetadata, type AuthConfig, type AuthMethod, AuthenticationError, BindingType, type BoundActionExecutor, type BoundActionWithParamsExecutor, type BoundFunctionExecutor, type ClientCredentialsAuth, ClientState, ClientType, ConfigError, ConsoleLogSink, type CustomApiTypeInfo, DEFAULT_LABEL_CONFIG, DataverseHttpClient, type DateTimeAttributeMetadata, type DecimalAttributeMetadata, type DeviceCodeAuth, DisplayState, type EntityFieldsGeneratorOptions, type EntityGenerationResult, type EntityGeneratorOptions, type EntityMetadata, type EntityNamesGeneratorOptions, type EntityTypeInfo, ErrorCode, FastXmlParser, type FormControl, type FormGeneratorOptions, FormNotificationLevel, 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, OperationType, type OptionMetadata, type OptionSetGeneratorOptions, type OptionSetMetadata, type ParameterMeta, type ParameterMetaMap, type ParsedForm, type PicklistAttributeMetadata, RequiredLevel, SaveMode, SilentLogSink, type SolutionComponent, type StateAttributeMetadata, type StatusAttributeMetadata, type StringAttributeMetadata, StructuralProperty, SubmitMode, type SystemFormMetadata, TypeGenerationOrchestrator, type UnboundActionExecutor, type UnboundActionWithParamsExecutor, type UnboundFunctionExecutor, type XmlElement, type XmlParser, XrmForgeError, configureLogging, createBoundAction, createBoundFunction, createCredential, createLogger, createUnboundAction, createUnboundFunction, defaultXmlParser, disambiguateEnumMembers, executeMultiple, executeRequest, 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, parseFormattedValue, parseLookup, parseLookups, select, selectExpand, shouldIncludeInEntityInterface, toLookupValueProperty, toPascalCase, toSafeIdentifier, withProgress };
2004
+ export { type ActionGeneratorOptions, ApiRequestError, type AttributeMetadata, type AuthConfig, type AuthMethod, AuthenticationError, BindingType, type BoundActionExecutor, type BoundActionWithParamsExecutor, type BoundFunctionExecutor, type CacheStats, type ChangeDetectionResult, ChangeDetector, type ClientCredentialsAuth, ClientState, ClientType, ConfigError, ConsoleLogSink, type CustomApiTypeInfo, DEFAULT_LABEL_CONFIG, DataverseHttpClient, type DateTimeAttributeMetadata, type DecimalAttributeMetadata, type DeviceCodeAuth, DisplayState, type EntityFieldsGeneratorOptions, type EntityGenerationResult, type EntityGeneratorOptions, type EntityMetadata, type EntityNamesGeneratorOptions, type EntityTypeInfo, ErrorCode, FastXmlParser, type FormControl, type FormGeneratorOptions, FormNotificationLevel, 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, OperationType, type OptionMetadata, type OptionSetGeneratorOptions, type OptionSetMetadata, type ParameterMeta, type ParameterMetaMap, type ParsedForm, type PicklistAttributeMetadata, RequiredLevel, SaveMode, SilentLogSink, type SolutionComponent, type StateAttributeMetadata, type StatusAttributeMetadata, type StringAttributeMetadata, StructuralProperty, SubmitMode, type SystemFormMetadata, TypeGenerationOrchestrator, type UnboundActionExecutor, type UnboundActionWithParamsExecutor, type UnboundFunctionExecutor, type XmlElement, type XmlParser, XrmForgeError, configureLogging, createBoundAction, createBoundFunction, createCredential, createLogger, createUnboundAction, createUnboundFunction, defaultXmlParser, disambiguateEnumMembers, executeMultiple, executeRequest, 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, parseFormattedValue, parseLookup, parseLookups, select, selectExpand, shouldIncludeInEntityInterface, toLookupValueProperty, toPascalCase, toSafeIdentifier, withProgress };