MCPcopy
hub / github.com/dosco/graphjin / classifyOne

Function classifyOne

core/openapi/classifier.go:74–199  ·  view source on GitHub ↗

classifyOne is the per-operation classifier. It first decides whether the operation can be exposed at all (mutating verbs, async patterns, non-JSON responses are immediately skipped) and then picks between RowJoin / SingleByID / List based on path shape and user configuration.

(
	specKey, path, method string,
	op *openapi3.Operation,
	pathItem *openapi3.PathItem,
	cfg SpecConfig,
)

Source from the content-addressed store, hash-verified

72// non-JSON responses are immediately skipped) and then picks between
73// RowJoin / SingleByID / List based on path shape and user configuration.
74func classifyOne(
75 specKey, path, method string,
76 op *openapi3.Operation,
77 pathItem *openapi3.PathItem,
78 cfg SpecConfig,
79) OpDescriptor {
80 d := OpDescriptor{
81 SpecKey: specKey,
82 OperationID: operationID(op, method, path),
83 Method: method,
84 PathTemplate: path,
85 Mode: OpModeSkipped,
86 }
87
88 // Read-only first cut: anything that mutates server state is out of
89 // scope until the write-side feature lands.
90 if method != "GET" {
91 d.SkipReason = "mutating verb (write-side not yet supported)"
92 return d
93 }
94
95 // Operations explicitly disabled via config never appear regardless
96 // of how they would otherwise classify.
97 if ov, ok := cfg.Operations[d.OperationID]; ok && ov.Disabled {
98 d.SkipReason = "disabled by config"
99 return d
100 }
101
102 // Find the success response. We only examine 200 — 201/202/204 are
103 // either non-applicable to GET or signal async/empty-body patterns
104 // that don't fit the join model.
105 resp := findSuccessResponse(op)
106 if resp == nil {
107 d.SkipReason = "no 200 success response declared"
108 return d
109 }
110
111 // Async / file-download responses can't participate in a query — they
112 // don't return JSON in their response body.
113 if hasLocationHeader(resp) {
114 d.SkipReason = "async pattern (Location header on success response)"
115 return d
116 }
117
118 jsonContent, mediaType := pickJSONContent(resp)
119 if jsonContent == nil {
120 d.SkipReason = fmt.Sprintf("non-JSON response (%s)", mediaType)
121 return d
122 }
123
124 // Parameters live in two places — on the path item (shared across
125 // methods) and on the operation itself. Merge and bucket by location.
126 pathParams, queryParams, headerParams := collectParams(pathItem, op)
127 d.PathParams = pathParams
128 d.QueryParams = queryParams
129 d.HeaderParams = headerParams
130
131 // Detect a sensible result_path by walking the response schema. List

Callers 1

classifyAllFunction · 0.85

Calls 9

operationIDFunction · 0.85
findSuccessResponseFunction · 0.85
hasLocationHeaderFunction · 0.85
pickJSONContentFunction · 0.85
collectParamsFunction · 0.85
deriveResultPathFunction · 0.85
splitPathFunction · 0.85
isSingleResourcePathFunction · 0.85
exposeAsFunction · 0.85

Tested by

no test coverage detected