@reinteractive/rails-insight 1.0.3 → 1.0.5

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reinteractive/rails-insight",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Rails-aware codebase indexer — MCP server for AI agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -18,8 +18,9 @@ export const ROUTE_PATTERNS = {
18
18
  member: /^\s*member\s+do/m,
19
19
  collection: /^\s*collection\s+do/m,
20
20
  draw: /^\s*draw\s*\(?:?(\w+)\)?/m,
21
- only: /only:\s*\[([^\]]+)\]/,
22
- except: /except:\s*\[([^\]]+)\]/,
21
+ only: /only:\s*(?:\[([^\]]+)\]|:([\w]+))/,
22
+ except: /except:\s*(?:\[([^\]]+)\]|:([\w]+))/,
23
+ httpVerbSymbol: /^\s*(?:get|post|put|patch|delete)\s+:(\w+)/m,
23
24
  defaults: /defaults:\s*\{([^}]+)\}/,
24
25
  healthCheck: /^\s*get\s+['"]up['"]/m,
25
26
  direct: /^\s*direct\s*\(:(\w+)\)/m,
@@ -112,7 +112,8 @@ function parseRouteContent(content, result, provider, namespaceStack) {
112
112
  let actions = ['show', 'new', 'create', 'edit', 'update', 'destroy']
113
113
  const onlyMatch = options.match(ROUTE_PATTERNS.only)
114
114
  if (onlyMatch) {
115
- actions = onlyMatch[1].match(/:(\w+)/g)?.map((a) => a.slice(1)) || []
115
+ const raw = onlyMatch[1] ?? `:${onlyMatch[2]}`
116
+ actions = raw.match(/:(\w+)/g)?.map((a) => a.slice(1)) || []
116
117
  }
117
118
 
118
119
  const entry = {
@@ -121,6 +122,8 @@ function parseRouteContent(content, result, provider, namespaceStack) {
121
122
  controller: ns ? `${ns}/${name}` : name,
122
123
  actions,
123
124
  singular: true,
125
+ member_routes: [],
126
+ collection_routes: [],
124
127
  }
125
128
 
126
129
  if (trimmed.includes('do')) {
@@ -151,12 +154,13 @@ function parseRouteContent(content, result, provider, namespaceStack) {
151
154
  ]
152
155
  const onlyMatch = options.match(ROUTE_PATTERNS.only)
153
156
  if (onlyMatch) {
154
- actions = onlyMatch[1].match(/:(\w+)/g)?.map((a) => a.slice(1)) || []
157
+ const raw = onlyMatch[1] ?? `:${onlyMatch[2]}`
158
+ actions = raw.match(/:(\w+)/g)?.map((a) => a.slice(1)) || []
155
159
  }
156
160
  const exceptMatch = options.match(ROUTE_PATTERNS.except)
157
161
  if (exceptMatch) {
158
- const except =
159
- exceptMatch[1].match(/:(\w+)/g)?.map((a) => a.slice(1)) || []
162
+ const raw = exceptMatch[1] ?? `:${exceptMatch[2]}`
163
+ const except = raw.match(/:(\w+)/g)?.map((a) => a.slice(1)) || []
160
164
  actions = actions.filter((a) => !except.includes(a))
161
165
  }
162
166
 
@@ -208,6 +212,20 @@ function parseRouteContent(content, result, provider, namespaceStack) {
208
212
  continue
209
213
  }
210
214
 
215
+ // Symbol-form verb routes inside member/collection blocks: `get :action_name`
216
+ if (inMember || inCollection) {
217
+ const symbolVerbMatch = trimmed.match(ROUTE_PATTERNS.httpVerbSymbol)
218
+ if (symbolVerbMatch) {
219
+ const action = symbolVerbMatch[1]
220
+ const currentResource = resourceStack[resourceStack.length - 1]
221
+ if (currentResource) {
222
+ if (inMember) currentResource.member_routes.push(action)
223
+ else currentResource.collection_routes.push(action)
224
+ }
225
+ continue
226
+ }
227
+ }
228
+
211
229
  // HTTP verb routes
212
230
  const verbMatch = trimmed.match(ROUTE_PATTERNS.httpVerb)
213
231
  if (verbMatch) {