@pikku/inspector 0.9.5 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/add/add-channel.d.ts +17 -0
  3. package/dist/{add-channel.js → add/add-channel.js} +60 -34
  4. package/dist/add/add-cli.d.ts +9 -0
  5. package/dist/add/add-cli.js +566 -0
  6. package/dist/{add-file-extends-core-type.d.ts → add/add-file-extends-core-type.d.ts} +2 -2
  7. package/dist/{add-file-extends-core-type.js → add/add-file-extends-core-type.js} +17 -4
  8. package/dist/{add-file-with-config.d.ts → add/add-file-with-config.d.ts} +1 -1
  9. package/dist/{add-file-with-config.js → add/add-file-with-config.js} +1 -1
  10. package/dist/{add-file-with-factory.d.ts → add/add-file-with-factory.d.ts} +2 -2
  11. package/dist/{add-file-with-factory.js → add/add-file-with-factory.js} +38 -5
  12. package/dist/add/add-functions.d.ts +6 -0
  13. package/dist/{add-functions.js → add/add-functions.js} +77 -10
  14. package/dist/{add-http-route.d.ts → add/add-http-route.d.ts} +2 -3
  15. package/dist/{add-http-route.js → add/add-http-route.js} +26 -13
  16. package/dist/add/add-mcp-prompt.d.ts +2 -0
  17. package/dist/add/add-mcp-prompt.js +74 -0
  18. package/dist/add/add-mcp-resource.d.ts +2 -0
  19. package/dist/add/add-mcp-resource.js +84 -0
  20. package/dist/add/add-mcp-tool.d.ts +2 -0
  21. package/dist/add/add-mcp-tool.js +80 -0
  22. package/dist/add/add-middleware.d.ts +5 -0
  23. package/dist/add/add-middleware.js +290 -0
  24. package/dist/add/add-permission.d.ts +5 -0
  25. package/dist/add/add-permission.js +292 -0
  26. package/dist/add/add-queue-worker.d.ts +2 -0
  27. package/dist/add/add-queue-worker.js +52 -0
  28. package/dist/{add-rpc-invocations.d.ts → add/add-rpc-invocations.d.ts} +1 -1
  29. package/dist/add/add-schedule.d.ts +2 -0
  30. package/dist/{add-schedule.js → add/add-schedule.js} +16 -11
  31. package/dist/error-codes.d.ts +35 -0
  32. package/dist/error-codes.js +40 -0
  33. package/dist/index.d.ts +6 -0
  34. package/dist/index.js +4 -0
  35. package/dist/inspector.d.ts +2 -3
  36. package/dist/inspector.js +38 -8
  37. package/dist/types.d.ts +108 -1
  38. package/dist/utils/ensure-function-metadata.d.ts +6 -0
  39. package/dist/utils/ensure-function-metadata.js +18 -0
  40. package/dist/utils/extract-function-name.d.ts +31 -0
  41. package/dist/{utils.js → utils/extract-function-name.js} +35 -149
  42. package/dist/utils/extract-services.d.ts +6 -0
  43. package/dist/utils/extract-services.js +29 -0
  44. package/dist/utils/filter-inspector-state.d.ts +6 -0
  45. package/dist/utils/filter-inspector-state.js +382 -0
  46. package/dist/utils/filter-utils.d.ts +19 -0
  47. package/dist/utils/filter-utils.js +109 -0
  48. package/dist/utils/find-root-dir.d.ts +23 -0
  49. package/dist/utils/find-root-dir.js +55 -0
  50. package/dist/utils/get-files-and-methods.d.ts +22 -0
  51. package/dist/utils/get-files-and-methods.js +61 -0
  52. package/dist/utils/get-property-value.d.ts +12 -0
  53. package/dist/{get-property-value.js → utils/get-property-value.js} +20 -0
  54. package/dist/utils/middleware.d.ts +39 -0
  55. package/dist/utils/middleware.js +157 -0
  56. package/dist/utils/permissions.d.ts +43 -0
  57. package/dist/utils/permissions.js +178 -0
  58. package/dist/utils/post-process.d.ts +16 -0
  59. package/dist/utils/post-process.js +132 -0
  60. package/dist/utils/serialize-inspector-state.d.ts +179 -0
  61. package/dist/utils/serialize-inspector-state.js +170 -0
  62. package/dist/utils/type-utils.d.ts +3 -0
  63. package/dist/utils/type-utils.js +50 -0
  64. package/dist/visit.d.ts +3 -3
  65. package/dist/visit.js +35 -31
  66. package/package.json +5 -6
  67. package/src/{add-channel.ts → add/add-channel.ts} +108 -56
  68. package/src/add/add-cli.ts +822 -0
  69. package/src/{add-file-extends-core-type.ts → add/add-file-extends-core-type.ts} +23 -5
  70. package/src/{add-file-with-config.ts → add/add-file-with-config.ts} +2 -2
  71. package/src/{add-file-with-factory.ts → add/add-file-with-factory.ts} +49 -6
  72. package/src/{add-functions.ts → add/add-functions.ts} +89 -19
  73. package/src/{add-http-route.ts → add/add-http-route.ts} +66 -32
  74. package/src/add/add-mcp-prompt.ts +128 -0
  75. package/src/add/add-mcp-prompt.ts.tmp +0 -0
  76. package/src/add/add-mcp-resource.ts +145 -0
  77. package/src/add/add-mcp-resource.ts.tmp +0 -0
  78. package/src/add/add-mcp-tool.ts +137 -0
  79. package/src/add/add-middleware.ts +385 -0
  80. package/src/add/add-permission.ts +391 -0
  81. package/src/add/add-queue-worker.ts +92 -0
  82. package/src/{add-rpc-invocations.ts → add/add-rpc-invocations.ts} +1 -1
  83. package/src/{add-schedule.ts → add/add-schedule.ts} +30 -28
  84. package/src/error-codes.ts +43 -0
  85. package/src/index.ts +12 -0
  86. package/src/inspector.ts +41 -17
  87. package/src/types.ts +128 -1
  88. package/src/utils/ensure-function-metadata.ts +24 -0
  89. package/src/{utils.ts → utils/extract-function-name.ts} +44 -206
  90. package/src/utils/extract-services.ts +35 -0
  91. package/src/utils/filter-inspector-state.test.ts +1433 -0
  92. package/src/utils/filter-inspector-state.ts +526 -0
  93. package/src/{utils.test.ts → utils/filter-utils.test.ts} +351 -2
  94. package/src/utils/filter-utils.ts +152 -0
  95. package/src/utils/find-root-dir.ts +68 -0
  96. package/src/utils/get-files-and-methods.ts +151 -0
  97. package/src/{get-property-value.ts → utils/get-property-value.ts} +27 -0
  98. package/src/utils/middleware.ts +241 -0
  99. package/src/utils/permissions.test.ts +327 -0
  100. package/src/utils/permissions.ts +262 -0
  101. package/src/utils/post-process.ts +178 -0
  102. package/src/utils/serialize-inspector-state.ts +375 -0
  103. package/src/utils/test-data/inspector-state.json +1680 -0
  104. package/src/utils/type-utils.ts +74 -0
  105. package/src/visit.ts +50 -34
  106. package/tsconfig.tsbuildinfo +1 -1
  107. package/dist/add-channel.d.ts +0 -13
  108. package/dist/add-functions.d.ts +0 -7
  109. package/dist/add-mcp-prompt.d.ts +0 -3
  110. package/dist/add-mcp-prompt.js +0 -61
  111. package/dist/add-mcp-resource.d.ts +0 -3
  112. package/dist/add-mcp-resource.js +0 -68
  113. package/dist/add-mcp-tool.d.ts +0 -3
  114. package/dist/add-mcp-tool.js +0 -64
  115. package/dist/add-middleware.d.ts +0 -7
  116. package/dist/add-middleware.js +0 -35
  117. package/dist/add-permission.d.ts +0 -7
  118. package/dist/add-permission.js +0 -35
  119. package/dist/add-queue-worker.d.ts +0 -3
  120. package/dist/add-queue-worker.js +0 -48
  121. package/dist/add-schedule.d.ts +0 -3
  122. package/dist/get-property-value.d.ts +0 -3
  123. package/dist/utils.d.ts +0 -39
  124. package/src/add-mcp-prompt.ts +0 -104
  125. package/src/add-mcp-resource.ts +0 -116
  126. package/src/add-mcp-tool.ts +0 -107
  127. package/src/add-middleware.ts +0 -51
  128. package/src/add-permission.ts +0 -53
  129. package/src/add-queue-worker.ts +0 -92
  130. /package/dist/{add-rpc-invocations.js → add/add-rpc-invocations.js} +0 -0
  131. /package/dist/{does-type-extend-core-type.d.ts → utils/does-type-extend-core-type.d.ts} +0 -0
  132. /package/dist/{does-type-extend-core-type.js → utils/does-type-extend-core-type.js} +0 -0
  133. /package/src/{does-type-extend-core-type.ts → utils/does-type-extend-core-type.ts} +0 -0
@@ -0,0 +1,151 @@
1
+ import {
2
+ PathToNameAndType,
3
+ InspectorState,
4
+ InspectorOptions,
5
+ } from '../types.js'
6
+
7
+ interface Meta {
8
+ file: string
9
+ variable: string
10
+ type: string
11
+ typePath: string
12
+ }
13
+
14
+ export type FilesAndMethods = {
15
+ userSessionType: Meta
16
+ sessionServicesType: Meta
17
+ singletonServicesType: Meta
18
+ pikkuConfigType: Meta
19
+ pikkuConfigFactory: Meta
20
+ singletonServicesFactory: Meta
21
+ sessionServicesFactory: Meta
22
+ }
23
+
24
+ export type FilesAndMethodsErrors = Map<string, PathToNameAndType>
25
+
26
+ const getMetaTypes = (
27
+ type: string,
28
+ map: PathToNameAndType,
29
+ desiredType?: string,
30
+ errors?: FilesAndMethodsErrors
31
+ ): Meta | undefined => {
32
+ if (desiredType) {
33
+ for (const [file, meta] of map.entries()) {
34
+ for (const { type: entryType, variable, typePath } of meta) {
35
+ if (entryType === desiredType) {
36
+ if (entryType === null || typePath === null) {
37
+ throw new Error(
38
+ `Unknown state due to metaType calculation: entryType or typePath is null for ${desiredType} in ${file}`
39
+ )
40
+ }
41
+ return { file, variable, type: entryType, typePath }
42
+ }
43
+ }
44
+ }
45
+ if (errors) {
46
+ errors.set(`No ${desiredType} found that extends ${type}`, map)
47
+ }
48
+ return
49
+ }
50
+
51
+ const totalValues = Array.from(map.values()).flat()
52
+
53
+ if (totalValues.length === 0) {
54
+ const helpMessage =
55
+ type === 'CoreConfig'
56
+ ? `No ${type} found. Make sure you have exported a createConfig function in your codebase:\n\n` +
57
+ `export const createConfig: CreateConfig<Config> = async () => {\n` +
58
+ ` return {}\n` +
59
+ `}\n\n` +
60
+ `Possible issues:\n` +
61
+ `- srcDirectories in pikku.config.json doesn't include the file with the createConfig method`
62
+ : `No ${type} found`
63
+ if (errors) {
64
+ errors.set(helpMessage, map)
65
+ }
66
+ } else if (totalValues.length > 1) {
67
+ if (errors) {
68
+ errors.set(`More than one ${type} found`, map)
69
+ }
70
+ } else {
71
+ const entry = Array.from(map.entries())[0]
72
+ if (entry) {
73
+ const [file, [{ type: entryType, variable, typePath }]] = entry
74
+ if (entryType === null || typePath === null) {
75
+ throw new Error(
76
+ `Unknown state due to metaType calculation: entryType or typePath is null for ${type} in ${file}`
77
+ )
78
+ }
79
+ return { file, type: entryType, variable, typePath }
80
+ }
81
+ }
82
+
83
+ return
84
+ }
85
+
86
+ export const getFilesAndMethods = (
87
+ {
88
+ singletonServicesTypeImportMap,
89
+ sessionServicesTypeImportMap,
90
+ userSessionTypeImportMap,
91
+ configTypeImportMap,
92
+ sessionServicesFactories,
93
+ singletonServicesFactories,
94
+ configFactories,
95
+ }: InspectorState,
96
+ {
97
+ configFileType,
98
+ userSessionType,
99
+ singletonServicesFactoryType,
100
+ sessionServicesFactoryType,
101
+ }: InspectorOptions['types'] = {}
102
+ ): { result: Partial<FilesAndMethods>; errors: FilesAndMethodsErrors } => {
103
+ const errors: FilesAndMethodsErrors = new Map()
104
+
105
+ const result: Partial<FilesAndMethods> = {
106
+ userSessionType: getMetaTypes(
107
+ 'CoreUserSession',
108
+ userSessionTypeImportMap,
109
+ userSessionType,
110
+ errors
111
+ ),
112
+ singletonServicesType: getMetaTypes(
113
+ 'CoreSingletonServices',
114
+ singletonServicesTypeImportMap,
115
+ undefined,
116
+ errors
117
+ ),
118
+ sessionServicesType: getMetaTypes(
119
+ 'CoreServices',
120
+ sessionServicesTypeImportMap,
121
+ undefined,
122
+ errors
123
+ ),
124
+ pikkuConfigType: getMetaTypes(
125
+ 'CoreConfig',
126
+ configTypeImportMap,
127
+ undefined,
128
+ errors
129
+ ),
130
+ pikkuConfigFactory: getMetaTypes(
131
+ 'CoreConfig',
132
+ configFactories,
133
+ configFileType,
134
+ errors
135
+ ),
136
+ singletonServicesFactory: getMetaTypes(
137
+ 'CreateSingletonServices',
138
+ singletonServicesFactories,
139
+ singletonServicesFactoryType,
140
+ errors
141
+ ),
142
+ sessionServicesFactory: getMetaTypes(
143
+ 'CreateSessionServices',
144
+ sessionServicesFactories,
145
+ sessionServicesFactoryType,
146
+ errors
147
+ ),
148
+ }
149
+
150
+ return { result, errors }
151
+ }
@@ -1,5 +1,6 @@
1
1
  import { PikkuDocs } from '@pikku/core'
2
2
  import * as ts from 'typescript'
3
+ import { ErrorCode } from '../error-codes.js'
3
4
 
4
5
  export const getPropertyValue = (
5
6
  obj: ts.ObjectLiteralExpression,
@@ -91,3 +92,29 @@ export const getPropertyValue = (
91
92
 
92
93
  return null
93
94
  }
95
+
96
+ /**
97
+ * Gets the 'tags' property from an object and validates it's an array.
98
+ * Logs a critical error if tags is not an array but still returns the value.
99
+ * @param logger - Optional logger instance; if not provided, uses console.error
100
+ */
101
+ export const getPropertyTags = (
102
+ obj: ts.ObjectLiteralExpression,
103
+ wiringType: string,
104
+ wiringName: string | null,
105
+ logger?: { critical: (code: ErrorCode, message: string) => void }
106
+ ): string[] | undefined => {
107
+ const tagsValue = getPropertyValue(obj, 'tags')
108
+
109
+ if (tagsValue !== null && !Array.isArray(tagsValue)) {
110
+ const errorMsg = `${wiringType} '${wiringName}' has invalid 'tags' property - must be an array of strings.`
111
+ if (logger) {
112
+ logger.critical(ErrorCode.INVALID_TAGS_TYPE, errorMsg)
113
+ } else {
114
+ console.error(errorMsg)
115
+ }
116
+ // Return undefined but don't stop processing - error will be caught by the exit handler
117
+ }
118
+
119
+ return Array.isArray(tagsValue) ? tagsValue : undefined
120
+ }
@@ -0,0 +1,241 @@
1
+ import * as ts from 'typescript'
2
+ import { MiddlewareMetadata } from '@pikku/core'
3
+ import { extractFunctionName } from './extract-function-name.js'
4
+ import { InspectorState } from '../types.js'
5
+
6
+ /**
7
+ * Extract middleware pikkuFuncNames from an array literal expression
8
+ * Resolves each identifier to its pikkuFuncName using extractFunctionName
9
+ * Also handles call expressions (like logCommandInfoAndTime({...}))
10
+ */
11
+ export function extractMiddlewarePikkuNames(
12
+ arrayNode: ts.Expression,
13
+ checker: ts.TypeChecker,
14
+ rootDir: string
15
+ ): string[] {
16
+ if (!ts.isArrayLiteralExpression(arrayNode)) {
17
+ return []
18
+ }
19
+
20
+ const names: string[] = []
21
+ for (const element of arrayNode.elements) {
22
+ if (ts.isIdentifier(element)) {
23
+ // Resolve the identifier to its pikkuFuncName
24
+ const { pikkuFuncName } = extractFunctionName(element, checker, rootDir)
25
+ names.push(pikkuFuncName)
26
+ } else if (ts.isCallExpression(element)) {
27
+ // Handle call expressions like rateLimiter(10) or logCommandInfoAndTime({...})
28
+ // Extract the function being called (e.g., 'rateLimiter' from 'rateLimiter(10)')
29
+ const { pikkuFuncName } = extractFunctionName(
30
+ element.expression,
31
+ checker,
32
+ rootDir
33
+ )
34
+ names.push(pikkuFuncName)
35
+ }
36
+ }
37
+ return names
38
+ }
39
+
40
+ /**
41
+ * Get middleware array from an object literal expression property
42
+ * Returns the initializer node for the 'middleware' property if it exists
43
+ */
44
+ export function getMiddlewareNode(
45
+ obj: ts.ObjectLiteralExpression
46
+ ): ts.Expression | undefined {
47
+ const middlewareProp = obj.properties.find(
48
+ (p) =>
49
+ ts.isPropertyAssignment(p) &&
50
+ ts.isIdentifier(p.name) &&
51
+ p.name.text === 'middleware'
52
+ ) as ts.PropertyAssignment | undefined
53
+
54
+ return middlewareProp?.initializer
55
+ }
56
+
57
+ /**
58
+ * Check if a route matches a pattern with wildcards
59
+ * Pattern can be exact match or use * as wildcard
60
+ * e.g., '/api/*' matches '/api/users', '/api/posts/123', etc.
61
+ */
62
+ export function routeMatchesPattern(route: string, pattern: string): boolean {
63
+ if (route === pattern) return true
64
+
65
+ // Convert pattern to regex: replace * with .*
66
+ const regexPattern = pattern
67
+ .replace(/[.+?^${}()|[\]\\]/g, '\\$&') // Escape regex special chars except *
68
+ .replace(/\*/g, '.*') // Replace * with .*
69
+
70
+ const regex = new RegExp(`^${regexPattern}$`)
71
+ return regex.test(route)
72
+ }
73
+
74
+ /**
75
+ * Resolve middleware for an HTTP wiring based on:
76
+ * 1. Global HTTP middleware (addd([...]))
77
+ * 2. Route-specific HTTP middleware (addHTTPMiddleware('/pattern', [...]))
78
+ * 3. Tag-based middleware (addMiddleware('tag', [...]))
79
+ * 4. Explicit wiring middleware (wireHTTP({ middleware: [...] }))
80
+ * Returns undefined if no middleware is found, otherwise returns array with at least one item
81
+ */
82
+ export function resolveHTTPMiddleware(
83
+ state: InspectorState,
84
+ route: string,
85
+ tags: string[] | undefined,
86
+ explicitMiddlewareNode: ts.Expression | undefined,
87
+ checker: ts.TypeChecker
88
+ ): MiddlewareMetadata[] | undefined {
89
+ const resolved: MiddlewareMetadata[] = []
90
+
91
+ // 1. HTTP route middleware groups (includes '*' for global)
92
+ for (const [pattern, _groupMeta] of state.http.routeMiddleware.entries()) {
93
+ if (routeMatchesPattern(route, pattern)) {
94
+ // Just reference the group by route pattern
95
+ resolved.push({
96
+ type: 'http',
97
+ route: pattern,
98
+ })
99
+ }
100
+ }
101
+
102
+ // 2. Tag-based middleware groups
103
+ if (tags && tags.length > 0) {
104
+ for (const tag of tags) {
105
+ if (state.middleware.tagMiddleware.has(tag)) {
106
+ // Just reference the group by tag
107
+ resolved.push({
108
+ type: 'tag',
109
+ tag,
110
+ })
111
+ }
112
+ }
113
+ }
114
+
115
+ // 3. Explicit wire middleware (inline is OK here)
116
+ if (explicitMiddlewareNode) {
117
+ const middlewareNames = extractMiddlewarePikkuNames(
118
+ explicitMiddlewareNode,
119
+ checker,
120
+ state.rootDir
121
+ )
122
+ for (const name of middlewareNames) {
123
+ const meta = state.middleware.meta[name]
124
+ resolved.push({
125
+ type: 'wire',
126
+ name,
127
+ inline: meta?.exportedName === null,
128
+ })
129
+ }
130
+ }
131
+
132
+ return resolved.length > 0 ? resolved : undefined
133
+ }
134
+
135
+ /**
136
+ * Resolve tag-based and explicit middleware (common logic for wires and functions)
137
+ * 1. Tag-based middleware (addMiddleware('tag', [...]))
138
+ * 2. Explicit middleware (wireHTTP/pikkuFunc({ middleware: [...] }))
139
+ */
140
+ function resolveTagAndExplicitMiddleware(
141
+ state: InspectorState,
142
+ tags: string[] | undefined,
143
+ explicitMiddlewareNode: ts.Expression | undefined,
144
+ checker: ts.TypeChecker
145
+ ): MiddlewareMetadata[] {
146
+ const resolved: MiddlewareMetadata[] = []
147
+
148
+ // 1. Tag-based middleware groups
149
+ if (tags && tags.length > 0) {
150
+ for (const tag of tags) {
151
+ if (state.middleware.tagMiddleware.has(tag)) {
152
+ // Just reference the group by tag
153
+ resolved.push({
154
+ type: 'tag',
155
+ tag,
156
+ })
157
+ }
158
+ }
159
+ }
160
+
161
+ // 2. Explicit middleware (inline is OK here - used directly in wire/function)
162
+ if (explicitMiddlewareNode) {
163
+ const middlewareNames = extractMiddlewarePikkuNames(
164
+ explicitMiddlewareNode,
165
+ checker,
166
+ state.rootDir
167
+ )
168
+ for (const name of middlewareNames) {
169
+ const meta = state.middleware.meta[name]
170
+ resolved.push({
171
+ type: 'wire',
172
+ name,
173
+ inline: meta?.exportedName === null,
174
+ })
175
+ }
176
+ }
177
+
178
+ return resolved
179
+ }
180
+
181
+ /**
182
+ * Resolve middleware for a function based on:
183
+ * 1. Tag-based middleware (addMiddleware('tag', [...]))
184
+ * 2. Explicit function middleware (pikkuFunc({ middleware: [...] }))
185
+ * Returns undefined if no middleware is found, otherwise returns array with at least one item
186
+ */
187
+ function resolveFunctionMiddlewareInternal(
188
+ state: InspectorState,
189
+ tags: string[] | undefined,
190
+ explicitMiddlewareNode: ts.Expression | undefined,
191
+ checker: ts.TypeChecker
192
+ ): MiddlewareMetadata[] | undefined {
193
+ const resolved = resolveTagAndExplicitMiddleware(
194
+ state,
195
+ tags,
196
+ explicitMiddlewareNode,
197
+ checker
198
+ )
199
+
200
+ return resolved.length > 0 ? resolved : undefined
201
+ }
202
+
203
+ /**
204
+ * Convenience wrapper: Extract middleware node from object and resolve
205
+ * Use this in add-* files for cleaner code
206
+ */
207
+ export function resolveMiddleware(
208
+ state: InspectorState,
209
+ obj: ts.ObjectLiteralExpression,
210
+ tags: string[] | undefined,
211
+ checker: ts.TypeChecker
212
+ ): MiddlewareMetadata[] | undefined {
213
+ const explicitMiddlewareNode = getMiddlewareNode(obj)
214
+ return resolveFunctionMiddlewareInternal(
215
+ state,
216
+ tags,
217
+ explicitMiddlewareNode,
218
+ checker
219
+ )
220
+ }
221
+
222
+ /**
223
+ * Convenience wrapper for HTTP: Extract middleware and resolve with HTTP-specific logic
224
+ * Use this in add-http-route.ts for cleaner code
225
+ */
226
+ export function resolveHTTPMiddlewareFromObject(
227
+ state: InspectorState,
228
+ route: string,
229
+ obj: ts.ObjectLiteralExpression,
230
+ tags: string[] | undefined,
231
+ checker: ts.TypeChecker
232
+ ): MiddlewareMetadata[] | undefined {
233
+ const explicitMiddlewareNode = getMiddlewareNode(obj)
234
+ return resolveHTTPMiddleware(
235
+ state,
236
+ route,
237
+ tags,
238
+ explicitMiddlewareNode,
239
+ checker
240
+ )
241
+ }