@pikku/inspector 0.12.35 → 0.12.37
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 +55 -0
- package/dist/add/add-functions.js +19 -2
- package/dist/add/add-workflow.d.ts +1 -1
- package/dist/add/add-workflow.js +37 -11
- package/dist/error-codes.d.ts +2 -1
- package/dist/error-codes.js +2 -1
- package/dist/utils/workflow/dsl/patterns.d.ts +1 -1
- package/dist/utils/workflow/dsl/patterns.js +1 -1
- package/dist/utils/workflow/graph/convert-dsl-to-graph.js +3 -3
- package/dist/utils/workflow/graph/workflow-graph.types.d.ts +5 -5
- package/package.json +2 -2
- package/src/add/add-functions.ts +36 -5
- package/src/add/add-workflow.ts +51 -14
- package/src/add/expect-eventually-scenario-only.test.ts +108 -0
- package/src/add/function-body-span.test.ts +96 -0
- package/src/error-codes.ts +2 -1
- package/src/utils/workflow/dsl/patterns.ts +1 -1
- package/src/utils/workflow/graph/convert-dsl-to-graph.ts +3 -3
- package/src/utils/workflow/graph/workflow-graph.types.ts +5 -5
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { strict as assert } from 'assert'
|
|
2
|
+
import { describe, test } from 'node:test'
|
|
3
|
+
import { mkdtemp, rm, writeFile } from 'node:fs/promises'
|
|
4
|
+
import { tmpdir } from 'node:os'
|
|
5
|
+
import { join } from 'node:path'
|
|
6
|
+
import { inspect } from '../inspector.js'
|
|
7
|
+
import type { InspectorLogger } from '../types.js'
|
|
8
|
+
|
|
9
|
+
const logger: InspectorLogger = {
|
|
10
|
+
debug: () => {},
|
|
11
|
+
info: () => {},
|
|
12
|
+
warn: () => {},
|
|
13
|
+
error: () => {},
|
|
14
|
+
diagnostic: () => {},
|
|
15
|
+
critical: () => {},
|
|
16
|
+
hasCriticalErrors: () => false,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe('function body spans in meta', () => {
|
|
20
|
+
test('meta records 1-indexed bodyStart/bodyEnd lines of the handler body', async () => {
|
|
21
|
+
const rootDir = await mkdtemp(join(tmpdir(), 'pikku-span-'))
|
|
22
|
+
const file = join(rootDir, 'my.function.ts')
|
|
23
|
+
await writeFile(
|
|
24
|
+
file,
|
|
25
|
+
[
|
|
26
|
+
"import { pikkuSessionlessFunc } from '@pikku/core'", // line 1
|
|
27
|
+
'', // 2
|
|
28
|
+
'export const spanProbe = pikkuSessionlessFunc({', // 3
|
|
29
|
+
' func: async ({ logger }, data: { n: number }) => {', // 4
|
|
30
|
+
' const doubled = data.n * 2', // 5
|
|
31
|
+
' return { doubled }', // 6
|
|
32
|
+
' },', // 7
|
|
33
|
+
'})', // 8
|
|
34
|
+
].join('\n')
|
|
35
|
+
)
|
|
36
|
+
try {
|
|
37
|
+
const state = await inspect(logger, [file], { rootDir })
|
|
38
|
+
const meta = (state.functions.meta as any).spanProbe
|
|
39
|
+
assert.ok(meta, 'spanProbe should be inspected')
|
|
40
|
+
assert.equal(
|
|
41
|
+
meta.bodyStart,
|
|
42
|
+
5,
|
|
43
|
+
`bodyStart should be 5, got ${meta.bodyStart}`
|
|
44
|
+
)
|
|
45
|
+
assert.equal(meta.bodyEnd, 6, `bodyEnd should be 6, got ${meta.bodyEnd}`)
|
|
46
|
+
} finally {
|
|
47
|
+
await rm(rootDir, { recursive: true, force: true })
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test('meta records bodySourceFile when the handler is imported from another file', async () => {
|
|
52
|
+
const rootDir = await mkdtemp(join(tmpdir(), 'pikku-span-'))
|
|
53
|
+
const handlerFile = join(rootDir, 'handlers.ts')
|
|
54
|
+
const wiringFile = join(rootDir, 'my.function.ts')
|
|
55
|
+
await writeFile(
|
|
56
|
+
handlerFile,
|
|
57
|
+
[
|
|
58
|
+
'export const importedHandler = async (', // line 1
|
|
59
|
+
' { logger }: any,', // 2
|
|
60
|
+
' data: { n: number }', // 3
|
|
61
|
+
') => {', // 4
|
|
62
|
+
' const doubled = data.n * 2', // 5
|
|
63
|
+
' return { doubled }', // 6
|
|
64
|
+
'}', // 7
|
|
65
|
+
].join('\n')
|
|
66
|
+
)
|
|
67
|
+
await writeFile(
|
|
68
|
+
wiringFile,
|
|
69
|
+
[
|
|
70
|
+
"import { pikkuSessionlessFunc } from '@pikku/core'",
|
|
71
|
+
"import { importedHandler } from './handlers.js'",
|
|
72
|
+
'',
|
|
73
|
+
'export const importedProbe = pikkuSessionlessFunc({',
|
|
74
|
+
' func: importedHandler,',
|
|
75
|
+
'})',
|
|
76
|
+
].join('\n')
|
|
77
|
+
)
|
|
78
|
+
try {
|
|
79
|
+
const state = await inspect(logger, [wiringFile, handlerFile], {
|
|
80
|
+
rootDir,
|
|
81
|
+
})
|
|
82
|
+
const meta = (state.functions.meta as any).importedProbe
|
|
83
|
+
assert.ok(meta, 'importedProbe should be inspected')
|
|
84
|
+
assert.equal(meta.sourceFile, wiringFile)
|
|
85
|
+
assert.equal(
|
|
86
|
+
meta.bodySourceFile,
|
|
87
|
+
handlerFile,
|
|
88
|
+
`bodySourceFile should be the handler file, got ${meta.bodySourceFile}`
|
|
89
|
+
)
|
|
90
|
+
assert.equal(meta.bodyStart, 5)
|
|
91
|
+
assert.equal(meta.bodyEnd, 6)
|
|
92
|
+
} finally {
|
|
93
|
+
await rm(rootDir, { recursive: true, force: true })
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
})
|
package/src/error-codes.ts
CHANGED
|
@@ -21,7 +21,8 @@ export enum ErrorCode {
|
|
|
21
21
|
MISSING_QUEUE_NAME = 'PKU384',
|
|
22
22
|
MISSING_CHANNEL_NAME = 'PKU400',
|
|
23
23
|
CLI_CLIENTSIDE_RENDERER_HAS_SERVICES = 'PKU672',
|
|
24
|
-
|
|
24
|
+
SCENARIO_HAS_SERVICES = 'PKU673',
|
|
25
|
+
EXPECT_EVENTUALLY_SCENARIO_ONLY = 'PKU675',
|
|
25
26
|
DYNAMIC_STEP_NAME = 'PKU529',
|
|
26
27
|
WORKFLOW_ORCHESTRATOR_NOT_CONFIGURED = 'PKU600',
|
|
27
28
|
INVALID_DSL_WORKFLOW = 'PKU641',
|
|
@@ -6,7 +6,7 @@ import * as ts from 'typescript'
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Check if a call expression is workflow.do() or workflow.expectEventually()
|
|
9
|
-
* (both are RPC steps; expectEventually is the polling variant used by
|
|
9
|
+
* (both are RPC steps; expectEventually is the polling variant used by scenarios)
|
|
10
10
|
*/
|
|
11
11
|
export function isWorkflowDoCall(
|
|
12
12
|
node: ts.CallExpression,
|
|
@@ -396,11 +396,11 @@ export function convertDslToGraph(
|
|
|
396
396
|
const entryNodeIds = nodes.length > 0 ? [nodes[0].nodeId] : []
|
|
397
397
|
|
|
398
398
|
// Determine source type:
|
|
399
|
-
// -
|
|
399
|
+
// - scenario: complex workflow whose steps run as actors (scenario)
|
|
400
400
|
// - dsl === true: pure DSL workflow, can be serialized
|
|
401
401
|
// - dsl === false: complex workflow with inline steps, not serializable
|
|
402
|
-
const source = meta.
|
|
403
|
-
? '
|
|
402
|
+
const source = meta.scenario
|
|
403
|
+
? 'scenario'
|
|
404
404
|
: meta.dsl === false
|
|
405
405
|
? 'complex'
|
|
406
406
|
: 'dsl'
|
|
@@ -142,9 +142,9 @@ export interface FunctionNode extends BaseNode {
|
|
|
142
142
|
outputVar?: string
|
|
143
143
|
/** Hash of nodeId + RPC input/output schemas for version detection */
|
|
144
144
|
stepHash?: string
|
|
145
|
-
/**
|
|
145
|
+
/** Scenario actor name this step runs as (workflow.do {actor: actors.x}) */
|
|
146
146
|
actor?: string
|
|
147
|
-
/** True for workflow.expectEventually polling steps (
|
|
147
|
+
/** True for workflow.expectEventually polling steps (scenarios) */
|
|
148
148
|
expectEventually?: boolean
|
|
149
149
|
}
|
|
150
150
|
|
|
@@ -181,9 +181,9 @@ export const isFlowNode = (node: SerializedGraphNode): node is FlowNode =>
|
|
|
181
181
|
* - 'dsl': Pure DSL workflow (pikkuWorkflowFunc) - can be round-tripped to code
|
|
182
182
|
* - 'complex': Complex workflow (pikkuWorkflowComplexFunc) - contains inline steps, not serializable
|
|
183
183
|
* - 'graph': Graph-based workflow (pikkuWorkflowGraph)
|
|
184
|
-
* - '
|
|
184
|
+
* - 'scenario': Scenario (pikkuScenario) - complex workflow whose steps run as actors
|
|
185
185
|
*/
|
|
186
|
-
export type WorkflowSourceType = 'dsl' | 'complex' | 'graph' | '
|
|
186
|
+
export type WorkflowSourceType = 'dsl' | 'complex' | 'graph' | 'scenario'
|
|
187
187
|
|
|
188
188
|
/**
|
|
189
189
|
* Serialized workflow graph - the canonical JSON format
|
|
@@ -201,7 +201,7 @@ export interface SerializedWorkflowGraph {
|
|
|
201
201
|
description?: string
|
|
202
202
|
/** Tags for organization */
|
|
203
203
|
tags?: string[]
|
|
204
|
-
/** Actor names a
|
|
204
|
+
/** Actor names a scenario's steps run as */
|
|
205
205
|
actors?: string[]
|
|
206
206
|
/** If true, workflow always executes inline without queues */
|
|
207
207
|
inline?: boolean
|