@pikku/inspector 0.12.75 → 0.12.81
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/CHANGELOG.md +330 -0
- package/dist/add/add-analytics.d.ts +9 -0
- package/dist/add/add-analytics.js +178 -0
- package/dist/add/add-auth.js +0 -54
- package/dist/add/add-feature-flag.d.ts +2 -0
- package/dist/add/add-feature-flag.js +162 -0
- package/dist/add/add-wire-addon.js +1 -0
- package/dist/add/add-wire-remote-addon.js +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/inspector.js +4 -0
- package/dist/surface/collect-surface.d.ts +58 -0
- package/dist/surface/collect-surface.js +613 -0
- package/dist/types.d.ts +20 -11
- package/dist/utils/filter-inspector-state.js +14 -0
- package/dist/utils/post-process.js +15 -0
- package/dist/utils/read-module-specifiers.d.ts +8 -0
- package/dist/utils/read-module-specifiers.js +23 -0
- package/dist/utils/read-tsconfig-out-dir.d.ts +5 -0
- package/dist/utils/read-tsconfig-out-dir.js +12 -0
- package/dist/utils/resolve-deploy-target.d.ts +7 -0
- package/dist/utils/resolve-deploy-target.js +15 -7
- package/dist/utils/serialize-inspector-state.d.ts +5 -0
- package/dist/utils/serialize-inspector-state.js +8 -0
- package/dist/visit.js +4 -0
- package/package.json +16 -6
- package/run-tests.sh +21 -6
- package/src/add/add-addon-bans.ts +0 -85
- package/src/add/add-agent-scorer.test.ts +0 -197
- package/src/add/add-agent-scorer.ts +0 -83
- package/src/add/add-agent.test.ts +0 -87
- package/src/add/add-agent.ts +0 -638
- package/src/add/add-approval-description.ts +0 -76
- package/src/add/add-auth.test.ts +0 -791
- package/src/add/add-auth.ts +0 -424
- package/src/add/add-channel.ts +0 -778
- package/src/add/add-cli-renderers.test.ts +0 -74
- package/src/add/add-cli.ts +0 -1006
- package/src/add/add-credential.ts +0 -186
- package/src/add/add-feature.test.ts +0 -306
- package/src/add/add-feature.ts +0 -253
- package/src/add/add-file-extends-core-type.ts +0 -66
- package/src/add/add-file-with-config.ts +0 -45
- package/src/add/add-file-with-factory.test.ts +0 -134
- package/src/add/add-file-with-factory.ts +0 -288
- package/src/add/add-functions.test.ts +0 -743
- package/src/add/add-functions.ts +0 -1548
- package/src/add/add-gateway.ts +0 -143
- package/src/add/add-http-route-ref.test.ts +0 -149
- package/src/add/add-http-route.ts +0 -530
- package/src/add/add-http-routes.ts +0 -471
- package/src/add/add-keyed-wiring.ts +0 -180
- package/src/add/add-mcp-prompt.ts +0 -157
- package/src/add/add-mcp-resource.ts +0 -175
- package/src/add/add-middleware.test.ts +0 -196
- package/src/add/add-middleware.ts +0 -879
- package/src/add/add-permission-auth.test.ts +0 -59
- package/src/add/add-permission.ts +0 -311
- package/src/add/add-personas.test.ts +0 -406
- package/src/add/add-personas.ts +0 -287
- package/src/add/add-queue-worker.ts +0 -117
- package/src/add/add-rpc-invocations.test.ts +0 -287
- package/src/add/add-rpc-invocations.ts +0 -221
- package/src/add/add-scenario-step.test.ts +0 -509
- package/src/add/add-schedule.ts +0 -120
- package/src/add/add-scope.test.ts +0 -419
- package/src/add/add-scope.ts +0 -221
- package/src/add/add-secret.ts +0 -10
- package/src/add/add-subject-scenario-steps.test.ts +0 -161
- package/src/add/add-system-role.test.ts +0 -297
- package/src/add/add-system-role.ts +0 -162
- package/src/add/add-trigger.ts +0 -165
- package/src/add/add-variable.ts +0 -10
- package/src/add/add-wire-addon.test.ts +0 -185
- package/src/add/add-wire-addon.ts +0 -146
- package/src/add/add-wire-remote-addon.ts +0 -80
- package/src/add/add-workflow-edge-cases.test.ts +0 -201
- package/src/add/add-workflow-fanout.test.ts +0 -166
- package/src/add/add-workflow-graph-foreach.test.ts +0 -174
- package/src/add/add-workflow-graph-input.test.ts +0 -94
- package/src/add/add-workflow-graph-notes.test.ts +0 -74
- package/src/add/add-workflow-graph.ts +0 -644
- package/src/add/add-workflow-on-error.test.ts +0 -118
- package/src/add/add-workflow-return-switch.test.ts +0 -121
- package/src/add/add-workflow-silent-drops.test.ts +0 -261
- package/src/add/add-workflow-sleep-expression.test.ts +0 -96
- package/src/add/add-workflow.test.ts +0 -155
- package/src/add/add-workflow.ts +0 -482
- package/src/add/addon-bans.test.ts +0 -121
- package/src/add/addon-contracts.test.ts +0 -221
- package/src/add/allow-escape-hatches.test.ts +0 -144
- package/src/add/audit-meta.test.ts +0 -75
- package/src/add/classified-sink-check.test.ts +0 -347
- package/src/add/config-value-metadata.test.ts +0 -263
- package/src/add/dynamic-import-check.test.ts +0 -119
- package/src/add/expect-eventually-scenario-only.test.ts +0 -108
- package/src/add/function-body-span.test.ts +0 -96
- package/src/add/inline-wiring-function.test.ts +0 -104
- package/src/add/pii-check.test.ts +0 -258
- package/src/add/rpc-type-cast.test.ts +0 -123
- package/src/add/scenario-instrumentation.test.ts +0 -89
- package/src/add/scenario-instrumentation.ts +0 -42
- package/src/add/scenario-marker.test.ts +0 -89
- package/src/add/scenario-not-extractable.test.ts +0 -159
- package/src/add/scenario-services.test.ts +0 -103
- package/src/add/scenario-skip.test.ts +0 -83
- package/src/add/validate-workflow-graph-addons.test.ts +0 -102
- package/src/add/wire-name-literal.test.ts +0 -117
- package/src/error-codes-emitted.test.ts +0 -76
- package/src/error-codes.ts +0 -145
- package/src/index.ts +0 -66
- package/src/inspector.ts +0 -575
- package/src/schema-generator.ts +0 -1
- package/src/source-file-cache.ts +0 -73
- package/src/tsconfig-paths.test.ts +0 -90
- package/src/types-map.ts +0 -141
- package/src/types.ts +0 -775
- package/src/utils/annotate-http-route-auth.test.ts +0 -161
- package/src/utils/annotate-http-route-auth.ts +0 -53
- package/src/utils/check-classified-sinks.ts +0 -215
- package/src/utils/check-pii-output.ts +0 -120
- package/src/utils/compute-diagnostics.test.ts +0 -106
- package/src/utils/compute-required-schemas.ts +0 -48
- package/src/utils/contract-hashes.test.ts +0 -553
- package/src/utils/contract-hashes.ts +0 -387
- package/src/utils/custom-types-generator.test.ts +0 -124
- package/src/utils/custom-types-generator.ts +0 -150
- package/src/utils/detect-schema-vendor.test.ts +0 -123
- package/src/utils/detect-schema-vendor.ts +0 -120
- package/src/utils/does-type-extend-core-type.ts +0 -53
- package/src/utils/ensure-function-metadata.ts +0 -385
- package/src/utils/extract-function-name.ts +0 -612
- package/src/utils/extract-function-node.ts +0 -70
- package/src/utils/extract-node-value.test.ts +0 -117
- package/src/utils/extract-node-value.ts +0 -172
- package/src/utils/extract-secret-usage.test.ts +0 -81
- package/src/utils/extract-secret-usage.ts +0 -73
- package/src/utils/extract-services.ts +0 -70
- package/src/utils/extract-surface-usage.test.ts +0 -147
- package/src/utils/extract-surface-usage.ts +0 -121
- package/src/utils/filter-inspector-state.test.ts +0 -2232
- package/src/utils/filter-inspector-state.ts +0 -1298
- package/src/utils/filter-utils.test.ts +0 -843
- package/src/utils/filter-utils.ts +0 -161
- package/src/utils/find-root-dir.ts +0 -68
- package/src/utils/find-zod-transform.test.ts +0 -70
- package/src/utils/find-zod-transform.ts +0 -103
- package/src/utils/get-exported-variable-name.ts +0 -48
- package/src/utils/get-files-and-methods.ts +0 -157
- package/src/utils/get-property-value.test.ts +0 -141
- package/src/utils/get-property-value.ts +0 -331
- package/src/utils/hash.ts +0 -26
- package/src/utils/literal-properties.ts +0 -97
- package/src/utils/load-addon-functions-meta.test.ts +0 -157
- package/src/utils/load-addon-functions-meta.ts +0 -508
- package/src/utils/load-addon-scopes.test.ts +0 -138
- package/src/utils/middleware.test.ts +0 -204
- package/src/utils/middleware.ts +0 -303
- package/src/utils/nested-project-filter.test.ts +0 -53
- package/src/utils/nested-project-filter.ts +0 -28
- package/src/utils/permissions-shorthand.test.ts +0 -79
- package/src/utils/permissions.test.ts +0 -125
- package/src/utils/permissions.ts +0 -129
- package/src/utils/post-process.test.ts +0 -1094
- package/src/utils/post-process.ts +0 -1604
- package/src/utils/resolve-addon-package.ts +0 -106
- package/src/utils/resolve-core-type.test.ts +0 -142
- package/src/utils/resolve-core-type.ts +0 -35
- package/src/utils/resolve-deploy-target.test.ts +0 -135
- package/src/utils/resolve-deploy-target.ts +0 -65
- package/src/utils/resolve-function-meta.ts +0 -25
- package/src/utils/resolve-function-types.ts +0 -42
- package/src/utils/resolve-identifier.ts +0 -46
- package/src/utils/resolve-ref-contract.ts +0 -71
- package/src/utils/resolve-versions.test.ts +0 -499
- package/src/utils/resolve-versions.ts +0 -228
- package/src/utils/schema-cache.test.ts +0 -124
- package/src/utils/schema-generator.test.ts +0 -272
- package/src/utils/schema-generator.ts +0 -780
- package/src/utils/secret-alias-services.test.ts +0 -146
- package/src/utils/secret-alias-services.ts +0 -58
- package/src/utils/serialize-inspector-state.ts +0 -742
- package/src/utils/serialize-mcp-json.ts +0 -150
- package/src/utils/serialize-middleware-groups-meta.ts +0 -36
- package/src/utils/serialize-openapi-json.ts +0 -277
- package/src/utils/serialize-permissions-groups-meta.ts +0 -7
- package/src/utils/single-declaration.ts +0 -57
- package/src/utils/type-utils.ts +0 -145
- package/src/utils/validate-auth-sessionless.ts +0 -30
- package/src/utils/validate-exposed-functions-gated.test.ts +0 -230
- package/src/utils/validate-exposed-functions-gated.ts +0 -103
- package/src/utils/validate-tags-resolve-to-middleware.test.ts +0 -108
- package/src/utils/validate-tags-resolve-to-middleware.ts +0 -48
- package/src/utils/workflow/derive-workflow-plan.test.ts +0 -178
- package/src/utils/workflow/derive-workflow-plan.ts +0 -117
- package/src/utils/workflow/dsl/deserialize-dsl-workflow.ts +0 -1465
- package/src/utils/workflow/dsl/deserialize-fanout-body.test.ts +0 -71
- package/src/utils/workflow/dsl/deserialize-fanout-fidelity.test.ts +0 -99
- package/src/utils/workflow/dsl/deserialize-graph-next.test.ts +0 -161
- package/src/utils/workflow/dsl/deserialize-roundtrip-bindings.test.ts +0 -121
- package/src/utils/workflow/dsl/deserialize-roundtrip-values.test.ts +0 -116
- package/src/utils/workflow/dsl/deserialize-roundtrip.test.ts +0 -145
- package/src/utils/workflow/dsl/extract-approval-policy.test.ts +0 -71
- package/src/utils/workflow/dsl/extract-dsl-workflow.ts +0 -2254
- package/src/utils/workflow/dsl/index.ts +0 -11
- package/src/utils/workflow/dsl/patterns.ts +0 -440
- package/src/utils/workflow/dsl/validation.ts +0 -203
- package/src/utils/workflow/graph/convert-dsl-to-graph-skip.test.ts +0 -35
- package/src/utils/workflow/graph/convert-dsl-to-graph.ts +0 -543
- package/src/utils/workflow/graph/fanout-node-identity.test.ts +0 -105
- package/src/utils/workflow/graph/finalize-workflow-wires.ts +0 -310
- package/src/utils/workflow/graph/finalize-workflows.test.ts +0 -50
- package/src/utils/workflow/graph/finalize-workflows.ts +0 -130
- package/src/utils/workflow/graph/index.ts +0 -28
- package/src/utils/workflow/graph/serialize-workflow-graph.ts +0 -240
- package/src/utils/workflow/graph/workflow-graph.types.ts +0 -281
- package/src/visit.ts +0 -181
- package/tsconfig.json +0 -19
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import type { InspectorLogger, InspectorState } from '../types.js'
|
|
2
|
-
import type { JSONValue } from '@pikku/core/utils'
|
|
3
|
-
import { resolveFunctionMeta } from './resolve-function-meta.js'
|
|
4
|
-
|
|
5
|
-
interface MCPEndpoint {
|
|
6
|
-
uri?: string
|
|
7
|
-
name: string
|
|
8
|
-
description?: string
|
|
9
|
-
parameters?: JSONValue
|
|
10
|
-
returns?: JSONValue
|
|
11
|
-
streaming?: boolean
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const serializeMCPJson = (
|
|
15
|
-
logger: InspectorLogger,
|
|
16
|
-
state: InspectorState
|
|
17
|
-
): string => {
|
|
18
|
-
const { mcpEndpoints, functions, schemas } = state
|
|
19
|
-
const { typesMap } = functions
|
|
20
|
-
const { resourcesMeta, toolsMeta, promptsMeta } = mcpEndpoints
|
|
21
|
-
|
|
22
|
-
const tools: MCPEndpoint[] = []
|
|
23
|
-
const resources: MCPEndpoint[] = []
|
|
24
|
-
const prompts: any[] = []
|
|
25
|
-
|
|
26
|
-
const loadSchema = (typeName: string | undefined): JSONValue | undefined => {
|
|
27
|
-
if (
|
|
28
|
-
!typeName ||
|
|
29
|
-
[
|
|
30
|
-
'boolean',
|
|
31
|
-
'string',
|
|
32
|
-
'number',
|
|
33
|
-
'null',
|
|
34
|
-
'undefined',
|
|
35
|
-
'void',
|
|
36
|
-
'unknown',
|
|
37
|
-
'never',
|
|
38
|
-
].includes(typeName)
|
|
39
|
-
) {
|
|
40
|
-
return undefined
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Try local typesMap first, fall back to direct schema lookup (for addon types)
|
|
44
|
-
let uniqueName: string | undefined
|
|
45
|
-
try {
|
|
46
|
-
uniqueName = typesMap.getUniqueName(typeName)
|
|
47
|
-
} catch {
|
|
48
|
-
// Type not in local typesMap — try direct schema lookup (addon schemas)
|
|
49
|
-
uniqueName = typeName
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const schema = schemas[uniqueName]
|
|
53
|
-
if (!schema) {
|
|
54
|
-
logger.warn(
|
|
55
|
-
`Serialize MCP: Could not find schema for type: ${uniqueName}`
|
|
56
|
-
)
|
|
57
|
-
return undefined
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return schema
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
for (const [name, endpointMeta] of Object.entries(resourcesMeta)) {
|
|
64
|
-
const functionMeta = resolveFunctionMeta(state, endpointMeta.pikkuFuncId)
|
|
65
|
-
if (!functionMeta) {
|
|
66
|
-
logger.warn(
|
|
67
|
-
`Function ${endpointMeta.pikkuFuncId} not found in functionsMeta. Skipping resource ${name}.`
|
|
68
|
-
)
|
|
69
|
-
continue
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const inputType = functionMeta.inputs?.[0]
|
|
73
|
-
const outputType = functionMeta.outputs?.[0]
|
|
74
|
-
|
|
75
|
-
const parameters = loadSchema(inputType)
|
|
76
|
-
const returns = loadSchema(outputType)
|
|
77
|
-
|
|
78
|
-
resources.push({
|
|
79
|
-
uri: name,
|
|
80
|
-
name,
|
|
81
|
-
description: endpointMeta.description,
|
|
82
|
-
...(parameters && { parameters }),
|
|
83
|
-
...(returns && { returns }),
|
|
84
|
-
...(endpointMeta.streaming && { streaming: true }),
|
|
85
|
-
})
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
for (const [name, endpointMeta] of Object.entries(toolsMeta)) {
|
|
89
|
-
const functionMeta = resolveFunctionMeta(state, endpointMeta.pikkuFuncId)
|
|
90
|
-
if (!functionMeta) {
|
|
91
|
-
logger.warn(
|
|
92
|
-
`Function ${endpointMeta.pikkuFuncId} not found in functionsMeta. Skipping tool ${name}.`
|
|
93
|
-
)
|
|
94
|
-
continue
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const inputType = functionMeta.inputs?.[0]
|
|
98
|
-
const outputType = functionMeta.outputs?.[0]
|
|
99
|
-
|
|
100
|
-
const parameters = loadSchema(inputType)
|
|
101
|
-
const returns = loadSchema(outputType)
|
|
102
|
-
|
|
103
|
-
tools.push({
|
|
104
|
-
name,
|
|
105
|
-
description: endpointMeta.description,
|
|
106
|
-
...(parameters && { parameters }),
|
|
107
|
-
...(returns && { returns }),
|
|
108
|
-
...(endpointMeta.streaming && { streaming: true }),
|
|
109
|
-
})
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
for (const [name, endpointMeta] of Object.entries(promptsMeta)) {
|
|
113
|
-
const functionMeta = resolveFunctionMeta(state, endpointMeta.pikkuFuncId)
|
|
114
|
-
if (!functionMeta) {
|
|
115
|
-
logger.warn(
|
|
116
|
-
`Function ${endpointMeta.pikkuFuncId} not found in functionsMeta. Skipping prompt ${name}.`
|
|
117
|
-
)
|
|
118
|
-
continue
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const inputType = functionMeta.inputs?.[0]
|
|
122
|
-
const inputSchema = loadSchema(inputType)
|
|
123
|
-
|
|
124
|
-
const argumentsArray: any[] = []
|
|
125
|
-
if (
|
|
126
|
-
inputSchema &&
|
|
127
|
-
typeof inputSchema === 'object' &&
|
|
128
|
-
!(inputSchema instanceof Array)
|
|
129
|
-
) {
|
|
130
|
-
const properties = inputSchema.properties as Record<string, any>
|
|
131
|
-
const required = (inputSchema.required as string[]) || []
|
|
132
|
-
|
|
133
|
-
for (const [propName, propSchema] of Object.entries(properties)) {
|
|
134
|
-
argumentsArray.push({
|
|
135
|
-
name: propName,
|
|
136
|
-
description: propSchema.description || `${propName} parameter`,
|
|
137
|
-
required: required.includes(propName),
|
|
138
|
-
})
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
prompts.push({
|
|
143
|
-
name,
|
|
144
|
-
description: endpointMeta.description,
|
|
145
|
-
arguments: argumentsArray,
|
|
146
|
-
})
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return JSON.stringify({ tools, resources, prompts }, null, 2)
|
|
150
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { InspectorState, MiddlewareGroupMeta } from '../types.js'
|
|
2
|
-
|
|
3
|
-
const serializeGroupMap = (
|
|
4
|
-
groupMap: Map<string, MiddlewareGroupMeta>
|
|
5
|
-
): Record<string, any> => {
|
|
6
|
-
const result: Record<string, any> = {}
|
|
7
|
-
for (const [key, meta] of groupMap.entries()) {
|
|
8
|
-
result[key] = {
|
|
9
|
-
exportName: meta.exportName,
|
|
10
|
-
sourceFile: meta.sourceFile,
|
|
11
|
-
position: meta.position,
|
|
12
|
-
services: meta.services,
|
|
13
|
-
count: meta.count,
|
|
14
|
-
instanceIds: meta.instanceIds,
|
|
15
|
-
isFactory: meta.isFactory,
|
|
16
|
-
...(meta.additionalRegistrations && {
|
|
17
|
-
additionalRegistrations: meta.additionalRegistrations,
|
|
18
|
-
}),
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return result
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export const serializeMiddlewareGroupsMeta = (state: InspectorState) => {
|
|
25
|
-
return {
|
|
26
|
-
definitions: state.middleware.definitions,
|
|
27
|
-
instances: state.middleware.instances,
|
|
28
|
-
httpGroups: serializeGroupMap(state.http.routeMiddleware),
|
|
29
|
-
tagGroups: serializeGroupMap(state.middleware.tagMiddleware),
|
|
30
|
-
channelMiddleware: {
|
|
31
|
-
definitions: state.channelMiddleware.definitions,
|
|
32
|
-
instances: state.channelMiddleware.instances,
|
|
33
|
-
tagGroups: serializeGroupMap(state.channelMiddleware.tagMiddleware),
|
|
34
|
-
},
|
|
35
|
-
}
|
|
36
|
-
}
|
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
import type { FunctionsMeta } from '@pikku/core/services'
|
|
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
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import type { ErrorCode } from '../error-codes.js'
|
|
2
|
-
import type { InspectorLogger } from '../types.js'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Claims the one call site a single-declaration construct is allowed.
|
|
6
|
-
*
|
|
7
|
-
* `definePersonas` takes a keyed object, so one call already declares as many
|
|
8
|
-
* entries as you like. Letting the call itself repeat buys nothing and costs
|
|
9
|
-
* the thing that matters: a single place to read the declared set from, and a
|
|
10
|
-
* single place to add to it. The same rule `pikkuBetterAuth` has had all along.
|
|
11
|
-
*
|
|
12
|
-
* A second call in the SAME file is refused too — "the file" is not an answer
|
|
13
|
-
* to "where do I add a persona?" when the file holds two calls, so allowing it
|
|
14
|
-
* would keep the ambiguity the rule exists to remove.
|
|
15
|
-
*
|
|
16
|
-
* A generated file is exempt, and never claims the slot either. The rule exists
|
|
17
|
-
* to name the one place a person adds to, and nobody adds to a file the CLI
|
|
18
|
-
* rewrites on the next run — `pikku-personas.gen.ts` would otherwise make every
|
|
19
|
-
* project that scaffolds one unbuildable, and take the app's own declaration
|
|
20
|
-
* down with it.
|
|
21
|
-
*
|
|
22
|
-
* `defineScope` and `defineSystemRole` held this rule too, briefly, and do not
|
|
23
|
-
* until the `admin` tree stops being app-declared. The exemption above is not
|
|
24
|
-
* enough for them: the CLI generates a `defineScope` in `user-admin.gen.ts` and
|
|
25
|
-
* `@pikku/addon-console` spells the same tree out again in a hand-written file,
|
|
26
|
-
* so two non-generated declarations remain and the build still fails. The fix
|
|
27
|
-
* is for `admin` to be a default scope nobody declares, and the rule comes back
|
|
28
|
-
* for scopes and roles once that lands.
|
|
29
|
-
*
|
|
30
|
-
* @param files - The construct's `files` set, which doubles as the claim.
|
|
31
|
-
* @returns true when the caller holds the claim and should carry on.
|
|
32
|
-
*/
|
|
33
|
-
export const claimSingleDeclaration = (
|
|
34
|
-
logger: InspectorLogger,
|
|
35
|
-
files: Set<string>,
|
|
36
|
-
code: ErrorCode,
|
|
37
|
-
helper: string,
|
|
38
|
-
sourceFile: string
|
|
39
|
-
): boolean => {
|
|
40
|
-
if (sourceFile.endsWith('.gen.ts')) {
|
|
41
|
-
return true
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const [first] = files
|
|
45
|
-
if (first === undefined) {
|
|
46
|
-
files.add(sourceFile)
|
|
47
|
-
return true
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
logger.critical(
|
|
51
|
-
code,
|
|
52
|
-
first === sourceFile
|
|
53
|
-
? `Only one ${helper}(...) is allowed per codebase, so there is one place to read the declarations from and one place to add to. Found a second call in ${sourceFile}. Declare them all in one call.`
|
|
54
|
-
: `Only one ${helper}(...) is allowed per codebase, so there is one place to read the declarations from and one place to add to. Found a second in ${sourceFile} (first: ${first}). Declare them all in one call.`
|
|
55
|
-
)
|
|
56
|
-
return false
|
|
57
|
-
}
|
package/src/utils/type-utils.ts
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import * as ts from 'typescript'
|
|
2
|
-
|
|
3
|
-
export const extractTypeKeys = (type: ts.Type): string[] => {
|
|
4
|
-
return type.getProperties().map((symbol) => symbol.getName())
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Resolve an identifier or call expression to the actual function declaration
|
|
9
|
-
*/
|
|
10
|
-
export function resolveFunctionDeclaration(
|
|
11
|
-
node: ts.Node,
|
|
12
|
-
checker: ts.TypeChecker
|
|
13
|
-
): ts.Node | null {
|
|
14
|
-
// If it's already a function-like node, return it
|
|
15
|
-
if (
|
|
16
|
-
ts.isFunctionDeclaration(node) ||
|
|
17
|
-
ts.isFunctionExpression(node) ||
|
|
18
|
-
ts.isArrowFunction(node)
|
|
19
|
-
) {
|
|
20
|
-
return node
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// If it's a call expression (e.g., pikkuWorkflowFunc(...)), get its first argument
|
|
24
|
-
if (ts.isCallExpression(node) && node.arguments.length > 0) {
|
|
25
|
-
const firstArg = node.arguments[0]
|
|
26
|
-
if (ts.isFunctionExpression(firstArg) || ts.isArrowFunction(firstArg)) {
|
|
27
|
-
return firstArg
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// If it's an identifier, resolve to declaration
|
|
32
|
-
if (ts.isIdentifier(node)) {
|
|
33
|
-
const symbol = checker.getSymbolAtLocation(node)
|
|
34
|
-
if (!symbol) return null
|
|
35
|
-
|
|
36
|
-
// Try valueDeclaration first, then fallback to declarations[0]
|
|
37
|
-
const decl = symbol.valueDeclaration || symbol.declarations?.[0]
|
|
38
|
-
if (!decl) return null
|
|
39
|
-
|
|
40
|
-
// If it's an import specifier, resolve the aliased symbol
|
|
41
|
-
if (ts.isImportSpecifier(decl)) {
|
|
42
|
-
const aliasedSymbol = checker.getAliasedSymbol(symbol)
|
|
43
|
-
if (aliasedSymbol) {
|
|
44
|
-
const aliasedDecl =
|
|
45
|
-
aliasedSymbol.valueDeclaration || aliasedSymbol.declarations?.[0]
|
|
46
|
-
if (aliasedDecl) {
|
|
47
|
-
// For variable declarations, get the initializer
|
|
48
|
-
if (
|
|
49
|
-
ts.isVariableDeclaration(aliasedDecl) &&
|
|
50
|
-
aliasedDecl.initializer
|
|
51
|
-
) {
|
|
52
|
-
return resolveFunctionDeclaration(aliasedDecl.initializer, checker)
|
|
53
|
-
}
|
|
54
|
-
// For function declarations, return directly
|
|
55
|
-
if (ts.isFunctionDeclaration(aliasedDecl)) {
|
|
56
|
-
return aliasedDecl
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// If it's a variable declaration, get the initializer
|
|
63
|
-
if (ts.isVariableDeclaration(decl) && decl.initializer) {
|
|
64
|
-
return resolveFunctionDeclaration(decl.initializer, checker)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// If it's a function declaration
|
|
68
|
-
if (ts.isFunctionDeclaration(decl)) {
|
|
69
|
-
return decl
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return null
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function getPropertyAssignmentInitializer(
|
|
77
|
-
obj: ts.ObjectLiteralExpression,
|
|
78
|
-
propName: string,
|
|
79
|
-
followShorthand = false,
|
|
80
|
-
checker?: ts.TypeChecker
|
|
81
|
-
): ts.Expression | undefined {
|
|
82
|
-
for (const prop of obj.properties) {
|
|
83
|
-
// ① foo: () => {}
|
|
84
|
-
if (
|
|
85
|
-
ts.isPropertyAssignment(prop) &&
|
|
86
|
-
ts.isIdentifier(prop.name) &&
|
|
87
|
-
prop.name.text === propName
|
|
88
|
-
) {
|
|
89
|
-
return prop.initializer
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// ② foo() { … }
|
|
93
|
-
if (
|
|
94
|
-
ts.isMethodDeclaration(prop) &&
|
|
95
|
-
ts.isIdentifier(prop.name) &&
|
|
96
|
-
prop.name.text === propName
|
|
97
|
-
) {
|
|
98
|
-
return prop.name // the method node *is* the function
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// ③ { foo } (shorthand)
|
|
102
|
-
if (
|
|
103
|
-
followShorthand &&
|
|
104
|
-
ts.isShorthandPropertyAssignment(prop) &&
|
|
105
|
-
prop.name.text === propName
|
|
106
|
-
) {
|
|
107
|
-
if (!checker) return prop.name // best effort without a checker
|
|
108
|
-
|
|
109
|
-
// Use the proper TypeScript API for shorthand property resolution
|
|
110
|
-
let sym = checker.getShorthandAssignmentValueSymbol(prop)
|
|
111
|
-
if (sym && sym.flags & ts.SymbolFlags.Alias) {
|
|
112
|
-
sym = checker.getAliasedSymbol(sym)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const decl = sym?.declarations?.[0]
|
|
116
|
-
|
|
117
|
-
// const foo = () => {} or const foo = pikkuFunc(...)
|
|
118
|
-
if (
|
|
119
|
-
decl &&
|
|
120
|
-
ts.isVariableDeclaration(decl) &&
|
|
121
|
-
decl.initializer &&
|
|
122
|
-
(ts.isArrowFunction(decl.initializer) ||
|
|
123
|
-
ts.isFunctionExpression(decl.initializer) ||
|
|
124
|
-
ts.isCallExpression(decl.initializer))
|
|
125
|
-
) {
|
|
126
|
-
return decl.initializer
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// function foo() {}
|
|
130
|
-
if (
|
|
131
|
-
decl &&
|
|
132
|
-
(ts.isFunctionDeclaration(decl) ||
|
|
133
|
-
ts.isArrowFunction(decl) ||
|
|
134
|
-
ts.isFunctionExpression(decl))
|
|
135
|
-
) {
|
|
136
|
-
return decl as ts.Expression
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// fallback – just give back the identifier
|
|
140
|
-
return prop.name
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return undefined
|
|
145
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import type * as ts from 'typescript'
|
|
2
|
-
import { getPropertyValue } from './get-property-value.js'
|
|
3
|
-
import { ErrorCode } from '../error-codes.js'
|
|
4
|
-
import type { InspectorLogger, InspectorState } from '../types.js'
|
|
5
|
-
import { resolveFunctionMeta } from './resolve-function-meta.js'
|
|
6
|
-
|
|
7
|
-
export function validateAuthSessionless(
|
|
8
|
-
logger: InspectorLogger,
|
|
9
|
-
obj: ts.ObjectLiteralExpression,
|
|
10
|
-
state: InspectorState,
|
|
11
|
-
funcName: string,
|
|
12
|
-
wireDescription: string,
|
|
13
|
-
inheritedAuth?: boolean
|
|
14
|
-
): boolean {
|
|
15
|
-
const fnMeta = resolveFunctionMeta(state, funcName)
|
|
16
|
-
if (!fnMeta) return true
|
|
17
|
-
|
|
18
|
-
const routeAuth = getPropertyValue(obj, 'auth')
|
|
19
|
-
const resolvedAuth =
|
|
20
|
-
routeAuth === true || routeAuth === false ? routeAuth : inheritedAuth
|
|
21
|
-
if (resolvedAuth === false && fnMeta.sessionless === false) {
|
|
22
|
-
logger.critical(
|
|
23
|
-
ErrorCode.AUTH_DISABLED_REQUIRES_SESSIONLESS,
|
|
24
|
-
`${wireDescription} has auth disabled but function '${funcName}' uses pikkuFunc (requires session). Use pikkuSessionlessFunc instead.`
|
|
25
|
-
)
|
|
26
|
-
return false
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return true
|
|
30
|
-
}
|