@pikku/inspector 0.11.1 → 0.12.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 (189) hide show
  1. package/CHANGELOG.md +26 -1
  2. package/OPTIMIZATION-PLAN.md +195 -0
  3. package/dist/add/add-ai-agent.d.ts +2 -0
  4. package/dist/add/add-ai-agent.js +314 -0
  5. package/dist/add/add-channel.js +69 -61
  6. package/dist/add/add-cli.js +36 -18
  7. package/dist/add/add-file-with-factory.js +2 -0
  8. package/dist/add/add-functions.js +327 -59
  9. package/dist/add/add-http-route.d.ts +19 -10
  10. package/dist/add/add-http-route.js +153 -44
  11. package/dist/add/add-http-routes.d.ts +5 -0
  12. package/dist/add/add-http-routes.js +159 -0
  13. package/dist/add/add-keyed-wiring.d.ts +12 -0
  14. package/dist/add/add-keyed-wiring.js +97 -0
  15. package/dist/add/add-mcp-prompt.js +14 -9
  16. package/dist/add/add-mcp-resource.js +14 -9
  17. package/dist/add/add-middleware.d.ts +1 -4
  18. package/dist/add/add-middleware.js +364 -79
  19. package/dist/add/add-permission.d.ts +1 -1
  20. package/dist/add/add-permission.js +152 -40
  21. package/dist/add/add-queue-worker.js +18 -12
  22. package/dist/add/add-rpc-invocations.d.ts +3 -0
  23. package/dist/add/add-rpc-invocations.js +65 -25
  24. package/dist/add/add-schedule.js +11 -5
  25. package/dist/add/add-secret.d.ts +3 -0
  26. package/dist/add/add-secret.js +82 -0
  27. package/dist/add/add-trigger.d.ts +2 -0
  28. package/dist/add/add-trigger.js +87 -0
  29. package/dist/add/add-variable.d.ts +1 -0
  30. package/dist/add/add-variable.js +8 -0
  31. package/dist/add/add-workflow-graph.d.ts +7 -0
  32. package/dist/add/add-workflow-graph.js +396 -0
  33. package/dist/add/add-workflow.js +124 -26
  34. package/dist/error-codes.d.ts +16 -1
  35. package/dist/error-codes.js +21 -1
  36. package/dist/index.d.ts +9 -5
  37. package/dist/index.js +5 -2
  38. package/dist/inspector.d.ts +1 -1
  39. package/dist/inspector.js +106 -13
  40. package/dist/schema-generator.d.ts +1 -0
  41. package/dist/schema-generator.js +1 -0
  42. package/dist/types-map.js +10 -1
  43. package/dist/types.d.ts +180 -30
  44. package/dist/utils/compute-required-schemas.d.ts +4 -0
  45. package/dist/utils/compute-required-schemas.js +41 -0
  46. package/dist/utils/contract-hashes.d.ts +35 -0
  47. package/dist/utils/contract-hashes.js +202 -0
  48. package/dist/utils/custom-types-generator.d.ts +9 -0
  49. package/dist/utils/custom-types-generator.js +71 -0
  50. package/dist/utils/detect-schema-vendor.d.ts +22 -0
  51. package/dist/utils/detect-schema-vendor.js +76 -0
  52. package/dist/utils/ensure-function-metadata.d.ts +5 -2
  53. package/dist/utils/ensure-function-metadata.js +220 -6
  54. package/dist/utils/extract-function-name.d.ts +5 -16
  55. package/dist/utils/extract-function-name.js +93 -298
  56. package/dist/utils/extract-services.d.ts +2 -1
  57. package/dist/utils/extract-services.js +25 -1
  58. package/dist/utils/filter-inspector-state.js +107 -23
  59. package/dist/utils/get-property-value.d.ts +8 -2
  60. package/dist/utils/get-property-value.js +33 -4
  61. package/dist/utils/hash.d.ts +2 -0
  62. package/dist/utils/hash.js +23 -0
  63. package/dist/utils/middleware.d.ts +7 -30
  64. package/dist/utils/middleware.js +80 -66
  65. package/dist/utils/permissions.d.ts +2 -2
  66. package/dist/utils/permissions.js +10 -10
  67. package/dist/utils/post-process.d.ts +9 -10
  68. package/dist/utils/post-process.js +231 -24
  69. package/dist/utils/resolve-external-package.d.ts +12 -0
  70. package/dist/utils/resolve-external-package.js +34 -0
  71. package/dist/utils/resolve-function-types.d.ts +6 -0
  72. package/dist/utils/resolve-function-types.js +29 -0
  73. package/dist/utils/resolve-identifier.d.ts +10 -0
  74. package/dist/utils/resolve-identifier.js +36 -0
  75. package/dist/utils/resolve-versions.d.ts +2 -0
  76. package/dist/utils/resolve-versions.js +78 -0
  77. package/dist/utils/schema-generator.d.ts +9 -0
  78. package/dist/utils/schema-generator.js +209 -0
  79. package/dist/utils/serialize-inspector-state.d.ts +73 -13
  80. package/dist/utils/serialize-inspector-state.js +102 -6
  81. package/dist/utils/serialize-mcp-json.d.ts +2 -0
  82. package/dist/utils/serialize-mcp-json.js +99 -0
  83. package/dist/utils/serialize-middleware-groups-meta.d.ts +12 -0
  84. package/dist/utils/serialize-middleware-groups-meta.js +28 -0
  85. package/dist/utils/serialize-openapi-json.d.ts +85 -0
  86. package/dist/utils/serialize-openapi-json.js +151 -0
  87. package/dist/utils/serialize-permissions-groups-meta.d.ts +6 -0
  88. package/dist/utils/serialize-permissions-groups-meta.js +31 -0
  89. package/dist/utils/workflow/dsl/deserialize-dsl-workflow.d.ts +24 -0
  90. package/dist/utils/workflow/dsl/deserialize-dsl-workflow.js +830 -0
  91. package/dist/{workflow/extract-simple-workflow.d.ts → utils/workflow/dsl/extract-dsl-workflow.d.ts} +4 -2
  92. package/dist/{workflow/extract-simple-workflow.js → utils/workflow/dsl/extract-dsl-workflow.js} +572 -72
  93. package/dist/utils/workflow/dsl/index.d.ts +7 -0
  94. package/dist/utils/workflow/dsl/index.js +7 -0
  95. package/dist/{workflow → utils/workflow/dsl}/patterns.d.ts +21 -0
  96. package/dist/{workflow → utils/workflow/dsl}/patterns.js +90 -10
  97. package/dist/{workflow → utils/workflow/dsl}/validation.d.ts +2 -0
  98. package/dist/{workflow → utils/workflow/dsl}/validation.js +25 -7
  99. package/dist/utils/workflow/graph/convert-dsl-to-graph.d.ts +13 -0
  100. package/dist/utils/workflow/graph/convert-dsl-to-graph.js +318 -0
  101. package/dist/utils/workflow/graph/finalize-workflow-wires.d.ts +3 -0
  102. package/dist/utils/workflow/graph/finalize-workflow-wires.js +276 -0
  103. package/dist/utils/workflow/graph/finalize-workflows.d.ts +2 -0
  104. package/dist/utils/workflow/graph/finalize-workflows.js +75 -0
  105. package/dist/utils/workflow/graph/index.d.ts +8 -0
  106. package/dist/utils/workflow/graph/index.js +8 -0
  107. package/dist/utils/workflow/graph/serialize-workflow-graph.d.ts +35 -0
  108. package/dist/utils/workflow/graph/serialize-workflow-graph.js +150 -0
  109. package/dist/utils/workflow/graph/workflow-graph.types.d.ts +203 -0
  110. package/dist/utils/workflow/graph/workflow-graph.types.js +38 -0
  111. package/dist/visit.js +13 -2
  112. package/package.json +26 -4
  113. package/src/add/add-ai-agent.ts +468 -0
  114. package/src/add/add-channel.ts +82 -79
  115. package/src/add/add-cli.ts +49 -20
  116. package/src/add/add-file-with-factory.ts +2 -0
  117. package/src/add/add-functions.ts +429 -71
  118. package/src/add/add-http-route.ts +246 -65
  119. package/src/add/add-http-routes.ts +228 -0
  120. package/src/add/add-keyed-wiring.ts +151 -0
  121. package/src/add/add-mcp-prompt.ts +26 -15
  122. package/src/add/add-mcp-resource.ts +27 -15
  123. package/src/add/add-middleware.ts +482 -80
  124. package/src/add/add-permission.ts +199 -40
  125. package/src/add/add-queue-worker.ts +24 -19
  126. package/src/add/add-rpc-invocations.ts +78 -31
  127. package/src/add/add-schedule.ts +16 -11
  128. package/src/add/add-secret.ts +140 -0
  129. package/src/add/add-trigger.ts +154 -0
  130. package/src/add/add-variable.ts +9 -0
  131. package/src/add/add-workflow-graph.ts +522 -0
  132. package/src/add/add-workflow.ts +117 -30
  133. package/src/error-codes.ts +26 -1
  134. package/src/index.ts +27 -8
  135. package/src/inspector.ts +145 -17
  136. package/src/schema-generator.ts +1 -0
  137. package/src/types-map.ts +12 -1
  138. package/src/types.ts +192 -51
  139. package/src/utils/compute-required-schemas.ts +49 -0
  140. package/src/utils/contract-hashes.test.ts +528 -0
  141. package/src/utils/contract-hashes.ts +290 -0
  142. package/src/utils/custom-types-generator.ts +88 -0
  143. package/src/utils/detect-schema-vendor.ts +90 -0
  144. package/src/utils/ensure-function-metadata.ts +324 -7
  145. package/src/utils/extract-function-name.ts +108 -358
  146. package/src/utils/extract-services.ts +35 -2
  147. package/src/utils/filter-inspector-state.test.ts +34 -20
  148. package/src/utils/filter-inspector-state.ts +140 -31
  149. package/src/utils/get-property-value.ts +50 -5
  150. package/src/utils/hash.ts +26 -0
  151. package/src/utils/middleware.test.ts +204 -0
  152. package/src/utils/middleware.ts +129 -67
  153. package/src/utils/permissions.test.ts +35 -12
  154. package/src/utils/permissions.ts +10 -10
  155. package/src/utils/post-process.ts +283 -43
  156. package/src/utils/resolve-external-package.ts +42 -0
  157. package/src/utils/resolve-function-types.ts +42 -0
  158. package/src/utils/resolve-identifier.ts +46 -0
  159. package/src/utils/resolve-versions.test.ts +249 -0
  160. package/src/utils/resolve-versions.ts +105 -0
  161. package/src/utils/schema-generator.ts +329 -0
  162. package/src/utils/serialize-inspector-state.ts +181 -20
  163. package/src/utils/serialize-mcp-json.ts +145 -0
  164. package/src/utils/serialize-middleware-groups-meta.ts +33 -0
  165. package/src/utils/serialize-openapi-json.ts +277 -0
  166. package/src/utils/serialize-permissions-groups-meta.ts +35 -0
  167. package/src/utils/test-data/inspector-state.json +69 -66
  168. package/src/utils/workflow/dsl/deserialize-dsl-workflow.ts +1104 -0
  169. package/src/{workflow/extract-simple-workflow.ts → utils/workflow/dsl/extract-dsl-workflow.ts} +678 -85
  170. package/src/utils/workflow/dsl/index.ts +11 -0
  171. package/src/{workflow → utils/workflow/dsl}/patterns.ts +108 -11
  172. package/src/{workflow → utils/workflow/dsl}/validation.ts +34 -7
  173. package/src/utils/workflow/graph/convert-dsl-to-graph.ts +422 -0
  174. package/src/utils/workflow/graph/finalize-workflow-wires.ts +310 -0
  175. package/src/utils/workflow/graph/finalize-workflows.ts +100 -0
  176. package/src/utils/workflow/graph/index.ts +11 -0
  177. package/src/utils/workflow/graph/serialize-workflow-graph.ts +216 -0
  178. package/src/utils/workflow/graph/workflow-graph.types.ts +231 -0
  179. package/src/visit.ts +14 -2
  180. package/tsconfig.tsbuildinfo +1 -1
  181. package/dist/add/add-mcp-tool.d.ts +0 -2
  182. package/dist/add/add-mcp-tool.js +0 -81
  183. package/dist/utils/extract-service-metadata.d.ts +0 -19
  184. package/dist/utils/extract-service-metadata.js +0 -244
  185. package/dist/utils/write-service-metadata.d.ts +0 -13
  186. package/dist/utils/write-service-metadata.js +0 -37
  187. package/src/add/add-mcp-tool.ts +0 -141
  188. package/src/utils/extract-service-metadata.ts +0 -353
  189. package/src/utils/write-service-metadata.ts +0 -51
@@ -0,0 +1,277 @@
1
+ import type { FunctionsMeta } from '@pikku/core'
2
+ import type { HTTPWiringsMeta } from '@pikku/core/http'
3
+ import type { InspectorLogger } from '../types.js'
4
+ import _convertSchema from '@openapi-contrib/json-schema-to-openapi-schema'
5
+ const convertSchema =
6
+ 'default' in _convertSchema ? (_convertSchema.default as any) : _convertSchema
7
+
8
+ interface ErrorDetails {
9
+ status: number
10
+ message: string
11
+ }
12
+
13
+ interface OpenAPISpec {
14
+ openapi: string
15
+ info: {
16
+ title: string
17
+ version: string
18
+ description?: string
19
+ termsOfService?: string
20
+ contact?: {
21
+ name?: string
22
+ url?: string
23
+ email?: string
24
+ }
25
+ license?: {
26
+ name: string
27
+ url?: string
28
+ }
29
+ }
30
+ servers: { url: string; description?: string }[]
31
+ paths: Record<string, any>
32
+ components: {
33
+ schemas: Record<string, any>
34
+ responses?: Record<string, any>
35
+ parameters?: Record<string, any>
36
+ examples?: Record<string, any>
37
+ requestBodies?: Record<string, any>
38
+ headers?: Record<string, any>
39
+ securitySchemes?: Record<string, any>
40
+ }
41
+ security?: { [key: string]: any[] }[]
42
+ tags?: { name: string; description?: string }[]
43
+ externalDocs?: {
44
+ description?: string
45
+ url: string
46
+ }
47
+ }
48
+
49
+ export interface OpenAPISpecInfo {
50
+ info: {
51
+ title: string
52
+ version: string
53
+ description: string
54
+ termsOfService?: string
55
+ contact?: {
56
+ name?: string
57
+ url?: string
58
+ email?: string
59
+ }
60
+ license?: {
61
+ name: string
62
+ url?: string
63
+ }
64
+ }
65
+ servers: { url: string; description?: string }[]
66
+ tags?: { name: string; description?: string }[]
67
+ externalDocs?: {
68
+ description?: string
69
+ url: string
70
+ }
71
+ securitySchemes?: Record<string, any>
72
+ security?: { [key: string]: any[] }[]
73
+ }
74
+
75
+ const getErrorResponseForConstructorName = (
76
+ constructorName: string,
77
+ errors: Map<any, ErrorDetails>
78
+ ) => {
79
+ const entries = Array.from(errors.entries())
80
+ const foundError = entries.find(([e]) => e.name === constructorName)
81
+ if (foundError) {
82
+ return foundError[1]
83
+ }
84
+ return undefined
85
+ }
86
+
87
+ const convertSchemasToBodyPayloads = async (
88
+ functionsMeta: FunctionsMeta,
89
+ routesMeta: HTTPWiringsMeta,
90
+ schemas: Record<string, any>
91
+ ) => {
92
+ const requiredSchemas = new Set<string>()
93
+ for (const routeMeta of Object.values(routesMeta)) {
94
+ for (const { inputTypes, pikkuFuncId } of Object.values(routeMeta)) {
95
+ const output = functionsMeta[pikkuFuncId]?.outputs?.[0]
96
+ if (inputTypes?.body) {
97
+ requiredSchemas.add(inputTypes?.body)
98
+ }
99
+ if (output) {
100
+ requiredSchemas.add(output)
101
+ }
102
+ }
103
+ }
104
+
105
+ const convertedEntries = await Promise.all(
106
+ Object.entries(schemas).map(async ([key, schema]) => {
107
+ if (requiredSchemas.has(key)) {
108
+ const convertedSchema = await convertSchema(schema, {
109
+ convertUnreferencedDefinitions: false,
110
+ dereference: { circular: 'ignore' },
111
+ })
112
+ return [key, convertedSchema]
113
+ }
114
+ return
115
+ })
116
+ )
117
+ return Object.fromEntries(convertedEntries.filter((s) => !!s))
118
+ }
119
+
120
+ export async function generateOpenAPISpec(
121
+ logger: InspectorLogger,
122
+ functionsMeta: FunctionsMeta,
123
+ httpMeta: HTTPWiringsMeta,
124
+ schemas: Record<string, any>,
125
+ additionalInfo: OpenAPISpecInfo,
126
+ errors?: Map<any, ErrorDetails>
127
+ ): Promise<OpenAPISpec> {
128
+ const paths: Record<string, any> = {}
129
+ const errorsMap = errors ?? new Map()
130
+
131
+ for (const routeMeta of Object.values(httpMeta)) {
132
+ for (const meta of Object.values(routeMeta)) {
133
+ const {
134
+ route,
135
+ method,
136
+ inputTypes,
137
+ pikkuFuncId,
138
+ params,
139
+ query,
140
+ errors,
141
+ description,
142
+ tags,
143
+ } = meta
144
+ const functionMeta = functionsMeta[pikkuFuncId]
145
+ if (!functionMeta) {
146
+ logger.error(
147
+ `• No function metadata found for '${pikkuFuncId}' in route '${route}'.`
148
+ )
149
+ continue
150
+ }
151
+
152
+ const output = functionMeta.outputs ? functionMeta.outputs[0] : undefined
153
+
154
+ const path = route.replace(/:(\w+)/g, '{$1}')
155
+
156
+ if (!paths[path]) {
157
+ paths[path] = {}
158
+ }
159
+
160
+ const responses = {}
161
+ errors?.forEach((error) => {
162
+ const errorResponse = getErrorResponseForConstructorName(
163
+ error,
164
+ errorsMap
165
+ )
166
+ if (errorResponse) {
167
+ responses[errorResponse.status] = {
168
+ description: errorResponse.message,
169
+ }
170
+ }
171
+ })
172
+
173
+ const operation: any = {
174
+ description:
175
+ description ||
176
+ `This endpoint handles the ${method.toUpperCase()} request for the route ${route}.`,
177
+ tags: tags || [route.split('/')[1] || 'default'],
178
+ parameters: [],
179
+ responses: {
180
+ ...responses,
181
+ '200': {
182
+ description: 'Successful response',
183
+ content: output
184
+ ? {
185
+ 'application/json': {
186
+ schema:
187
+ typeof output === 'string' &&
188
+ ['boolean', 'string', 'number'].includes(output)
189
+ ? { type: output }
190
+ : { $ref: `#/components/schemas/${output}` },
191
+ },
192
+ }
193
+ : undefined,
194
+ },
195
+ },
196
+ }
197
+
198
+ const bodyType = inputTypes?.body
199
+ if (bodyType) {
200
+ operation.requestBody = {
201
+ required: true,
202
+ content: {
203
+ 'application/json': {
204
+ schema:
205
+ typeof bodyType === 'string' &&
206
+ ['boolean', 'string', 'number'].includes(bodyType)
207
+ ? { type: bodyType }
208
+ : { $ref: `#/components/schemas/${bodyType}` },
209
+ },
210
+ },
211
+ }
212
+ }
213
+
214
+ if (params) {
215
+ operation.parameters = params.map((param) => ({
216
+ name: param,
217
+ in: 'path',
218
+ required: true,
219
+ schema: { type: 'string' },
220
+ }))
221
+ }
222
+
223
+ if (query) {
224
+ operation.parameters.push(
225
+ ...query.map((query) => ({
226
+ name: query,
227
+ in: 'query',
228
+ required: false,
229
+ schema: { type: 'string' },
230
+ }))
231
+ )
232
+ }
233
+
234
+ paths[path][method] = operation
235
+ }
236
+ }
237
+
238
+ return {
239
+ openapi: '3.1.0',
240
+ info: additionalInfo.info,
241
+ servers: additionalInfo.servers,
242
+ paths,
243
+ components: {
244
+ schemas: await convertSchemasToBodyPayloads(
245
+ functionsMeta,
246
+ httpMeta,
247
+ schemas
248
+ ),
249
+ responses: {},
250
+ parameters: {},
251
+ examples: {},
252
+ requestBodies: {},
253
+ headers: {},
254
+ securitySchemes: additionalInfo.securitySchemes || {
255
+ ApiKeyAuth: {
256
+ type: 'apiKey',
257
+ in: 'header',
258
+ name: 'x-api-key',
259
+ },
260
+ BearerAuth: {
261
+ type: 'http',
262
+ scheme: 'bearer',
263
+ },
264
+ },
265
+ },
266
+ security: additionalInfo.security || [
267
+ {
268
+ ApiKeyAuth: [],
269
+ },
270
+ {
271
+ BearerAuth: [],
272
+ },
273
+ ],
274
+ tags: additionalInfo.tags,
275
+ externalDocs: additionalInfo.externalDocs,
276
+ }
277
+ }
@@ -0,0 +1,35 @@
1
+ import type { InspectorState } from '../types.js'
2
+
3
+ export const serializePermissionsGroupsMeta = (state: InspectorState) => {
4
+ const httpGroups: Record<string, any> = {}
5
+ for (const [pattern, meta] of state.http.routePermissions.entries()) {
6
+ httpGroups[pattern] = {
7
+ exportName: meta.exportName,
8
+ sourceFile: meta.sourceFile,
9
+ position: meta.position,
10
+ services: meta.services,
11
+ count: meta.count,
12
+ instanceIds: meta.instanceIds,
13
+ isFactory: meta.isFactory,
14
+ }
15
+ }
16
+
17
+ const tagGroups: Record<string, any> = {}
18
+ for (const [tag, meta] of state.permissions.tagPermissions.entries()) {
19
+ tagGroups[tag] = {
20
+ exportName: meta.exportName,
21
+ sourceFile: meta.sourceFile,
22
+ position: meta.position,
23
+ services: meta.services,
24
+ count: meta.count,
25
+ instanceIds: meta.instanceIds,
26
+ isFactory: meta.isFactory,
27
+ }
28
+ }
29
+
30
+ return {
31
+ definitions: state.permissions.definitions,
32
+ httpGroups,
33
+ tagGroups,
34
+ }
35
+ }