@xrmforge/typegen 0.11.1 → 0.12.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 +68 -70
- package/dist/index.js +21 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -489,6 +489,10 @@ interface SystemFormMetadata {
|
|
|
489
489
|
formxml: string;
|
|
490
490
|
description: string | null;
|
|
491
491
|
isdefault: boolean;
|
|
492
|
+
/** Form type (systemform_type): 2 = Main, 7 = Quick Create, ... */
|
|
493
|
+
type: number;
|
|
494
|
+
/** Activation state (systemform_formactivationstate): 0 = Inactive, 1 = Active */
|
|
495
|
+
formactivationstate: number;
|
|
492
496
|
}
|
|
493
497
|
/** Parsed data-bound control from FormXml (bound to an attribute) */
|
|
494
498
|
interface FormControl {
|
|
@@ -541,6 +545,8 @@ interface ParsedForm {
|
|
|
541
545
|
name: string;
|
|
542
546
|
formId: string;
|
|
543
547
|
isDefault: boolean;
|
|
548
|
+
/** Form type (systemform_type): 2 = Main, 7 = Quick Create */
|
|
549
|
+
type: number;
|
|
544
550
|
tabs: FormTab[];
|
|
545
551
|
/** All data-bound controls across all tabs/sections (flattened) */
|
|
546
552
|
allControls: FormControl[];
|
|
@@ -712,10 +718,14 @@ declare class MetadataClient {
|
|
|
712
718
|
*/
|
|
713
719
|
getStateAttributes(logicalName: string): Promise<StateAttributeMetadata[]>;
|
|
714
720
|
/**
|
|
715
|
-
* Get and parse
|
|
716
|
-
*
|
|
721
|
+
* Get and parse the form types relevant for type generation (Main type=2 and
|
|
722
|
+
* Quick Create type=7), restricted to ACTIVE forms (formactivationstate=1).
|
|
723
|
+
* Inactive forms are leftovers that no app surfaces, so they get no interface -
|
|
724
|
+
* this applies to both Main and Quick Create forms.
|
|
725
|
+
*
|
|
726
|
+
* Returns parsed form structures with tabs, sections, controls, and the form type.
|
|
717
727
|
*/
|
|
718
|
-
|
|
728
|
+
getForms(logicalName: string): Promise<ParsedForm[]>;
|
|
719
729
|
/**
|
|
720
730
|
* Get a global OptionSet by its exact name.
|
|
721
731
|
*/
|
|
@@ -1202,14 +1212,12 @@ declare function disambiguateEnumMembers(members: Array<{
|
|
|
1202
1212
|
* Generates TypeScript declaration files (.d.ts) for Dataverse entity interfaces.
|
|
1203
1213
|
* These interfaces represent the data types returned by the Web API.
|
|
1204
1214
|
*
|
|
1205
|
-
* Output pattern:
|
|
1215
|
+
* Output pattern (flat ES module, one file per entity):
|
|
1206
1216
|
* ```typescript
|
|
1207
|
-
*
|
|
1208
|
-
*
|
|
1209
|
-
*
|
|
1210
|
-
*
|
|
1211
|
-
* // ...
|
|
1212
|
-
* }
|
|
1217
|
+
* export interface Account {
|
|
1218
|
+
* accountid: string;
|
|
1219
|
+
* name: string | null;
|
|
1220
|
+
* // ...
|
|
1213
1221
|
* }
|
|
1214
1222
|
* ```
|
|
1215
1223
|
*/
|
|
@@ -1235,13 +1243,11 @@ declare function generateEntityInterface(info: EntityTypeInfo, options?: EntityG
|
|
|
1235
1243
|
* Uses const enum because D365 form scripts have no module system at runtime,
|
|
1236
1244
|
* so enum values must be inlined at compile time.
|
|
1237
1245
|
*
|
|
1238
|
-
* Output pattern:
|
|
1246
|
+
* Output pattern (flat ES module, all OptionSets of an entity in one file):
|
|
1239
1247
|
* ```typescript
|
|
1240
|
-
*
|
|
1241
|
-
*
|
|
1242
|
-
*
|
|
1243
|
-
* Standard = 2,
|
|
1244
|
-
* }
|
|
1248
|
+
* export const enum AccountCategoryCode {
|
|
1249
|
+
* PreferredCustomer = 1,
|
|
1250
|
+
* Standard = 2,
|
|
1245
1251
|
* }
|
|
1246
1252
|
* ```
|
|
1247
1253
|
*/
|
|
@@ -1291,38 +1297,37 @@ declare function generateEntityOptionSets(picklistAttributes: Array<{
|
|
|
1291
1297
|
* 4. Fields const enum: provides autocomplete with dual-language labels
|
|
1292
1298
|
* 5. NO fallback getAttribute(name: string): unknown fields are compile errors
|
|
1293
1299
|
*
|
|
1294
|
-
* Output pattern:
|
|
1300
|
+
* Output pattern (flat ES module, one file per entity, all forms combined):
|
|
1295
1301
|
* ```typescript
|
|
1296
|
-
*
|
|
1297
|
-
*
|
|
1298
|
-
*
|
|
1299
|
-
*
|
|
1300
|
-
*
|
|
1301
|
-
*
|
|
1302
|
-
*
|
|
1303
|
-
*
|
|
1304
|
-
*
|
|
1305
|
-
*
|
|
1306
|
-
*
|
|
1307
|
-
*
|
|
1308
|
-
*
|
|
1309
|
-
*
|
|
1310
|
-
*
|
|
1311
|
-
*
|
|
1312
|
-
*
|
|
1313
|
-
*
|
|
1314
|
-
*
|
|
1315
|
-
*
|
|
1316
|
-
*
|
|
1317
|
-
*
|
|
1318
|
-
*
|
|
1319
|
-
*
|
|
1320
|
-
*
|
|
1321
|
-
*
|
|
1322
|
-
*
|
|
1323
|
-
* getControl(): Xrm.Controls.Control[];
|
|
1324
|
-
* }
|
|
1302
|
+
* export type AccountMainFormFields = "name" | "telephone1" | "revenue";
|
|
1303
|
+
*
|
|
1304
|
+
* export type AccountMainFormAttributeMap = {
|
|
1305
|
+
* name: Xrm.Attributes.StringAttribute;
|
|
1306
|
+
* telephone1: Xrm.Attributes.StringAttribute;
|
|
1307
|
+
* revenue: Xrm.Attributes.NumberAttribute;
|
|
1308
|
+
* };
|
|
1309
|
+
*
|
|
1310
|
+
* export type AccountMainFormControlMap = {
|
|
1311
|
+
* name: Xrm.Controls.StringControl;
|
|
1312
|
+
* telephone1: Xrm.Controls.StringControl;
|
|
1313
|
+
* revenue: Xrm.Controls.NumberControl;
|
|
1314
|
+
* };
|
|
1315
|
+
*
|
|
1316
|
+
* export const enum AccountMainFormFieldsEnum {
|
|
1317
|
+
* Name = 'name',
|
|
1318
|
+
* Telephone1 = 'telephone1',
|
|
1319
|
+
* Revenue = 'revenue',
|
|
1320
|
+
* }
|
|
1321
|
+
*
|
|
1322
|
+
* export interface AccountMainForm extends Omit<Xrm.FormContext, 'getAttribute' | 'getControl'> {
|
|
1323
|
+
* getAttribute<K extends AccountMainFormFields>(name: K): AccountMainFormAttributeMap[K];
|
|
1324
|
+
* getAttribute(index: number): Xrm.Attributes.Attribute;
|
|
1325
|
+
* getAttribute(): Xrm.Attributes.Attribute[];
|
|
1326
|
+
* getControl<K extends AccountMainFormFields>(name: K): AccountMainFormControlMap[K];
|
|
1327
|
+
* getControl(index: number): Xrm.Controls.Control;
|
|
1328
|
+
* getControl(): Xrm.Controls.Control[];
|
|
1325
1329
|
* }
|
|
1330
|
+
* // plus ...FormTabs/...Sections/...FormSubgrids enums, ...FormTypeInfo, ...FormMockValues
|
|
1326
1331
|
* ```
|
|
1327
1332
|
*/
|
|
1328
1333
|
|
|
@@ -1364,15 +1369,13 @@ declare function generateEntityForms(forms: ParsedForm[], entityLogicalName: str
|
|
|
1364
1369
|
* Generates a const enum with ALL entity fields for use with Xrm.WebApi.
|
|
1365
1370
|
* Unlike form-specific Fields enums, this contains every readable attribute.
|
|
1366
1371
|
*
|
|
1367
|
-
* Output pattern:
|
|
1372
|
+
* Output pattern (flat ES module):
|
|
1368
1373
|
* ```typescript
|
|
1369
|
-
*
|
|
1370
|
-
*
|
|
1371
|
-
*
|
|
1372
|
-
*
|
|
1373
|
-
*
|
|
1374
|
-
* Telephone1 = 'telephone1',
|
|
1375
|
-
* }
|
|
1374
|
+
* export const enum AccountFields {
|
|
1375
|
+
* /** Account Name | Firmenname *\/
|
|
1376
|
+
* Name = 'name',
|
|
1377
|
+
* /** Main Phone | Haupttelefon *\/
|
|
1378
|
+
* Telephone1 = 'telephone1',
|
|
1376
1379
|
* }
|
|
1377
1380
|
* ```
|
|
1378
1381
|
*/
|
|
@@ -1422,14 +1425,12 @@ declare function generateEntityNavigationProperties(info: EntityTypeInfo, option
|
|
|
1422
1425
|
* Generates a single const enum with all entity logical names.
|
|
1423
1426
|
* Eliminates raw strings in Xrm.WebApi calls.
|
|
1424
1427
|
*
|
|
1425
|
-
* Output pattern:
|
|
1428
|
+
* Output pattern (flat ES module):
|
|
1426
1429
|
* ```typescript
|
|
1427
|
-
*
|
|
1428
|
-
*
|
|
1429
|
-
*
|
|
1430
|
-
*
|
|
1431
|
-
* Lead = 'lead',
|
|
1432
|
-
* }
|
|
1430
|
+
* export const enum EntityNames {
|
|
1431
|
+
* Account = 'account',
|
|
1432
|
+
* Contact = 'contact',
|
|
1433
|
+
* Lead = 'lead',
|
|
1433
1434
|
* }
|
|
1434
1435
|
* ```
|
|
1435
1436
|
*/
|
|
@@ -1454,17 +1455,14 @@ declare function generateEntityNamesEnum(entityNames: string[], _options?: Entit
|
|
|
1454
1455
|
* Input: CustomApiTypeInfo[] (from fixture JSON or live Dataverse query)
|
|
1455
1456
|
* Output: Grouped by entity (bound) or "global" (unbound)
|
|
1456
1457
|
*
|
|
1457
|
-
* @example Generated output for markant_NormalizePhone (unbound action):
|
|
1458
|
+
* @example Generated output for markant_NormalizePhone (unbound action) in actions/global.ts:
|
|
1458
1459
|
* ```typescript
|
|
1459
|
-
* // global.d.ts
|
|
1460
|
-
* declare namespace XrmForge.Actions {
|
|
1461
|
-
* interface NormalizePhoneParams { Input: string; AllowSuspicious?: boolean; }
|
|
1462
|
-
* interface NormalizePhoneResult { Normalized: string; Status: number; Message: string; }
|
|
1463
|
-
* }
|
|
1464
|
-
*
|
|
1465
|
-
* // global.ts
|
|
1466
1460
|
* import { createUnboundAction } from '@xrmforge/helpers';
|
|
1467
|
-
*
|
|
1461
|
+
*
|
|
1462
|
+
* export type NormalizePhoneParams = { Input: string; AllowSuspicious?: boolean; };
|
|
1463
|
+
* export type NormalizePhoneResult = { Normalized: string; Status: number; Message: string; };
|
|
1464
|
+
* export const NormalizePhone =
|
|
1465
|
+
* createUnboundAction<NormalizePhoneParams, NormalizePhoneResult>('markant_NormalizePhone', { ... });
|
|
1468
1466
|
* ```
|
|
1469
1467
|
*/
|
|
1470
1468
|
|
package/dist/index.js
CHANGED
|
@@ -774,6 +774,7 @@ function parseForm(form, parser = defaultXmlParser) {
|
|
|
774
774
|
name: form.name,
|
|
775
775
|
formId: form.formid,
|
|
776
776
|
isDefault: form.isdefault,
|
|
777
|
+
type: form.type,
|
|
777
778
|
tabs,
|
|
778
779
|
allControls,
|
|
779
780
|
allSpecialControls
|
|
@@ -918,13 +919,15 @@ function extractParameter(controlElement, paramName) {
|
|
|
918
919
|
// src/metadata/client.ts
|
|
919
920
|
var log4 = createLogger("metadata");
|
|
920
921
|
var FORM_TYPE_MAIN = 2;
|
|
922
|
+
var FORM_TYPE_QUICK_CREATE = 7;
|
|
923
|
+
var FORM_ACTIVATION_ACTIVE = 1;
|
|
921
924
|
var COMPONENT_TYPE_ENTITY = 1;
|
|
922
925
|
function byUniqueName(a, b) {
|
|
923
926
|
return a.uniquename < b.uniquename ? -1 : a.uniquename > b.uniquename ? 1 : 0;
|
|
924
927
|
}
|
|
925
928
|
var ENTITY_SELECT = "LogicalName,SchemaName,EntitySetName,DisplayName,PrimaryIdAttribute,PrimaryNameAttribute,OwnershipType,IsCustomEntity,LogicalCollectionName,MetadataId";
|
|
926
929
|
var ATTRIBUTE_SELECT = "LogicalName,SchemaName,AttributeType,AttributeTypeName,DisplayName,IsPrimaryId,IsPrimaryName,RequiredLevel,IsValidForRead,IsValidForCreate,IsValidForUpdate,MetadataId";
|
|
927
|
-
var FORM_SELECT = "name,formid,formxml,description,isdefault";
|
|
930
|
+
var FORM_SELECT = "name,formid,formxml,description,isdefault,type,formactivationstate";
|
|
928
931
|
var MetadataClient = class {
|
|
929
932
|
http;
|
|
930
933
|
constructor(httpClient) {
|
|
@@ -1001,16 +1004,22 @@ var MetadataClient = class {
|
|
|
1001
1004
|
}
|
|
1002
1005
|
// ─── Form Metadata ────────────────────────────────────────────────────
|
|
1003
1006
|
/**
|
|
1004
|
-
* Get and parse
|
|
1005
|
-
*
|
|
1007
|
+
* Get and parse the form types relevant for type generation (Main type=2 and
|
|
1008
|
+
* Quick Create type=7), restricted to ACTIVE forms (formactivationstate=1).
|
|
1009
|
+
* Inactive forms are leftovers that no app surfaces, so they get no interface -
|
|
1010
|
+
* this applies to both Main and Quick Create forms.
|
|
1011
|
+
*
|
|
1012
|
+
* Returns parsed form structures with tabs, sections, controls, and the form type.
|
|
1006
1013
|
*/
|
|
1007
|
-
async
|
|
1014
|
+
async getForms(logicalName) {
|
|
1008
1015
|
const safeName = DataverseHttpClient.sanitizeIdentifier(logicalName);
|
|
1009
|
-
log4.info(`Fetching Main forms for: ${safeName}`);
|
|
1016
|
+
log4.info(`Fetching active Main + Quick Create forms for: ${safeName}`);
|
|
1010
1017
|
const forms = await this.http.getAll(
|
|
1011
|
-
`/systemforms?$filter=objecttypecode eq '${safeName}' and type eq ${FORM_TYPE_MAIN}&$select=${FORM_SELECT}`
|
|
1018
|
+
`/systemforms?$filter=objecttypecode eq '${safeName}' and (type eq ${FORM_TYPE_MAIN} or type eq ${FORM_TYPE_QUICK_CREATE}) and formactivationstate eq ${FORM_ACTIVATION_ACTIVE}&$select=${FORM_SELECT}`
|
|
1012
1019
|
);
|
|
1013
|
-
|
|
1020
|
+
const mainCount = forms.filter((f) => f.type === FORM_TYPE_MAIN).length;
|
|
1021
|
+
const qcCount = forms.filter((f) => f.type === FORM_TYPE_QUICK_CREATE).length;
|
|
1022
|
+
log4.info(`Found ${mainCount} Main + ${qcCount} Quick Create active form(s) for "${safeName}"`);
|
|
1014
1023
|
return forms.map((form) => {
|
|
1015
1024
|
try {
|
|
1016
1025
|
return parseForm(form);
|
|
@@ -1024,6 +1033,7 @@ var MetadataClient = class {
|
|
|
1024
1033
|
name: form.name,
|
|
1025
1034
|
formId: form.formid,
|
|
1026
1035
|
isDefault: form.isdefault,
|
|
1036
|
+
type: form.type,
|
|
1027
1037
|
tabs: [],
|
|
1028
1038
|
allControls: [],
|
|
1029
1039
|
allSpecialControls: []
|
|
@@ -1152,7 +1162,7 @@ var MetadataClient = class {
|
|
|
1152
1162
|
this.getLookupAttributes(safeName),
|
|
1153
1163
|
this.getStatusAttributes(safeName),
|
|
1154
1164
|
this.getStateAttributes(safeName),
|
|
1155
|
-
this.
|
|
1165
|
+
this.getForms(safeName),
|
|
1156
1166
|
this.getRelationships(safeName)
|
|
1157
1167
|
]);
|
|
1158
1168
|
const result = {
|
|
@@ -1937,6 +1947,7 @@ function generateEntityOptionSets(picklistAttributes, entityLogicalName, options
|
|
|
1937
1947
|
}
|
|
1938
1948
|
|
|
1939
1949
|
// src/generators/form-generator.ts
|
|
1950
|
+
var FORM_TYPE_QUICK_CREATE2 = 7;
|
|
1940
1951
|
function specialControlToXrmType(controlType) {
|
|
1941
1952
|
switch (controlType) {
|
|
1942
1953
|
case "subgrid":
|
|
@@ -2239,8 +2250,8 @@ function generateEntityForms(forms, entityLogicalName, attributes, options = {})
|
|
|
2239
2250
|
const entityPascal = toPascalCase(entityLogicalName);
|
|
2240
2251
|
const validForms = forms.filter((f) => f.allControls.length > 0);
|
|
2241
2252
|
const baseNames = validForms.map((form) => {
|
|
2242
|
-
const
|
|
2243
|
-
return
|
|
2253
|
+
const base = buildFormBaseName(entityPascal, toSafeFormName(form.name));
|
|
2254
|
+
return form.type === FORM_TYPE_QUICK_CREATE2 ? `${base}QuickCreate` : base;
|
|
2244
2255
|
});
|
|
2245
2256
|
const baseNameCounts = /* @__PURE__ */ new Map();
|
|
2246
2257
|
for (const name of baseNames) {
|