Skip to content

Commit 33ae4d9

Browse files
EMaherCopilot
andcommitted
fix: strip schemaId/typeName from operation PATCH during reconciliation
After spec import, APIM assigns its own auto-generated schema IDs to operation request/response representations. The reconciliation PATCH was sending the source instance's schema IDs, which don't exist on the target. APIM silently drops schemaId/typeName when the referenced schema doesn't exist, causing the compare phase to report missing fields. By stripping these fields from the PATCH body, APIM retains the schema references it assigned during its own spec import. The compare script already normalizes auto-generated hex IDs, so both sides match. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 31b9bef commit 33ae4d9

1 file changed

Lines changed: 48 additions & 0 deletions

File tree

src/services/api-publisher.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,13 @@ async function reconcileOperationsAfterSpecImport(
434434
}
435435
}
436436

437+
// Strip schemaId/typeName from representations in request/responses.
438+
// These reference source-specific auto-generated schema IDs that won't exist
439+
// on the target after a fresh spec import. APIM re-links representations to
440+
// its own schema IDs during import, so sending stale source IDs causes APIM
441+
// to silently drop the fields.
442+
stripRepresentationSchemaRefs(patchProps);
443+
437444
if (Object.keys(patchProps).length === 0) return;
438445

439446
const patchBody: Record<string, unknown> = { properties: patchProps };
@@ -456,6 +463,47 @@ async function reconcileOperationsAfterSpecImport(
456463
}
457464
}
458465

466+
/**
467+
* Strip schemaId and typeName from all representations in request/responses.
468+
* After a spec import, APIM assigns its own auto-generated schema IDs to
469+
* operation representations. The persisted JSON references the *source* instance's
470+
* schema IDs, which don't exist on the target. Sending them in a PATCH causes APIM
471+
* to silently drop the fields. By stripping them, we let APIM keep its own
472+
* freshly-assigned schema references intact while still reconciling other metadata
473+
* (displayName, description, templateParameters, etc.).
474+
*/
475+
function stripRepresentationSchemaRefs(patchProps: Record<string, unknown>): void {
476+
const SCHEMA_REF_FIELDS = ['schemaId', 'typeName'];
477+
478+
function stripFromRepresentations(representations: unknown): void {
479+
if (!Array.isArray(representations)) return;
480+
for (const rep of representations) {
481+
if (rep && typeof rep === 'object') {
482+
for (const field of SCHEMA_REF_FIELDS) {
483+
delete (rep as Record<string, unknown>)[field];
484+
}
485+
}
486+
}
487+
}
488+
489+
// Strip from request.representations
490+
const request = patchProps.request;
491+
if (request && typeof request === 'object') {
492+
const req = request as Record<string, unknown>;
493+
stripFromRepresentations(req.representations);
494+
}
495+
496+
// Strip from responses[].representations
497+
const responses = patchProps.responses;
498+
if (Array.isArray(responses)) {
499+
for (const response of responses) {
500+
if (response && typeof response === 'object') {
501+
stripFromRepresentations((response as Record<string, unknown>).representations);
502+
}
503+
}
504+
}
505+
}
506+
459507
/**
460508
* Extract revision number from API name (e.g., "my-api;rev=2" -> 2)
461509
*/

0 commit comments

Comments
 (0)