ondc-code-generator 0.9.0 → 1.0.1
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/alpha/docs/rag-docs/confirm.md +301 -0
- package/alpha/docs/rag-docs/init.md +422 -0
- package/alpha/docs/rag-docs/on_confirm.md +921 -0
- package/alpha/docs/rag-docs/on_init.md +823 -0
- package/alpha/docs/rag-docs/on_search.md +897 -0
- package/alpha/docs/rag-docs/on_select.md +522 -0
- package/alpha/docs/rag-docs/on_status.md +854 -0
- package/alpha/docs/rag-docs/on_update.md +921 -0
- package/alpha/docs/rag-docs/search.md +678 -0
- package/alpha/docs/rag-docs/select.md +344 -0
- package/alpha/docs/rag-docs/status.md +178 -0
- package/alpha/docs/rag-docs/update.md +229 -0
- package/alpha/docs/rag-table-docs/confirm.md +63 -0
- package/alpha/docs/rag-table-docs/init.md +81 -0
- package/alpha/docs/rag-table-docs/on_confirm.md +164 -0
- package/alpha/docs/rag-table-docs/on_init.md +146 -0
- package/alpha/docs/rag-table-docs/on_search.md +163 -0
- package/alpha/docs/rag-table-docs/on_select.md +99 -0
- package/alpha/docs/rag-table-docs/on_status.md +153 -0
- package/alpha/docs/rag-table-docs/on_update.md +164 -0
- package/alpha/docs/rag-table-docs/raw_table.json +11198 -0
- package/alpha/docs/rag-table-docs/search.md +128 -0
- package/alpha/docs/rag-table-docs/select.md +70 -0
- package/alpha/docs/rag-table-docs/status.md +44 -0
- package/alpha/docs/rag-table-docs/update.md +51 -0
- package/alpha/docs/validPaths.json +34134 -0
- package/alpha/possible-json-paths.json +34134 -0
- package/alpha/table/rag-table-docs/confirm.md +3 -0
- package/alpha/table/rag-table-docs/init.md +3 -0
- package/alpha/table/rag-table-docs/on_confirm.md +3 -0
- package/alpha/table/rag-table-docs/on_init.md +3 -0
- package/alpha/table/rag-table-docs/on_search.md +3 -0
- package/alpha/table/rag-table-docs/on_select.md +3 -0
- package/alpha/table/rag-table-docs/on_status.md +3 -0
- package/alpha/table/rag-table-docs/on_update.md +3 -0
- package/alpha/table/rag-table-docs/search.md +3 -0
- package/alpha/table/rag-table-docs/select.md +3 -0
- package/alpha/table/rag-table-docs/status.md +3 -0
- package/alpha/table/rag-table-docs/update.md +3 -0
- package/dist/generator/config-compiler.d.ts +16 -2
- package/dist/generator/config-compiler.js +45 -19
- package/dist/generator/generators/classes/abstract-generator.d.ts +2 -0
- package/dist/generator/generators/documentation/markdown-message-generator.js +4 -1
- package/dist/generator/generators/documentation/md-generator.d.ts +2 -1
- package/dist/generator/generators/documentation/md-generator.js +3 -2
- package/dist/generator/generators/go/go-generator.js +1 -1
- package/dist/generator/generators/javascript/js-generator.js +1 -1
- package/dist/generator/generators/python/py-generator.js +1 -1
- package/dist/generator/generators/rag/rag-generator.d.ts +39 -28
- package/dist/generator/generators/rag/rag-generator.js +149 -103
- package/dist/generator/generators/rag/rag-table-generator.d.ts +7 -1
- package/dist/generator/generators/rag/rag-table-generator.js +24 -8
- package/dist/generator/generators/typescript/ts-generator.js +1 -1
- package/dist/index.test.js +12 -3
- package/dist/types/build.d.ts +4 -0
- package/package.json +1 -1
|
@@ -2,184 +2,230 @@ import { ConfigSyntax, TestObjectSyntax } from "../../../constants/syntax.js";
|
|
|
2
2
|
import { CodeGenerator, } from "../classes/abstract-generator.js";
|
|
3
3
|
import { writeFileWithFsExtra } from "../../../utils/fs-utils.js";
|
|
4
4
|
import { markdownMessageGenerator } from "../documentation/markdown-message-generator.js";
|
|
5
|
-
import { buildAstFromInput } from "../../../services/return-complier/combined.js";
|
|
6
|
-
import { CompileToMarkdownForSkip } from "../../../services/return-complier/ast-functions/compile-to-markdown.js";
|
|
7
|
-
import { addBlockquoteToMarkdown, ConvertArrayToStringsInTestObject, } from "../../../utils/general-utils/string-utils.js";
|
|
8
|
-
import Mustache from "mustache";
|
|
9
5
|
/**
|
|
10
|
-
* RagGenerator — produces one Markdown file per API action
|
|
6
|
+
* RagGenerator — produces one richly structured Markdown file per API action
|
|
7
|
+
* under `./rag-docs/`, designed for direct RAG pipeline ingestion.
|
|
11
8
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* Layout per file:
|
|
9
|
+
* Format:
|
|
10
|
+
* ---
|
|
11
|
+
* YAML frontmatter (action, codeName, numTests, generated, domain, version)
|
|
16
12
|
* ---
|
|
17
|
-
*
|
|
13
|
+
* # Heading + context paragraph
|
|
14
|
+
*
|
|
15
|
+
* ## TOP_LEVEL_GROUP
|
|
16
|
+
* Prose intro listing child names, scope, skip condition.
|
|
18
17
|
* ---
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
18
|
+
* ### CHILD_GROUP
|
|
19
|
+
* **LEAF_NAME**
|
|
20
|
+
* `group: PATH | type: leaf | error_code: X`
|
|
21
|
+
*
|
|
22
|
+
* - bullet description lines
|
|
23
|
+
* - Skipped if ...
|
|
23
24
|
*/
|
|
24
25
|
export class RagGenerator extends CodeGenerator {
|
|
25
26
|
constructor() {
|
|
26
27
|
super(...arguments);
|
|
27
|
-
this.generateValidationCode = async () => {
|
|
28
|
-
// Driven by generateCode
|
|
29
|
-
};
|
|
28
|
+
this.generateValidationCode = async () => { };
|
|
30
29
|
this.generateCode = async (codeConfig) => {
|
|
31
30
|
const testConfig = this.validationConfig[ConfigSyntax.Tests];
|
|
32
31
|
const { codeName } = codeConfig;
|
|
33
32
|
for (const action of Object.keys(testConfig)) {
|
|
34
33
|
const testArray = testConfig[action];
|
|
35
|
-
const md = this.buildActionMarkdown(action, codeName, testArray);
|
|
34
|
+
const md = this.buildActionMarkdown(action, codeName, testArray, codeConfig);
|
|
36
35
|
writeFileWithFsExtra(this.rootPath, `./rag-docs/${action}.md`, md);
|
|
37
36
|
}
|
|
38
37
|
};
|
|
39
38
|
}
|
|
40
39
|
generateSessionDataCode() {
|
|
41
|
-
// Session-data code not needed for RAG output
|
|
42
40
|
return Promise.resolve();
|
|
43
41
|
}
|
|
44
42
|
generateUnitTestingCode() {
|
|
45
|
-
// Unit-test code not needed for RAG output
|
|
46
43
|
return Promise.resolve();
|
|
47
44
|
}
|
|
48
45
|
// -------------------------------------------------------------------------
|
|
49
46
|
// Private helpers
|
|
50
47
|
// -------------------------------------------------------------------------
|
|
51
|
-
buildActionMarkdown(action, codeName, testArray) {
|
|
48
|
+
buildActionMarkdown(action, codeName, testArray, codeConfig) {
|
|
52
49
|
const leafCount = this.countLeafTests(testArray);
|
|
50
|
+
const topCount = testArray.length;
|
|
53
51
|
const dateStr = new Date().toISOString().split("T")[0];
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
const domainText = Array.isArray(codeConfig.domain)
|
|
53
|
+
? codeConfig.domain.join(", ")
|
|
54
|
+
: (codeConfig.domain ?? "");
|
|
55
|
+
const fmLines = [
|
|
56
56
|
"---",
|
|
57
57
|
`action: ${action}`,
|
|
58
58
|
`codeName: ${codeName}`,
|
|
59
59
|
`numTests: ${leafCount}`,
|
|
60
60
|
`generated: ${dateStr}`,
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
];
|
|
62
|
+
if (domainText)
|
|
63
|
+
fmLines.push(`domain: ${domainText}`);
|
|
64
|
+
if (codeConfig.version)
|
|
65
|
+
fmLines.push(`version: ${codeConfig.version}`);
|
|
66
|
+
fmLines.push("---");
|
|
67
|
+
const frontmatter = fmLines.join("\n");
|
|
64
68
|
const header = [
|
|
65
69
|
`# ${codeName} — \`${action}\` Validations`,
|
|
66
70
|
"",
|
|
67
|
-
`
|
|
68
|
-
`
|
|
69
|
-
`Each rule maps to a single test object and is evaluated sequentially against the`,
|
|
70
|
-
`request/response payload.`,
|
|
71
|
+
`These are the validation rules applied when processing the \`${action}\` API call in the ${codeName} flow.`,
|
|
72
|
+
`There are **${leafCount}** validation rules organized into **${topCount}** top-level group(s).`,
|
|
71
73
|
"",
|
|
72
74
|
"---",
|
|
73
75
|
"",
|
|
74
76
|
].join("\n");
|
|
75
|
-
// One numbered ## section per top-level test object only.
|
|
76
|
-
// Group nodes embed their children as ### sub-sections inside themselves.
|
|
77
77
|
const sections = testArray
|
|
78
|
-
.map((test
|
|
79
|
-
.join("\n\n");
|
|
78
|
+
.map((test) => this.buildTopLevelSection(test))
|
|
79
|
+
.join("\n\n---\n\n");
|
|
80
80
|
return `${frontmatter}\n\n${header}${sections}\n`;
|
|
81
81
|
}
|
|
82
|
-
/**
|
|
82
|
+
/** Counts leaf (non-group) tests recursively. */
|
|
83
83
|
countLeafTests(tests) {
|
|
84
84
|
let count = 0;
|
|
85
|
-
for (const
|
|
86
|
-
const ret =
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
count += this.countLeafTests(ret);
|
|
92
|
-
}
|
|
85
|
+
for (const t of tests) {
|
|
86
|
+
const ret = t[TestObjectSyntax.Return];
|
|
87
|
+
count +=
|
|
88
|
+
typeof ret === "string"
|
|
89
|
+
? 1
|
|
90
|
+
: this.countLeafTests(ret);
|
|
93
91
|
}
|
|
94
92
|
return count;
|
|
95
93
|
}
|
|
94
|
+
/** Formats a list of names as English prose: "A, B, and C". */
|
|
95
|
+
englishList(names) {
|
|
96
|
+
if (names.length === 0)
|
|
97
|
+
return "";
|
|
98
|
+
if (names.length === 1)
|
|
99
|
+
return names[0];
|
|
100
|
+
if (names.length === 2)
|
|
101
|
+
return `${names[0]} and ${names[1]}`;
|
|
102
|
+
return (names.slice(0, -1).join(", ") + ", and " + names[names.length - 1]);
|
|
103
|
+
}
|
|
96
104
|
/**
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
* -
|
|
100
|
-
* - Group node → brief intro line + all children rendered as ### sub-sections
|
|
101
|
-
* (recursing further for deeply nested groups)
|
|
102
|
-
*
|
|
103
|
-
* This preserves the parent→child relationship in the output so RAG
|
|
104
|
-
* consumers can see exactly which sub-validations belong to which group.
|
|
105
|
+
* Top-level `##` section.
|
|
106
|
+
* - Leaf → `## NAME` + metadata line + body
|
|
107
|
+
* - Group → `## NAME` + prose intro + `---` + children
|
|
105
108
|
*/
|
|
106
|
-
|
|
107
|
-
const name = test[TestObjectSyntax.Name] ??
|
|
109
|
+
buildTopLevelSection(test) {
|
|
110
|
+
const name = test[TestObjectSyntax.Name] ?? "unknown";
|
|
108
111
|
const ret = test[TestObjectSyntax.Return];
|
|
109
112
|
if (typeof ret === "string") {
|
|
110
|
-
|
|
113
|
+
const body = this.renderLeafBody(test, "top-level", false);
|
|
114
|
+
return [`## ${name}`, "", body].join("\n");
|
|
111
115
|
}
|
|
112
|
-
|
|
113
|
-
const childSections = ret
|
|
114
|
-
.map((child, i) => this.renderChildSection(child, i + 1, "###"))
|
|
115
|
-
.join("\n\n");
|
|
116
|
-
const groupSkip = this.renderSkipBlock(test);
|
|
117
|
-
return [
|
|
118
|
-
`## ${index}. ${name}`,
|
|
119
|
-
"",
|
|
120
|
-
`Group of **${ret.length}** sub-validation(s). **All** of the following must pass:`,
|
|
121
|
-
...(groupSkip ? ["", groupSkip] : []),
|
|
122
|
-
"",
|
|
123
|
-
childSections,
|
|
124
|
-
].join("\n");
|
|
116
|
+
return this.renderGroupSection(test, name, "##", "###", []);
|
|
125
117
|
}
|
|
126
118
|
/**
|
|
127
|
-
* Renders a
|
|
128
|
-
*
|
|
119
|
+
* Renders a group section recursively.
|
|
120
|
+
* @param headingLevel Markdown heading for this group node (e.g. "##")
|
|
121
|
+
* @param childLevel Markdown heading for its direct children (e.g. "###")
|
|
122
|
+
* @param ancestorPath Names of ancestor groups, used to build breadcrumbs
|
|
129
123
|
*/
|
|
130
|
-
|
|
131
|
-
const name = test[TestObjectSyntax.Name] ?? `sub_test_${index}`;
|
|
124
|
+
renderGroupSection(test, name, headingLevel, childLevel, ancestorPath) {
|
|
132
125
|
const ret = test[TestObjectSyntax.Return];
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
126
|
+
const skip = test[TestObjectSyntax.Continue];
|
|
127
|
+
const scope = test[TestObjectSyntax.Scope];
|
|
128
|
+
const childNames = ret.map((c) => c[TestObjectSyntax.Name] ?? "?");
|
|
129
|
+
const leafCount = this.countLeafTests(ret);
|
|
130
|
+
const allLeaves = ret.every((c) => typeof c[TestObjectSyntax.Return] === "string");
|
|
131
|
+
// Prose intro sentence
|
|
132
|
+
const introParts = [];
|
|
133
|
+
if (allLeaves) {
|
|
134
|
+
introParts.push(`This is a group of **${leafCount}** sub-validation(s) that all must pass: ` +
|
|
135
|
+
`${this.englishList(childNames)}.`);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
introParts.push(`This group contains **${ret.length}** sub-group(s)/validation(s): ` +
|
|
139
|
+
`${this.englishList(childNames)}.`);
|
|
140
|
+
}
|
|
141
|
+
if (scope) {
|
|
142
|
+
introParts.push(`It validates the \`${scope}\` path in the payload.`);
|
|
136
143
|
}
|
|
137
|
-
|
|
138
|
-
|
|
144
|
+
const introLine = introParts.join(" ");
|
|
145
|
+
// Skip block for the group itself (blockquote, before children)
|
|
146
|
+
let skipBlock = "";
|
|
147
|
+
if (skip) {
|
|
148
|
+
skipBlock = this.renderSkipInlineBullet(test, skip);
|
|
149
|
+
}
|
|
150
|
+
// Render children
|
|
151
|
+
const currentPath = [...ancestorPath, name];
|
|
152
|
+
const grandChildLevel = childLevel + "#";
|
|
139
153
|
const childSections = ret
|
|
140
|
-
.map((child
|
|
154
|
+
.map((child) => {
|
|
155
|
+
const childName = child[TestObjectSyntax.Name] ?? "unknown";
|
|
156
|
+
const childRet = child[TestObjectSyntax.Return];
|
|
157
|
+
if (typeof childRet === "string") {
|
|
158
|
+
return this.renderLeafBody(child, currentPath.join(" > "));
|
|
159
|
+
}
|
|
160
|
+
return this.renderGroupSection(child, childName, childLevel, grandChildLevel, currentPath);
|
|
161
|
+
})
|
|
141
162
|
.join("\n\n");
|
|
142
|
-
const groupSkip = this.renderSkipBlock(test);
|
|
143
163
|
return [
|
|
144
|
-
|
|
164
|
+
`${headingLevel} ${name}`,
|
|
145
165
|
"",
|
|
146
|
-
|
|
147
|
-
...(
|
|
166
|
+
introLine,
|
|
167
|
+
...(skipBlock ? ["", skipBlock] : []),
|
|
168
|
+
"",
|
|
169
|
+
"---",
|
|
148
170
|
"",
|
|
149
171
|
childSections,
|
|
150
172
|
].join("\n");
|
|
151
173
|
}
|
|
152
174
|
/**
|
|
153
|
-
* Renders
|
|
154
|
-
*
|
|
175
|
+
* Renders a leaf node's full content block:
|
|
176
|
+
* **NAME**
|
|
177
|
+
* `group: PATH | type: leaf | error_code: X`
|
|
178
|
+
*
|
|
179
|
+
* - bullet description lines
|
|
180
|
+
* - Skipped if ... (inline, from markdownMessageGenerator)
|
|
155
181
|
*/
|
|
156
|
-
|
|
157
|
-
const
|
|
158
|
-
if (!skip)
|
|
159
|
-
return "";
|
|
160
|
-
let skipMarkdown = `**Skip if:**\n`;
|
|
161
|
-
const skAst = buildAstFromInput(skip);
|
|
162
|
-
const skBlock = CompileToMarkdownForSkip(skAst, false, 2, false);
|
|
163
|
-
skipMarkdown += `\n${skBlock}`;
|
|
164
|
-
const rendered = Mustache.render(skipMarkdown, ConvertArrayToStringsInTestObject(test));
|
|
165
|
-
return addBlockquoteToMarkdown(rendered);
|
|
166
|
-
}
|
|
167
|
-
/** Renders a leaf test's heading, metadata badges, and compiled description. */
|
|
168
|
-
renderLeaf(test, name, heading) {
|
|
182
|
+
renderLeafBody(test, groupPath, showBoldName = true) {
|
|
183
|
+
const name = test[TestObjectSyntax.Name] ?? "unknown";
|
|
169
184
|
const scope = test[TestObjectSyntax.Scope];
|
|
170
185
|
const errorCode = test[TestObjectSyntax.ErrorCode];
|
|
171
186
|
const successCode = test[TestObjectSyntax.SuccessCode];
|
|
172
187
|
const skip = test[TestObjectSyntax.Continue];
|
|
173
188
|
const ret = test[TestObjectSyntax.Return];
|
|
174
|
-
|
|
189
|
+
// Metadata inline-code line
|
|
190
|
+
const metaParts = [`group: ${groupPath}`, `type: leaf`];
|
|
175
191
|
if (scope)
|
|
176
|
-
|
|
192
|
+
metaParts.push(`scope: ${scope}`);
|
|
177
193
|
if (errorCode !== undefined)
|
|
178
|
-
|
|
194
|
+
metaParts.push(`error_code: ${errorCode}`);
|
|
179
195
|
if (successCode !== undefined)
|
|
180
|
-
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
196
|
+
metaParts.push(`success_code: ${successCode}`);
|
|
197
|
+
const metaLine = `\`${metaParts.join(" | ")}\``;
|
|
198
|
+
// Get bullet-point body from compiler; strip the "#### **name**\n\n" heading.
|
|
199
|
+
let bodyContent;
|
|
200
|
+
try {
|
|
201
|
+
const full = markdownMessageGenerator(ret, test, name, skip ? [skip] : undefined);
|
|
202
|
+
bodyContent = full
|
|
203
|
+
.replace(/^#{1,6}\s+\*\*[^*]+\*\*\s*\n\n?/, "")
|
|
204
|
+
.trim();
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
bodyContent = `- ${ret}`;
|
|
208
|
+
if (skip)
|
|
209
|
+
bodyContent += `\n- Skipped if: ${skip}`;
|
|
210
|
+
}
|
|
211
|
+
return showBoldName
|
|
212
|
+
? [`**${name}**`, metaLine, "", bodyContent].join("\n")
|
|
213
|
+
: [metaLine, "", bodyContent].join("\n");
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Renders a group's skip condition as a blockquote paragraph.
|
|
217
|
+
* Uses markdownMessageGenerator to compile the JVAL expression.
|
|
218
|
+
*/
|
|
219
|
+
renderSkipInlineBullet(test, skip) {
|
|
220
|
+
try {
|
|
221
|
+
const full = markdownMessageGenerator(skip, test, "skip", undefined);
|
|
222
|
+
const body = full
|
|
223
|
+
.replace(/^#{1,6}\s+\*\*[^*]+\*\*\s*\n\n?/, "")
|
|
224
|
+
.trim();
|
|
225
|
+
return `> **Skip if:**\n> ${body.replace(/\n/g, "\n> ")}`;
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
return `> **Skip if:** ${skip}`;
|
|
229
|
+
}
|
|
184
230
|
}
|
|
185
231
|
}
|
|
@@ -26,7 +26,7 @@ export declare class RagTableGenerator extends CodeGenerator {
|
|
|
26
26
|
generateCode: (codeConfig: CodeGeneratorProps) => Promise<void>;
|
|
27
27
|
/** Collects rows and returns structured JSON for one action. */
|
|
28
28
|
private buildActionJson;
|
|
29
|
-
buildActionMarkdown(action: string, codeName: string, testArray: TestObject[]): string;
|
|
29
|
+
buildActionMarkdown(action: string, codeName: string, testArray: TestObject[], codeConfig: CodeGeneratorProps): string;
|
|
30
30
|
/**
|
|
31
31
|
* Walks the test tree depth-first.
|
|
32
32
|
*
|
|
@@ -45,6 +45,12 @@ export declare class RagTableGenerator extends CodeGenerator {
|
|
|
45
45
|
* - `Scope`, `Skip If`, `Error Code`, `Success Code` similarly pruned
|
|
46
46
|
*/
|
|
47
47
|
private renderTable;
|
|
48
|
+
/**
|
|
49
|
+
* Compiles a JVAL skip expression to plain text suitable for a table cell.
|
|
50
|
+
* Uses CompileToMarkdownForSkip (not CompileToMarkdown) so the output
|
|
51
|
+
* correctly renders conditional/negation skip logic.
|
|
52
|
+
*/
|
|
53
|
+
private compileSkipToText;
|
|
48
54
|
/**
|
|
49
55
|
* Sanitises a string for safe use inside a GFM table cell:
|
|
50
56
|
* - Collapses newlines and excess whitespace to a single space
|
|
@@ -2,6 +2,10 @@ import { ConfigSyntax, TestObjectSyntax } from "../../../constants/syntax.js";
|
|
|
2
2
|
import { CodeGenerator, } from "../classes/abstract-generator.js";
|
|
3
3
|
import { writeFileWithFsExtra } from "../../../utils/fs-utils.js";
|
|
4
4
|
import { markdownMessageGenerator } from "../documentation/markdown-message-generator.js";
|
|
5
|
+
import { buildAstFromInput } from "../../../services/return-complier/combined.js";
|
|
6
|
+
import { CompileToMarkdownForSkip } from "../../../services/return-complier/ast-functions/compile-to-markdown.js";
|
|
7
|
+
import { ConvertArrayToStringsInTestObject } from "../../../utils/general-utils/string-utils.js";
|
|
8
|
+
import Mustache from "mustache";
|
|
5
9
|
/**
|
|
6
10
|
* RagTableGenerator — produces one Markdown **table** file per API action
|
|
7
11
|
* under `./rag-table-docs/`.
|
|
@@ -33,7 +37,7 @@ export class RagTableGenerator extends CodeGenerator {
|
|
|
33
37
|
const rawJson = {};
|
|
34
38
|
for (const action of Object.keys(testConfig)) {
|
|
35
39
|
const testArray = testConfig[action];
|
|
36
|
-
const md = this.buildActionMarkdown(action, codeName, testArray);
|
|
40
|
+
const md = this.buildActionMarkdown(action, codeName, testArray, codeConfig);
|
|
37
41
|
writeFileWithFsExtra(this.rootPath, `./rag-table-docs/${action}.md`, md);
|
|
38
42
|
rawJson[action] = this.buildActionJson(action, codeName, testArray);
|
|
39
43
|
}
|
|
@@ -62,18 +66,23 @@ export class RagTableGenerator extends CodeGenerator {
|
|
|
62
66
|
rows: rows.map(({ index: _idx, ...rest }) => rest),
|
|
63
67
|
};
|
|
64
68
|
}
|
|
65
|
-
buildActionMarkdown(action, codeName, testArray) {
|
|
69
|
+
buildActionMarkdown(action, codeName, testArray, codeConfig) {
|
|
66
70
|
const rows = [];
|
|
67
71
|
this.collectRows(testArray, rows, "");
|
|
68
72
|
// Re-index after collection so numbering is clean
|
|
69
73
|
rows.forEach((r, i) => (r.index = i + 1));
|
|
70
74
|
const dateStr = new Date().toISOString().split("T")[0];
|
|
75
|
+
const domainText = Array.isArray(codeConfig.domain)
|
|
76
|
+
? codeConfig.domain.join(", ")
|
|
77
|
+
: (codeConfig.domain ?? "-");
|
|
71
78
|
const frontmatter = [
|
|
72
79
|
"---",
|
|
73
80
|
`action: ${action}`,
|
|
74
81
|
`codeName: ${codeName}`,
|
|
75
82
|
`numTests: ${rows.length}`,
|
|
76
83
|
`generated: ${dateStr}`,
|
|
84
|
+
`domain: ${domainText}`,
|
|
85
|
+
`version: ${codeConfig.version ?? "-"}`,
|
|
77
86
|
"---",
|
|
78
87
|
].join("\n");
|
|
79
88
|
const leafCount = rows.filter((r) => r.rowType === "leaf").length;
|
|
@@ -81,6 +90,7 @@ export class RagTableGenerator extends CodeGenerator {
|
|
|
81
90
|
`# ${codeName} — \`${action}\` Validations (Table View)`,
|
|
82
91
|
"",
|
|
83
92
|
`**${leafCount}** leaf validation rule(s) applied to \`${action}\` in the **${codeName}** flow.`,
|
|
93
|
+
`Domain: \`${domainText}\`, Version: \`${codeConfig.version ?? "-"}\``,
|
|
84
94
|
`Group rows (GRP) list their immediate sub-tests. Leaf rows (LF) show the actual validation logic.`,
|
|
85
95
|
"",
|
|
86
96
|
"---",
|
|
@@ -120,9 +130,7 @@ export class RagTableGenerator extends CodeGenerator {
|
|
|
120
130
|
let skipText = "";
|
|
121
131
|
if (ownSkip) {
|
|
122
132
|
try {
|
|
123
|
-
skipText =
|
|
124
|
-
.replace(/^#{1,6}\s+\*\*[^*]+\*\*\s*\n\n?/, "")
|
|
125
|
-
.trim();
|
|
133
|
+
skipText = this.compileSkipToText(ownSkip, test);
|
|
126
134
|
}
|
|
127
135
|
catch {
|
|
128
136
|
skipText = ownSkip;
|
|
@@ -148,9 +156,7 @@ export class RagTableGenerator extends CodeGenerator {
|
|
|
148
156
|
let skipText = "";
|
|
149
157
|
if (ownSkip) {
|
|
150
158
|
try {
|
|
151
|
-
skipText =
|
|
152
|
-
.replace(/^#{1,6}\s+\*\*[^*]+\*\*\s*\n\n?/, "")
|
|
153
|
-
.trim();
|
|
159
|
+
skipText = this.compileSkipToText(ownSkip, test);
|
|
154
160
|
}
|
|
155
161
|
catch {
|
|
156
162
|
skipText = ownSkip;
|
|
@@ -247,6 +253,16 @@ export class RagTableGenerator extends CodeGenerator {
|
|
|
247
253
|
const dataRows = rows.map((r) => `| ${cols.map((c) => c.value(r) || "—").join(" | ")} |`);
|
|
248
254
|
return [headerRow, sepRow, ...dataRows].join("\n");
|
|
249
255
|
}
|
|
256
|
+
/**
|
|
257
|
+
* Compiles a JVAL skip expression to plain text suitable for a table cell.
|
|
258
|
+
* Uses CompileToMarkdownForSkip (not CompileToMarkdown) so the output
|
|
259
|
+
* correctly renders conditional/negation skip logic.
|
|
260
|
+
*/
|
|
261
|
+
compileSkipToText(skipExpr, test) {
|
|
262
|
+
const skAst = buildAstFromInput(skipExpr);
|
|
263
|
+
const skBlock = CompileToMarkdownForSkip(skAst, false, 2, false);
|
|
264
|
+
return Mustache.render(skBlock, ConvertArrayToStringsInTestObject(test));
|
|
265
|
+
}
|
|
250
266
|
/**
|
|
251
267
|
* Sanitises a string for safe use inside a GFM table cell:
|
|
252
268
|
* - Collapses newlines and excess whitespace to a single space
|
|
@@ -100,7 +100,7 @@ export class TypescriptGenerator extends CodeGenerator {
|
|
|
100
100
|
await this.generateValidationCode();
|
|
101
101
|
await writeAndFormatCode(this.rootPath, "error.ts", this.generateErrorFile(this.errorCodes), "typescript");
|
|
102
102
|
await writeAndFormatCode(this.rootPath, "index.ts", this.generateIndexFile(Object.keys(this.validationConfig[ConfigSyntax.Tests]), codeConfig.codeName), "typescript");
|
|
103
|
-
await new MarkdownDocGenerator(this.validationConfig, this.errorCodes, this.rootPath).generateCode();
|
|
103
|
+
await new MarkdownDocGenerator(this.validationConfig, this.errorCodes, this.rootPath).generateCode(codeConfig);
|
|
104
104
|
await this.generateSessionDataCode();
|
|
105
105
|
};
|
|
106
106
|
this.generateTestFunction = async (testObject) => {
|
package/dist/index.test.js
CHANGED
|
@@ -14,15 +14,24 @@ const main = async () => {
|
|
|
14
14
|
await compiler.initialize(buildYaml);
|
|
15
15
|
const validPaths = await compiler.generateValidPaths();
|
|
16
16
|
writeFileSync(path.resolve(__dirname, "../alpha/possible-json-paths.json"), JSON.stringify(validPaths, null, 2), "utf-8");
|
|
17
|
-
await compiler.generateCode(valConfig,
|
|
17
|
+
await compiler.generateCode(valConfig, {
|
|
18
|
+
codeName: "L1_validations",
|
|
19
|
+
outputPath: "./alpha/python/",
|
|
20
|
+
});
|
|
18
21
|
const compilerTy = new ConfigCompiler(SupportedLanguages.Typescript);
|
|
19
22
|
await compilerTy.initialize(buildYaml);
|
|
20
|
-
await compilerTy.generateCode(valConfig,
|
|
23
|
+
await compilerTy.generateCode(valConfig, {
|
|
24
|
+
codeName: "L1_validations",
|
|
25
|
+
outputPath: "./alpha/typescript/",
|
|
26
|
+
});
|
|
21
27
|
await compilerTy.generateL0Schema("./alpha/typescript/L0_schema/");
|
|
22
28
|
await compilerTy.generateL0Schema("./alpha/json/", "json");
|
|
23
29
|
const compilerGo = new ConfigCompiler(SupportedLanguages.Golang);
|
|
24
30
|
await compilerGo.initialize(buildYaml);
|
|
25
|
-
await compilerGo.generateCode(valConfig,
|
|
31
|
+
await compilerGo.generateCode(valConfig, {
|
|
32
|
+
codeName: "L1_validations",
|
|
33
|
+
outputPath: "./alpha/golang/",
|
|
34
|
+
});
|
|
26
35
|
// JavaScript generation example
|
|
27
36
|
// const compilerJs = new ConfigCompiler(SupportedLanguages.Javascript);
|
|
28
37
|
// await compilerJs.initialize(buildYaml);
|
package/dist/types/build.d.ts
CHANGED