@pikku/inspector 0.12.0 → 0.12.2

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 (112) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/add/add-ai-agent.d.ts +1 -1
  3. package/dist/add/add-ai-agent.js +1 -1
  4. package/dist/add/add-channel.js +14 -0
  5. package/dist/add/add-cli.d.ts +1 -1
  6. package/dist/add/add-cli.js +29 -8
  7. package/dist/add/add-file-extends-core-type.d.ts +1 -1
  8. package/dist/add/add-file-with-config.d.ts +1 -1
  9. package/dist/add/add-file-with-factory.d.ts +1 -1
  10. package/dist/add/add-file-with-factory.js +2 -2
  11. package/dist/add/add-functions.d.ts +1 -1
  12. package/dist/add/add-functions.js +6 -7
  13. package/dist/add/add-gateway.d.ts +2 -0
  14. package/dist/add/add-gateway.js +57 -0
  15. package/dist/add/add-http-route.d.ts +3 -2
  16. package/dist/add/add-http-route.js +5 -1
  17. package/dist/add/add-http-routes.d.ts +1 -1
  18. package/dist/add/add-http-routes.js +1 -0
  19. package/dist/add/add-keyed-wiring.d.ts +1 -1
  20. package/dist/add/add-mcp-prompt.d.ts +1 -1
  21. package/dist/add/add-mcp-resource.d.ts +1 -1
  22. package/dist/add/add-queue-worker.d.ts +1 -1
  23. package/dist/add/add-rpc-invocations.d.ts +3 -3
  24. package/dist/add/add-rpc-invocations.js +10 -10
  25. package/dist/add/add-schedule.d.ts +1 -1
  26. package/dist/add/add-secret.d.ts +1 -1
  27. package/dist/add/add-trigger.d.ts +1 -1
  28. package/dist/add/add-trigger.js +2 -2
  29. package/dist/add/add-wire-addon.d.ts +7 -0
  30. package/dist/add/add-wire-addon.js +70 -0
  31. package/dist/add/add-workflow.d.ts +1 -1
  32. package/dist/error-codes.d.ts +1 -0
  33. package/dist/error-codes.js +1 -0
  34. package/dist/index.d.ts +1 -1
  35. package/dist/inspector.d.ts +1 -1
  36. package/dist/inspector.js +11 -4
  37. package/dist/types.d.ts +31 -20
  38. package/dist/utils/compute-required-schemas.js +1 -2
  39. package/dist/utils/contract-hashes.d.ts +20 -3
  40. package/dist/utils/contract-hashes.js +77 -10
  41. package/dist/utils/custom-types-generator.d.ts +1 -1
  42. package/dist/utils/detect-schema-vendor.d.ts +1 -1
  43. package/dist/utils/does-type-extend-core-type.d.ts +1 -1
  44. package/dist/utils/ensure-function-metadata.d.ts +1 -1
  45. package/dist/utils/extract-services.d.ts +1 -1
  46. package/dist/utils/filter-inspector-state.d.ts +1 -1
  47. package/dist/utils/filter-utils.d.ts +2 -2
  48. package/dist/utils/get-files-and-methods.d.ts +1 -1
  49. package/dist/utils/middleware.d.ts +2 -2
  50. package/dist/utils/permissions.d.ts +2 -2
  51. package/dist/utils/post-process.d.ts +4 -3
  52. package/dist/utils/post-process.js +24 -8
  53. package/dist/utils/resolve-addon-package.d.ts +16 -0
  54. package/dist/utils/{resolve-external-package.js → resolve-addon-package.js} +8 -8
  55. package/dist/utils/schema-generator.d.ts +2 -2
  56. package/dist/utils/serialize-inspector-state.d.ts +17 -3
  57. package/dist/utils/serialize-inspector-state.js +14 -2
  58. package/dist/utils/validate-auth-sessionless.d.ts +3 -0
  59. package/dist/utils/validate-auth-sessionless.js +14 -0
  60. package/dist/utils/workflow/dsl/extract-dsl-workflow.d.ts +1 -1
  61. package/dist/visit.d.ts +1 -1
  62. package/dist/visit.js +4 -0
  63. package/package.json +3 -3
  64. package/src/add/add-ai-agent.ts +2 -2
  65. package/src/add/add-channel.ts +17 -0
  66. package/src/add/add-cli.ts +53 -15
  67. package/src/add/add-file-extends-core-type.ts +1 -1
  68. package/src/add/add-file-with-config.ts +1 -1
  69. package/src/add/add-file-with-factory.ts +3 -3
  70. package/src/add/add-functions.ts +21 -19
  71. package/src/add/add-gateway.ts +95 -0
  72. package/src/add/add-http-route.ts +19 -2
  73. package/src/add/add-http-routes.ts +2 -1
  74. package/src/add/add-keyed-wiring.ts +1 -1
  75. package/src/add/add-mcp-prompt.ts +1 -1
  76. package/src/add/add-mcp-resource.ts +1 -1
  77. package/src/add/add-queue-worker.ts +1 -1
  78. package/src/add/add-rpc-invocations.ts +11 -11
  79. package/src/add/add-schedule.ts +1 -1
  80. package/src/add/add-secret.ts +1 -1
  81. package/src/add/add-trigger.ts +4 -4
  82. package/src/add/add-wire-addon.ts +80 -0
  83. package/src/add/add-workflow.ts +2 -2
  84. package/src/error-codes.ts +1 -0
  85. package/src/index.ts +1 -0
  86. package/src/inspector.ts +17 -5
  87. package/src/types.ts +38 -20
  88. package/src/utils/compute-required-schemas.ts +1 -2
  89. package/src/utils/contract-hashes.test.ts +30 -5
  90. package/src/utils/contract-hashes.ts +110 -14
  91. package/src/utils/custom-types-generator.ts +1 -1
  92. package/src/utils/detect-schema-vendor.ts +1 -1
  93. package/src/utils/does-type-extend-core-type.ts +1 -1
  94. package/src/utils/ensure-function-metadata.ts +1 -1
  95. package/src/utils/extract-services.ts +1 -1
  96. package/src/utils/filter-inspector-state.test.ts +3 -5
  97. package/src/utils/filter-inspector-state.ts +7 -2
  98. package/src/utils/filter-utils.test.ts +1 -1
  99. package/src/utils/filter-utils.ts +2 -2
  100. package/src/utils/get-files-and-methods.ts +1 -1
  101. package/src/utils/middleware.ts +2 -2
  102. package/src/utils/permissions.ts +2 -2
  103. package/src/utils/post-process.ts +34 -12
  104. package/src/utils/{resolve-external-package.ts → resolve-addon-package.ts} +17 -10
  105. package/src/utils/resolve-versions.test.ts +1 -1
  106. package/src/utils/schema-generator.ts +4 -4
  107. package/src/utils/serialize-inspector-state.ts +35 -5
  108. package/src/utils/validate-auth-sessionless.ts +29 -0
  109. package/src/utils/workflow/dsl/extract-dsl-workflow.ts +2 -2
  110. package/src/visit.ts +9 -1
  111. package/tsconfig.tsbuildinfo +1 -1
  112. package/dist/utils/resolve-external-package.d.ts +0 -12
@@ -1,5 +1,5 @@
1
1
  import * as ts from 'typescript'
2
- import { InspectorState, InspectorLogger } from '../types.js'
2
+ import type { InspectorState, InspectorLogger } from '../types.js'
3
3
 
4
4
  /**
5
5
  * Helper to extract namespace from a namespaced function reference like 'ext:hello'
@@ -14,31 +14,31 @@ function extractNamespace(functionRef: string): string | null {
14
14
 
15
15
  /**
16
16
  * Scan for rpc.invoke() calls to track which functions are actually being invoked
17
- * Also detects external package usage via:
17
+ * Also detects addon usage via:
18
18
  * - Namespaced calls: rpc.invoke('namespace:function')
19
- * - External helper: external('namespace:function')
19
+ * - Addon helper: addon('namespace:function')
20
20
  */
21
21
  export function addRPCInvocations(
22
22
  node: ts.Node,
23
23
  state: InspectorState,
24
24
  logger: InspectorLogger
25
25
  ) {
26
- // Look for call expressions: external('ext:hello') or rpc.invoke('...')
26
+ // Look for call expressions: addon('ext:hello') or rpc.invoke('...')
27
27
  if (ts.isCallExpression(node)) {
28
28
  const { expression, arguments: args } = node
29
29
 
30
- // Check for external('namespace:function') calls
31
- if (ts.isIdentifier(expression) && expression.text === 'external') {
30
+ // Check for addon('namespace:function') calls
31
+ if (ts.isIdentifier(expression) && expression.text === 'addon') {
32
32
  const [firstArg] = args
33
33
  if (firstArg && ts.isStringLiteral(firstArg)) {
34
34
  const functionRef = firstArg.text
35
- logger.debug(`• Found external() call: ${functionRef}`)
35
+ logger.debug(`• Found addon() call: ${functionRef}`)
36
36
  state.rpc.invokedFunctions.add(functionRef)
37
37
 
38
38
  const namespace = extractNamespace(functionRef)
39
39
  if (namespace) {
40
- logger.debug(` → External package detected: ${namespace}`)
41
- state.rpc.usedExternalPackages.add(namespace)
40
+ logger.debug(` → Addon detected: ${namespace}`)
41
+ state.rpc.usedAddons.add(namespace)
42
42
  }
43
43
  }
44
44
  }
@@ -76,8 +76,8 @@ export function addRPCInvocations(
76
76
 
77
77
  const namespace = extractNamespace(functionRef)
78
78
  if (namespace) {
79
- logger.debug(` → External package detected: ${namespace}`)
80
- state.rpc.usedExternalPackages.add(namespace)
79
+ logger.debug(` → Addon detected: ${namespace}`)
80
+ state.rpc.usedAddons.add(namespace)
81
81
  }
82
82
  }
83
83
  // Handle template literals like `function-${name}`
@@ -3,7 +3,7 @@ import {
3
3
  getPropertyValue,
4
4
  getCommonWireMetaData,
5
5
  } from '../utils/get-property-value.js'
6
- import { AddWiring } from '../types.js'
6
+ import type { AddWiring } from '../types.js'
7
7
  import {
8
8
  extractFunctionName,
9
9
  makeContextBasedId,
@@ -3,7 +3,7 @@ import {
3
3
  getPropertyValue,
4
4
  getArrayPropertyValue,
5
5
  } from '../utils/get-property-value.js'
6
- import { AddWiring } from '../types.js'
6
+ import type { AddWiring } from '../types.js'
7
7
  import { ErrorCode } from '../error-codes.js'
8
8
  import { createAddKeyedWiring } from './add-keyed-wiring.js'
9
9
 
@@ -3,7 +3,7 @@ import {
3
3
  getPropertyValue,
4
4
  getCommonWireMetaData,
5
5
  } from '../utils/get-property-value.js'
6
- import { AddWiring } from '../types.js'
6
+ import type { AddWiring } from '../types.js'
7
7
  import {
8
8
  extractFunctionName,
9
9
  makeContextBasedId,
@@ -11,7 +11,7 @@ import {
11
11
  import { getPropertyAssignmentInitializer } from '../utils/type-utils.js'
12
12
  import { resolveMiddleware } from '../utils/middleware.js'
13
13
  import { extractWireNames } from '../utils/post-process.js'
14
- import { resolveExternalPackageName } from '../utils/resolve-external-package.js'
14
+ import { resolveAddonName } from '../utils/resolve-addon-package.js'
15
15
 
16
16
  import { ErrorCode } from '../error-codes.js'
17
17
  export const addTrigger: AddWiring = (
@@ -138,10 +138,10 @@ const addWireTriggerSource: (
138
138
  }
139
139
 
140
140
  if (ts.isIdentifier(funcInitializer)) {
141
- const packageName = resolveExternalPackageName(
141
+ const packageName = resolveAddonName(
142
142
  funcInitializer,
143
143
  checker,
144
- options.externalPackages
144
+ state.rpc.wireAddonDeclarations
145
145
  )
146
146
  state.triggers.sourceMeta[nameValue] = {
147
147
  name: nameValue,
@@ -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
+ }
@@ -1,9 +1,9 @@
1
1
  import * as ts from 'typescript'
2
- import { AddWiring, InspectorState } from '../types.js'
2
+ import type { AddWiring, InspectorState } from '../types.js'
3
3
  import { extractFunctionName } from '../utils/extract-function-name.js'
4
4
  import { extractFunctionNode } from '../utils/extract-function-node.js'
5
5
  import { ErrorCode } from '../error-codes.js'
6
- import { WorkflowStepMeta, WorkflowContext } from '@pikku/core/workflow'
6
+ import type { WorkflowStepMeta, WorkflowContext } from '@pikku/core/workflow'
7
7
  import {
8
8
  extractStringLiteral,
9
9
  isStringLike,
@@ -39,6 +39,7 @@ export enum ErrorCode {
39
39
  // HTTP Route errors
40
40
  ROUTE_PARAM_MISMATCH = 'PKU571',
41
41
  ROUTE_QUERY_MISMATCH = 'PKU572',
42
+ AUTH_DISABLED_REQUIRES_SESSIONLESS = 'PKU573',
42
43
 
43
44
  // Middleware/Permission errors
44
45
  MIDDLEWARE_HANDLER_INVALID = 'PKU685',
package/src/index.ts CHANGED
@@ -19,6 +19,7 @@ export {
19
19
  } from './utils/contract-hashes.js'
20
20
  export type {
21
21
  ContractEntry,
22
+ VersionHashEntry,
22
23
  VersionValidateError,
23
24
  VersionManifest,
24
25
  VersionManifestEntry,
package/src/inspector.ts CHANGED
@@ -2,14 +2,19 @@ import * as ts from 'typescript'
2
2
  import { performance } from 'perf_hooks'
3
3
  import { visitSetup, visitRoutes } from './visit.js'
4
4
  import { TypesMap } from './types-map.js'
5
- import { InspectorState, InspectorLogger, InspectorOptions } from './types.js'
5
+ import type {
6
+ InspectorState,
7
+ InspectorLogger,
8
+ InspectorOptions,
9
+ } from './types.js'
6
10
  import { getFilesAndMethods } from './utils/get-files-and-methods.js'
7
11
  import { findCommonAncestor } from './utils/find-root-dir.js'
8
12
  import {
9
13
  aggregateRequiredServices,
10
- validateSecretOverrides,
11
14
  validateAgentModels,
12
15
  validateAgentOverrides,
16
+ validateSecretOverrides,
17
+ validateVariableOverrides,
13
18
  computeResolvedIOTypes,
14
19
  computeMiddlewareGroupsMeta,
15
20
  computePermissionsGroupsMeta,
@@ -17,7 +22,7 @@ import {
17
22
  computeDiagnostics,
18
23
  } from './utils/post-process.js'
19
24
  import { generateOpenAPISpec } from './utils/serialize-openapi-json.js'
20
- import { pikkuState } from '@pikku/core'
25
+ import { pikkuState } from '@pikku/core/internal'
21
26
  import { resolveLatestVersions } from './utils/resolve-versions.js'
22
27
  import { finalizeWorkflows } from './utils/workflow/graph/finalize-workflows.js'
23
28
  import {
@@ -78,6 +83,10 @@ export function getInitialInspectorState(rootDir: string): InspectorState {
78
83
  files: new Set(),
79
84
  meta: {},
80
85
  },
86
+ gateways: {
87
+ meta: {},
88
+ files: new Set(),
89
+ },
81
90
  triggers: {
82
91
  meta: {},
83
92
  sourceMeta: {},
@@ -104,7 +113,9 @@ export function getInitialInspectorState(rootDir: string): InspectorState {
104
113
  exposedMeta: {},
105
114
  exposedFiles: new Map(),
106
115
  invokedFunctions: new Set(),
107
- usedExternalPackages: new Set(),
116
+ usedAddons: new Set(),
117
+ wireAddonDeclarations: new Map(),
118
+ wireAddonFiles: new Set(),
108
119
  },
109
120
  mcpEndpoints: {
110
121
  resourcesMeta: {},
@@ -312,9 +323,10 @@ export const inspect = async (
312
323
  )
313
324
  }
314
325
 
315
- validateSecretOverrides(logger, state, options.externalPackages)
316
326
  validateAgentModels(logger, state, options.modelConfig)
317
327
  validateAgentOverrides(logger, state, options.modelConfig)
328
+ validateSecretOverrides(logger, state)
329
+ validateVariableOverrides(logger, state)
318
330
  }
319
331
 
320
332
  return state
package/src/types.ts CHANGED
@@ -1,25 +1,30 @@
1
- import * as ts from 'typescript'
2
- import { ChannelsMeta } from '@pikku/core/channel'
3
- import { HTTPWiringsMeta } from '@pikku/core/http'
4
- import { ScheduledTasksMeta } from '@pikku/core/scheduler'
5
- import { TriggerMeta, TriggerSourceMeta } from '@pikku/core/trigger'
6
- import { QueueWorkersMeta } from '@pikku/core/queue'
7
- import { WorkflowsMeta } from '@pikku/core/workflow'
8
- import { MCPResourceMeta, MCPToolMeta, MCPPromptMeta } from '@pikku/core/mcp'
9
- import { AIAgentMeta } from '@pikku/core/ai-agent'
10
- import { CLIMeta } from '@pikku/core/cli'
11
- import { NodesMeta } from '@pikku/core/node'
12
- import { SecretDefinitions } from '@pikku/core/secret'
13
- import { VariableDefinitions } from '@pikku/core/variable'
14
- import { TypesMap } from './types-map.js'
15
- import {
1
+ import type * as ts from 'typescript'
2
+ import type { ChannelsMeta } from '@pikku/core/channel'
3
+ import type { GatewaysMeta } from '@pikku/core/gateway'
4
+ import type { HTTPWiringsMeta } from '@pikku/core/http'
5
+ import type { ScheduledTasksMeta } from '@pikku/core/scheduler'
6
+ import type { TriggerMeta, TriggerSourceMeta } from '@pikku/core/trigger'
7
+ import type { QueueWorkersMeta } from '@pikku/core/queue'
8
+ import type { WorkflowsMeta } from '@pikku/core/workflow'
9
+ import type {
10
+ MCPResourceMeta,
11
+ MCPToolMeta,
12
+ MCPPromptMeta,
13
+ } from '@pikku/core/mcp'
14
+ import type { AIAgentMeta } from '@pikku/core/ai-agent'
15
+ import type { CLIMeta } from '@pikku/core/cli'
16
+ import type { NodesMeta } from '@pikku/core/node'
17
+ import type { SecretDefinitions } from '@pikku/core/secret'
18
+ import type { VariableDefinitions } from '@pikku/core/variable'
19
+ import type { TypesMap } from './types-map.js'
20
+ import type {
16
21
  FunctionsMeta,
17
22
  FunctionServicesMeta,
18
23
  FunctionWiresMeta,
19
24
  JSONValue,
20
25
  } from '@pikku/core'
21
26
  import type { OpenAPISpecInfo } from './utils/serialize-openapi-json.js'
22
- import { ErrorCode } from './error-codes.js'
27
+ import type { ErrorCode } from './error-codes.js'
23
28
  import type {
24
29
  VersionManifest,
25
30
  VersionValidateError,
@@ -170,7 +175,7 @@ export type InspectorFilters = {
170
175
  httpMethods?: string[] // HTTP methods: "GET", "POST", "DELETE", etc.
171
176
  }
172
177
 
173
- export type ExternalPackageConfig = {
178
+ export type AddonConfig = {
174
179
  package: string
175
180
  rpcEndpoint?: string
176
181
  secretOverrides?: Record<string, string>
@@ -193,14 +198,13 @@ export type InspectorModelConfig = {
193
198
  export type InspectorOptions = Partial<{
194
199
  setupOnly: boolean
195
200
  rootDir: string
196
- isExternalPackage: boolean
201
+ isAddon: boolean
197
202
  types: Partial<{
198
203
  configFileType: string
199
204
  userSessionType: string
200
205
  singletonServicesFactoryType: string
201
206
  wireServicesFactoryType: string
202
207
  }>
203
- externalPackages: Record<string, ExternalPackageConfig>
204
208
  schemaConfig: {
205
209
  tsconfig: string
206
210
  schemasFromTypes?: string[]
@@ -300,6 +304,10 @@ export interface InspectorState {
300
304
  http: InspectorHTTPState
301
305
  functions: InspectorFunctionState
302
306
  channels: InspectorChannelState
307
+ gateways: {
308
+ meta: GatewaysMeta
309
+ files: Set<string>
310
+ }
303
311
  triggers: {
304
312
  meta: TriggerMeta
305
313
  sourceMeta: TriggerSourceMeta
@@ -326,7 +334,17 @@ export interface InspectorState {
326
334
  exposedMeta: Record<string, string>
327
335
  exposedFiles: Map<string, { path: string; exportedName: string }>
328
336
  invokedFunctions: Set<string>
329
- usedExternalPackages: Set<string>
337
+ usedAddons: Set<string>
338
+ wireAddonDeclarations: Map<
339
+ string,
340
+ {
341
+ package: string
342
+ rpcEndpoint?: string
343
+ secretOverrides?: Record<string, string>
344
+ variableOverrides?: Record<string, string>
345
+ }
346
+ >
347
+ wireAddonFiles: Set<string>
330
348
  }
331
349
  mcpEndpoints: {
332
350
  resourcesMeta: MCPResourceMeta
@@ -22,7 +22,7 @@ export function computeRequiredSchemas(
22
22
  ): Set<string> {
23
23
  return new Set<string>([
24
24
  ...Object.values(functionsMeta)
25
- .map(({ inputs, outputs }) => {
25
+ .flatMap(({ inputs, outputs }) => {
26
26
  const types: (string | undefined)[] = []
27
27
  if (inputs?.[0]) {
28
28
  try {
@@ -40,7 +40,6 @@ export function computeRequiredSchemas(
40
40
  }
41
41
  return types
42
42
  })
43
- .flat()
44
43
  .filter((s): s is string => !!s && !PRIMITIVE_TYPES.has(s)),
45
44
  ...typesMap.customTypes.keys(),
46
45
  ...(additionalTypes || []),
@@ -16,12 +16,22 @@ import { ErrorCode } from '../error-codes.js'
16
16
  function makeContracts(
17
17
  entries: Record<
18
18
  string,
19
- { functionKey: string; version: number; contractHash: string }
19
+ {
20
+ functionKey: string
21
+ version: number
22
+ contractHash: string
23
+ inputHash?: string
24
+ outputHash?: string
25
+ }
20
26
  >
21
27
  ): Map<string, ContractEntry> {
22
28
  const map = new Map<string, ContractEntry>()
23
29
  for (const [id, entry] of Object.entries(entries)) {
24
- map.set(id, entry)
30
+ map.set(id, {
31
+ ...entry,
32
+ inputHash: entry.inputHash ?? entry.contractHash.slice(0, 8),
33
+ outputHash: entry.outputHash ?? entry.contractHash.slice(0, 8),
34
+ })
25
35
  }
26
36
  return map
27
37
  }
@@ -414,11 +424,16 @@ describe('updateManifest', () => {
414
424
  functionKey: 'createUser',
415
425
  version: 1,
416
426
  contractHash: 'abc',
427
+ inputHash: 'in123456',
428
+ outputHash: 'out1234',
417
429
  },
418
430
  })
419
431
  const result = updateManifest(manifest, contracts)
420
432
  assert.strictEqual(result.contracts.createUser.latest, 1)
421
- assert.strictEqual(result.contracts.createUser.versions['1'], 'abc')
433
+ assert.deepStrictEqual(result.contracts.createUser.versions['1'], {
434
+ inputHash: 'in123456',
435
+ outputHash: 'out1234',
436
+ })
422
437
  })
423
438
 
424
439
  test('adds new version to existing function and updates latest', () => {
@@ -433,17 +448,27 @@ describe('updateManifest', () => {
433
448
  functionKey: 'createUser',
434
449
  version: 1,
435
450
  contractHash: 'aaa',
451
+ inputHash: 'inaaa123',
452
+ outputHash: 'outaaa12',
436
453
  },
437
454
  'createUser@v2': {
438
455
  functionKey: 'createUser',
439
456
  version: 2,
440
457
  contractHash: 'bbb',
458
+ inputHash: 'inbbb123',
459
+ outputHash: 'outbbb12',
441
460
  },
442
461
  })
443
462
  const result = updateManifest(manifest, contracts)
444
463
  assert.strictEqual(result.contracts.createUser.latest, 2)
445
- assert.strictEqual(result.contracts.createUser.versions['2'], 'bbb')
446
- assert.strictEqual(result.contracts.createUser.versions['1'], 'aaa')
464
+ assert.deepStrictEqual(result.contracts.createUser.versions['2'], {
465
+ inputHash: 'inbbb123',
466
+ outputHash: 'outbbb12',
467
+ })
468
+ assert.deepStrictEqual(result.contracts.createUser.versions['1'], {
469
+ inputHash: 'inaaa123',
470
+ outputHash: 'outaaa12',
471
+ })
447
472
  })
448
473
 
449
474
  test('preserves deleted functions', () => {