@pikku/inspector 0.12.3 → 0.12.5
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 +42 -0
- package/dist/add/add-credential.d.ts +2 -0
- package/dist/add/add-credential.js +118 -0
- package/dist/add/add-middleware.js +6 -10
- package/dist/add/add-permission.js +10 -12
- package/dist/add/add-secret.d.ts +1 -3
- package/dist/add/add-secret.js +0 -74
- package/dist/add/add-workflow.js +7 -1
- package/dist/error-codes.d.ts +1 -0
- package/dist/error-codes.js +2 -0
- package/dist/inspector.js +18 -7
- package/dist/types.d.ts +7 -0
- package/dist/utils/custom-types-generator.js +1 -0
- package/dist/utils/post-process.d.ts +9 -0
- package/dist/utils/post-process.js +46 -0
- package/dist/utils/schema-generator.js +26 -6
- package/dist/utils/serialize-inspector-state.d.ts +4 -0
- package/dist/utils/serialize-inspector-state.js +9 -0
- package/dist/utils/workflow/graph/convert-dsl-to-graph.js +1 -0
- package/dist/utils/workflow/graph/workflow-graph.types.d.ts +2 -0
- package/dist/visit.js +3 -2
- package/package.json +4 -3
- package/src/add/add-credential.ts +178 -0
- package/src/add/add-middleware.ts +6 -14
- package/src/add/add-permission.ts +10 -16
- package/src/add/add-secret.ts +0 -131
- package/src/add/add-workflow.ts +11 -1
- package/src/error-codes.ts +3 -0
- package/src/inspector.ts +25 -6
- package/src/types.ts +7 -0
- package/src/utils/custom-types-generator.ts +1 -0
- package/src/utils/post-process.ts +59 -0
- package/src/utils/schema-generator.ts +38 -10
- package/src/utils/serialize-inspector-state.ts +13 -0
- package/src/utils/workflow/graph/convert-dsl-to-graph.ts +1 -0
- package/src/utils/workflow/graph/workflow-graph.types.ts +2 -0
- package/src/visit.ts +3 -2
- package/tsconfig.tsbuildinfo +1 -1
package/src/types.ts
CHANGED
|
@@ -15,6 +15,7 @@ import type { AIAgentMeta } from '@pikku/core/ai-agent'
|
|
|
15
15
|
import type { CLIMeta } from '@pikku/core/cli'
|
|
16
16
|
import type { NodesMeta } from '@pikku/core/node'
|
|
17
17
|
import type { SecretDefinitions } from '@pikku/core/secret'
|
|
18
|
+
import type { CredentialDefinitions } from '@pikku/core/credential'
|
|
18
19
|
import type { VariableDefinitions } from '@pikku/core/variable'
|
|
19
20
|
import type { TypesMap } from './types-map.js'
|
|
20
21
|
import type {
|
|
@@ -225,6 +226,7 @@ export type InspectorOptions = Partial<{
|
|
|
225
226
|
tags: string[]
|
|
226
227
|
manifest: VersionManifest
|
|
227
228
|
modelConfig: InspectorModelConfig
|
|
229
|
+
oldProgram: ts.Program | undefined
|
|
228
230
|
}>
|
|
229
231
|
|
|
230
232
|
export interface InspectorLogger {
|
|
@@ -378,6 +380,10 @@ export interface InspectorState {
|
|
|
378
380
|
definitions: SecretDefinitions
|
|
379
381
|
files: Set<string>
|
|
380
382
|
}
|
|
383
|
+
credentials: {
|
|
384
|
+
definitions: CredentialDefinitions
|
|
385
|
+
files: Set<string>
|
|
386
|
+
}
|
|
381
387
|
variables: {
|
|
382
388
|
definitions: VariableDefinitions
|
|
383
389
|
files: Set<string>
|
|
@@ -420,4 +426,5 @@ export interface InspectorState {
|
|
|
420
426
|
openAPISpec: Record<string, any> | null
|
|
421
427
|
diagnostics: InspectorDiagnostic[]
|
|
422
428
|
addonFunctions: Record<string, FunctionsMeta> // namespace -> addon's function metadata
|
|
429
|
+
program: ts.Program | null // Retained for incremental re-inspection
|
|
423
430
|
}
|
|
@@ -16,6 +16,7 @@ export function generateCustomTypes(
|
|
|
16
16
|
requiredTypes: Set<string>
|
|
17
17
|
) {
|
|
18
18
|
const typeDeclarations = Array.from(typesMap.customTypes.entries())
|
|
19
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
19
20
|
.filter(([_name, { type }]) => {
|
|
20
21
|
const hasUndefinedGeneric =
|
|
21
22
|
/\b(Name|In|Out|Key)\b/.test(type) && /\[.*\]/.test(type)
|
|
@@ -492,6 +492,65 @@ export function validateAgentOverrides(
|
|
|
492
492
|
}
|
|
493
493
|
}
|
|
494
494
|
|
|
495
|
+
/**
|
|
496
|
+
* Validates that Zod schemas and wiring side-effects (wireHTTPRoutes,
|
|
497
|
+
* addPermission, addHTTPMiddleware, etc.) do not coexist in the same file.
|
|
498
|
+
*
|
|
499
|
+
* The CLI uses tsImport to extract Zod schemas at runtime, which executes
|
|
500
|
+
* all top-level code in the file. Wiring calls crash during this process
|
|
501
|
+
* because the pikku state metadata doesn't exist in the CLI context.
|
|
502
|
+
*/
|
|
503
|
+
export function validateSchemaWiringSeparation(
|
|
504
|
+
logger: InspectorLogger,
|
|
505
|
+
state: InspectorState
|
|
506
|
+
): void {
|
|
507
|
+
// Collect files that contain schemas
|
|
508
|
+
const schemaFiles = new Set<string>()
|
|
509
|
+
for (const ref of state.schemaLookup.values()) {
|
|
510
|
+
schemaFiles.add(ref.sourceFile)
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// Collect files that contain wiring side-effects
|
|
514
|
+
const wiringFiles = new Set<string>()
|
|
515
|
+
|
|
516
|
+
// HTTP route wirings
|
|
517
|
+
for (const file of state.http.files) {
|
|
518
|
+
wiringFiles.add(file)
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// Permission wirings (addPermission calls)
|
|
522
|
+
for (const meta of state.permissions.tagPermissions.values()) {
|
|
523
|
+
wiringFiles.add(meta.sourceFile)
|
|
524
|
+
}
|
|
525
|
+
for (const meta of state.http.routePermissions.values()) {
|
|
526
|
+
wiringFiles.add(meta.sourceFile)
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// Middleware wirings (addHTTPMiddleware calls)
|
|
530
|
+
for (const meta of state.http.routeMiddleware.values()) {
|
|
531
|
+
wiringFiles.add(meta.sourceFile)
|
|
532
|
+
}
|
|
533
|
+
for (const meta of state.middleware.tagMiddleware.values()) {
|
|
534
|
+
wiringFiles.add(meta.sourceFile)
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// Check for overlap
|
|
538
|
+
for (const file of schemaFiles) {
|
|
539
|
+
if (wiringFiles.has(file)) {
|
|
540
|
+
const schemas = Array.from(state.schemaLookup.entries())
|
|
541
|
+
.filter(([, ref]) => ref.sourceFile === file)
|
|
542
|
+
.map(([name]) => name)
|
|
543
|
+
|
|
544
|
+
logger.critical(
|
|
545
|
+
ErrorCode.SCHEMA_AND_WIRING_COLOCATED,
|
|
546
|
+
`File '${file}' contains both Zod schemas (${schemas.join(', ')}) and wiring calls (wireHTTPRoutes, addPermission, etc.). ` +
|
|
547
|
+
`These must be in separate files because the CLI imports schema files at runtime, which triggers wiring side-effects that crash without server context. ` +
|
|
548
|
+
`Move the route/wiring definitions to a dedicated wiring file.`
|
|
549
|
+
)
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
495
554
|
export function computeDiagnostics(state: InspectorState): void {
|
|
496
555
|
const diagnostics: InspectorDiagnostic[] = []
|
|
497
556
|
|
|
@@ -63,24 +63,37 @@ function primitiveTypeToSchema(typeStr: string): JSONValue | null {
|
|
|
63
63
|
return null
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
// Cached state for schema program reuse across inspect() calls
|
|
67
|
+
let cachedSchemaProgram: ts.Program | undefined
|
|
68
|
+
let cachedParsedConfig: ts.ParsedCommandLine | undefined
|
|
69
|
+
let cachedTsconfigPath: string | undefined
|
|
70
|
+
let cachedCustomTypesContent: string | undefined
|
|
71
|
+
let cachedTSSchemas: Record<string, JSONValue> | undefined
|
|
72
|
+
|
|
66
73
|
function createProgramWithVirtualFile(
|
|
67
74
|
tsconfig: string,
|
|
68
75
|
virtualFilePath: string,
|
|
69
76
|
virtualFileContent: string
|
|
70
77
|
): ts.Program {
|
|
71
78
|
const configPath = resolve(tsconfig)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
configFile.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
|
|
80
|
+
// Cache the parsed tsconfig — it doesn't change between runs
|
|
81
|
+
if (!cachedParsedConfig || cachedTsconfigPath !== configPath) {
|
|
82
|
+
const configFile = ts.readConfigFile(configPath, ts.sys.readFile)
|
|
83
|
+
const basePath = dirname(configPath)
|
|
84
|
+
cachedParsedConfig = ts.parseJsonConfigFileContent(
|
|
85
|
+
configFile.config,
|
|
86
|
+
ts.sys,
|
|
87
|
+
basePath
|
|
88
|
+
)
|
|
89
|
+
cachedTsconfigPath = configPath
|
|
90
|
+
cachedSchemaProgram = undefined
|
|
91
|
+
}
|
|
79
92
|
|
|
80
93
|
const resolvedVirtualPath = resolve(virtualFilePath)
|
|
81
|
-
const fileNames = [...
|
|
94
|
+
const fileNames = [...cachedParsedConfig.fileNames, resolvedVirtualPath]
|
|
82
95
|
|
|
83
|
-
const defaultHost = ts.createCompilerHost(
|
|
96
|
+
const defaultHost = ts.createCompilerHost(cachedParsedConfig.options)
|
|
84
97
|
const customHost: ts.CompilerHost = {
|
|
85
98
|
...defaultHost,
|
|
86
99
|
getSourceFile(
|
|
@@ -113,7 +126,14 @@ function createProgramWithVirtualFile(
|
|
|
113
126
|
},
|
|
114
127
|
}
|
|
115
128
|
|
|
116
|
-
|
|
129
|
+
const program = ts.createProgram(
|
|
130
|
+
fileNames,
|
|
131
|
+
cachedParsedConfig.options,
|
|
132
|
+
customHost,
|
|
133
|
+
cachedSchemaProgram // reuse previous program for incremental compilation
|
|
134
|
+
)
|
|
135
|
+
cachedSchemaProgram = program
|
|
136
|
+
return program
|
|
117
137
|
}
|
|
118
138
|
|
|
119
139
|
function generateTSSchemas(
|
|
@@ -313,6 +333,11 @@ export async function generateAllSchemas(
|
|
|
313
333
|
requiredTypes
|
|
314
334
|
)
|
|
315
335
|
|
|
336
|
+
if (cachedTSSchemas && cachedCustomTypesContent === customTypesContent) {
|
|
337
|
+
logger.debug('Reusing cached TS schemas (types unchanged)')
|
|
338
|
+
return { ...cachedTSSchemas, ...zodSchemas }
|
|
339
|
+
}
|
|
340
|
+
|
|
316
341
|
const tsSchemas = generateTSSchemas(
|
|
317
342
|
logger,
|
|
318
343
|
config.tsconfig,
|
|
@@ -325,5 +350,8 @@ export async function generateAllSchemas(
|
|
|
325
350
|
state.schemaLookup
|
|
326
351
|
)
|
|
327
352
|
|
|
353
|
+
cachedCustomTypesContent = customTypesContent
|
|
354
|
+
cachedTSSchemas = tsSchemas
|
|
355
|
+
|
|
328
356
|
return { ...tsSchemas, ...zodSchemas }
|
|
329
357
|
}
|
|
@@ -183,6 +183,10 @@ export interface SerializableInspectorState {
|
|
|
183
183
|
definitions: InspectorState['secrets']['definitions']
|
|
184
184
|
files: string[]
|
|
185
185
|
}
|
|
186
|
+
credentials: {
|
|
187
|
+
definitions: InspectorState['credentials']['definitions']
|
|
188
|
+
files: string[]
|
|
189
|
+
}
|
|
186
190
|
variables: {
|
|
187
191
|
definitions: InspectorState['variables']['definitions']
|
|
188
192
|
files: string[]
|
|
@@ -380,6 +384,10 @@ export function serializeInspectorState(
|
|
|
380
384
|
definitions: state.secrets.definitions,
|
|
381
385
|
files: Array.from(state.secrets.files),
|
|
382
386
|
},
|
|
387
|
+
credentials: {
|
|
388
|
+
definitions: state.credentials.definitions,
|
|
389
|
+
files: Array.from(state.credentials.files),
|
|
390
|
+
},
|
|
383
391
|
variables: {
|
|
384
392
|
definitions: state.variables.definitions,
|
|
385
393
|
files: Array.from(state.variables.files),
|
|
@@ -548,6 +556,10 @@ export function deserializeInspectorState(
|
|
|
548
556
|
definitions: data.secrets?.definitions || [],
|
|
549
557
|
files: new Set(data.secrets?.files || []),
|
|
550
558
|
},
|
|
559
|
+
credentials: {
|
|
560
|
+
definitions: data.credentials?.definitions || [],
|
|
561
|
+
files: new Set(data.credentials?.files || []),
|
|
562
|
+
},
|
|
551
563
|
variables: {
|
|
552
564
|
definitions: data.variables?.definitions || [],
|
|
553
565
|
files: new Set(data.variables?.files || []),
|
|
@@ -596,5 +608,6 @@ export function deserializeInspectorState(
|
|
|
596
608
|
openAPISpec: data.openAPISpec || null,
|
|
597
609
|
diagnostics: data.diagnostics || [],
|
|
598
610
|
addonFunctions: data.addonFunctions || {},
|
|
611
|
+
program: null,
|
|
599
612
|
}
|
|
600
613
|
}
|
|
@@ -192,6 +192,8 @@ export interface SerializedWorkflowGraph {
|
|
|
192
192
|
description?: string
|
|
193
193
|
/** Tags for organization */
|
|
194
194
|
tags?: string[]
|
|
195
|
+
/** If true, workflow always executes inline without queues */
|
|
196
|
+
inline?: boolean
|
|
195
197
|
/** Workflow context/state variables (from Zod schema) */
|
|
196
198
|
context?: WorkflowContext
|
|
197
199
|
/** Serialized nodes */
|
package/src/visit.ts
CHANGED
|
@@ -22,7 +22,8 @@ import { addWireAddon } from './add/add-wire-addon.js'
|
|
|
22
22
|
import { addMiddleware } from './add/add-middleware.js'
|
|
23
23
|
import { addPermission } from './add/add-permission.js'
|
|
24
24
|
import { addCLI, addCLIRenderers } from './add/add-cli.js'
|
|
25
|
-
import { addSecret
|
|
25
|
+
import { addSecret } from './add/add-secret.js'
|
|
26
|
+
import { addCredential } from './add/add-credential.js'
|
|
26
27
|
import { addVariable } from './add/add-variable.js'
|
|
27
28
|
import { addWorkflowGraph } from './add/add-workflow-graph.js'
|
|
28
29
|
import { addAIAgent } from './add/add-ai-agent.js'
|
|
@@ -105,7 +106,7 @@ export const visitRoutes = (
|
|
|
105
106
|
) => {
|
|
106
107
|
addFunctions(logger, node, checker, state, options)
|
|
107
108
|
addSecret(logger, node, checker, state, options)
|
|
108
|
-
|
|
109
|
+
addCredential(logger, node, checker, state, options)
|
|
109
110
|
addVariable(logger, node, checker, state, options)
|
|
110
111
|
|
|
111
112
|
addHTTPRoute(logger, node, checker, state, options)
|