@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.
Files changed (219) hide show
  1. package/CHANGELOG.md +347 -0
  2. package/dist/add/add-analytics.d.ts +9 -0
  3. package/dist/add/add-analytics.js +178 -0
  4. package/dist/add/add-auth.js +0 -54
  5. package/dist/add/add-feature-flag.d.ts +2 -0
  6. package/dist/add/add-feature-flag.js +162 -0
  7. package/dist/add/add-wire-addon.js +1 -0
  8. package/dist/add/add-wire-remote-addon.js +1 -0
  9. package/dist/index.d.ts +3 -1
  10. package/dist/index.js +3 -1
  11. package/dist/inspector.js +4 -0
  12. package/dist/surface/collect-surface.d.ts +58 -0
  13. package/dist/surface/collect-surface.js +613 -0
  14. package/dist/types.d.ts +20 -11
  15. package/dist/utils/filter-inspector-state.js +23 -13
  16. package/dist/utils/post-process.js +15 -0
  17. package/dist/utils/read-module-specifiers.d.ts +8 -0
  18. package/dist/utils/read-module-specifiers.js +23 -0
  19. package/dist/utils/read-tsconfig-out-dir.d.ts +5 -0
  20. package/dist/utils/read-tsconfig-out-dir.js +12 -0
  21. package/dist/utils/resolve-deploy-target.d.ts +7 -0
  22. package/dist/utils/resolve-deploy-target.js +15 -7
  23. package/dist/utils/serialize-inspector-state.d.ts +5 -0
  24. package/dist/utils/serialize-inspector-state.js +8 -0
  25. package/dist/visit.js +4 -0
  26. package/package.json +16 -6
  27. package/run-tests.sh +21 -6
  28. package/src/add/add-addon-bans.ts +0 -85
  29. package/src/add/add-agent-scorer.test.ts +0 -197
  30. package/src/add/add-agent-scorer.ts +0 -83
  31. package/src/add/add-agent.test.ts +0 -87
  32. package/src/add/add-agent.ts +0 -638
  33. package/src/add/add-approval-description.ts +0 -76
  34. package/src/add/add-auth.test.ts +0 -791
  35. package/src/add/add-auth.ts +0 -424
  36. package/src/add/add-channel.ts +0 -778
  37. package/src/add/add-cli-renderers.test.ts +0 -74
  38. package/src/add/add-cli.ts +0 -1006
  39. package/src/add/add-credential.ts +0 -186
  40. package/src/add/add-feature.test.ts +0 -306
  41. package/src/add/add-feature.ts +0 -253
  42. package/src/add/add-file-extends-core-type.ts +0 -66
  43. package/src/add/add-file-with-config.ts +0 -45
  44. package/src/add/add-file-with-factory.test.ts +0 -134
  45. package/src/add/add-file-with-factory.ts +0 -288
  46. package/src/add/add-functions.test.ts +0 -743
  47. package/src/add/add-functions.ts +0 -1548
  48. package/src/add/add-gateway.ts +0 -143
  49. package/src/add/add-http-route-ref.test.ts +0 -149
  50. package/src/add/add-http-route.ts +0 -530
  51. package/src/add/add-http-routes.ts +0 -471
  52. package/src/add/add-keyed-wiring.ts +0 -180
  53. package/src/add/add-mcp-prompt.ts +0 -157
  54. package/src/add/add-mcp-resource.ts +0 -175
  55. package/src/add/add-middleware.test.ts +0 -196
  56. package/src/add/add-middleware.ts +0 -879
  57. package/src/add/add-permission-auth.test.ts +0 -59
  58. package/src/add/add-permission.ts +0 -311
  59. package/src/add/add-personas.test.ts +0 -406
  60. package/src/add/add-personas.ts +0 -287
  61. package/src/add/add-queue-worker.ts +0 -117
  62. package/src/add/add-rpc-invocations.test.ts +0 -287
  63. package/src/add/add-rpc-invocations.ts +0 -221
  64. package/src/add/add-scenario-step.test.ts +0 -509
  65. package/src/add/add-schedule.ts +0 -120
  66. package/src/add/add-scope.test.ts +0 -419
  67. package/src/add/add-scope.ts +0 -221
  68. package/src/add/add-secret.ts +0 -10
  69. package/src/add/add-subject-scenario-steps.test.ts +0 -161
  70. package/src/add/add-system-role.test.ts +0 -297
  71. package/src/add/add-system-role.ts +0 -162
  72. package/src/add/add-trigger.ts +0 -165
  73. package/src/add/add-variable.ts +0 -10
  74. package/src/add/add-wire-addon.test.ts +0 -185
  75. package/src/add/add-wire-addon.ts +0 -146
  76. package/src/add/add-wire-remote-addon.ts +0 -80
  77. package/src/add/add-workflow-edge-cases.test.ts +0 -201
  78. package/src/add/add-workflow-fanout.test.ts +0 -166
  79. package/src/add/add-workflow-graph-foreach.test.ts +0 -174
  80. package/src/add/add-workflow-graph-input.test.ts +0 -94
  81. package/src/add/add-workflow-graph-notes.test.ts +0 -74
  82. package/src/add/add-workflow-graph.ts +0 -644
  83. package/src/add/add-workflow-on-error.test.ts +0 -118
  84. package/src/add/add-workflow-return-switch.test.ts +0 -121
  85. package/src/add/add-workflow-silent-drops.test.ts +0 -261
  86. package/src/add/add-workflow-sleep-expression.test.ts +0 -96
  87. package/src/add/add-workflow.test.ts +0 -155
  88. package/src/add/add-workflow.ts +0 -482
  89. package/src/add/addon-bans.test.ts +0 -121
  90. package/src/add/addon-contracts.test.ts +0 -221
  91. package/src/add/allow-escape-hatches.test.ts +0 -144
  92. package/src/add/audit-meta.test.ts +0 -75
  93. package/src/add/classified-sink-check.test.ts +0 -347
  94. package/src/add/config-value-metadata.test.ts +0 -263
  95. package/src/add/dynamic-import-check.test.ts +0 -119
  96. package/src/add/expect-eventually-scenario-only.test.ts +0 -108
  97. package/src/add/function-body-span.test.ts +0 -96
  98. package/src/add/inline-wiring-function.test.ts +0 -104
  99. package/src/add/pii-check.test.ts +0 -258
  100. package/src/add/rpc-type-cast.test.ts +0 -123
  101. package/src/add/scenario-instrumentation.test.ts +0 -89
  102. package/src/add/scenario-instrumentation.ts +0 -42
  103. package/src/add/scenario-marker.test.ts +0 -89
  104. package/src/add/scenario-not-extractable.test.ts +0 -159
  105. package/src/add/scenario-services.test.ts +0 -103
  106. package/src/add/scenario-skip.test.ts +0 -83
  107. package/src/add/validate-workflow-graph-addons.test.ts +0 -102
  108. package/src/add/wire-name-literal.test.ts +0 -117
  109. package/src/error-codes-emitted.test.ts +0 -76
  110. package/src/error-codes.ts +0 -145
  111. package/src/index.ts +0 -66
  112. package/src/inspector.ts +0 -575
  113. package/src/schema-generator.ts +0 -1
  114. package/src/source-file-cache.ts +0 -73
  115. package/src/tsconfig-paths.test.ts +0 -90
  116. package/src/types-map.ts +0 -141
  117. package/src/types.ts +0 -775
  118. package/src/utils/annotate-http-route-auth.test.ts +0 -161
  119. package/src/utils/annotate-http-route-auth.ts +0 -53
  120. package/src/utils/check-classified-sinks.ts +0 -215
  121. package/src/utils/check-pii-output.ts +0 -120
  122. package/src/utils/compute-diagnostics.test.ts +0 -106
  123. package/src/utils/compute-required-schemas.ts +0 -48
  124. package/src/utils/contract-hashes.test.ts +0 -553
  125. package/src/utils/contract-hashes.ts +0 -387
  126. package/src/utils/custom-types-generator.test.ts +0 -124
  127. package/src/utils/custom-types-generator.ts +0 -150
  128. package/src/utils/detect-schema-vendor.test.ts +0 -123
  129. package/src/utils/detect-schema-vendor.ts +0 -120
  130. package/src/utils/does-type-extend-core-type.ts +0 -53
  131. package/src/utils/ensure-function-metadata.ts +0 -385
  132. package/src/utils/extract-function-name.ts +0 -612
  133. package/src/utils/extract-function-node.ts +0 -70
  134. package/src/utils/extract-node-value.test.ts +0 -117
  135. package/src/utils/extract-node-value.ts +0 -172
  136. package/src/utils/extract-secret-usage.test.ts +0 -81
  137. package/src/utils/extract-secret-usage.ts +0 -73
  138. package/src/utils/extract-services.ts +0 -70
  139. package/src/utils/extract-surface-usage.test.ts +0 -147
  140. package/src/utils/extract-surface-usage.ts +0 -121
  141. package/src/utils/filter-inspector-state.test.ts +0 -2207
  142. package/src/utils/filter-inspector-state.ts +0 -1302
  143. package/src/utils/filter-utils.test.ts +0 -843
  144. package/src/utils/filter-utils.ts +0 -161
  145. package/src/utils/find-root-dir.ts +0 -68
  146. package/src/utils/find-zod-transform.test.ts +0 -70
  147. package/src/utils/find-zod-transform.ts +0 -103
  148. package/src/utils/get-exported-variable-name.ts +0 -48
  149. package/src/utils/get-files-and-methods.ts +0 -157
  150. package/src/utils/get-property-value.test.ts +0 -141
  151. package/src/utils/get-property-value.ts +0 -331
  152. package/src/utils/hash.ts +0 -26
  153. package/src/utils/literal-properties.ts +0 -97
  154. package/src/utils/load-addon-functions-meta.test.ts +0 -157
  155. package/src/utils/load-addon-functions-meta.ts +0 -508
  156. package/src/utils/load-addon-scopes.test.ts +0 -138
  157. package/src/utils/middleware.test.ts +0 -204
  158. package/src/utils/middleware.ts +0 -303
  159. package/src/utils/nested-project-filter.test.ts +0 -53
  160. package/src/utils/nested-project-filter.ts +0 -28
  161. package/src/utils/permissions-shorthand.test.ts +0 -79
  162. package/src/utils/permissions.test.ts +0 -125
  163. package/src/utils/permissions.ts +0 -129
  164. package/src/utils/post-process.test.ts +0 -1094
  165. package/src/utils/post-process.ts +0 -1604
  166. package/src/utils/resolve-addon-package.ts +0 -106
  167. package/src/utils/resolve-core-type.test.ts +0 -142
  168. package/src/utils/resolve-core-type.ts +0 -35
  169. package/src/utils/resolve-deploy-target.test.ts +0 -135
  170. package/src/utils/resolve-deploy-target.ts +0 -65
  171. package/src/utils/resolve-function-meta.ts +0 -25
  172. package/src/utils/resolve-function-types.ts +0 -42
  173. package/src/utils/resolve-identifier.ts +0 -46
  174. package/src/utils/resolve-ref-contract.ts +0 -71
  175. package/src/utils/resolve-versions.test.ts +0 -499
  176. package/src/utils/resolve-versions.ts +0 -228
  177. package/src/utils/schema-cache.test.ts +0 -124
  178. package/src/utils/schema-generator.test.ts +0 -272
  179. package/src/utils/schema-generator.ts +0 -780
  180. package/src/utils/secret-alias-services.test.ts +0 -146
  181. package/src/utils/secret-alias-services.ts +0 -58
  182. package/src/utils/serialize-inspector-state.ts +0 -742
  183. package/src/utils/serialize-mcp-json.ts +0 -150
  184. package/src/utils/serialize-middleware-groups-meta.ts +0 -36
  185. package/src/utils/serialize-openapi-json.ts +0 -277
  186. package/src/utils/serialize-permissions-groups-meta.ts +0 -7
  187. package/src/utils/single-declaration.ts +0 -57
  188. package/src/utils/type-utils.ts +0 -145
  189. package/src/utils/validate-auth-sessionless.ts +0 -30
  190. package/src/utils/validate-exposed-functions-gated.test.ts +0 -230
  191. package/src/utils/validate-exposed-functions-gated.ts +0 -103
  192. package/src/utils/validate-tags-resolve-to-middleware.test.ts +0 -108
  193. package/src/utils/validate-tags-resolve-to-middleware.ts +0 -48
  194. package/src/utils/workflow/derive-workflow-plan.test.ts +0 -178
  195. package/src/utils/workflow/derive-workflow-plan.ts +0 -117
  196. package/src/utils/workflow/dsl/deserialize-dsl-workflow.ts +0 -1465
  197. package/src/utils/workflow/dsl/deserialize-fanout-body.test.ts +0 -71
  198. package/src/utils/workflow/dsl/deserialize-fanout-fidelity.test.ts +0 -99
  199. package/src/utils/workflow/dsl/deserialize-graph-next.test.ts +0 -161
  200. package/src/utils/workflow/dsl/deserialize-roundtrip-bindings.test.ts +0 -121
  201. package/src/utils/workflow/dsl/deserialize-roundtrip-values.test.ts +0 -116
  202. package/src/utils/workflow/dsl/deserialize-roundtrip.test.ts +0 -145
  203. package/src/utils/workflow/dsl/extract-approval-policy.test.ts +0 -71
  204. package/src/utils/workflow/dsl/extract-dsl-workflow.ts +0 -2254
  205. package/src/utils/workflow/dsl/index.ts +0 -11
  206. package/src/utils/workflow/dsl/patterns.ts +0 -440
  207. package/src/utils/workflow/dsl/validation.ts +0 -203
  208. package/src/utils/workflow/graph/convert-dsl-to-graph-skip.test.ts +0 -35
  209. package/src/utils/workflow/graph/convert-dsl-to-graph.ts +0 -543
  210. package/src/utils/workflow/graph/fanout-node-identity.test.ts +0 -105
  211. package/src/utils/workflow/graph/finalize-workflow-wires.ts +0 -310
  212. package/src/utils/workflow/graph/finalize-workflows.test.ts +0 -50
  213. package/src/utils/workflow/graph/finalize-workflows.ts +0 -130
  214. package/src/utils/workflow/graph/index.ts +0 -28
  215. package/src/utils/workflow/graph/serialize-workflow-graph.ts +0 -240
  216. package/src/utils/workflow/graph/workflow-graph.types.ts +0 -281
  217. package/src/visit.ts +0 -181
  218. package/tsconfig.json +0 -19
  219. package/tsconfig.tsbuildinfo +0 -1
@@ -1,161 +0,0 @@
1
- import type { InspectorFilters, InspectorLogger } from '../types.js'
2
- import type { PikkuWiringTypes } from '@pikku/core/types'
3
-
4
- /**
5
- * Match a value against a pattern with wildcard support
6
- * Supports "*" at the beginning, end, or both (e.g., "send*", "*Payment", "*process*")
7
- * @param value - The value to check
8
- * @param pattern - The pattern with optional "*" wildcard(s)
9
- */
10
- export function matchesWildcard(value: string, pattern: string): boolean {
11
- // If pattern is just '*', match everything
12
- if (pattern === '*') {
13
- return true
14
- }
15
-
16
- const startsWithWildcard = pattern.startsWith('*')
17
- const endsWithWildcard = pattern.endsWith('*')
18
-
19
- if (startsWithWildcard && endsWithWildcard) {
20
- // Pattern like "*middle*" - check if value contains the middle part
21
- const middle = pattern.slice(1, -1)
22
- if (middle === '') {
23
- return true // Pattern is "**", match everything
24
- }
25
- return value.includes(middle)
26
- } else if (startsWithWildcard) {
27
- // Pattern like "*suffix" - check if value ends with suffix and has content before
28
- const suffix = pattern.slice(1)
29
- return value.endsWith(suffix) && value.length > suffix.length
30
- } else if (endsWithWildcard) {
31
- // Pattern like "prefix*" - check if value starts with prefix and has content after
32
- const prefix = pattern.slice(0, -1)
33
- return value.startsWith(prefix) && value.length > prefix.length
34
- }
35
-
36
- // No wildcard, exact match
37
- return value === pattern
38
- }
39
-
40
- export const matchesFilters = (
41
- filters: InspectorFilters,
42
- params: {
43
- tags?: string[]
44
- name?: string // Wire/function name for name filter
45
- },
46
- meta: {
47
- type: PikkuWiringTypes
48
- name: string
49
- filePath?: string
50
- httpRoute?: string // For HTTP route filtering
51
- httpMethod?: string // For HTTP method filtering
52
- },
53
- logger: InspectorLogger
54
- ) => {
55
- // If no filters are provided, allow everything
56
- if (Object.keys(filters).length === 0) {
57
- return true
58
- }
59
-
60
- // If all filter arrays are empty, allow everything
61
- if (
62
- (!filters.names || filters.names.length === 0) &&
63
- (!filters.tags || filters.tags.length === 0) &&
64
- (!filters.wires || filters.wires.length === 0) &&
65
- (!filters.excludeWires || filters.excludeWires.length === 0) &&
66
- (!filters.directories || filters.directories.length === 0) &&
67
- (!filters.httpRoutes || filters.httpRoutes.length === 0) &&
68
- (!filters.httpMethods || filters.httpMethods.length === 0)
69
- ) {
70
- return true
71
- }
72
-
73
- // Check wire include filter
74
- if (filters.wires && filters.wires.length > 0) {
75
- if (!filters.wires.includes(meta.type)) {
76
- logger.debug(`⒡ Filtered by wire include: ${meta.type}:${meta.name}`)
77
- return false
78
- }
79
- }
80
-
81
- // Check wire exclude filter
82
- if (filters.excludeWires && filters.excludeWires.length > 0) {
83
- if (filters.excludeWires.includes(meta.type)) {
84
- logger.debug(`⒡ Filtered by wire exclude: ${meta.type}:${meta.name}`)
85
- return false
86
- }
87
- }
88
-
89
- // Check directory filter
90
- if (filters.directories && filters.directories.length > 0) {
91
- if (!meta.filePath) {
92
- logger.debug(
93
- `⒡ Filtered by directory: ${meta.type}:${meta.name} (${meta.filePath})`
94
- )
95
- return false
96
- }
97
-
98
- const matchesDirectory = filters.directories.some((dir) => {
99
- // Normalize paths for comparison
100
- const normalizedFilePath = meta.filePath!.replace(/\\/g, '/')
101
- const normalizedDir = dir.replace(/\\/g, '/')
102
- return normalizedFilePath.includes(normalizedDir)
103
- })
104
-
105
- if (!matchesDirectory) {
106
- logger.debug(
107
- `⒡ Filtered by directory: ${meta.type}:${meta.name} (${meta.filePath})`
108
- )
109
- return false
110
- }
111
- }
112
-
113
- // Check tag filter
114
- if (filters.tags && filters.tags.length > 0) {
115
- if (
116
- !params.tags ||
117
- !filters.tags.some((tag) => params.tags!.includes(tag))
118
- ) {
119
- logger.debug(`⒡ Filtered by tags: ${meta.type}:${meta.name}`)
120
- return false
121
- }
122
- }
123
-
124
- // Check name filter (with wildcard support)
125
- if (filters.names && filters.names.length > 0) {
126
- const nameToMatch = params.name || meta.name
127
- const nameMatches = filters.names.some((pattern) =>
128
- matchesWildcard(nameToMatch, pattern)
129
- )
130
- if (!nameMatches) {
131
- logger.debug(`⒡ Filtered by name: ${meta.type}:${meta.name}`)
132
- return false
133
- }
134
- }
135
-
136
- // Check HTTP route filter (with wildcard support)
137
- if (filters.httpRoutes && filters.httpRoutes.length > 0 && meta.httpRoute) {
138
- const routeMatches = filters.httpRoutes.some((pattern) =>
139
- matchesWildcard(meta.httpRoute!, pattern)
140
- )
141
- if (!routeMatches) {
142
- logger.debug(`⒡ Filtered by HTTP route: ${meta.httpRoute}`)
143
- return false
144
- }
145
- }
146
-
147
- // Check HTTP method filter
148
- if (
149
- filters.httpMethods &&
150
- filters.httpMethods.length > 0 &&
151
- meta.httpMethod
152
- ) {
153
- const normalizedMethod = meta.httpMethod.toUpperCase()
154
- if (!filters.httpMethods.includes(normalizedMethod)) {
155
- logger.debug(`⒡ Filtered by HTTP method: ${meta.httpMethod}`)
156
- return false
157
- }
158
- }
159
-
160
- return true
161
- }
@@ -1,68 +0,0 @@
1
- import path from 'path'
2
-
3
- /**
4
- * Finds the common ancestor directory of all the given file paths.
5
- * This is used to determine the project root directory.
6
- *
7
- * @param filePaths - Array of absolute file paths
8
- * @returns The common ancestor directory path
9
- *
10
- * @example
11
- * findCommonAncestor([
12
- * '/Users/yasser/git/pikku/pikku/src/functions/a.ts',
13
- * '/Users/yasser/git/pikku/pikku/src/routes/b.ts'
14
- * ])
15
- * // Returns: '/Users/yasser/git/pikku/pikku'
16
- */
17
- export function findCommonAncestor(filePaths: string[]): string {
18
- if (filePaths.length === 0) {
19
- return process.cwd()
20
- }
21
-
22
- if (filePaths.length === 1) {
23
- return path.dirname(filePaths[0]!)
24
- }
25
-
26
- // Normalize all paths and get their directory parts
27
- const normalizedPaths = filePaths.map((p) =>
28
- path.dirname(path.normalize(p)).split(path.sep)
29
- )
30
-
31
- // Start with the first path's parts
32
- const firstPath = normalizedPaths[0]!
33
- let commonParts: string[] = []
34
-
35
- // Check each part of the first path
36
- for (let i = 0; i < firstPath.length; i++) {
37
- const part = firstPath[i]!
38
-
39
- // Check if this part exists in all other paths at the same position
40
- const existsInAll = normalizedPaths.every(
41
- (pathParts) => pathParts[i] === part
42
- )
43
-
44
- if (existsInAll) {
45
- commonParts.push(part)
46
- } else {
47
- break
48
- }
49
- }
50
-
51
- // If no common parts, return root
52
- if (commonParts.length === 0) {
53
- return path.sep
54
- }
55
-
56
- return commonParts.join(path.sep)
57
- }
58
-
59
- /**
60
- * Converts an absolute file path to a relative path from the root directory.
61
- *
62
- * @param absolutePath - The absolute file path
63
- * @param rootDir - The root directory to make the path relative to
64
- * @returns A relative path from rootDir to the file
65
- */
66
- export function toRelativePath(absolutePath: string, rootDir: string): string {
67
- return path.relative(rootDir, absolutePath)
68
- }
@@ -1,70 +0,0 @@
1
- import { test } from 'node:test'
2
- import assert from 'node:assert/strict'
3
- import * as z from 'zod'
4
- import { findZodTransform } from './find-zod-transform.js'
5
-
6
- test('a schema with no transform is reported as clean', () => {
7
- assert.equal(findZodTransform(z.object({ id: z.string() })), undefined)
8
- assert.equal(findZodTransform(z.string().min(1).trim()), undefined)
9
- // a refinement narrows the value, it does not change its shape
10
- assert.equal(
11
- findZodTransform(z.object({ id: z.string() }).refine(() => true)),
12
- undefined
13
- )
14
- })
15
-
16
- test('a transform on the schema itself is found at the root', () => {
17
- assert.equal(
18
- findZodTransform(z.object({ id: z.string() }).transform((v) => v)),
19
- ''
20
- )
21
- })
22
-
23
- test('a transform on a field is found by path', () => {
24
- assert.equal(
25
- findZodTransform(
26
- z.object({
27
- id: z.string(),
28
- when: z.string().transform((s) => new Date(s)),
29
- })
30
- ),
31
- '.when'
32
- )
33
- })
34
-
35
- test('a transform is found through wrappers, arrays and unions', () => {
36
- assert.equal(
37
- findZodTransform(
38
- z.object({ tags: z.array(z.string().transform((s) => s.trim())) })
39
- ),
40
- '.tags[]'
41
- )
42
- assert.equal(
43
- findZodTransform(z.object({ n: z.string().transform(Number).optional() })),
44
- '.n'
45
- )
46
- assert.equal(
47
- findZodTransform(
48
- z.object({ v: z.union([z.string(), z.number().transform(String)]) })
49
- ),
50
- '.v|1'
51
- )
52
- assert.equal(
53
- findZodTransform(
54
- z.object({
55
- m: z.record(
56
- z.string(),
57
- z.string().transform((s) => s)
58
- ),
59
- })
60
- ),
61
- '.m[]'
62
- )
63
- })
64
-
65
- test('a self-referencing schema terminates instead of recursing forever', () => {
66
- const node: z.ZodType = z.lazy(() =>
67
- z.object({ name: z.string(), children: z.array(node) })
68
- )
69
- assert.equal(findZodTransform(node), undefined)
70
- })
@@ -1,103 +0,0 @@
1
- /**
2
- * Locate a `.transform()` anywhere inside a Zod schema.
3
- *
4
- * A transform is why a schema cannot be a function's `input`: the value the
5
- * caller sends and the value the function receives are different, and a wire
6
- * contract has to describe one shape. Zod says so twice, in two different
7
- * places, and neither says it usefully on its own — `toJSONSchema` with
8
- * `unrepresentable: 'any'` quietly yields `{}`, a schema that accepts
9
- * everything, and `zodToTs` throws about TypeScript rather than about the
10
- * wiring. Finding it up front lets the diagnostic name the schema, the path,
11
- * and the call.
12
- *
13
- * Zod 4 models `x.transform(fn)` as a `pipe` whose `out` is a `transform`, so
14
- * the walk looks for that node rather than for the method.
15
- */
16
-
17
- /** Max nodes visited, so a pathological or cyclic schema cannot hang the walk. */
18
- const MAX_NODES = 10_000
19
-
20
- interface ZodNode {
21
- _zod?: { def?: Record<string, any> }
22
- }
23
-
24
- const isNode = (value: unknown): value is ZodNode =>
25
- typeof value === 'object' &&
26
- value !== null &&
27
- typeof (value as ZodNode)._zod?.def?.type === 'string'
28
-
29
- /**
30
- * The path to the first `.transform()` found — `''` when the transform is the
31
- * schema itself, `'.user.email'` when it is nested — or `undefined` when there
32
- * is none.
33
- */
34
- export function findZodTransform(schema: unknown): string | undefined {
35
- const seen = new Set<unknown>()
36
- let budget = MAX_NODES
37
-
38
- const walk = (node: unknown, path: string): string | undefined => {
39
- if (budget-- <= 0 || !isNode(node) || seen.has(node)) return undefined
40
- seen.add(node)
41
-
42
- const def = node._zod!.def!
43
- if (def.type === 'transform') return path
44
-
45
- const children: Array<[unknown, string]> = []
46
- switch (def.type) {
47
- case 'object':
48
- case 'interface':
49
- for (const [key, child] of Object.entries(def.shape ?? {})) {
50
- children.push([child, `${path}.${key}`])
51
- }
52
- break
53
- case 'array':
54
- case 'set':
55
- children.push([def.element, `${path}[]`])
56
- break
57
- case 'tuple':
58
- for (const [i, child] of (def.items ?? []).entries()) {
59
- children.push([child, `${path}[${i}]`])
60
- }
61
- if (def.rest) children.push([def.rest, `${path}[]`])
62
- break
63
- case 'union':
64
- for (const [i, child] of (def.options ?? []).entries()) {
65
- children.push([child, `${path}|${i}`])
66
- }
67
- break
68
- case 'intersection':
69
- children.push([def.left, path], [def.right, path])
70
- break
71
- case 'record':
72
- case 'map':
73
- children.push(
74
- [def.keyType, `${path}[key]`],
75
- [def.valueType, `${path}[]`]
76
- )
77
- break
78
- case 'pipe':
79
- // `.transform()` itself: report the pipe's own path, not `out`'s.
80
- children.push([def.in, path], [def.out, path])
81
- break
82
- default:
83
- // optional, nullable, default, prefault, nonoptional, readonly, catch,
84
- // promise, lazy, success — every wrapper Zod spells `innerType`.
85
- if (def.innerType) children.push([def.innerType, path])
86
- if (def.getter) {
87
- try {
88
- children.push([def.getter(), path])
89
- } catch {
90
- // A lazy schema that cannot be forced tells us nothing; skip it.
91
- }
92
- }
93
- }
94
-
95
- for (const [child, childPath] of children) {
96
- const found = walk(child, childPath)
97
- if (found !== undefined) return found
98
- }
99
- return undefined
100
- }
101
-
102
- return walk(schema, '')
103
- }
@@ -1,48 +0,0 @@
1
- import * as ts from 'typescript'
2
-
3
- const isExportedVariableStatement = (
4
- statement: ts.Statement
5
- ): statement is ts.VariableStatement =>
6
- ts.isVariableStatement(statement) &&
7
- (statement.modifiers?.some(
8
- (modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword
9
- ) ??
10
- false)
11
-
12
- export const getExportedVariableName = (
13
- node: ts.Node,
14
- sourceFile: ts.SourceFile | undefined
15
- ): string | null => {
16
- if (!sourceFile) {
17
- return null
18
- }
19
-
20
- if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name)) {
21
- for (const statement of sourceFile.statements) {
22
- if (!isExportedVariableStatement(statement)) continue
23
- for (const declaration of statement.declarationList.declarations) {
24
- if (declaration === node) {
25
- return node.name.text
26
- }
27
- }
28
- }
29
- }
30
-
31
- if (!ts.isCallExpression(node)) {
32
- return null
33
- }
34
-
35
- for (const statement of sourceFile.statements) {
36
- if (!isExportedVariableStatement(statement)) continue
37
- for (const declaration of statement.declarationList.declarations) {
38
- if (
39
- ts.isIdentifier(declaration.name) &&
40
- declaration.initializer === node
41
- ) {
42
- return declaration.name.text
43
- }
44
- }
45
- }
46
-
47
- return null
48
- }
@@ -1,157 +0,0 @@
1
- import type {
2
- PathToNameAndType,
3
- InspectorState,
4
- InspectorOptions,
5
- } from '../types.js'
6
-
7
- interface Meta {
8
- file: string
9
- variable: string
10
- type: string
11
- typePath: string
12
- }
13
-
14
- export type FilesAndMethods = {
15
- userSessionType: Meta
16
- wireServicesType: Meta
17
- singletonServicesType: Meta
18
- pikkuConfigType: Meta
19
- pikkuConfigFactory: Meta
20
- singletonServicesFactory: Meta
21
- wireServicesFactory: Meta
22
- serverLifecycleFactory: Meta
23
- }
24
-
25
- export type FilesAndMethodsErrors = Map<string, PathToNameAndType>
26
-
27
- const getMetaTypes = (
28
- type: string,
29
- map: PathToNameAndType,
30
- desiredType?: string,
31
- errors?: FilesAndMethodsErrors
32
- ): Meta | undefined => {
33
- if (desiredType) {
34
- for (const [file, meta] of map.entries()) {
35
- for (const { type: entryType, variable, typePath } of meta) {
36
- if (entryType === desiredType) {
37
- if (entryType === null || typePath === null) {
38
- throw new Error(
39
- `Unknown state due to metaType calculation: entryType or typePath is null for ${desiredType} in ${file}`
40
- )
41
- }
42
- return { file, variable, type: entryType, typePath }
43
- }
44
- }
45
- }
46
- if (errors) {
47
- errors.set(`No ${desiredType} found that extends ${type}`, map)
48
- }
49
- return
50
- }
51
-
52
- const totalValues = Array.from(map.values()).flat()
53
-
54
- if (totalValues.length === 0) {
55
- const helpMessage =
56
- type === 'CoreConfig'
57
- ? `No ${type} found. Make sure you have exported a createConfig function in your codebase:\n\n` +
58
- `export const createConfig = pikkuConfig(async () => {\n` +
59
- ` return {}\n` +
60
- `})\n\n` +
61
- `Possible issues:\n` +
62
- `- srcDirectories in pikku.config.json doesn't include the file with the createConfig method`
63
- : `No ${type} found`
64
- if (errors) {
65
- errors.set(helpMessage, map)
66
- }
67
- } else if (totalValues.length > 1) {
68
- if (errors) {
69
- errors.set(`More than one ${type} found`, map)
70
- }
71
- } else {
72
- const entry = Array.from(map.entries())[0]
73
- if (entry) {
74
- const [file, [{ type: entryType, variable, typePath }]] = entry
75
- if (entryType === null || typePath === null) {
76
- throw new Error(
77
- `Unknown state due to metaType calculation: entryType or typePath is null for ${type} in ${file}`
78
- )
79
- }
80
- return { file, type: entryType, variable, typePath }
81
- }
82
- }
83
-
84
- return
85
- }
86
-
87
- export const getFilesAndMethods = (
88
- {
89
- singletonServicesTypeImportMap,
90
- wireServicesTypeImportMap,
91
- userSessionTypeImportMap,
92
- configTypeImportMap,
93
- wireServicesFactories,
94
- singletonServicesFactories,
95
- configFactories,
96
- serverLifecycleFactories,
97
- }: InspectorState,
98
- {
99
- configFileType,
100
- userSessionType,
101
- singletonServicesFactoryType,
102
- wireServicesFactoryType,
103
- }: InspectorOptions['types'] = {}
104
- ): { result: Partial<FilesAndMethods>; errors: FilesAndMethodsErrors } => {
105
- const errors: FilesAndMethodsErrors = new Map()
106
-
107
- const result: Partial<FilesAndMethods> = {
108
- userSessionType: getMetaTypes(
109
- 'CoreUserSession',
110
- userSessionTypeImportMap,
111
- userSessionType,
112
- errors
113
- ),
114
- singletonServicesType: getMetaTypes(
115
- 'CoreSingletonServices',
116
- singletonServicesTypeImportMap,
117
- undefined,
118
- errors
119
- ),
120
- wireServicesType: getMetaTypes(
121
- 'CoreServices',
122
- wireServicesTypeImportMap,
123
- undefined,
124
- errors
125
- ),
126
- pikkuConfigType: getMetaTypes(
127
- 'CoreConfig',
128
- configTypeImportMap,
129
- undefined,
130
- errors
131
- ),
132
- pikkuConfigFactory: getMetaTypes(
133
- 'CoreConfig',
134
- configFactories,
135
- configFileType,
136
- errors
137
- ),
138
- singletonServicesFactory: getMetaTypes(
139
- 'CreateSingletonServices',
140
- singletonServicesFactories,
141
- singletonServicesFactoryType,
142
- errors
143
- ),
144
- wireServicesFactory: getMetaTypes(
145
- 'CreateWireServices',
146
- wireServicesFactories,
147
- wireServicesFactoryType,
148
- errors
149
- ),
150
- serverLifecycleFactory: getMetaTypes(
151
- 'ServerLifecycle',
152
- serverLifecycleFactories
153
- ),
154
- }
155
-
156
- return { result, errors }
157
- }