blokctl 0.2.0
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/dist/commands/build/index.d.ts +2 -0
- package/dist/commands/build/index.js +210 -0
- package/dist/commands/config/index.d.ts +1 -0
- package/dist/commands/config/index.js +46 -0
- package/dist/commands/cost/index.d.ts +1 -0
- package/dist/commands/cost/index.js +74 -0
- package/dist/commands/create/node.d.ts +2 -0
- package/dist/commands/create/node.js +541 -0
- package/dist/commands/create/project.d.ts +2 -0
- package/dist/commands/create/project.js +941 -0
- package/dist/commands/create/utils/Examples.d.ts +39 -0
- package/dist/commands/create/utils/Examples.js +983 -0
- package/dist/commands/create/workflow.d.ts +2 -0
- package/dist/commands/create/workflow.js +109 -0
- package/dist/commands/deploy/index.d.ts +2 -0
- package/dist/commands/deploy/index.js +176 -0
- package/dist/commands/dev/index.d.ts +2 -0
- package/dist/commands/dev/index.js +190 -0
- package/dist/commands/generate/GenerationAnalytics.d.ts +61 -0
- package/dist/commands/generate/GenerationAnalytics.js +162 -0
- package/dist/commands/generate/GenerationAnalytics.test.d.ts +1 -0
- package/dist/commands/generate/GenerationAnalytics.test.js +407 -0
- package/dist/commands/generate/NodeFileWriter.d.ts +5 -0
- package/dist/commands/generate/NodeFileWriter.js +240 -0
- package/dist/commands/generate/NodeGenerator.d.ts +20 -0
- package/dist/commands/generate/NodeGenerator.js +181 -0
- package/dist/commands/generate/NodeGenerator.test.d.ts +1 -0
- package/dist/commands/generate/NodeGenerator.test.js +101 -0
- package/dist/commands/generate/PromptVersioning.d.ts +25 -0
- package/dist/commands/generate/PromptVersioning.js +71 -0
- package/dist/commands/generate/PromptVersioning.test.d.ts +1 -0
- package/dist/commands/generate/PromptVersioning.test.js +120 -0
- package/dist/commands/generate/RegisterNode.d.ts +3 -0
- package/dist/commands/generate/RegisterNode.js +37 -0
- package/dist/commands/generate/RuntimeGenerator.d.ts +40 -0
- package/dist/commands/generate/RuntimeGenerator.js +369 -0
- package/dist/commands/generate/RuntimeGenerator.test.d.ts +1 -0
- package/dist/commands/generate/RuntimeGenerator.test.js +553 -0
- package/dist/commands/generate/TriggerGenerator.d.ts +22 -0
- package/dist/commands/generate/TriggerGenerator.js +220 -0
- package/dist/commands/generate/TriggerGenerator.test.d.ts +1 -0
- package/dist/commands/generate/TriggerGenerator.test.js +209 -0
- package/dist/commands/generate/WorkflowGenerator.d.ts +20 -0
- package/dist/commands/generate/WorkflowGenerator.js +131 -0
- package/dist/commands/generate/WorkflowGenerator.test.d.ts +1 -0
- package/dist/commands/generate/WorkflowGenerator.test.js +77 -0
- package/dist/commands/generate/e2e/NodeGenerator.e2e.test.d.ts +1 -0
- package/dist/commands/generate/e2e/NodeGenerator.e2e.test.js +216 -0
- package/dist/commands/generate/e2e/RuntimeGenerator.e2e.test.d.ts +1 -0
- package/dist/commands/generate/e2e/RuntimeGenerator.e2e.test.js +759 -0
- package/dist/commands/generate/e2e/TriggerGenerator.e2e.test.d.ts +1 -0
- package/dist/commands/generate/e2e/TriggerGenerator.e2e.test.js +295 -0
- package/dist/commands/generate/e2e/WorkflowGenerator.e2e.test.d.ts +1 -0
- package/dist/commands/generate/e2e/WorkflowGenerator.e2e.test.js +353 -0
- package/dist/commands/generate/index.d.ts +1 -0
- package/dist/commands/generate/index.js +418 -0
- package/dist/commands/generate/prompts/create-fn-node.system.d.ts +5 -0
- package/dist/commands/generate/prompts/create-fn-node.system.js +256 -0
- package/dist/commands/generate/prompts/create-node-manifest.system.d.ts +4 -0
- package/dist/commands/generate/prompts/create-node-manifest.system.js +41 -0
- package/dist/commands/generate/prompts/create-node.system.d.ts +5 -0
- package/dist/commands/generate/prompts/create-node.system.js +114 -0
- package/dist/commands/generate/prompts/create-readme.system.d.ts +4 -0
- package/dist/commands/generate/prompts/create-readme.system.js +83 -0
- package/dist/commands/generate/prompts/create-runtime.system.d.ts +5 -0
- package/dist/commands/generate/prompts/create-runtime.system.js +284 -0
- package/dist/commands/generate/prompts/create-trigger.system.d.ts +5 -0
- package/dist/commands/generate/prompts/create-trigger.system.js +293 -0
- package/dist/commands/generate/prompts/create-workflow.system.d.ts +5 -0
- package/dist/commands/generate/prompts/create-workflow.system.js +476 -0
- package/dist/commands/generate/prompts/register-node.system.d.ts +4 -0
- package/dist/commands/generate/prompts/register-node.system.js +26 -0
- package/dist/commands/generate/validators/CompilationValidator.d.ts +9 -0
- package/dist/commands/generate/validators/CompilationValidator.js +86 -0
- package/dist/commands/generate/validators/CompilationValidator.test.d.ts +1 -0
- package/dist/commands/generate/validators/CompilationValidator.test.js +161 -0
- package/dist/commands/generate/validators/NodeValidator.d.ts +18 -0
- package/dist/commands/generate/validators/NodeValidator.js +217 -0
- package/dist/commands/generate/validators/NodeValidator.test.d.ts +1 -0
- package/dist/commands/generate/validators/NodeValidator.test.js +281 -0
- package/dist/commands/generate/validators/WorkflowValidator.d.ts +6 -0
- package/dist/commands/generate/validators/WorkflowValidator.js +301 -0
- package/dist/commands/generate/validators/WorkflowValidator.test.d.ts +1 -0
- package/dist/commands/generate/validators/WorkflowValidator.test.js +647 -0
- package/dist/commands/generate/validators/index.d.ts +4 -0
- package/dist/commands/generate/validators/index.js +2 -0
- package/dist/commands/graph/index.d.ts +1 -0
- package/dist/commands/graph/index.js +69 -0
- package/dist/commands/install/index.d.ts +1 -0
- package/dist/commands/install/index.js +4 -0
- package/dist/commands/install/node.d.ts +4 -0
- package/dist/commands/install/node.js +136 -0
- package/dist/commands/install/workflow.d.ts +4 -0
- package/dist/commands/install/workflow.js +62 -0
- package/dist/commands/login/index.d.ts +2 -0
- package/dist/commands/login/index.js +77 -0
- package/dist/commands/logout/index.d.ts +2 -0
- package/dist/commands/logout/index.js +20 -0
- package/dist/commands/marketplace/runtime.d.ts +54 -0
- package/dist/commands/marketplace/runtime.js +350 -0
- package/dist/commands/migrate/index.d.ts +1 -0
- package/dist/commands/migrate/index.js +14 -0
- package/dist/commands/migrate/node.d.ts +2 -0
- package/dist/commands/migrate/node.js +110 -0
- package/dist/commands/monitor/index.d.ts +1 -0
- package/dist/commands/monitor/index.js +28 -0
- package/dist/commands/monitor/monitor-component.d.ts +1 -0
- package/dist/commands/monitor/monitor-component.js +271 -0
- package/dist/commands/monitor/static/index.html +2124 -0
- package/dist/commands/monitor/static-web-server.d.ts +1 -0
- package/dist/commands/monitor/static-web-server.js +89 -0
- package/dist/commands/profile/index.d.ts +1 -0
- package/dist/commands/profile/index.js +112 -0
- package/dist/commands/publish/index.d.ts +1 -0
- package/dist/commands/publish/index.js +4 -0
- package/dist/commands/publish/node.d.ts +4 -0
- package/dist/commands/publish/node.js +231 -0
- package/dist/commands/publish/workflow.d.ts +4 -0
- package/dist/commands/publish/workflow.js +165 -0
- package/dist/commands/search/docs.d.ts +17 -0
- package/dist/commands/search/docs.js +179 -0
- package/dist/commands/search/index.d.ts +1 -0
- package/dist/commands/search/index.js +5 -0
- package/dist/commands/search/indexer.d.ts +10 -0
- package/dist/commands/search/indexer.js +265 -0
- package/dist/commands/search/nodes.d.ts +4 -0
- package/dist/commands/search/nodes.js +101 -0
- package/dist/commands/search/workflow.d.ts +4 -0
- package/dist/commands/search/workflow.js +100 -0
- package/dist/commands/trace/index.d.ts +1 -0
- package/dist/commands/trace/index.js +26 -0
- package/dist/commands/trace/startStudio.d.ts +8 -0
- package/dist/commands/trace/startStudio.js +116 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +186 -0
- package/dist/services/commander.d.ts +9 -0
- package/dist/services/commander.js +20 -0
- package/dist/services/constants.d.ts +1 -0
- package/dist/services/constants.js +3 -0
- package/dist/services/local-token-manager.d.ts +14 -0
- package/dist/services/local-token-manager.js +99 -0
- package/dist/services/non-interactive.d.ts +5 -0
- package/dist/services/non-interactive.js +30 -0
- package/dist/services/package-manager.d.ts +35 -0
- package/dist/services/package-manager.js +111 -0
- package/dist/services/posthog.d.ts +31 -0
- package/dist/services/posthog.js +159 -0
- package/dist/services/registry-manager.d.ts +9 -0
- package/dist/services/registry-manager.js +26 -0
- package/dist/services/runtime-detector.d.ts +23 -0
- package/dist/services/runtime-detector.js +181 -0
- package/dist/services/runtime-setup.d.ts +36 -0
- package/dist/services/runtime-setup.js +250 -0
- package/dist/services/utils.d.ts +2 -0
- package/dist/services/utils.js +29 -0
- package/dist/services/workflow-loader.d.ts +30 -0
- package/dist/services/workflow-loader.js +46 -0
- package/dist/studio-dist/assets/charts-Dso0hPUR.js +68 -0
- package/dist/studio-dist/assets/graph-CsV2nWGn.js +23 -0
- package/dist/studio-dist/assets/icons-zP8LLgPh.js +311 -0
- package/dist/studio-dist/assets/index-CLyEkXMx.css +1 -0
- package/dist/studio-dist/assets/index-CNXFX_ar.js +27 -0
- package/dist/studio-dist/assets/react-vendor--Eh9ivFN.js +17 -0
- package/dist/studio-dist/assets/tanstack-query-CiM1U6F5.js +1 -0
- package/dist/studio-dist/assets/tanstack-router-Btjy0MKq.js +25 -0
- package/dist/studio-dist/assets/tanstack-table-DhwRvuH2.js +22 -0
- package/dist/studio-dist/favicon.svg +5 -0
- package/dist/studio-dist/index.html +21 -0
- package/package.json +75 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
vi.mock("ai", () => ({
|
|
3
|
+
generateText: vi.fn(),
|
|
4
|
+
}));
|
|
5
|
+
vi.mock("@ai-sdk/openai", () => ({
|
|
6
|
+
createOpenAI: vi.fn(() => (model) => ({ model })),
|
|
7
|
+
}));
|
|
8
|
+
vi.mock("../validators/CompilationValidator.js", () => ({
|
|
9
|
+
validateCode: vi.fn(),
|
|
10
|
+
}));
|
|
11
|
+
vi.mock("../validators/NodeValidator.js", () => ({
|
|
12
|
+
validateFunctionFirstStructure: vi.fn(),
|
|
13
|
+
}));
|
|
14
|
+
import { generateText } from "ai";
|
|
15
|
+
import NodeGenerator from "../NodeGenerator.js";
|
|
16
|
+
import * as CompilationValidator from "../validators/CompilationValidator.js";
|
|
17
|
+
import * as NodeValidator from "../validators/NodeValidator.js";
|
|
18
|
+
const mockedGenerateText = vi.mocked(generateText);
|
|
19
|
+
const mockedValidateCode = vi.mocked(CompilationValidator.validateCode);
|
|
20
|
+
const mockedValidateStructure = vi.mocked(NodeValidator.validateFunctionFirstStructure);
|
|
21
|
+
const VALID_FUNCTION_FIRST_NODE = `
|
|
22
|
+
import type { Context } from "@blok/shared";
|
|
23
|
+
import { z } from "zod";
|
|
24
|
+
import { defineNode } from "@blok/runner";
|
|
25
|
+
|
|
26
|
+
export default defineNode({
|
|
27
|
+
name: "fetch-user",
|
|
28
|
+
description: "Fetches user data from an external API",
|
|
29
|
+
input: z.object({ userId: z.string() }),
|
|
30
|
+
output: z.object({ id: z.string(), name: z.string(), email: z.string() }),
|
|
31
|
+
async execute(ctx, input) {
|
|
32
|
+
return { id: "1", name: "John", email: "john@example.com" };
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
`;
|
|
36
|
+
const INVALID_NODE_MISSING_IMPORTS = `
|
|
37
|
+
export default defineNode({
|
|
38
|
+
name: "broken-node",
|
|
39
|
+
description: "Missing imports",
|
|
40
|
+
input: z.object({ id: z.string() }),
|
|
41
|
+
output: z.object({ result: z.string() }),
|
|
42
|
+
async execute(ctx, input) { return { result: "hello" }; },
|
|
43
|
+
});
|
|
44
|
+
`;
|
|
45
|
+
const VALID_CLASS_BASED_NODE = `
|
|
46
|
+
import BlokService, { BlokResponse, GlobalError } from "@blok/runner";
|
|
47
|
+
import type { Context } from "@blok/shared";
|
|
48
|
+
|
|
49
|
+
type InputType = { message: string; };
|
|
50
|
+
|
|
51
|
+
export default class HelloNode extends BlokService<InputType> {
|
|
52
|
+
async handle(ctx: Context, inputs: InputType): Promise<BlokResponse> {
|
|
53
|
+
const response = new BlokResponse();
|
|
54
|
+
response.setSuccess({ greeting: inputs.message });
|
|
55
|
+
return response;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
`;
|
|
59
|
+
function mockValidPass() {
|
|
60
|
+
mockedValidateCode.mockReturnValue({ success: true, errors: [], warnings: [] });
|
|
61
|
+
mockedValidateStructure.mockReturnValue({ valid: true, errors: [], warnings: [], suggestions: [] });
|
|
62
|
+
}
|
|
63
|
+
function mockCompilationFail(errors) {
|
|
64
|
+
mockedValidateCode.mockReturnValueOnce({ success: false, errors, warnings: [] });
|
|
65
|
+
}
|
|
66
|
+
describe("NodeGenerator E2E", () => {
|
|
67
|
+
let generator;
|
|
68
|
+
beforeEach(() => {
|
|
69
|
+
generator = new NodeGenerator();
|
|
70
|
+
vi.clearAllMocks();
|
|
71
|
+
vi.spyOn(console, "log").mockImplementation(() => { });
|
|
72
|
+
});
|
|
73
|
+
afterEach(() => {
|
|
74
|
+
vi.restoreAllMocks();
|
|
75
|
+
});
|
|
76
|
+
describe("successful generation - first attempt", () => {
|
|
77
|
+
it("should generate a valid function-first node on first attempt", async () => {
|
|
78
|
+
mockedGenerateText.mockResolvedValueOnce({ text: VALID_FUNCTION_FIRST_NODE });
|
|
79
|
+
mockValidPass();
|
|
80
|
+
const result = await generator.generateNode("fetch-user", "Create a node that fetches user data from an API", "test-api-key", false, "function");
|
|
81
|
+
expect(result.nodeName).toBe("fetch-user");
|
|
82
|
+
expect(result.code).toBe(VALID_FUNCTION_FIRST_NODE);
|
|
83
|
+
expect(result.validationResult).toBeDefined();
|
|
84
|
+
expect(result.validationResult.attempts).toBe(1);
|
|
85
|
+
expect(result.validationResult.valid).toBe(true);
|
|
86
|
+
expect(mockedGenerateText).toHaveBeenCalledTimes(1);
|
|
87
|
+
});
|
|
88
|
+
it("should generate a valid class-based node on first attempt", async () => {
|
|
89
|
+
mockedGenerateText.mockResolvedValueOnce({ text: VALID_CLASS_BASED_NODE });
|
|
90
|
+
mockedValidateCode.mockReturnValue({ success: true, errors: [], warnings: [] });
|
|
91
|
+
const result = await generator.generateNode("hello-node", "Create a hello world node", "test-api-key", false, "class");
|
|
92
|
+
expect(result.nodeName).toBe("hello-node");
|
|
93
|
+
expect(result.validationResult.attempts).toBe(1);
|
|
94
|
+
expect(result.validationResult.valid).toBe(true);
|
|
95
|
+
});
|
|
96
|
+
it("should pass correct system prompt for function-first style", async () => {
|
|
97
|
+
mockedGenerateText.mockResolvedValueOnce({ text: VALID_FUNCTION_FIRST_NODE });
|
|
98
|
+
mockValidPass();
|
|
99
|
+
await generator.generateNode("test-node", "Create a test node", "test-api-key", false, "function");
|
|
100
|
+
const callArgs = mockedGenerateText.mock.calls[0][0];
|
|
101
|
+
expect(callArgs.system).toContain("defineNode");
|
|
102
|
+
expect(callArgs.system).toContain("function-first");
|
|
103
|
+
});
|
|
104
|
+
it("should pass correct system prompt for class-based style", async () => {
|
|
105
|
+
mockedGenerateText.mockResolvedValueOnce({ text: VALID_CLASS_BASED_NODE });
|
|
106
|
+
mockedValidateCode.mockReturnValue({ success: true, errors: [], warnings: [] });
|
|
107
|
+
await generator.generateNode("test-node", "Create a test node", "test-api-key", false, "class");
|
|
108
|
+
const callArgs = mockedGenerateText.mock.calls[0][0];
|
|
109
|
+
expect(callArgs.system).toContain("BlokService");
|
|
110
|
+
});
|
|
111
|
+
it("should use temperature 0.2 for deterministic output", async () => {
|
|
112
|
+
mockedGenerateText.mockResolvedValueOnce({ text: VALID_FUNCTION_FIRST_NODE });
|
|
113
|
+
mockValidPass();
|
|
114
|
+
await generator.generateNode("test-node", "Create a test node", "test-api-key", false, "function");
|
|
115
|
+
const callArgs = mockedGenerateText.mock.calls[0][0];
|
|
116
|
+
expect(callArgs.temperature).toBe(0.2);
|
|
117
|
+
});
|
|
118
|
+
it("should include prompt version in validation result", async () => {
|
|
119
|
+
mockedGenerateText.mockResolvedValueOnce({ text: VALID_FUNCTION_FIRST_NODE });
|
|
120
|
+
mockValidPass();
|
|
121
|
+
const result = await generator.generateNode("test-node", "Create a test node", "test-api-key", false, "function");
|
|
122
|
+
expect(result.validationResult.promptVersion).toContain("create-fn-node@");
|
|
123
|
+
});
|
|
124
|
+
it("should include duration in validation result", async () => {
|
|
125
|
+
mockedGenerateText.mockResolvedValueOnce({ text: VALID_FUNCTION_FIRST_NODE });
|
|
126
|
+
mockValidPass();
|
|
127
|
+
const result = await generator.generateNode("test-node", "Create a test node", "test-api-key", false, "function");
|
|
128
|
+
expect(result.validationResult.durationMs).toBeGreaterThanOrEqual(0);
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
describe("validation feedback loop", () => {
|
|
132
|
+
it("should retry with feedback on first failure and succeed on second attempt", async () => {
|
|
133
|
+
mockedGenerateText.mockResolvedValueOnce({ text: INVALID_NODE_MISSING_IMPORTS });
|
|
134
|
+
mockedGenerateText.mockResolvedValueOnce({ text: VALID_FUNCTION_FIRST_NODE });
|
|
135
|
+
mockCompilationFail(["Missing defineNode import"]);
|
|
136
|
+
mockValidPass();
|
|
137
|
+
const result = await generator.generateNode("fetch-user", "Create a node that fetches user data", "test-api-key", false, "function");
|
|
138
|
+
expect(result.validationResult.attempts).toBe(2);
|
|
139
|
+
expect(result.validationResult.valid).toBe(true);
|
|
140
|
+
expect(result.code).toBe(VALID_FUNCTION_FIRST_NODE);
|
|
141
|
+
expect(mockedGenerateText).toHaveBeenCalledTimes(2);
|
|
142
|
+
});
|
|
143
|
+
it("should include error feedback in retry prompt", async () => {
|
|
144
|
+
mockedGenerateText.mockResolvedValueOnce({ text: INVALID_NODE_MISSING_IMPORTS });
|
|
145
|
+
mockedGenerateText.mockResolvedValueOnce({ text: VALID_FUNCTION_FIRST_NODE });
|
|
146
|
+
mockCompilationFail(["Missing defineNode import"]);
|
|
147
|
+
mockValidPass();
|
|
148
|
+
await generator.generateNode("test-node", "Create a test node", "test-api-key", false, "function");
|
|
149
|
+
const secondCallArgs = mockedGenerateText.mock.calls[1][0];
|
|
150
|
+
const prompt = secondCallArgs.prompt;
|
|
151
|
+
expect(prompt).toContain("validation errors");
|
|
152
|
+
expect(prompt).toContain("Previous code:");
|
|
153
|
+
expect(prompt).toContain("Missing defineNode import");
|
|
154
|
+
});
|
|
155
|
+
it("should exhaust all 3 attempts when code keeps failing", async () => {
|
|
156
|
+
mockedGenerateText.mockResolvedValue({ text: INVALID_NODE_MISSING_IMPORTS });
|
|
157
|
+
mockedValidateCode.mockReturnValue({ success: false, errors: ["Missing imports"], warnings: [] });
|
|
158
|
+
const result = await generator.generateNode("broken-node", "Create something broken", "test-api-key", false, "function");
|
|
159
|
+
expect(result.validationResult.valid).toBe(false);
|
|
160
|
+
expect(result.validationResult.attempts).toBe(3);
|
|
161
|
+
expect(mockedGenerateText).toHaveBeenCalledTimes(3);
|
|
162
|
+
});
|
|
163
|
+
it("should succeed on third attempt", async () => {
|
|
164
|
+
mockedGenerateText.mockResolvedValueOnce({ text: INVALID_NODE_MISSING_IMPORTS });
|
|
165
|
+
mockedGenerateText.mockResolvedValueOnce({ text: INVALID_NODE_MISSING_IMPORTS });
|
|
166
|
+
mockedGenerateText.mockResolvedValueOnce({ text: VALID_FUNCTION_FIRST_NODE });
|
|
167
|
+
mockCompilationFail(["Missing imports"]);
|
|
168
|
+
mockCompilationFail(["Still missing imports"]);
|
|
169
|
+
mockValidPass();
|
|
170
|
+
const result = await generator.generateNode("fetch-user", "Create a user fetcher", "test-api-key", false, "function");
|
|
171
|
+
expect(result.validationResult.attempts).toBe(3);
|
|
172
|
+
expect(result.validationResult.valid).toBe(true);
|
|
173
|
+
expect(result.code).toBe(VALID_FUNCTION_FIRST_NODE);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
describe("structural validation for function-first", () => {
|
|
177
|
+
it("should detect missing defineNode via structural validation", async () => {
|
|
178
|
+
mockedGenerateText.mockResolvedValue({ text: "const x = 1;" });
|
|
179
|
+
mockedValidateCode.mockReturnValue({ success: true, errors: [], warnings: [] });
|
|
180
|
+
mockedValidateStructure.mockReturnValue({
|
|
181
|
+
valid: false,
|
|
182
|
+
errors: ["Missing defineNode import from @blok/runner"],
|
|
183
|
+
warnings: [],
|
|
184
|
+
suggestions: [],
|
|
185
|
+
});
|
|
186
|
+
const result = await generator.generateNode("test-node", "Create test node", "test-api-key", false, "function");
|
|
187
|
+
expect(result.validationResult.valid).toBe(false);
|
|
188
|
+
expect(result.validationResult.errors.some((e) => e.toLowerCase().includes("definenode"))).toBe(true);
|
|
189
|
+
});
|
|
190
|
+
it("should skip structural validation for class-based style", async () => {
|
|
191
|
+
mockedGenerateText.mockResolvedValueOnce({ text: VALID_CLASS_BASED_NODE });
|
|
192
|
+
mockedValidateCode.mockReturnValue({ success: true, errors: [], warnings: [] });
|
|
193
|
+
const result = await generator.generateNode("test-node", "Create test node", "test-api-key", false, "class");
|
|
194
|
+
expect(result.validationResult.valid).toBe(true);
|
|
195
|
+
expect(mockedValidateStructure).not.toHaveBeenCalled();
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
describe("code with markdown fences", () => {
|
|
199
|
+
it("should return code as-is from LLM (cleanup happens at CLI layer)", async () => {
|
|
200
|
+
const wrappedCode = "```typescript\n" + VALID_FUNCTION_FIRST_NODE + "\n```";
|
|
201
|
+
mockedGenerateText.mockResolvedValueOnce({ text: wrappedCode });
|
|
202
|
+
mockValidPass();
|
|
203
|
+
const result = await generator.generateNode("fetch-user", "Create a user fetcher", "test-api-key", false, "function");
|
|
204
|
+
expect(result.code).toBe(wrappedCode);
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
describe("default node style", () => {
|
|
208
|
+
it("should default to function style when no style specified", async () => {
|
|
209
|
+
mockedGenerateText.mockResolvedValueOnce({ text: VALID_FUNCTION_FIRST_NODE });
|
|
210
|
+
mockValidPass();
|
|
211
|
+
await generator.generateNode("test-node", "Create a test node", "test-api-key", false);
|
|
212
|
+
const callArgs = mockedGenerateText.mock.calls[0][0];
|
|
213
|
+
expect(callArgs.system).toContain("defineNode");
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|