Skip to content

Commit 2e82de2

Browse files
committed
refactor: matcher helpers
1 parent 1f34534 commit 2e82de2

File tree

9 files changed

+116
-182
lines changed

9 files changed

+116
-182
lines changed

dev-helpers/index.html

+3
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
window["SwaggerUIStandalonePreset"] = window["swagger-ui-standalone-preset"]
4343
// Build a system
4444
const ui = SwaggerUIBundle({
45+
advancedFilter: {
46+
enabled: true
47+
},
4548
url: "https://petstore.swagger.io/v2/swagger.json",
4649
dom_id: '#swagger-ui',
4750
presets: [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/* eslint-disable no-useless-escape */
2+
3+
import { List, Map, Set } from "immutable"
4+
5+
const getNameMatcher = ({ fn, specSelectors }) => {
6+
const { schemaPathBaseRegex } = fn.schemaPathBase(specSelectors)
7+
return new RegExp(`(?<=${schemaPathBaseRegex}).*?(?=(?=\/)|$)`)
8+
}
9+
export const extractSchema = (schemaContainer, system) => {
10+
const nameMatcher = getNameMatcher(system)
11+
return schemaContainer
12+
.map(v => v.getIn(["schema", "$ref"], v.getIn(["schema", "items", "$ref"])))
13+
.filter(ref => ref != null)
14+
.valueSeq()
15+
.toSet()
16+
.map(requestBodyRef => {
17+
const nameMatch = nameMatcher.exec(requestBodyRef)
18+
return nameMatch ? nameMatch[0] : nameMatch
19+
})
20+
.filter(name => name != null)
21+
}
22+
export const extractSchemasFromOperations = (operations, system) => {
23+
const { fn, specSelectors } = system
24+
const isOAS3 = specSelectors.isOAS3()
25+
let schemaNamesForOperations = Set()
26+
operations.forEach((path) => {
27+
path.forEach(op => {
28+
schemaNamesForOperations = schemaNamesForOperations
29+
.union(fn.extractSchema(op.getIn(["requestBody", "content"], Map()), system))
30+
.union(fn.extractSchema(op
31+
.getIn(["parameters"], List())
32+
.filter(param => param.get("in") === "body"), system))
33+
.union(fn.extractSchema(op
34+
.getIn(["responses"], Map())
35+
.map(v => isOAS3 ? v.get("content") : v)
36+
.filter(content => content != null), system))
37+
})
38+
})
39+
return schemaNamesForOperations
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export const extractTagsFromOperations = (operations) => {
2+
return operations
3+
.flatMap(method => method.map(op => op.get("tags")))
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export const schemaPathBase = (specSelectors) => {
2+
const isOAS3 = specSelectors.isOAS3()
3+
const schemaPathBaseRegex = isOAS3
4+
? "\\/components\\/schemas\\/"
5+
: "\\/definitions\\/"
6+
const schemaPathBase = isOAS3
7+
? ["components", "schemas"]
8+
: ["definitions"]
9+
return { schemaPathBaseRegex, schemaPathBase }
10+
}
+11-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
import { applyMatchersToSpec } from "./apply-matchers"
22
/* eslint-disable camelcase */
3-
import { advancedFilterMatcher_operations } from "./matchers/operation-matcher"
3+
import { advancedFilterMatcher_operations, getMatchedOperationsSpec } from "./matchers/operation-matcher"
44
import { advancedFilterMatcher_tags } from "./matchers/tag-matcher"
55
import { advancedFilterMatcher_definitions } from "./matchers/definition-matcher"
6+
import { getRegularFilterExpr } from "./regular-filter-expr"
7+
import { schemaPathBase } from "./helper/schema-path-base"
8+
import { extractSchema, extractSchemasFromOperations } from "./helper/extract-schemas"
9+
import { extractTagsFromOperations } from "./helper/extract-tags"
610

711
export default {
812
advancedFilterMatcher_operations,
913
advancedFilterMatcher_tags,
1014
advancedFilterMatcher_definitions,
1115
applyMatchersToSpec,
16+
getRegularFilterExpr,
17+
schemaPathBase,
18+
extractSchema,
19+
extractSchemasFromOperations,
20+
extractTagsFromOperations,
21+
getMatchedOperationsSpec
1222
}

src/core/plugins/advanced-filter/fn/matchers/definition-matcher.js

+4-16
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,15 @@ const escapeRegExp = (string) => {
55
}
66
/* eslint-disable camelcase */
77

8-
export const advancedFilterMatcher_definitions = (spec, options, phrase, { specSelectors }) => {
8+
export const advancedFilterMatcher_definitions = (spec, options, phrase, { fn, specSelectors }) => {
99
const isOAS3 = specSelectors.isOAS3()
10-
const schemaPathBase = isOAS3
11-
? ["components", "schemas"]
12-
: ["definitions"]
10+
const { schemaPathBase } = fn.schemaPathBase(specSelectors)
11+
1312
const partialSpecResult = fromJS(isOAS3
1413
? { components: { schemas: {} } }
1514
: { definitions: {} })
1615

17-
phrase = escapeRegExp(phrase)
18-
let expr
19-
try {
20-
expr = new RegExp(
21-
options.get("matchWholeWord")
22-
? `\\b${phrase}\\b`
23-
: phrase,
24-
!options.get("matchCase") ? "i" : "",
25-
)
26-
} catch {
27-
// TODO: add errors to state
28-
}
16+
const expr = fn.getRegularFilterExpr(options, escapeRegExp(phrase))
2917
if (expr) {
3018
const filteredSchemas = spec
3119
.getIn(schemaPathBase)
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,35 @@
1-
import { fromJS, List, Map, Set } from "immutable"
1+
import { fromJS, Map } from "immutable"
22
// taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
33
const escapeRegExp = (string) => {
44
return string.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&") // $& means the whole matched string
55
}
66
/* eslint-disable camelcase */
7-
/* eslint-disable no-useless-escape */
8-
9-
export const advancedFilterMatcher_operations = (spec, options, phrase, { specSelectors }) => {
7+
export const getMatchedOperationsSpec = (operationFilterPredicate, spec, options, phrase, { fn, specSelectors, getSystem }) => {
8+
const system = getSystem()
109
const isOAS3 = specSelectors.isOAS3()
11-
const schemaPathBaseRegex = isOAS3
12-
? "\\/components\\/schemas\\/"
13-
: "\\/definitions\\/"
14-
const schemaPathBase = isOAS3
15-
? ["components", "schemas"]
16-
: ["definitions"]
10+
const { schemaPathBase } = fn.schemaPathBase(specSelectors)
1711
const partialSpecResult = fromJS(isOAS3
1812
? { paths: {}, tags: [], components: { schemas: {} } }
1913
: { paths: {}, tags: [], definitions: {} })
20-
const nameMatcher = new RegExp(`(?<=${schemaPathBaseRegex}).*?(?=(?=\/)|$)`)
2114

22-
phrase = escapeRegExp(phrase)
23-
let expr
24-
try {
25-
expr = new RegExp(
26-
options.get("matchWholeWord")
27-
? `\\b${phrase}\\b`
28-
: phrase,
29-
!options.get("matchCase") ? "i" : "",
30-
)
31-
} catch {
32-
// TODO: add errors to state
33-
}
15+
const filteredPaths = operationFilterPredicate(spec.get("paths") || Map())
16+
const filteredTags = fn.extractTagsFromOperations(filteredPaths)
17+
let schemaNamesForOperations = fn.extractSchemasFromOperations(filteredPaths, system)
18+
const filteredOperationSchemas = spec
19+
.getIn(schemaPathBase)
20+
.filter((schema, name) => schemaNamesForOperations.includes(name))
21+
return partialSpecResult
22+
.set("paths", filteredPaths)
23+
.set("tags", filteredTags)
24+
.setIn(schemaPathBase, filteredOperationSchemas)
25+
}
26+
export const advancedFilterMatcher_operations = (spec, options, phrase, { getSystem }) => {
27+
const system = getSystem()
28+
const expr = system.fn.getRegularFilterExpr(options, escapeRegExp(phrase))
3429
if (expr) {
35-
const filteredPaths = (spec.get("paths") || Map())
36-
.filter((path, pathName) => expr.test(pathName))
37-
const filteredTags = filteredPaths
38-
.flatMap(method => method.map(op => op.get("tags")))
39-
let schemaNamesForOperations = Set()
40-
filteredPaths.forEach((path) => {
41-
path.forEach(op => {
42-
schemaNamesForOperations = schemaNamesForOperations
43-
.union(op
44-
.getIn(["requestBody", "content"], Map())
45-
.map(v => v.getIn(["schema", "$ref"], v.getIn(["schema", "items", "$ref"])))
46-
.filter(ref => ref != null)
47-
.valueSeq()
48-
.toSet()
49-
.map(requestBodyRef => {
50-
const nameMatch = nameMatcher.exec(requestBodyRef)
51-
return nameMatch ? nameMatch[0] : nameMatch
52-
})
53-
.filter(name => name != null),
54-
)
55-
.union(op
56-
.getIn(["parameters"], List())
57-
.filter(param => param.get("in") === "body")
58-
.map(v => v.getIn(["schema", "$ref"], v.getIn(["schema", "items", "$ref"])))
59-
.filter(ref => ref != null)
60-
.valueSeq()
61-
.toSet()
62-
.map(requestBodyRef => {
63-
const nameMatch = nameMatcher.exec(requestBodyRef)
64-
return nameMatch ? nameMatch[0] : nameMatch
65-
})
66-
.filter(name => name != null),
67-
)
68-
.union(op
69-
.getIn(["responses"], Map())
70-
.map(v => isOAS3 ? v.get("content") : v)
71-
.filter(content => content != null)
72-
.map(content => content.getIn(["schema", "$ref"], content.getIn(["schema", "items", "$ref"])))
73-
.filter(ref => ref != null)
74-
.valueSeq()
75-
.toSet()
76-
.map(requestBodyRef => {
77-
const nameMatch = nameMatcher.exec(requestBodyRef)
78-
return nameMatch ? nameMatch[0] : nameMatch
79-
})
80-
.filter(name => name != null),
81-
)
82-
})
83-
})
84-
const filteredOperationSchemas = spec
85-
.getIn(schemaPathBase)
86-
.filter((schema, name) => schemaNamesForOperations.includes(name))
87-
return partialSpecResult
88-
.set("paths", filteredPaths)
89-
.set("tags", filteredTags)
90-
.setIn(schemaPathBase, filteredOperationSchemas)
30+
return system.fn.getMatchedOperationsSpec(
31+
(ops) => ops.filter((path, pathName) => expr.test(pathName)),
32+
spec, options, phrase, system,
33+
)
9134
}
92-
return partialSpecResult
9335
}
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,18 @@
1-
import { fromJS, List, Map, Set } from "immutable"
21
// taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
32
const escapeRegExp = (string) => {
43
return string.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&") // $& means the whole matched string
54
}
65
/* eslint-disable camelcase */
7-
/* eslint-disable no-useless-escape */
86

9-
export const advancedFilterMatcher_tags = (spec, options, phrase, { specSelectors }) => {
10-
const isOAS3 = specSelectors.isOAS3()
11-
const schemaPathBaseRegex = isOAS3
12-
? "\\/components\\/schemas\\/"
13-
: "\\/definitions\\/"
14-
const schemaPathBase = isOAS3
15-
? ["components", "schemas"]
16-
: ["definitions"]
17-
const partialSpecResult = fromJS(isOAS3
18-
? { paths: {}, tags: [], components: { schemas: {} } }
19-
: { paths: {}, tags: [], definitions: {} })
20-
const nameMatcher = new RegExp(`(?<=${schemaPathBaseRegex}).*?(?=(?=\/)|$)`)
21-
22-
phrase = escapeRegExp(phrase)
23-
let expr
24-
try {
25-
expr = new RegExp(
26-
options.get("matchWholeWord")
27-
? `\\b${phrase}\\b`
28-
: phrase,
29-
!options.get("matchCase") ? "i" : "",
30-
)
31-
} catch {
32-
// TODO: add errors to state
33-
}
7+
export const advancedFilterMatcher_tags = (spec, options, phrase, { getSystem }) => {
8+
const system = getSystem()
9+
const expr = system.fn.getRegularFilterExpr(options, escapeRegExp(phrase))
3410
if (expr) {
35-
const filteredPaths = (spec.get("paths") || Map())
36-
.map(path => path
11+
return system.fn.getMatchedOperationsSpec(
12+
(ops) => ops.map(path => path
3713
.filter(op => op.get("tags").filter(tag => expr.test(tag)).count() > 0),
38-
)
39-
.filter(method => method.count() > 0)
40-
const filteredTags = filteredPaths
41-
.flatMap(method => method.map(op => op.get("tags")))
42-
let schemaNamesForOperations = Set()
43-
filteredPaths.forEach((path) => {
44-
path.forEach(op => {
45-
schemaNamesForOperations = schemaNamesForOperations
46-
.union(op
47-
.getIn(["requestBody", "content"], Map())
48-
.map(v => v.getIn(["schema", "$ref"], v.getIn(["schema", "items", "$ref"])))
49-
.valueSeq()
50-
.toSet()
51-
.map(requestBodyRef => {
52-
const nameMatch = nameMatcher.exec(requestBodyRef)
53-
return nameMatch ? nameMatch[0] : nameMatch
54-
})
55-
.filter(name => name != null),
56-
)
57-
.union(op
58-
.getIn(["parameters"], List())
59-
.filter(param => param.get("in") === "body")
60-
.map(v => v.getIn(["schema", "$ref"], v.getIn(["schema", "items", "$ref"])))
61-
.filter(ref => ref != null)
62-
.valueSeq()
63-
.toSet()
64-
.map(requestBodyRef => {
65-
const nameMatch = nameMatcher.exec(requestBodyRef)
66-
return nameMatch ? nameMatch[0] : nameMatch
67-
})
68-
.filter(name => name != null),
69-
)
70-
.union(op
71-
.getIn(["responses"], Map())
72-
.map(v => isOAS3 ? v.get("content") : v)
73-
.filter(content => content != null)
74-
.map(content => content.getIn(["schema", "$ref"], content.getIn(["schema", "items", "$ref"])))
75-
.filter(ref => ref != null)
76-
.valueSeq()
77-
.toSet()
78-
.map(requestBodyRef => {
79-
const nameMatch = nameMatcher.exec(requestBodyRef)
80-
return nameMatch ? nameMatch[0] : nameMatch
81-
})
82-
.filter(name => name != null),
83-
)
84-
})
85-
})
86-
const filteredOperationSchemas = spec
87-
.getIn(schemaPathBase)
88-
.filter((schema, name) => schemaNamesForOperations.includes(name))
89-
return partialSpecResult
90-
.set("paths", filteredPaths)
91-
.set("tags", filteredTags)
92-
.setIn(schemaPathBase, filteredOperationSchemas)
14+
),
15+
spec, options, phrase, system,
16+
)
9317
}
94-
return partialSpecResult
9518
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export const getRegularFilterExpr = (options, phrase) => {
2+
let expr
3+
try {
4+
expr = new RegExp(
5+
options.get("matchWholeWord")
6+
? `\\b${phrase}\\b`
7+
: phrase,
8+
!options.get("matchCase") ? "i" : "",
9+
)
10+
} catch {
11+
// TODO: add errors to state
12+
}
13+
return expr
14+
}

0 commit comments

Comments
 (0)