···88/**
99 * Recursively walks the entire spec object and replaces all $ref strings
1010 * according to the provided rename mapping.
1111- *
1212- * @param node - Current node being visited
1313- * @param renameMap - Map from old pointer to new pointer
1411 */
1512const rewriteRefs = (node: unknown, renameMap: Record<string, string>) => {
1613 if (node instanceof Array) {
···1815 } else if (node && typeof node === 'object') {
1916 for (const [key, value] of Object.entries(node)) {
2017 if (key === '$ref' && typeof value === 'string' && value in renameMap) {
2121- // Replace the $ref with the new name
2218 (node as Record<string, unknown>)[key] = renameMap[value];
2319 } else {
2420 rewriteRefs(value, renameMap);
···2824};
29253026/**
3131- * Applies the schema name transform to rename schema component keys and
3232- * update all $ref pointers throughout the spec.
3333- *
3434- * This transform:
3535- * 1. Iterates all schema keys in components.schemas (or definitions for Swagger 2.0)
3636- * 2. Applies the name transformer to compute new names
3737- * 3. Handles name collisions (skips rename if new name already exists)
3838- * 4. Renames schema keys in the schemas object
3939- * 5. Updates all $ref pointers throughout the spec to use the new names
4040- *
4141- * @param config - The schema name transformer
4242- * @param spec - The OpenAPI spec object to transform
2727+ * Renames schema component keys and updates all $ref pointers throughout
2828+ * the spec. Handles collisions by skipping renames when the target name
2929+ * already exists or conflicts with another rename.
4330 */
4431export const schemaNameTransform = ({
4532 config,
···6249 return;
6350 }
64516565- // Build rename map: oldPointer -> newPointer
6652 const renameMap: Record<string, string> = {};
6753 const newNames = new Set<string>();
5454+ const namingConfig = { name: config };
68556969- // Create a simple config object for applyNaming
7070- const namingConfig = typeof config === 'function' ? { name: config } : { name: config };
7171-7272- // First pass: compute all new names and check for collisions
7356 for (const oldName of Object.keys(schemasObj)) {
7457 const newName = applyNaming(oldName, namingConfig);
75587676- // Skip if name doesn't change
7759 if (newName === oldName) {
7860 continue;
7961 }
80628181- // Skip if new name collides with an existing schema
8263 if (newName in schemasObj) {
8364 continue;
8465 }
85668686- // Skip if new name collides with another renamed schema
8767 if (newNames.has(newName)) {
8868 continue;
8969 }
90709191- // Record the rename
9271 renameMap[`${schemasPointerNamespace}${oldName}`] = `${schemasPointerNamespace}${newName}`;
9372 newNames.add(newName);
9473 }
95749696- // Second pass: rename schema keys
9797- // We need to be careful about the order to avoid overwriting
9898- const renamedSchemas: Record<string, unknown> = {};
9999- const processedOldNames = new Set<string>();
100100-10175 for (const [oldPointer, newPointer] of Object.entries(renameMap)) {
10276 const oldName = oldPointer.slice(schemasPointerNamespace.length);
10377 const newName = newPointer.slice(schemasPointerNamespace.length);
104104-105105- // Store the schema under the new name
106106- renamedSchemas[newName] = schemasObj[oldName];
107107- processedOldNames.add(oldName);
108108- }
7878+ const schema = schemasObj[oldName];
10979110110- // Add all schemas that weren't renamed
111111- for (const [name, schema] of Object.entries(schemasObj)) {
112112- if (!processedOldNames.has(name)) {
113113- renamedSchemas[name] = schema;
114114- }
8080+ delete schemasObj[oldName];
8181+ schemasObj[newName] = schema;
11582 }
11683117117- // Replace the entire schemas object with the renamed version
118118- Object.keys(schemasObj).forEach((key) => delete schemasObj[key]);
119119- Object.assign(schemasObj, renamedSchemas);
120120-121121- // Third pass: rewrite all $ref pointers throughout the spec
12284 if (Object.keys(renameMap).length > 0) {
12385 rewriteRefs(spec, renameMap);
12486 }