@pikku/inspector 0.11.2 → 0.12.1

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 (211) hide show
  1. package/CHANGELOG.md +36 -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 +81 -61
  6. package/dist/add/add-cli.d.ts +1 -1
  7. package/dist/add/add-cli.js +42 -19
  8. package/dist/add/add-file-extends-core-type.d.ts +1 -1
  9. package/dist/add/add-file-with-config.d.ts +1 -1
  10. package/dist/add/add-file-with-factory.d.ts +1 -1
  11. package/dist/add/add-file-with-factory.js +2 -0
  12. package/dist/add/add-functions.d.ts +1 -1
  13. package/dist/add/add-functions.js +256 -82
  14. package/dist/add/add-http-route.d.ts +20 -10
  15. package/dist/add/add-http-route.js +156 -66
  16. package/dist/add/add-http-routes.d.ts +5 -0
  17. package/dist/add/add-http-routes.js +160 -0
  18. package/dist/add/add-keyed-wiring.d.ts +12 -0
  19. package/dist/add/add-keyed-wiring.js +97 -0
  20. package/dist/add/add-mcp-prompt.d.ts +1 -1
  21. package/dist/add/add-mcp-prompt.js +14 -9
  22. package/dist/add/add-mcp-resource.d.ts +1 -1
  23. package/dist/add/add-mcp-resource.js +14 -9
  24. package/dist/add/add-middleware.d.ts +1 -4
  25. package/dist/add/add-middleware.js +364 -79
  26. package/dist/add/add-permission.d.ts +1 -1
  27. package/dist/add/add-permission.js +152 -40
  28. package/dist/add/add-queue-worker.d.ts +1 -1
  29. package/dist/add/add-queue-worker.js +18 -12
  30. package/dist/add/add-rpc-invocations.d.ts +3 -3
  31. package/dist/add/add-rpc-invocations.js +24 -10
  32. package/dist/add/add-schedule.d.ts +1 -1
  33. package/dist/add/add-schedule.js +11 -5
  34. package/dist/add/add-secret.d.ts +3 -0
  35. package/dist/add/add-secret.js +82 -0
  36. package/dist/add/add-trigger.d.ts +2 -0
  37. package/dist/add/add-trigger.js +87 -0
  38. package/dist/add/add-variable.d.ts +1 -0
  39. package/dist/add/add-variable.js +8 -0
  40. package/dist/add/add-wire-addon.d.ts +7 -0
  41. package/dist/add/add-wire-addon.js +70 -0
  42. package/dist/add/add-workflow-graph.d.ts +3 -2
  43. package/dist/add/add-workflow-graph.js +143 -406
  44. package/dist/add/add-workflow.d.ts +1 -1
  45. package/dist/add/add-workflow.js +6 -4
  46. package/dist/error-codes.d.ts +15 -1
  47. package/dist/error-codes.js +20 -1
  48. package/dist/index.d.ts +9 -8
  49. package/dist/index.js +5 -4
  50. package/dist/inspector.d.ts +2 -2
  51. package/dist/inspector.js +95 -15
  52. package/dist/schema-generator.d.ts +1 -0
  53. package/dist/schema-generator.js +1 -0
  54. package/dist/types-map.js +10 -1
  55. package/dist/types.d.ts +180 -50
  56. package/dist/utils/compute-required-schemas.d.ts +4 -0
  57. package/dist/utils/compute-required-schemas.js +40 -0
  58. package/dist/utils/contract-hashes.d.ts +52 -0
  59. package/dist/utils/contract-hashes.js +269 -0
  60. package/dist/utils/custom-types-generator.d.ts +9 -0
  61. package/dist/utils/custom-types-generator.js +71 -0
  62. package/dist/utils/detect-schema-vendor.d.ts +22 -0
  63. package/dist/utils/detect-schema-vendor.js +76 -0
  64. package/dist/utils/does-type-extend-core-type.d.ts +1 -1
  65. package/dist/utils/ensure-function-metadata.d.ts +6 -3
  66. package/dist/utils/ensure-function-metadata.js +220 -6
  67. package/dist/utils/extract-function-name.d.ts +5 -16
  68. package/dist/utils/extract-function-name.js +86 -291
  69. package/dist/utils/extract-services.d.ts +2 -1
  70. package/dist/utils/extract-services.js +25 -1
  71. package/dist/utils/filter-inspector-state.d.ts +1 -1
  72. package/dist/utils/filter-inspector-state.js +107 -23
  73. package/dist/utils/filter-utils.d.ts +2 -2
  74. package/dist/utils/get-files-and-methods.d.ts +1 -1
  75. package/dist/utils/get-property-value.d.ts +6 -1
  76. package/dist/utils/get-property-value.js +28 -3
  77. package/dist/utils/hash.d.ts +2 -0
  78. package/dist/utils/hash.js +23 -0
  79. package/dist/utils/middleware.d.ts +9 -32
  80. package/dist/utils/middleware.js +80 -66
  81. package/dist/utils/permissions.d.ts +4 -4
  82. package/dist/utils/permissions.js +10 -10
  83. package/dist/utils/post-process.d.ts +11 -11
  84. package/dist/utils/post-process.js +247 -24
  85. package/dist/utils/resolve-addon-package.d.ts +16 -0
  86. package/dist/utils/resolve-addon-package.js +34 -0
  87. package/dist/utils/resolve-function-types.d.ts +6 -0
  88. package/dist/utils/resolve-function-types.js +29 -0
  89. package/dist/utils/resolve-identifier.d.ts +10 -0
  90. package/dist/utils/resolve-identifier.js +36 -0
  91. package/dist/utils/resolve-versions.d.ts +2 -0
  92. package/dist/utils/resolve-versions.js +78 -0
  93. package/dist/utils/schema-generator.d.ts +9 -0
  94. package/dist/utils/schema-generator.js +209 -0
  95. package/dist/utils/serialize-inspector-state.d.ts +70 -23
  96. package/dist/utils/serialize-inspector-state.js +98 -22
  97. package/dist/utils/serialize-mcp-json.d.ts +2 -0
  98. package/dist/utils/serialize-mcp-json.js +99 -0
  99. package/dist/utils/serialize-middleware-groups-meta.d.ts +12 -0
  100. package/dist/utils/serialize-middleware-groups-meta.js +28 -0
  101. package/dist/utils/serialize-openapi-json.d.ts +85 -0
  102. package/dist/utils/serialize-openapi-json.js +151 -0
  103. package/dist/utils/serialize-permissions-groups-meta.d.ts +6 -0
  104. package/dist/utils/serialize-permissions-groups-meta.js +31 -0
  105. package/dist/utils/validate-auth-sessionless.d.ts +3 -0
  106. package/dist/utils/validate-auth-sessionless.js +14 -0
  107. package/dist/utils/workflow/dsl/deserialize-dsl-workflow.js +34 -102
  108. package/dist/utils/workflow/dsl/extract-dsl-workflow.d.ts +1 -1
  109. package/dist/utils/workflow/dsl/extract-dsl-workflow.js +23 -4
  110. package/dist/utils/workflow/graph/convert-dsl-to-graph.js +12 -10
  111. package/dist/utils/workflow/graph/finalize-workflow-wires.d.ts +3 -0
  112. package/dist/utils/workflow/graph/finalize-workflow-wires.js +276 -0
  113. package/dist/utils/workflow/graph/finalize-workflows.d.ts +2 -0
  114. package/dist/utils/workflow/graph/finalize-workflows.js +75 -0
  115. package/dist/utils/workflow/graph/index.d.ts +2 -0
  116. package/dist/utils/workflow/graph/index.js +2 -0
  117. package/dist/utils/workflow/graph/serialize-workflow-graph.d.ts +0 -8
  118. package/dist/utils/workflow/graph/serialize-workflow-graph.js +1 -3
  119. package/dist/utils/workflow/graph/workflow-graph.types.d.ts +53 -79
  120. package/dist/utils/workflow/graph/workflow-graph.types.js +1 -1
  121. package/dist/visit.d.ts +1 -1
  122. package/dist/visit.js +13 -6
  123. package/package.json +14 -4
  124. package/src/add/add-ai-agent.ts +468 -0
  125. package/src/add/add-channel.ts +103 -79
  126. package/src/add/add-cli.ts +68 -24
  127. package/src/add/add-file-extends-core-type.ts +1 -1
  128. package/src/add/add-file-with-config.ts +1 -1
  129. package/src/add/add-file-with-factory.ts +3 -1
  130. package/src/add/add-functions.ts +349 -103
  131. package/src/add/add-http-route.ts +263 -89
  132. package/src/add/add-http-routes.ts +229 -0
  133. package/src/add/add-keyed-wiring.ts +151 -0
  134. package/src/add/add-mcp-prompt.ts +27 -16
  135. package/src/add/add-mcp-resource.ts +28 -16
  136. package/src/add/add-middleware.ts +482 -80
  137. package/src/add/add-permission.ts +199 -40
  138. package/src/add/add-queue-worker.ts +25 -20
  139. package/src/add/add-rpc-invocations.ts +28 -11
  140. package/src/add/add-schedule.ts +17 -12
  141. package/src/add/add-secret.ts +140 -0
  142. package/src/add/add-trigger.ts +154 -0
  143. package/src/add/add-variable.ts +9 -0
  144. package/src/add/add-wire-addon.ts +80 -0
  145. package/src/add/add-workflow-graph.ts +180 -522
  146. package/src/add/add-workflow.ts +7 -6
  147. package/src/error-codes.ts +25 -1
  148. package/src/index.ts +23 -13
  149. package/src/inspector.ts +139 -19
  150. package/src/schema-generator.ts +1 -0
  151. package/src/types-map.ts +12 -1
  152. package/src/types.ts +199 -69
  153. package/src/utils/compute-required-schemas.ts +48 -0
  154. package/src/utils/contract-hashes.test.ts +553 -0
  155. package/src/utils/contract-hashes.ts +386 -0
  156. package/src/utils/custom-types-generator.ts +88 -0
  157. package/src/utils/detect-schema-vendor.ts +90 -0
  158. package/src/utils/does-type-extend-core-type.ts +1 -1
  159. package/src/utils/ensure-function-metadata.ts +325 -8
  160. package/src/utils/extract-function-name.ts +101 -351
  161. package/src/utils/extract-services.ts +35 -2
  162. package/src/utils/filter-inspector-state.test.ts +37 -25
  163. package/src/utils/filter-inspector-state.ts +146 -32
  164. package/src/utils/filter-utils.test.ts +1 -1
  165. package/src/utils/filter-utils.ts +2 -2
  166. package/src/utils/get-files-and-methods.ts +1 -1
  167. package/src/utils/get-property-value.ts +42 -4
  168. package/src/utils/hash.ts +26 -0
  169. package/src/utils/middleware.test.ts +204 -0
  170. package/src/utils/middleware.ts +131 -69
  171. package/src/utils/permissions.test.ts +35 -12
  172. package/src/utils/permissions.ts +12 -12
  173. package/src/utils/post-process.ts +306 -44
  174. package/src/utils/resolve-addon-package.ts +49 -0
  175. package/src/utils/resolve-function-types.ts +42 -0
  176. package/src/utils/resolve-identifier.ts +46 -0
  177. package/src/utils/resolve-versions.test.ts +249 -0
  178. package/src/utils/resolve-versions.ts +105 -0
  179. package/src/utils/schema-generator.ts +329 -0
  180. package/src/utils/serialize-inspector-state.ts +184 -43
  181. package/src/utils/serialize-mcp-json.ts +145 -0
  182. package/src/utils/serialize-middleware-groups-meta.ts +33 -0
  183. package/src/utils/serialize-openapi-json.ts +277 -0
  184. package/src/utils/serialize-permissions-groups-meta.ts +35 -0
  185. package/src/utils/test-data/inspector-state.json +69 -66
  186. package/src/utils/validate-auth-sessionless.ts +29 -0
  187. package/src/utils/workflow/dsl/deserialize-dsl-workflow.ts +43 -119
  188. package/src/utils/workflow/dsl/extract-dsl-workflow.ts +26 -6
  189. package/src/utils/workflow/graph/convert-dsl-to-graph.ts +17 -10
  190. package/src/utils/workflow/graph/finalize-workflow-wires.ts +310 -0
  191. package/src/utils/workflow/graph/finalize-workflows.ts +100 -0
  192. package/src/utils/workflow/graph/index.ts +5 -0
  193. package/src/utils/workflow/graph/serialize-workflow-graph.ts +1 -8
  194. package/src/utils/workflow/graph/workflow-graph.types.ts +29 -78
  195. package/src/visit.ts +19 -7
  196. package/tsconfig.tsbuildinfo +1 -1
  197. package/dist/add/add-forge-credential.d.ts +0 -8
  198. package/dist/add/add-forge-credential.js +0 -77
  199. package/dist/add/add-forge-node.d.ts +0 -7
  200. package/dist/add/add-forge-node.js +0 -77
  201. package/dist/add/add-mcp-tool.d.ts +0 -2
  202. package/dist/add/add-mcp-tool.js +0 -81
  203. package/dist/utils/extract-service-metadata.d.ts +0 -19
  204. package/dist/utils/extract-service-metadata.js +0 -244
  205. package/dist/utils/write-service-metadata.d.ts +0 -13
  206. package/dist/utils/write-service-metadata.js +0 -37
  207. package/src/add/add-forge-credential.ts +0 -119
  208. package/src/add/add-forge-node.ts +0 -132
  209. package/src/add/add-mcp-tool.ts +0 -141
  210. package/src/utils/extract-service-metadata.ts +0 -353
  211. package/src/utils/write-service-metadata.ts +0 -51
@@ -0,0 +1,140 @@
1
+ import * as ts from 'typescript'
2
+ import {
3
+ getPropertyValue,
4
+ getArrayPropertyValue,
5
+ } from '../utils/get-property-value.js'
6
+ import type { AddWiring } from '../types.js'
7
+ import { ErrorCode } from '../error-codes.js'
8
+ import { createAddKeyedWiring } from './add-keyed-wiring.js'
9
+
10
+ export const addSecret = createAddKeyedWiring({
11
+ functionName: 'wireSecret',
12
+ idField: 'secretId',
13
+ label: 'Secret',
14
+ schemaPrefix: 'SecretSchema',
15
+ getState: (state) => state.secrets,
16
+ })
17
+
18
+ export const addOAuth2Credential: AddWiring = (
19
+ logger,
20
+ node,
21
+ _checker,
22
+ state,
23
+ _options
24
+ ) => {
25
+ if (!ts.isCallExpression(node)) {
26
+ return
27
+ }
28
+
29
+ const args = node.arguments
30
+ const firstArg = args[0]
31
+ const expression = node.expression
32
+
33
+ if (
34
+ !ts.isIdentifier(expression) ||
35
+ expression.text !== 'wireOAuth2Credential'
36
+ ) {
37
+ return
38
+ }
39
+
40
+ if (!firstArg) {
41
+ return
42
+ }
43
+
44
+ if (ts.isObjectLiteralExpression(firstArg)) {
45
+ const obj = firstArg
46
+
47
+ const nameValue = getPropertyValue(obj, 'name') as string | null
48
+ const displayNameValue = getPropertyValue(obj, 'displayName') as
49
+ | string
50
+ | null
51
+ const descriptionValue = getPropertyValue(obj, 'description') as
52
+ | string
53
+ | null
54
+ const secretIdValue = getPropertyValue(obj, 'secretId') as string | null
55
+ const tokenSecretIdValue = getPropertyValue(obj, 'tokenSecretId') as
56
+ | string
57
+ | null
58
+ const authorizationUrlValue = getPropertyValue(obj, 'authorizationUrl') as
59
+ | string
60
+ | null
61
+ const tokenUrlValue = getPropertyValue(obj, 'tokenUrl') as string | null
62
+ const scopesValue = getArrayPropertyValue(obj, 'scopes')
63
+ const pkceValue = getPropertyValue(obj, 'pkce') as boolean | null
64
+
65
+ if (!nameValue) {
66
+ logger.critical(
67
+ ErrorCode.MISSING_NAME,
68
+ "OAuth2 Credential is missing the required 'name' property."
69
+ )
70
+ return
71
+ }
72
+
73
+ if (!displayNameValue) {
74
+ logger.critical(
75
+ ErrorCode.MISSING_NAME,
76
+ `OAuth2 Credential '${nameValue}' is missing the required 'displayName' property.`
77
+ )
78
+ return
79
+ }
80
+
81
+ if (!secretIdValue) {
82
+ logger.critical(
83
+ ErrorCode.MISSING_NAME,
84
+ `OAuth2 Credential '${nameValue}' is missing the required 'secretId' property.`
85
+ )
86
+ return
87
+ }
88
+
89
+ if (!tokenSecretIdValue) {
90
+ logger.critical(
91
+ ErrorCode.MISSING_NAME,
92
+ `OAuth2 Credential '${nameValue}' is missing the required 'tokenSecretId' property.`
93
+ )
94
+ return
95
+ }
96
+
97
+ if (!authorizationUrlValue) {
98
+ logger.critical(
99
+ ErrorCode.MISSING_NAME,
100
+ `OAuth2 Credential '${nameValue}' is missing the required 'authorizationUrl' property.`
101
+ )
102
+ return
103
+ }
104
+
105
+ if (!tokenUrlValue) {
106
+ logger.critical(
107
+ ErrorCode.MISSING_NAME,
108
+ `OAuth2 Credential '${nameValue}' is missing the required 'tokenUrl' property.`
109
+ )
110
+ return
111
+ }
112
+
113
+ if (!scopesValue || scopesValue.length === 0) {
114
+ logger.critical(
115
+ ErrorCode.MISSING_NAME,
116
+ `OAuth2 Credential '${nameValue}' is missing the required 'scopes' property.`
117
+ )
118
+ return
119
+ }
120
+
121
+ const sourceFile = node.getSourceFile().fileName
122
+
123
+ state.secrets.files.add(sourceFile)
124
+
125
+ state.secrets.definitions.push({
126
+ name: nameValue,
127
+ displayName: displayNameValue,
128
+ description: descriptionValue || undefined,
129
+ secretId: secretIdValue,
130
+ oauth2: {
131
+ tokenSecretId: tokenSecretIdValue,
132
+ authorizationUrl: authorizationUrlValue,
133
+ tokenUrl: tokenUrlValue,
134
+ scopes: scopesValue,
135
+ pkce: pkceValue || undefined,
136
+ },
137
+ sourceFile,
138
+ })
139
+ }
140
+ }
@@ -0,0 +1,154 @@
1
+ import * as ts from 'typescript'
2
+ import {
3
+ getPropertyValue,
4
+ getCommonWireMetaData,
5
+ } from '../utils/get-property-value.js'
6
+ import type { AddWiring } from '../types.js'
7
+ import {
8
+ extractFunctionName,
9
+ makeContextBasedId,
10
+ } from '../utils/extract-function-name.js'
11
+ import { getPropertyAssignmentInitializer } from '../utils/type-utils.js'
12
+ import { resolveMiddleware } from '../utils/middleware.js'
13
+ import { extractWireNames } from '../utils/post-process.js'
14
+ import { resolveAddonName } from '../utils/resolve-addon-package.js'
15
+
16
+ import { ErrorCode } from '../error-codes.js'
17
+ export const addTrigger: AddWiring = (
18
+ logger,
19
+ node,
20
+ checker,
21
+ state,
22
+ options
23
+ ) => {
24
+ if (!ts.isCallExpression(node)) {
25
+ return
26
+ }
27
+
28
+ const args = node.arguments
29
+ const firstArg = args[0]
30
+ const expression = node.expression
31
+
32
+ if (!ts.isIdentifier(expression)) {
33
+ return
34
+ }
35
+
36
+ if (expression.text === 'wireTrigger') {
37
+ addWireTrigger(logger, node, checker, state, firstArg)
38
+ } else if (expression.text === 'wireTriggerSource') {
39
+ addWireTriggerSource(logger, node, checker, state, options, firstArg)
40
+ }
41
+ }
42
+
43
+ const addWireTrigger: (
44
+ logger: Parameters<AddWiring>[0],
45
+ node: ts.CallExpression,
46
+ checker: Parameters<AddWiring>[2],
47
+ state: Parameters<AddWiring>[3],
48
+ firstArg: ts.Expression | undefined
49
+ ) => void = (logger, node, checker, state, firstArg) => {
50
+ if (!firstArg || !ts.isObjectLiteralExpression(firstArg)) {
51
+ return
52
+ }
53
+
54
+ const obj = firstArg
55
+
56
+ const nameValue = getPropertyValue(obj, 'name') as string | null
57
+ const { disabled, tags, summary, description, errors } =
58
+ getCommonWireMetaData(obj, 'Trigger', nameValue, logger)
59
+
60
+ if (disabled) return
61
+
62
+ const funcInitializer = getPropertyAssignmentInitializer(
63
+ obj,
64
+ 'func',
65
+ true,
66
+ checker
67
+ )
68
+ if (!funcInitializer) {
69
+ logger.critical(
70
+ ErrorCode.MISSING_FUNC,
71
+ `No valid 'func' property for trigger '${nameValue}'.`
72
+ )
73
+ return
74
+ }
75
+
76
+ const extracted = extractFunctionName(funcInitializer, checker, state.rootDir)
77
+ let pikkuFuncId = extracted.pikkuFuncId
78
+ if (pikkuFuncId.startsWith('__temp_') && nameValue) {
79
+ pikkuFuncId = makeContextBasedId('trigger', nameValue)
80
+ }
81
+
82
+ if (!nameValue) {
83
+ return
84
+ }
85
+
86
+ // --- resolve middleware ---
87
+ const middleware = resolveMiddleware(state, obj, tags, checker)
88
+
89
+ // --- track used functions/middleware for service aggregation ---
90
+ state.serviceAggregation.usedFunctions.add(pikkuFuncId)
91
+ extractWireNames(middleware).forEach((name) =>
92
+ state.serviceAggregation.usedMiddleware.add(name)
93
+ )
94
+
95
+ state.triggers.files.add(node.getSourceFile().fileName)
96
+ state.triggers.meta[nameValue] = {
97
+ pikkuFuncId,
98
+ name: nameValue,
99
+ summary,
100
+ description,
101
+ errors,
102
+ tags,
103
+ middleware,
104
+ }
105
+ }
106
+
107
+ const addWireTriggerSource: (
108
+ logger: Parameters<AddWiring>[0],
109
+ node: ts.CallExpression,
110
+ checker: Parameters<AddWiring>[2],
111
+ state: Parameters<AddWiring>[3],
112
+ options: Parameters<AddWiring>[4],
113
+ firstArg: ts.Expression | undefined
114
+ ) => void = (logger, node, checker, state, options, firstArg) => {
115
+ if (!firstArg || !ts.isObjectLiteralExpression(firstArg)) {
116
+ return
117
+ }
118
+
119
+ const obj = firstArg
120
+
121
+ const nameValue = getPropertyValue(obj, 'name') as string | null
122
+ if (!nameValue) {
123
+ return
124
+ }
125
+
126
+ const funcInitializer = getPropertyAssignmentInitializer(
127
+ obj,
128
+ 'func',
129
+ true,
130
+ checker
131
+ )
132
+ if (!funcInitializer) {
133
+ logger.critical(
134
+ ErrorCode.MISSING_FUNC,
135
+ `No valid 'func' property for trigger source '${nameValue}'.`
136
+ )
137
+ return
138
+ }
139
+
140
+ if (ts.isIdentifier(funcInitializer)) {
141
+ const packageName = resolveAddonName(
142
+ funcInitializer,
143
+ checker,
144
+ state.rpc.wireAddonDeclarations
145
+ )
146
+ state.triggers.sourceMeta[nameValue] = {
147
+ name: nameValue,
148
+ pikkuFuncId: funcInitializer.text,
149
+ packageName: packageName || undefined,
150
+ }
151
+ }
152
+
153
+ state.triggers.files.add(node.getSourceFile().fileName)
154
+ }
@@ -0,0 +1,9 @@
1
+ import { createAddKeyedWiring } from './add-keyed-wiring.js'
2
+
3
+ export const addVariable = createAddKeyedWiring({
4
+ functionName: 'wireVariable',
5
+ idField: 'variableId',
6
+ label: 'Variable',
7
+ schemaPrefix: 'VariableSchema',
8
+ getState: (state) => state.variables,
9
+ })
@@ -0,0 +1,80 @@
1
+ import * as ts from 'typescript'
2
+ import type { InspectorState, InspectorLogger } from '../types.js'
3
+
4
+ function parseStringRecord(
5
+ obj: ts.ObjectLiteralExpression
6
+ ): Record<string, string> {
7
+ const result: Record<string, string> = {}
8
+ for (const prop of obj.properties) {
9
+ if (!ts.isPropertyAssignment(prop)) continue
10
+ const keyNode = prop.name
11
+ const key = ts.isIdentifier(keyNode)
12
+ ? keyNode.text
13
+ : ts.isStringLiteral(keyNode)
14
+ ? keyNode.text
15
+ : undefined
16
+ if (key && ts.isStringLiteral(prop.initializer)) {
17
+ result[key] = prop.initializer.text
18
+ }
19
+ }
20
+ return result
21
+ }
22
+
23
+ /**
24
+ * Detect wireAddon({ name: '...', package: '...' }) call expressions and
25
+ * populate state.rpc.wireAddonDeclarations and state.rpc.usedAddons.
26
+ */
27
+ export function addWireAddon(
28
+ node: ts.Node,
29
+ state: InspectorState,
30
+ logger: InspectorLogger
31
+ ) {
32
+ if (!ts.isCallExpression(node)) return
33
+
34
+ const { expression, arguments: args } = node
35
+ if (!ts.isIdentifier(expression) || expression.text !== 'wireAddon') return
36
+
37
+ const [firstArg] = args
38
+ if (!firstArg || !ts.isObjectLiteralExpression(firstArg)) return
39
+
40
+ let name: string | undefined
41
+ let pkg: string | undefined
42
+ let rpcEndpoint: string | undefined
43
+ let secretOverrides: Record<string, string> | undefined
44
+ let variableOverrides: Record<string, string> | undefined
45
+
46
+ for (const prop of firstArg.properties) {
47
+ if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name)) continue
48
+
49
+ const key = prop.name.text
50
+ if (key === 'name' && ts.isStringLiteral(prop.initializer)) {
51
+ name = prop.initializer.text
52
+ } else if (key === 'package' && ts.isStringLiteral(prop.initializer)) {
53
+ pkg = prop.initializer.text
54
+ } else if (key === 'rpcEndpoint' && ts.isStringLiteral(prop.initializer)) {
55
+ rpcEndpoint = prop.initializer.text
56
+ } else if (
57
+ key === 'secretOverrides' &&
58
+ ts.isObjectLiteralExpression(prop.initializer)
59
+ ) {
60
+ secretOverrides = parseStringRecord(prop.initializer)
61
+ } else if (
62
+ key === 'variableOverrides' &&
63
+ ts.isObjectLiteralExpression(prop.initializer)
64
+ ) {
65
+ variableOverrides = parseStringRecord(prop.initializer)
66
+ }
67
+ }
68
+
69
+ if (!name || !pkg) return
70
+
71
+ logger.debug(`• Found wireAddon: ${name} → ${pkg}`)
72
+ state.rpc.wireAddonDeclarations.set(name, {
73
+ package: pkg,
74
+ rpcEndpoint,
75
+ secretOverrides,
76
+ variableOverrides,
77
+ })
78
+ state.rpc.usedAddons.add(name)
79
+ state.rpc.wireAddonFiles.add(node.getSourceFile().fileName)
80
+ }