@pikku/inspector 0.12.74 → 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 +347 -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 +23 -13
- 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 -2207
- package/src/utils/filter-inspector-state.ts +0 -1302
- 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,612 +0,0 @@
|
|
|
1
|
-
import * as ts from 'typescript'
|
|
2
|
-
import { createHash } from 'crypto'
|
|
3
|
-
import { relative } from 'path'
|
|
4
|
-
import { formatVersionedId } from '@pikku/core/utils'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Deterministic placeholder id for an anonymous/unnamed pikku function or
|
|
8
|
-
* permission. Derived from the call expression's source location (relative path
|
|
9
|
-
* + start position) so `pikku all` produces byte-identical output across runs —
|
|
10
|
-
* a `randomUUID()` here made generated meta non-reproducible. Still `__temp_`
|
|
11
|
-
* prefixed so downstream resolution (which keys off that prefix) is unchanged.
|
|
12
|
-
*/
|
|
13
|
-
function tempFuncId(callExpr: ts.Node, rootDir: string): string {
|
|
14
|
-
const sourceFile = callExpr.getSourceFile()
|
|
15
|
-
const relPath = relative(rootDir, sourceFile.fileName)
|
|
16
|
-
const hash = createHash('sha1')
|
|
17
|
-
.update(`${relPath}:${callExpr.getStart()}`)
|
|
18
|
-
.digest('hex')
|
|
19
|
-
.slice(0, 16)
|
|
20
|
-
return `__temp_${hash}`
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export type ExtractedFunctionName = {
|
|
24
|
-
pikkuFuncId: string
|
|
25
|
-
name: string
|
|
26
|
-
explicitName: string | null
|
|
27
|
-
exportedName: string | null
|
|
28
|
-
propertyName: string | null
|
|
29
|
-
isHelper: boolean
|
|
30
|
-
version: number | null
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function makeContextBasedId(
|
|
34
|
-
wiringType: string,
|
|
35
|
-
...segments: string[]
|
|
36
|
-
): string {
|
|
37
|
-
return [wiringType, ...segments].join(':')
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function funcIdToTypeName(id: string): string {
|
|
41
|
-
return id
|
|
42
|
-
.split(/[^a-zA-Z0-9]/)
|
|
43
|
-
.filter(Boolean)
|
|
44
|
-
.map((s) => s.charAt(0).toUpperCase() + s.slice(1))
|
|
45
|
-
.join('')
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* The step wrappers, whichever kind of subject acts in them. A scenario calls a
|
|
50
|
-
* platform or addon step by name exactly as it calls a persona one.
|
|
51
|
-
*/
|
|
52
|
-
const SCENARIO_STEP_WRAPPERS = new Set([
|
|
53
|
-
'pikkuScenarioStep',
|
|
54
|
-
'pikkuPlatformScenarioStep',
|
|
55
|
-
'pikkuAddonScenarioStep',
|
|
56
|
-
])
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* A scenario step is the one wrapper whose `name` is its identity: scenarios
|
|
60
|
-
* reference a step by that string, so it must become the pikkuFuncId (and hence
|
|
61
|
-
* the generated step map's key), not just a cosmetic label the way
|
|
62
|
-
* `pikkuMiddleware`/`pikkuAgent` use it.
|
|
63
|
-
*/
|
|
64
|
-
function extractScenarioStepName(
|
|
65
|
-
callExpr: ts.Node,
|
|
66
|
-
result: ExtractedFunctionName
|
|
67
|
-
): void {
|
|
68
|
-
if (
|
|
69
|
-
!ts.isCallExpression(callExpr) ||
|
|
70
|
-
!ts.isIdentifier(callExpr.expression) ||
|
|
71
|
-
!SCENARIO_STEP_WRAPPERS.has(callExpr.expression.text)
|
|
72
|
-
) {
|
|
73
|
-
return
|
|
74
|
-
}
|
|
75
|
-
const firstArg = callExpr.arguments[0]
|
|
76
|
-
if (!firstArg || !ts.isObjectLiteralExpression(firstArg)) {
|
|
77
|
-
return
|
|
78
|
-
}
|
|
79
|
-
for (const prop of firstArg.properties) {
|
|
80
|
-
if (
|
|
81
|
-
ts.isPropertyAssignment(prop) &&
|
|
82
|
-
ts.isIdentifier(prop.name) &&
|
|
83
|
-
prop.name.text === 'name' &&
|
|
84
|
-
ts.isStringLiteral(prop.initializer)
|
|
85
|
-
) {
|
|
86
|
-
result.explicitName = prop.initializer.text
|
|
87
|
-
return
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export function extractFunctionName(
|
|
93
|
-
callExpr: ts.Node,
|
|
94
|
-
checker: ts.TypeChecker,
|
|
95
|
-
rootDir: string
|
|
96
|
-
): ExtractedFunctionName {
|
|
97
|
-
const parent: any = callExpr.parent
|
|
98
|
-
|
|
99
|
-
// Initialize the result
|
|
100
|
-
const result: ExtractedFunctionName = {
|
|
101
|
-
pikkuFuncId: '',
|
|
102
|
-
name: '',
|
|
103
|
-
exportedName: null,
|
|
104
|
-
propertyName: null,
|
|
105
|
-
explicitName: null,
|
|
106
|
-
isHelper: false,
|
|
107
|
-
version: null,
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
extractScenarioStepName(callExpr, result)
|
|
111
|
-
|
|
112
|
-
const workflowHelpers = new Set([
|
|
113
|
-
'workflow',
|
|
114
|
-
'workflowStart',
|
|
115
|
-
'workflowStatus',
|
|
116
|
-
'graphStart',
|
|
117
|
-
])
|
|
118
|
-
|
|
119
|
-
if (
|
|
120
|
-
ts.isCallExpression(callExpr) &&
|
|
121
|
-
ts.isIdentifier(callExpr.expression) &&
|
|
122
|
-
workflowHelpers.has(callExpr.expression.text)
|
|
123
|
-
) {
|
|
124
|
-
const helperName = callExpr.expression.text
|
|
125
|
-
const [firstArg, secondArg] = callExpr.arguments
|
|
126
|
-
if (firstArg && ts.isStringLiteral(firstArg)) {
|
|
127
|
-
const workflowName = firstArg.text
|
|
128
|
-
let funcName: string
|
|
129
|
-
if (
|
|
130
|
-
helperName === 'graphStart' &&
|
|
131
|
-
secondArg &&
|
|
132
|
-
ts.isStringLiteral(secondArg)
|
|
133
|
-
) {
|
|
134
|
-
funcName = `${helperName}:${workflowName}:${secondArg.text}`
|
|
135
|
-
} else {
|
|
136
|
-
funcName = `${helperName}:${workflowName}`
|
|
137
|
-
}
|
|
138
|
-
result.pikkuFuncId = funcName
|
|
139
|
-
result.name = funcName
|
|
140
|
-
result.explicitName = funcName
|
|
141
|
-
result.isHelper = true
|
|
142
|
-
return result
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// Special case for wireHTTP: if this is an identifier within an object literal,
|
|
147
|
-
// it might be coming from the HTTP route handling flow
|
|
148
|
-
if (
|
|
149
|
-
ts.isIdentifier(callExpr) &&
|
|
150
|
-
callExpr.parent &&
|
|
151
|
-
ts.isPropertyAssignment(callExpr.parent)
|
|
152
|
-
) {
|
|
153
|
-
// Try to handle the special case for HTTP route functions
|
|
154
|
-
const sym = checker.getSymbolAtLocation(callExpr)
|
|
155
|
-
if (sym) {
|
|
156
|
-
let resolvedSym = sym
|
|
157
|
-
if (resolvedSym.flags & ts.SymbolFlags.Alias) {
|
|
158
|
-
resolvedSym = checker.getAliasedSymbol(resolvedSym) ?? resolvedSym
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const decls = resolvedSym.declarations ?? []
|
|
162
|
-
if (decls.length > 0) {
|
|
163
|
-
const decl = decls[0]!
|
|
164
|
-
// Check if the declaration is a variable that uses a pikkuFun
|
|
165
|
-
if (ts.isVariableDeclaration(decl) && decl.initializer) {
|
|
166
|
-
if (
|
|
167
|
-
ts.isCallExpression(decl.initializer) &&
|
|
168
|
-
ts.isIdentifier(decl.initializer.expression) &&
|
|
169
|
-
decl.initializer.expression.text.startsWith('pikku')
|
|
170
|
-
) {
|
|
171
|
-
const args = decl.initializer.arguments
|
|
172
|
-
const firstArg = args[0]
|
|
173
|
-
if (
|
|
174
|
-
firstArg &&
|
|
175
|
-
(ts.isArrowFunction(firstArg) ||
|
|
176
|
-
ts.isFunctionExpression(firstArg))
|
|
177
|
-
) {
|
|
178
|
-
// Continue with name extraction
|
|
179
|
-
if (ts.isIdentifier(parent.name)) {
|
|
180
|
-
result.propertyName = parent.name.text
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (
|
|
184
|
-
ts.isVariableDeclaration(decl) &&
|
|
185
|
-
isNamedExport(decl, checker) &&
|
|
186
|
-
ts.isIdentifier(decl.name)
|
|
187
|
-
) {
|
|
188
|
-
result.exportedName = decl.name.text
|
|
189
|
-
result.pikkuFuncId = decl.name.text
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (!result.pikkuFuncId) {
|
|
193
|
-
result.pikkuFuncId = tempFuncId(callExpr, rootDir)
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
populateNameByPriority(result)
|
|
197
|
-
return result
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (ts.isCallExpression(callExpr)) {
|
|
206
|
-
const { expression, arguments: args } = callExpr
|
|
207
|
-
|
|
208
|
-
// Check if this is a pikku function call (pikkuFunc, pikkuSessionlessFunc, etc)
|
|
209
|
-
if (ts.isIdentifier(expression) && expression.text.startsWith('pikku')) {
|
|
210
|
-
// Check for object with 'name' property in first argument
|
|
211
|
-
const firstArg = args[0]
|
|
212
|
-
if (firstArg && ts.isObjectLiteralExpression(firstArg)) {
|
|
213
|
-
extractOverrideAndVersion(firstArg, result)
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// Special handling for pikkuSessionlessFunc pattern - use the arrow function directly
|
|
217
|
-
if (expression.text.startsWith('pikku')) {
|
|
218
|
-
if (args.length > 0) {
|
|
219
|
-
const firstArg = args[0]!
|
|
220
|
-
if (
|
|
221
|
-
ts.isArrowFunction(firstArg) ||
|
|
222
|
-
ts.isFunctionExpression(firstArg)
|
|
223
|
-
) {
|
|
224
|
-
// mainFunc = firstArg // Use the arrow function directly instead of the call expression
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// Handle object initializer with a func property (for both patterns)
|
|
231
|
-
if (args.length > 0) {
|
|
232
|
-
const firstArg = args[0]
|
|
233
|
-
if (firstArg && ts.isObjectLiteralExpression(firstArg)) {
|
|
234
|
-
// Look for func property in the object
|
|
235
|
-
for (const prop of firstArg.properties) {
|
|
236
|
-
if (
|
|
237
|
-
ts.isPropertyAssignment(prop) &&
|
|
238
|
-
ts.isIdentifier(prop.name) &&
|
|
239
|
-
prop.name.text === 'func'
|
|
240
|
-
) {
|
|
241
|
-
if (ts.isIdentifier(prop.initializer)) {
|
|
242
|
-
// func: someFunction - resolve the function
|
|
243
|
-
const funcSym = checker.getSymbolAtLocation(prop.initializer)
|
|
244
|
-
if (funcSym) {
|
|
245
|
-
let resolvedFuncSym = funcSym
|
|
246
|
-
if (resolvedFuncSym.flags & ts.SymbolFlags.Alias) {
|
|
247
|
-
resolvedFuncSym =
|
|
248
|
-
checker.getAliasedSymbol(resolvedFuncSym) ?? resolvedFuncSym
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const funcDecls = resolvedFuncSym.declarations ?? []
|
|
252
|
-
if (funcDecls.length > 0) {
|
|
253
|
-
const funcDecl = funcDecls[0]!
|
|
254
|
-
// Check if it's a pikkuSessionlessFunc
|
|
255
|
-
if (
|
|
256
|
-
ts.isVariableDeclaration(funcDecl) &&
|
|
257
|
-
funcDecl.initializer
|
|
258
|
-
) {
|
|
259
|
-
if (
|
|
260
|
-
ts.isCallExpression(funcDecl.initializer) &&
|
|
261
|
-
ts.isIdentifier(funcDecl.initializer.expression) &&
|
|
262
|
-
funcDecl.initializer.expression.text.startsWith('pikku')
|
|
263
|
-
) {
|
|
264
|
-
const funcArgs = funcDecl.initializer.arguments
|
|
265
|
-
const firstArg = funcArgs[0]
|
|
266
|
-
if (
|
|
267
|
-
firstArg &&
|
|
268
|
-
(ts.isArrowFunction(firstArg) ||
|
|
269
|
-
ts.isFunctionExpression(firstArg))
|
|
270
|
-
) {
|
|
271
|
-
// mainFunc = firstArg
|
|
272
|
-
|
|
273
|
-
// Check if the variable is exported
|
|
274
|
-
if (
|
|
275
|
-
isNamedExport(funcDecl, checker) &&
|
|
276
|
-
ts.isIdentifier(funcDecl.name)
|
|
277
|
-
) {
|
|
278
|
-
result.exportedName = funcDecl.name.text
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
break
|
|
282
|
-
}
|
|
283
|
-
} else if (
|
|
284
|
-
ts.isFunctionExpression(funcDecl.initializer) ||
|
|
285
|
-
ts.isArrowFunction(funcDecl.initializer)
|
|
286
|
-
) {
|
|
287
|
-
if (
|
|
288
|
-
isNamedExport(funcDecl, checker) &&
|
|
289
|
-
ts.isIdentifier(funcDecl.name)
|
|
290
|
-
) {
|
|
291
|
-
result.exportedName = funcDecl.name.text
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
break
|
|
295
|
-
}
|
|
296
|
-
} else if (ts.isFunctionDeclaration(funcDecl)) {
|
|
297
|
-
// mainFunc = funcDecl
|
|
298
|
-
|
|
299
|
-
// Check if the function is exported
|
|
300
|
-
if (
|
|
301
|
-
funcDecl.modifiers?.some(
|
|
302
|
-
(m) => m.kind === ts.SyntaxKind.ExportKeyword
|
|
303
|
-
) &&
|
|
304
|
-
funcDecl.name &&
|
|
305
|
-
ts.isIdentifier(funcDecl.name)
|
|
306
|
-
) {
|
|
307
|
-
result.exportedName = funcDecl.name.text
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
break
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
} else {
|
|
314
|
-
// If we can't resolve the symbol, use the identifier itself
|
|
315
|
-
// mainFunc = prop.initializer
|
|
316
|
-
}
|
|
317
|
-
break
|
|
318
|
-
} else if (
|
|
319
|
-
ts.isFunctionExpression(prop.initializer) ||
|
|
320
|
-
ts.isArrowFunction(prop.initializer)
|
|
321
|
-
) {
|
|
322
|
-
// func: () => {} or func: function() {} - use directly
|
|
323
|
-
// mainFunc = prop.initializer
|
|
324
|
-
break
|
|
325
|
-
}
|
|
326
|
-
} else if (
|
|
327
|
-
ts.isShorthandPropertyAssignment(prop) &&
|
|
328
|
-
ts.isIdentifier(prop.name) &&
|
|
329
|
-
prop.name.text === 'func'
|
|
330
|
-
) {
|
|
331
|
-
// Handle func shorthand property
|
|
332
|
-
const shorthandSym = checker.getShorthandAssignmentValueSymbol(prop)
|
|
333
|
-
if (
|
|
334
|
-
shorthandSym &&
|
|
335
|
-
shorthandSym.declarations &&
|
|
336
|
-
shorthandSym.declarations.length > 0
|
|
337
|
-
) {
|
|
338
|
-
const shorthandDecl = shorthandSym.declarations[0]
|
|
339
|
-
if (!shorthandDecl) {
|
|
340
|
-
throw new Error('No shorthand declaration found')
|
|
341
|
-
}
|
|
342
|
-
if (
|
|
343
|
-
ts.isVariableDeclaration(shorthandDecl) &&
|
|
344
|
-
shorthandDecl.initializer
|
|
345
|
-
) {
|
|
346
|
-
if (
|
|
347
|
-
ts.isCallExpression(shorthandDecl.initializer) &&
|
|
348
|
-
ts.isIdentifier(shorthandDecl.initializer.expression) &&
|
|
349
|
-
shorthandDecl.initializer.expression.text.startsWith('pikku')
|
|
350
|
-
) {
|
|
351
|
-
const args = shorthandDecl.initializer.arguments
|
|
352
|
-
const firstArg = args[0]
|
|
353
|
-
if (
|
|
354
|
-
firstArg &&
|
|
355
|
-
(ts.isArrowFunction(firstArg) ||
|
|
356
|
-
ts.isFunctionExpression(firstArg))
|
|
357
|
-
) {
|
|
358
|
-
// mainFunc = firstArg
|
|
359
|
-
|
|
360
|
-
// Check if the variable is exported
|
|
361
|
-
if (
|
|
362
|
-
isNamedExport(shorthandDecl, checker) &&
|
|
363
|
-
ts.isIdentifier(shorthandDecl.name)
|
|
364
|
-
) {
|
|
365
|
-
result.exportedName = shorthandDecl.name.text
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
break
|
|
369
|
-
}
|
|
370
|
-
} else if (
|
|
371
|
-
ts.isFunctionExpression(shorthandDecl.initializer) ||
|
|
372
|
-
ts.isArrowFunction(shorthandDecl.initializer)
|
|
373
|
-
) {
|
|
374
|
-
if (
|
|
375
|
-
isNamedExport(shorthandDecl, checker) &&
|
|
376
|
-
ts.isIdentifier(shorthandDecl.name)
|
|
377
|
-
) {
|
|
378
|
-
result.exportedName = shorthandDecl.name.text
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
break
|
|
382
|
-
}
|
|
383
|
-
} else if (ts.isFunctionDeclaration(shorthandDecl)) {
|
|
384
|
-
// mainFunc = shorthandDecl
|
|
385
|
-
|
|
386
|
-
// Check if the function is exported
|
|
387
|
-
if (
|
|
388
|
-
shorthandDecl.modifiers?.some(
|
|
389
|
-
(m) => m.kind === ts.SyntaxKind.ExportKeyword
|
|
390
|
-
) &&
|
|
391
|
-
shorthandDecl.name &&
|
|
392
|
-
ts.isIdentifier(shorthandDecl.name)
|
|
393
|
-
) {
|
|
394
|
-
result.exportedName = shorthandDecl.name.text
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
break
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
// Handle direct identifier case
|
|
406
|
-
else if (ts.isIdentifier(callExpr)) {
|
|
407
|
-
const sym = checker.getSymbolAtLocation(callExpr)
|
|
408
|
-
if (sym) {
|
|
409
|
-
let resolvedSym = sym
|
|
410
|
-
if (resolvedSym.flags & ts.SymbolFlags.Alias) {
|
|
411
|
-
resolvedSym = checker.getAliasedSymbol(resolvedSym) ?? resolvedSym
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
const decls = resolvedSym.declarations ?? []
|
|
415
|
-
if (decls.length > 0) {
|
|
416
|
-
const decl = decls[0]
|
|
417
|
-
if (!decl) {
|
|
418
|
-
throw new Error('No declaration found')
|
|
419
|
-
}
|
|
420
|
-
if (ts.isVariableDeclaration(decl) && decl.initializer) {
|
|
421
|
-
if (
|
|
422
|
-
ts.isCallExpression(decl.initializer) &&
|
|
423
|
-
ts.isIdentifier(decl.initializer.expression) &&
|
|
424
|
-
decl.initializer.expression.text.startsWith('pikku')
|
|
425
|
-
) {
|
|
426
|
-
const firstArg = decl.initializer.arguments[0]
|
|
427
|
-
if (firstArg && ts.isObjectLiteralExpression(firstArg)) {
|
|
428
|
-
extractOverrideAndVersion(firstArg, result)
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
if (decl.initializer.expression.text.startsWith('pikku')) {
|
|
432
|
-
if (
|
|
433
|
-
firstArg &&
|
|
434
|
-
(ts.isArrowFunction(firstArg) ||
|
|
435
|
-
ts.isFunctionExpression(firstArg))
|
|
436
|
-
) {
|
|
437
|
-
// mainFunc = firstArg
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
// Check if the variable is exported
|
|
442
|
-
if (isNamedExport(decl, checker) && ts.isIdentifier(decl.name)) {
|
|
443
|
-
result.exportedName = decl.name.text
|
|
444
|
-
}
|
|
445
|
-
} else if (
|
|
446
|
-
ts.isFunctionExpression(decl.initializer) ||
|
|
447
|
-
ts.isArrowFunction(decl.initializer)
|
|
448
|
-
) {
|
|
449
|
-
// mainFunc = decl.initializer
|
|
450
|
-
|
|
451
|
-
// Check if the variable is exported
|
|
452
|
-
if (isNamedExport(decl, checker) && ts.isIdentifier(decl.name)) {
|
|
453
|
-
result.exportedName = decl.name.text
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
} else if (ts.isFunctionDeclaration(decl)) {
|
|
457
|
-
// mainFunc = decl
|
|
458
|
-
|
|
459
|
-
// Check if the function is exported
|
|
460
|
-
if (
|
|
461
|
-
decl.modifiers?.some(
|
|
462
|
-
(m) => m.kind === ts.SyntaxKind.ExportKeyword
|
|
463
|
-
) &&
|
|
464
|
-
decl.name &&
|
|
465
|
-
ts.isIdentifier(decl.name)
|
|
466
|
-
) {
|
|
467
|
-
result.exportedName = decl.name.text
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
// 1) const foo = pikkuFunc(...)
|
|
475
|
-
if (ts.isVariableDeclaration(parent) && ts.isIdentifier(parent.name)) {
|
|
476
|
-
if (isNamedExport(parent, checker)) {
|
|
477
|
-
result.exportedName = parent.name.text
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
// 2) { foo: pikkuFunc(...) }
|
|
481
|
-
else if (ts.isPropertyAssignment(parent) && ts.isIdentifier(parent.name)) {
|
|
482
|
-
result.propertyName = parent.name.text
|
|
483
|
-
}
|
|
484
|
-
// 2b) Handle shorthand property { foo } - which is equivalent to { foo: foo }
|
|
485
|
-
else if (
|
|
486
|
-
ts.isShorthandPropertyAssignment(parent) &&
|
|
487
|
-
ts.isIdentifier(parent.name)
|
|
488
|
-
) {
|
|
489
|
-
result.propertyName = parent.name.text
|
|
490
|
-
}
|
|
491
|
-
// 3) Handle any remaining cases for pikkuFunc({ override: '…', func: … })
|
|
492
|
-
else if (ts.isCallExpression(callExpr)) {
|
|
493
|
-
const firstArg = callExpr.arguments[0]
|
|
494
|
-
if (firstArg && ts.isObjectLiteralExpression(firstArg)) {
|
|
495
|
-
extractOverrideAndVersion(firstArg, result)
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
// Apply name priority logic
|
|
500
|
-
populateNameByPriority(result)
|
|
501
|
-
|
|
502
|
-
if (result.explicitName) {
|
|
503
|
-
result.pikkuFuncId = result.explicitName
|
|
504
|
-
} else if (result.exportedName) {
|
|
505
|
-
result.pikkuFuncId = result.exportedName
|
|
506
|
-
} else {
|
|
507
|
-
result.pikkuFuncId = tempFuncId(callExpr, rootDir)
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
if (result.version !== null) {
|
|
511
|
-
// Strip trailing VN suffix if it matches the version (e.g. createCardV1 + version:1 → createCard@v1)
|
|
512
|
-
const vSuffix = `V${result.version}`
|
|
513
|
-
if (
|
|
514
|
-
result.pikkuFuncId.endsWith(vSuffix) &&
|
|
515
|
-
result.pikkuFuncId.length > vSuffix.length
|
|
516
|
-
) {
|
|
517
|
-
result.pikkuFuncId = result.pikkuFuncId.slice(0, -vSuffix.length)
|
|
518
|
-
}
|
|
519
|
-
result.pikkuFuncId = formatVersionedId(result.pikkuFuncId, result.version)
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
return result
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
/**
|
|
526
|
-
* Helper function to populate the 'name' field based on priority
|
|
527
|
-
*/
|
|
528
|
-
export function populateNameByPriority(result: ExtractedFunctionName): void {
|
|
529
|
-
// Priority 1: If we have an explict name, use that
|
|
530
|
-
if (result.explicitName) {
|
|
531
|
-
result.name = result.explicitName
|
|
532
|
-
}
|
|
533
|
-
// Priority 2: If we have an exported name, use that
|
|
534
|
-
else if (result.exportedName) {
|
|
535
|
-
result.name = result.exportedName
|
|
536
|
-
}
|
|
537
|
-
// Fallback: Use the deterministic name, but we could shorten it in the future
|
|
538
|
-
else {
|
|
539
|
-
// For now, just use the full pikkuFuncId
|
|
540
|
-
result.name = result.pikkuFuncId
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
/**
|
|
545
|
-
* Helper function to check if a variable declaration is a named export
|
|
546
|
-
*/
|
|
547
|
-
export function isNamedExport(
|
|
548
|
-
declaration: ts.VariableDeclaration,
|
|
549
|
-
checker?: ts.TypeChecker
|
|
550
|
-
): boolean {
|
|
551
|
-
let parent: any = declaration.parent
|
|
552
|
-
if (!parent) return false
|
|
553
|
-
|
|
554
|
-
if (ts.isVariableDeclarationList(parent)) {
|
|
555
|
-
parent = parent.parent
|
|
556
|
-
if (!parent) return false
|
|
557
|
-
|
|
558
|
-
if (ts.isVariableStatement(parent)) {
|
|
559
|
-
if (
|
|
560
|
-
parent.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)
|
|
561
|
-
) {
|
|
562
|
-
return true
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
if (checker && ts.isIdentifier(declaration.name)) {
|
|
568
|
-
const sourceFile = declaration.getSourceFile()
|
|
569
|
-
const sourceFileSymbol = checker.getSymbolAtLocation(sourceFile)
|
|
570
|
-
if (sourceFileSymbol) {
|
|
571
|
-
const exports = checker.getExportsOfModule(sourceFileSymbol)
|
|
572
|
-
const declSymbol = checker.getSymbolAtLocation(declaration.name)
|
|
573
|
-
if (declSymbol) {
|
|
574
|
-
return exports.some((exp) => {
|
|
575
|
-
let resolved = exp
|
|
576
|
-
if (resolved.flags & ts.SymbolFlags.Alias) {
|
|
577
|
-
resolved = checker.getAliasedSymbol(resolved) ?? resolved
|
|
578
|
-
}
|
|
579
|
-
return resolved === declSymbol
|
|
580
|
-
})
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
return false
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
function extractOverrideAndVersion(
|
|
589
|
-
objLiteral: ts.ObjectLiteralExpression,
|
|
590
|
-
result: ExtractedFunctionName
|
|
591
|
-
): void {
|
|
592
|
-
for (const prop of objLiteral.properties) {
|
|
593
|
-
if (ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name)) {
|
|
594
|
-
if (
|
|
595
|
-
prop.name.text === 'override' &&
|
|
596
|
-
ts.isStringLiteral(prop.initializer) &&
|
|
597
|
-
!result.explicitName
|
|
598
|
-
) {
|
|
599
|
-
result.explicitName = prop.initializer.text
|
|
600
|
-
} else if (
|
|
601
|
-
prop.name.text === 'version' &&
|
|
602
|
-
ts.isNumericLiteral(prop.initializer) &&
|
|
603
|
-
result.version === null
|
|
604
|
-
) {
|
|
605
|
-
const parsed = Number(prop.initializer.text)
|
|
606
|
-
if (Number.isInteger(parsed) && parsed >= 1) {
|
|
607
|
-
result.version = parsed
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import * as ts from 'typescript'
|
|
2
|
-
import {
|
|
3
|
-
getPropertyAssignmentInitializer,
|
|
4
|
-
resolveFunctionDeclaration,
|
|
5
|
-
} from './type-utils.js'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Where a config object's implementation can live, in the order it is looked for.
|
|
9
|
-
*
|
|
10
|
-
* `func` is the ordinary case. A `pikkuScenarioStep` instead declares one
|
|
11
|
-
* implementation per surface, and every binding shares the step's input and
|
|
12
|
-
* output — that is what makes them interchangeable — so any one of them types
|
|
13
|
-
* the step. `default` is preferred because it is the binding every step is
|
|
14
|
-
* expected to have.
|
|
15
|
-
*/
|
|
16
|
-
const IMPLEMENTATION_KEYS = ['func', 'default', 'browser', 'cli'] as const
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Extracts the actual function node from a pikkuFunc/pikkuWorkflowFunc call
|
|
20
|
-
* Handles both direct function form and config object form { func: ... }
|
|
21
|
-
*/
|
|
22
|
-
export function extractFunctionNode(
|
|
23
|
-
firstArg: ts.Expression,
|
|
24
|
-
checker: ts.TypeChecker
|
|
25
|
-
): {
|
|
26
|
-
funcNode: ts.Node
|
|
27
|
-
resolvedFunc: ts.Node | null
|
|
28
|
-
isDirectFunction: boolean
|
|
29
|
-
} {
|
|
30
|
-
let funcNode: ts.Node = firstArg
|
|
31
|
-
let isDirectFunction = true
|
|
32
|
-
|
|
33
|
-
// Check if first argument is a config object with 'func' property
|
|
34
|
-
if (ts.isObjectLiteralExpression(firstArg)) {
|
|
35
|
-
isDirectFunction = false
|
|
36
|
-
let funcInitializer: ts.Expression | undefined
|
|
37
|
-
for (const key of IMPLEMENTATION_KEYS) {
|
|
38
|
-
funcInitializer =
|
|
39
|
-
getPropertyAssignmentInitializer(firstArg, key, true, checker) ??
|
|
40
|
-
undefined
|
|
41
|
-
if (funcInitializer) break
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (funcInitializer) {
|
|
45
|
-
funcNode = funcInitializer
|
|
46
|
-
} else {
|
|
47
|
-
// Return the original node if no func property found
|
|
48
|
-
// Caller should handle validation
|
|
49
|
-
funcNode = firstArg
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Resolve identifier to get the actual function node
|
|
54
|
-
if (ts.isIdentifier(funcNode)) {
|
|
55
|
-
const symbol = checker.getSymbolAtLocation(funcNode)
|
|
56
|
-
const decl = symbol?.valueDeclaration || symbol?.declarations?.[0]
|
|
57
|
-
if (decl && ts.isVariableDeclaration(decl) && decl.initializer) {
|
|
58
|
-
funcNode = decl.initializer
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Resolve function declaration for deeper analysis
|
|
63
|
-
const resolvedFunc = resolveFunctionDeclaration(funcNode, checker)
|
|
64
|
-
|
|
65
|
-
return {
|
|
66
|
-
funcNode,
|
|
67
|
-
resolvedFunc,
|
|
68
|
-
isDirectFunction,
|
|
69
|
-
}
|
|
70
|
-
}
|