@xrmforge/typegen 0.4.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 +0 -10
- package/dist/index.js +71 -55
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -330,16 +330,6 @@ declare class DataverseHttpClient {
|
|
|
330
330
|
* @param signal - Optional AbortSignal to cancel the request
|
|
331
331
|
*/
|
|
332
332
|
getAll<T>(path: string, signal?: AbortSignal): Promise<T[]>;
|
|
333
|
-
/**
|
|
334
|
-
* Execute a POST request that is semantically a read operation.
|
|
335
|
-
* Used for Dataverse actions like RetrieveMetadataChanges that require POST
|
|
336
|
-
* but do not modify data. Allowed even in read-only mode.
|
|
337
|
-
*
|
|
338
|
-
* @param path - API path (relative to apiUrl)
|
|
339
|
-
* @param body - JSON body to send
|
|
340
|
-
* @param signal - Optional AbortSignal to cancel the request
|
|
341
|
-
*/
|
|
342
|
-
postReadOnly<T>(path: string, body: unknown, signal?: AbortSignal): Promise<T>;
|
|
343
333
|
/**
|
|
344
334
|
* Returns true if this client is in read-only mode (the safe default).
|
|
345
335
|
*/
|
package/dist/index.js
CHANGED
|
@@ -404,28 +404,6 @@ var DataverseHttpClient = class {
|
|
|
404
404
|
}
|
|
405
405
|
return allResults;
|
|
406
406
|
}
|
|
407
|
-
/**
|
|
408
|
-
* Execute a POST request that is semantically a read operation.
|
|
409
|
-
* Used for Dataverse actions like RetrieveMetadataChanges that require POST
|
|
410
|
-
* but do not modify data. Allowed even in read-only mode.
|
|
411
|
-
*
|
|
412
|
-
* @param path - API path (relative to apiUrl)
|
|
413
|
-
* @param body - JSON body to send
|
|
414
|
-
* @param signal - Optional AbortSignal to cancel the request
|
|
415
|
-
*/
|
|
416
|
-
async postReadOnly(path2, body, signal) {
|
|
417
|
-
const ALLOWED_PATHS = ["/RetrieveMetadataChanges"];
|
|
418
|
-
const normalizedPath = path2.startsWith("/") ? path2 : `/${path2}`;
|
|
419
|
-
if (!ALLOWED_PATHS.some((p) => normalizedPath.startsWith(p))) {
|
|
420
|
-
throw new ApiRequestError(
|
|
421
|
-
"API_2001" /* API_REQUEST_FAILED */,
|
|
422
|
-
`postReadOnly is only allowed for safe read operations: ${ALLOWED_PATHS.join(", ")}. Got: "${normalizedPath}"`,
|
|
423
|
-
{ path: normalizedPath }
|
|
424
|
-
);
|
|
425
|
-
}
|
|
426
|
-
const url = this.resolveUrl(path2);
|
|
427
|
-
return this.executeWithConcurrency(url, signal, "POST", body);
|
|
428
|
-
}
|
|
429
407
|
// ─── Read-Only Enforcement ─────────────────────────────────────────────
|
|
430
408
|
/**
|
|
431
409
|
* Returns true if this client is in read-only mode (the safe default).
|
|
@@ -514,12 +492,14 @@ var DataverseHttpClient = class {
|
|
|
514
492
|
try {
|
|
515
493
|
tokenResponse = await this.credential.getToken(scope);
|
|
516
494
|
} catch (error) {
|
|
495
|
+
const cause = error instanceof Error ? error.message : String(error);
|
|
517
496
|
throw new AuthenticationError(
|
|
518
497
|
"AUTH_1003" /* AUTH_TOKEN_FAILED */,
|
|
519
|
-
`Failed to acquire access token for ${this.baseUrl}. Verify your authentication configuration
|
|
498
|
+
`Failed to acquire access token for ${this.baseUrl}. Verify your authentication configuration.
|
|
499
|
+
Cause: ${cause}`,
|
|
520
500
|
{
|
|
521
501
|
environmentUrl: this.baseUrl,
|
|
522
|
-
originalError:
|
|
502
|
+
originalError: cause
|
|
523
503
|
}
|
|
524
504
|
);
|
|
525
505
|
}
|
|
@@ -1421,26 +1401,22 @@ var ChangeDetector = class {
|
|
|
1421
1401
|
*/
|
|
1422
1402
|
async detectChanges(clientVersionStamp) {
|
|
1423
1403
|
log6.info("Detecting metadata changes since last run");
|
|
1424
|
-
const
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
Conditions: []
|
|
1429
|
-
},
|
|
1430
|
-
Properties: {
|
|
1431
|
-
AllProperties: false,
|
|
1432
|
-
PropertyNames: ["LogicalName"]
|
|
1433
|
-
}
|
|
1404
|
+
const query = {
|
|
1405
|
+
Criteria: {
|
|
1406
|
+
FilterOperator: "And",
|
|
1407
|
+
Conditions: []
|
|
1434
1408
|
},
|
|
1435
|
-
|
|
1436
|
-
|
|
1409
|
+
Properties: {
|
|
1410
|
+
AllProperties: false,
|
|
1411
|
+
PropertyNames: ["LogicalName"]
|
|
1412
|
+
}
|
|
1437
1413
|
};
|
|
1414
|
+
const queryJson = encodeURIComponent(JSON.stringify(query));
|
|
1415
|
+
const deletedFilter = `Microsoft.Dynamics.CRM.DeletedMetadataFilters'Default'`;
|
|
1416
|
+
const path2 = `/RetrieveMetadataChanges(Query=@q,ClientVersionStamp=@s,DeletedMetadataFilters=@d)?@q=${queryJson}&@s='${clientVersionStamp}'&@d=${deletedFilter}`;
|
|
1438
1417
|
let response;
|
|
1439
1418
|
try {
|
|
1440
|
-
response = await this.http.
|
|
1441
|
-
"/RetrieveMetadataChanges",
|
|
1442
|
-
requestBody
|
|
1443
|
-
);
|
|
1419
|
+
response = await this.http.get(path2);
|
|
1444
1420
|
} catch (error) {
|
|
1445
1421
|
if (this.isExpiredVersionStampError(error)) {
|
|
1446
1422
|
throw new MetadataError(
|
|
@@ -1475,22 +1451,19 @@ var ChangeDetector = class {
|
|
|
1475
1451
|
*/
|
|
1476
1452
|
async getInitialVersionStamp() {
|
|
1477
1453
|
log6.info("Fetching initial server version stamp");
|
|
1478
|
-
const
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
PropertyNames: ["LogicalName"]
|
|
1487
|
-
}
|
|
1454
|
+
const query = {
|
|
1455
|
+
Criteria: {
|
|
1456
|
+
FilterOperator: "And",
|
|
1457
|
+
Conditions: []
|
|
1458
|
+
},
|
|
1459
|
+
Properties: {
|
|
1460
|
+
AllProperties: false,
|
|
1461
|
+
PropertyNames: ["LogicalName"]
|
|
1488
1462
|
}
|
|
1489
1463
|
};
|
|
1490
|
-
const
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
);
|
|
1464
|
+
const queryParam = encodeURIComponent(JSON.stringify(query));
|
|
1465
|
+
const path2 = `/RetrieveMetadataChanges(Query=@q)?@q=${queryParam}`;
|
|
1466
|
+
const response = await this.http.get(path2);
|
|
1494
1467
|
log6.info("Initial version stamp acquired");
|
|
1495
1468
|
return response.ServerVersionStamp;
|
|
1496
1469
|
}
|
|
@@ -2135,6 +2108,50 @@ function generateFormInterface(form, entityLogicalName, attributeMap, options =
|
|
|
2135
2108
|
lines.push("");
|
|
2136
2109
|
}
|
|
2137
2110
|
}
|
|
2111
|
+
const specialControls = form.allSpecialControls || [];
|
|
2112
|
+
const subgrids = specialControls.filter((sc) => sc.controlType === "subgrid" || sc.controlType === "editablegrid");
|
|
2113
|
+
const quickViews = specialControls.filter((sc) => sc.controlType === "quickview");
|
|
2114
|
+
if (subgrids.length > 0) {
|
|
2115
|
+
const subgridsEnumName = `${baseName}FormSubgrids`;
|
|
2116
|
+
lines.push(` /** Subgrid constants for "${form.name}" (compile-time only, zero runtime) */`);
|
|
2117
|
+
lines.push(` const enum ${subgridsEnumName} {`);
|
|
2118
|
+
const usedMembers = /* @__PURE__ */ new Set();
|
|
2119
|
+
for (const sg of subgrids) {
|
|
2120
|
+
let member = toSafeFormName(sg.id) || toPascalCase(sg.id);
|
|
2121
|
+
const original = member;
|
|
2122
|
+
let counter = 2;
|
|
2123
|
+
while (usedMembers.has(member)) {
|
|
2124
|
+
member = `${original}${counter}`;
|
|
2125
|
+
counter++;
|
|
2126
|
+
}
|
|
2127
|
+
usedMembers.add(member);
|
|
2128
|
+
const label = sg.targetEntityType ? `Subgrid: ${sg.targetEntityType}` : `Subgrid`;
|
|
2129
|
+
lines.push(` /** ${label} */`);
|
|
2130
|
+
lines.push(` ${member} = '${sg.id}',`);
|
|
2131
|
+
}
|
|
2132
|
+
lines.push(" }");
|
|
2133
|
+
lines.push("");
|
|
2134
|
+
}
|
|
2135
|
+
if (quickViews.length > 0) {
|
|
2136
|
+
const qvEnumName = `${baseName}FormQuickViews`;
|
|
2137
|
+
lines.push(` /** Quick View constants for "${form.name}" (compile-time only, zero runtime) */`);
|
|
2138
|
+
lines.push(` const enum ${qvEnumName} {`);
|
|
2139
|
+
const usedMembers = /* @__PURE__ */ new Set();
|
|
2140
|
+
for (const qv of quickViews) {
|
|
2141
|
+
let member = toSafeFormName(qv.id) || toPascalCase(qv.id);
|
|
2142
|
+
const original = member;
|
|
2143
|
+
let counter = 2;
|
|
2144
|
+
while (usedMembers.has(member)) {
|
|
2145
|
+
member = `${original}${counter}`;
|
|
2146
|
+
counter++;
|
|
2147
|
+
}
|
|
2148
|
+
usedMembers.add(member);
|
|
2149
|
+
lines.push(` /** Quick View */`);
|
|
2150
|
+
lines.push(` ${member} = '${qv.id}',`);
|
|
2151
|
+
}
|
|
2152
|
+
lines.push(" }");
|
|
2153
|
+
lines.push("");
|
|
2154
|
+
}
|
|
2138
2155
|
lines.push(` /** ${form.name} */`);
|
|
2139
2156
|
lines.push(` interface ${interfaceName} extends Omit<Xrm.FormContext, 'getAttribute' | 'getControl'> {`);
|
|
2140
2157
|
lines.push(` /** Typisierter Feldzugriff: nur Felder die auf diesem Formular existieren */`);
|
|
@@ -2144,7 +2161,6 @@ function generateFormInterface(form, entityLogicalName, attributeMap, options =
|
|
|
2144
2161
|
lines.push("");
|
|
2145
2162
|
lines.push(` /** Typisierter Control-Zugriff: nur Controls die auf diesem Formular existieren */`);
|
|
2146
2163
|
lines.push(` getControl<K extends ${fieldsTypeName}>(name: K): ${ctrlMapName}[K];`);
|
|
2147
|
-
const specialControls = form.allSpecialControls || [];
|
|
2148
2164
|
for (const sc of specialControls) {
|
|
2149
2165
|
const xrmType = specialControlToXrmType(sc.controlType);
|
|
2150
2166
|
if (xrmType) {
|