forked from opensearch-project/opensearch-protobufs
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathVendorExtensionProcessor.ts
More file actions
131 lines (110 loc) · 4.98 KB
/
Copy pathVendorExtensionProcessor.ts
File metadata and controls
131 lines (110 loc) · 4.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import { OpenAPIV3 } from 'openapi-types';
import { traverse } from './utils/OpenApiTraverser';
import Logger from './utils/logger';
/**
* VendorExtensionProcessor class:
* Handles processing of vendor extensions in OpenAPI specifications.
*/
export class VendorExtensionProcessor {
private static readonly GRPC_REMOVED_EXTENSION = 'x-protobuf-excluded';
private root: OpenAPIV3.Document;
private logger: Logger;
constructor(root: OpenAPIV3.Document, logger: Logger = new Logger()) {
this.root = root;
this.logger = logger;
}
/**
* Process the spec by pruning anything marked with x-protobuf-excluded
* Direct path-level handling + traverse for schemas only
*/
public process(): OpenAPIV3.Document {
this.logger.info(`Processing vendor extensions (${VendorExtensionProcessor.GRPC_REMOVED_EXTENSION})...`);
this.removeGrpcRemovedFromPaths();
traverse(this.root, {
onSchema: (schema: any, name: string) => {
if ('$ref' in schema) return;
this.removeGrpcRemovedProperties(schema);
},
onResponseSchema: (schema: any, name: string) => {
this.removeGrpcRemovedProperties(schema);
},
onRequestSchema: (schema: any, name: string) => {
this.removeGrpcRemovedProperties(schema);
}
});
return this.root;
}
private hasGrpcRemoved(item: any): boolean {
if (!item || typeof item !== 'object') return false;
if (VendorExtensionProcessor.GRPC_REMOVED_EXTENSION in item && !!item[VendorExtensionProcessor.GRPC_REMOVED_EXTENSION]) {
return true;
}
if ('$ref' in item && typeof item.$ref === 'string') {
const resolved = this.resolveRef(item.$ref);
if (resolved && VendorExtensionProcessor.GRPC_REMOVED_EXTENSION in resolved && !!resolved[VendorExtensionProcessor.GRPC_REMOVED_EXTENSION]) {
return true;
}
}
return false;
}
/**
* Resolve a $ref string to the actual object
*/
private resolveRef(ref: string): any {
if (!ref.startsWith('#/')) return null;
const parts = ref.substring(2).split('/');
let current: any = this.root;
for (const part of parts) {
if (!current || typeof current !== 'object') return null;
current = current[part];
}
return current;
}
/**
* Remove x-protobuf-excluded items from path-level elements directly
*/
private removeGrpcRemovedFromPaths(): void {
if (!this.root.paths) return;
for (const pathKey in this.root.paths) {
const pathItem = this.root.paths[pathKey];
if (!pathItem || typeof pathItem !== 'object' || '$ref' in pathItem) continue;
// Handle operations
for (const method in pathItem) {
if (method === 'parameters' || method === '$ref' || method === 'summary' ||
method === 'description' || method === 'servers') continue;
const operation = (pathItem as any)[method];
if (!operation || typeof operation !== 'object') continue;
// Remove parameters with x-protobuf-excluded
if (Array.isArray(operation.parameters)) {
const originalLength = operation.parameters.length;
operation.parameters = operation.parameters.filter((p: any) => !this.hasGrpcRemoved(p));
const removedCount = originalLength - operation.parameters.length;
if (removedCount > 0) {
this.logger.info(`Removed ${removedCount} parameter(s) from ${method.toUpperCase()} ${pathKey} (${VendorExtensionProcessor.GRPC_REMOVED_EXTENSION})`);
}
}
// Remove responses with x-protobuf-excluded
if (operation.responses) {
for (const status in operation.responses) {
if (this.hasGrpcRemoved(operation.responses[status])) {
delete operation.responses[status];
this.logger.info(`Removed response ${status} from ${method.toUpperCase()} ${pathKey} (${VendorExtensionProcessor.GRPC_REMOVED_EXTENSION})`);
}
}
}
}
}
}
private removeGrpcRemovedProperties(schema: OpenAPIV3.SchemaObject): void {
if (!schema?.properties) return;
for (const prop in schema.properties) {
const propSchema = schema.properties[prop];
if (propSchema && typeof propSchema === 'object' && !('$ref' in propSchema)) {
if (this.hasGrpcRemoved(propSchema)) {
delete schema.properties[prop];
this.logger.info(`Removed schema property ${prop} (${VendorExtensionProcessor.GRPC_REMOVED_EXTENSION})`);
}
}
}
}
}